1 /*
2  * marvel_mod.c
3  *
4  * Marvell specific modules for handling BMC and MC functions.
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2012,2013 MontaVista Software Inc.
11  *
12  * This software is available to you under a choice of one of two
13  * licenses.  You may choose to be licensed under the terms of the GNU
14  * Lesser General Public License (GPL) Version 2 or the modified BSD
15  * license below.  The following disclamer applies to both licenses:
16  *
17  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * GNU Lesser General Public Licence
29  *
30  *  This program is free software; you can redistribute it and/or
31  *  modify it under the terms of the GNU Lesser General Public License
32  *  as published by the Free Software Foundation; either version 2 of
33  *  the License, or (at your option) any later version.
34  *
35  *  You should have received a copy of the GNU Lesser General Public
36  *  License along with this program; if not, write to the Free
37  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38  *
39  * Modified BSD Licence
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  *
45  *   1. Redistributions of source code must retain the above copyright
46  *      notice, this list of conditions and the following disclaimer.
47  *   2. Redistributions in binary form must reproduce the above
48  *      copyright notice, this list of conditions and the following
49  *      disclaimer in the documentation and/or other materials provided
50  *      with the distribution.
51  *   3. The name of the author may not be used to endorse or promote
52  *      products derived from this software without specific prior
53  *      written permission.
54  */
55 
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <errno.h>
59 #include <string.h>
60 #include <sys/time.h>
61 #include <sys/ioctl.h>
62 #include <unistd.h>
63 #include <signal.h>
64 #include <pthread.h>
65 #include <sys/types.h>
66 #include <sys/stat.h>
67 #include <fcntl.h>
68 #include <semaphore.h>
69 
70 #include <OpenIPMI/ipmi_msgbits.h>
71 #include <OpenIPMI/ipmi_bits.h>
72 #include <OpenIPMI/serv.h>
73 
74 #include "wiw.h"
75 
76 #define PVERSION "2.0.12"
77 
78 #define NUM_BOARDS 6
79 
80 #define CHASSIS_FRU_SIZE 1024
81 #define BOARD_FRU_SIZE 2048
82 
83 #define BOARD_TEMP_SHUTDOWN 105
84 #define SWITCH_TEMP_SHUTDOWN 115
85 #define FRONT_TEMP_SHUTDOWN 50
86 
87 #define MARVELL_SEMI_ISREAL_IANA	20495
88 #define DISABLE_NETWORK_SRVC_CMD	1
89 #define RELOAD_BOARD_FRU_CMD		2
90 #define SET_ALL_FANS_DUTY_CMD		3
91 #define GET_ALL_FANS_DUTY_CMD		4
92 
93 #define BOARD_FRU_FILE "/etc/ipmi/axp_board_fru"
94 #define COLD_POWER_FILE "/var/lib/ipmi_sim_coldpower"
95 #define RESET_REASON_FILE "/var/lib/reset_reason"
96 #define RESET_REASON_UNKNOWN 0
97 #define RESET_REASON_COLD_BOOT 1
98 #define RESET_REASON_WARM_BOOT 2
99 static int init_complete;
100 
101 #define GPIODIR "/sys/class/astgpio/GPIO"
102 
103 #define COLD_POWER_UP_IO "/sys/class/astgpio/ColdBoot"
104 static unsigned int cold_power_up = 1;
105 
106 /*
107  * Set debugging with bits:
108  * bit 0 - power
109  * bit 1 - sensor reading
110  * bit 2 - sensor writing
111  * bit 3 - fan
112  */
113 static unsigned int debug;
114 
115 /* 1 second poll time */
116 static unsigned int poll_time = 2000000;
117 
118 static lmc_data_t *bmc_mc;
119 
120 /* Set the file to "0" to enable reset */
121 #define BOARD_RESET_ON 0
122 #define BOARD_RESET_OFF 1
123 static const char *trg_reset[NUM_BOARDS] =
124 {
125     GPIODIR "H0",
126     GPIODIR "H1",
127     GPIODIR "H2",
128     GPIODIR "H3",
129     GPIODIR "H4",
130     GPIODIR "H5"
131 };
132 
133 /* Set the file to "1" to power on, "0" to power off. */
134 #define BOARD_POWER_ON 1
135 #define BOARD_POWER_OFF 0
136 static const char *trg_power[NUM_BOARDS] =
137 {
138     GPIODIR "D6",
139     GPIODIR "D7",
140     GPIODIR "B0",
141     GPIODIR "B1",
142     GPIODIR "B2",
143     GPIODIR "B3"
144 };
145 
146 /* Will contain "0" if present, "1" if not present. */
147 #define BOARD_PRESENT 0
148 #define BOARD_ABSENT 1
149 static const char *trg_present[NUM_BOARDS] =
150 {
151     GPIODIR "C0",
152     GPIODIR "C1",
153     GPIODIR "C2",
154     GPIODIR "C3",
155     GPIODIR "C4",
156     GPIODIR "C5",
157 };
158 
159 static int simulate_board_absent[NUM_BOARDS];
160 
161 /* Set this to zero to request that the board power off.  */
162 #define BOARD_OFF_REQUEST_ON 0
163 #define BOARD_OFF_REQUEST_OFF 1
164 static const char *pow_off_request[NUM_BOARDS] =
165 {
166     GPIODIR "A6",
167     GPIODIR "A7",
168     GPIODIR "I4",
169     GPIODIR "I5",
170     GPIODIR "I6",
171     GPIODIR "I7"
172 };
173 
174 /* The board will set the value to 0 when it is ready to power off.  */
175 #define BOARD_OFF_READY 0
176 #define BOARD_OFF_NOT_READY 1
177 static const char *pow_off_ready[NUM_BOARDS] =
178 {
179     GPIODIR "A0",
180     GPIODIR "A1",
181     GPIODIR "A2",
182     GPIODIR "A3",
183     GPIODIR "G4",
184     GPIODIR "G5"
185 };
186 
187 
188 #define I2CDIR "/sys/class/i2c-adapter/i2c-"
189 
190 struct eeprom {
191     unsigned char addr;
192     const char *part;
193     const char *dev;
194     unsigned int size;
195 };
196 
197 static struct board_i2c_info
198 {
199     const char *add_dev;
200     struct eeprom fru;
201 } const board_i2c[NUM_BOARDS] =
202 {
203     {
204 	.add_dev = I2CDIR "1/new_device",
205 	.fru = {
206 	    .addr = 0x50,
207 	    .part = "24c64",
208 	    .dev = I2CDIR "1/1-0050/at24c64",
209 	    .size = BOARD_FRU_SIZE
210 	},
211     },
212     {
213 	.add_dev = I2CDIR "2/new_device",
214 	.fru = {
215 	    .addr = 0x50,
216 	    .part = "24c64",
217 	    .dev = I2CDIR "2/2-0050/at24c64",
218 	    .size = BOARD_FRU_SIZE
219 	},
220     },
221     {
222 	.add_dev = I2CDIR "3/new_device",
223 	.fru = {
224 	    .addr = 0x50,
225 	    .part = "24c64",
226 	    .dev = I2CDIR "3/3-0050/at24c64",
227 	    .size = BOARD_FRU_SIZE
228 	},
229     },
230     {
231 	.add_dev = I2CDIR "4/new_device",
232 	.fru = {
233 	    .addr = 0x50,
234 	    .part = "24c64",
235 	    .dev = I2CDIR "4/4-0050/at24c64",
236 	    .size = BOARD_FRU_SIZE
237 	},
238     },
239     {
240 	.add_dev = I2CDIR "5/new_device",
241 	.fru = {
242 	    .addr = 0x50,
243 	    .part = "24c64",
244 	    .dev = I2CDIR "5/5-0050/at24c64",
245 	    .size = BOARD_FRU_SIZE
246 	},
247     },
248     {
249 	.add_dev = I2CDIR "6/new_device",
250 	.fru = {
251 	    .addr = 0x50,
252 	    .part = "24c64",
253 	    .dev = I2CDIR "6/6-0050/at24c64",
254 	    .size = BOARD_FRU_SIZE
255 	},
256     },
257 };
258 
259 static struct board_i2c_info *chassis_i2c;
260 
261 /* For older systems (before DVT2) */
262 static struct board_i2c_info chassis_i2c_old =
263 {
264     .add_dev = I2CDIR "7/new_device",
265     .fru = {
266 	.addr = 0x54,
267 	.part = "24c128",
268 	.dev = I2CDIR "7/7-0054/at24c128",
269 	.size = CHASSIS_FRU_SIZE
270     }
271 };
272 
273 /* For newer systems (DVT2 and later) */
274 static struct board_i2c_info chassis_i2c_new =
275 {
276     .add_dev = I2CDIR "0/new_device",
277     .fru = {
278 	.addr = 0x54,
279 	.part = "24c128",
280 	.dev = I2CDIR "0/0-0051/at24c128",
281 	.size = CHASSIS_FRU_SIZE
282     }
283 };
284 
285 static struct board_info {
286     sys_data_t *sys;
287 
288     lmc_data_t *mc;
289     unsigned char num;
290     char present;
291     char fru_good;
292     unsigned char fru[BOARD_FRU_SIZE];
293     struct timeval button_press_time;
294     unsigned int power_off_countdown;
295     char button_pressed;
296     char waiting_power_off;
297 
298     volatile char fru_data_ready_for_handling;
299 
300     /*
301      * Tracks the state of the power request line, request happens
302      * on a 1->0 transition.
303      */
304     char last_power_request;
305 } boards[NUM_BOARDS];
306 
307 struct timeval last_board_power_on;
308 
309 static unsigned char chassis_fru[CHASSIS_FRU_SIZE];
310 static unsigned int chassis_iuse;
311 static unsigned int chassis_iuse_len;
312 static unsigned int chassis_chinfo;
313 static unsigned int chassis_chinfo_len;
314 static unsigned int chassis_brdinfo;
315 static unsigned int chassis_brdinfo_len;
316 
317 /* Offset from beginning of chassis info area */
318 static unsigned int sernum_offset;
319 static unsigned int sernum_offset2;
320 static unsigned int sernum_len;
321 static unsigned int sysmac_offset;
322 
323 /* Pieces of the serial number and MAC we need for generating board info */
324 static unsigned char sernum[10];
325 static unsigned char sysmac[17];
326 
327 static const unsigned char board_ipmb[NUM_BOARDS] = { 1, 2, 3, 4, 5, 6 };
328 
329 static int disable_wdt;
330 static int wdt_fd;
331 static ipmi_timer_t *wdt_test_timer;
332 static volatile int wdt_test_timer_ran;
333 
334 static void
add_to_timeval(struct timeval * tv,unsigned int usecs)335 add_to_timeval(struct timeval *tv, unsigned int usecs)
336 {
337     while (usecs >= 1000000) {
338 	tv->tv_sec += 1;
339 	usecs -= 1000000;
340     }
341     tv->tv_usec += usecs;
342     while (tv->tv_usec >= 1000000) {
343 	tv->tv_sec += 1;
344 	tv->tv_usec -= 1000000;
345     }
346 }
347 
348 static void
diff_timeval(struct timeval * result,struct timeval * tv1,struct timeval * tv2)349 diff_timeval(struct timeval *result, struct timeval *tv1, struct timeval *tv2)
350 {
351     result->tv_sec = tv1->tv_sec - tv2->tv_sec;
352     result->tv_usec = tv1->tv_usec - tv2->tv_usec;
353     while (result->tv_usec < 0) {
354 	result->tv_usec += 1000000;
355 	result->tv_sec -= 1;
356     }
357 }
358 
359 static long
diff_timeval_ms(struct timeval * tv1,struct timeval * tv2)360 diff_timeval_ms(struct timeval *tv1, struct timeval *tv2)
361 {
362     struct timeval tv;
363     diff_timeval(&tv, tv1, tv2);
364 
365     if (tv.tv_sec > 1000)
366 	return 1000000;
367     if (tv.tv_sec < -1000)
368 	return -1000000;
369     return (tv.tv_sec * 1000) + ((tv.tv_usec + 500) / 1000);
370 }
371 
372 
373 /**************************************************************************
374  * EEPROM handling
375  *************************************************************************/
376 
377 static unsigned char
checksum(unsigned char * data,int size)378 checksum(unsigned char *data, int size)
379 {
380 	unsigned char csum = 0;
381 
382 	for (; size > 0; size--, data++)
383 		csum += *data;
384 
385 	return csum;
386 }
387 
388 /*
389  * Validate that the eeprom device exists and can be opened.
390  */
391 static int
check_eeprom(sys_data_t * sys,const struct eeprom * e)392 check_eeprom(sys_data_t *sys, const struct eeprom *e)
393 {
394     int fd;
395 
396     fd = open(e->dev, O_RDONLY);
397     if (fd == -1)
398 	return errno;
399     close(fd);
400     return 0;
401 }
402 
403 /*
404  * Write to the sysfs file to create the eeprom device.  Sometimes it
405  * doesn't get automatically created, so create it here.
406  */
407 static int
create_eeprom(sys_data_t * sys,const char * add_dev,const struct eeprom * e)408 create_eeprom(sys_data_t *sys, const char *add_dev, const struct eeprom *e)
409 {
410     int fd;
411 
412     fd = open(e->dev, O_RDONLY);
413     if (fd == -1) {
414 	FILE *f;
415 	f = fopen(add_dev, "w");
416 	if (!f)
417 	    return errno;
418 	fprintf(f, "%s %d\n", e->part, e->addr);
419 	fclose(f);
420 	fd = open(e->dev, O_RDONLY);
421 	if (fd == -1)
422 	    return errno;
423     }
424     close(fd);
425     return 0;
426 }
427 
428 /* Note: Data must be at least e->size */
429 static int
read_eeprom(const struct eeprom * e,unsigned char * data,unsigned int offset,int size)430 read_eeprom(const struct eeprom *e, unsigned char *data,
431 	    unsigned int offset, int size)
432 {
433     int rv;
434     int err = 0;
435     int fd;
436 
437     if (offset + size > e->size)
438 	return EINVAL;
439 
440     fd = open(e->dev, O_RDONLY);
441     if (fd == -1)
442 	return errno;
443     if (lseek(fd, offset, SEEK_SET) == -1) {
444 	err = errno;
445 	close(fd);
446 	return err;
447     }
448     rv = read(fd, data, size);
449     if (rv == -1)
450 	err = errno;
451     else if (rv < size)
452 	err = EIO;
453     close(fd);
454     return err;
455 }
456 
457 /* Note: Data must be at least e->size */
458 static int
write_eeprom(const struct eeprom * e,unsigned char * data,unsigned int offset,unsigned int size)459 write_eeprom(const struct eeprom *e, unsigned char *data,
460 	     unsigned int offset, unsigned int size)
461 {
462     int rv;
463     int err = 0;
464     int fd;
465 
466     if (size + offset > e->size)
467 	return EINVAL;
468 
469     fd = open(e->dev, O_WRONLY);
470     if (fd == -1)
471 	return errno;
472     if (lseek(fd, offset, SEEK_SET) == -1) {
473 	close(fd);
474 	return errno;
475     }
476     rv = write(fd, data, size);
477     if (rv == -1)
478 	err = errno;
479     else if (rv < size)
480 	err = EIO;
481     close(fd);
482     return err;
483 }
484 
485 
486 /**************************************************************************
487  * General file handling.  These are functions that read and write
488  * sysfs files, generally.
489  *************************************************************************/
490 
491 /*
492  * Convert an integer value to a string and write it to the device.
493  */
494 static int
set_intval(const char * fname,unsigned int val)495 set_intval(const char *fname, unsigned int val)
496 {
497     FILE *f;
498 
499     f = fopen(fname, "w");
500     if (!f)
501 	return errno;
502     fprintf(f, "%u\n", val);
503     fclose(f);
504     return 0;
505 }
506 
507 /*
508  * Fetch an unsigned integer ASCII value from a file an convert it.
509  */
510 static int
get_uintval(const char * fname,unsigned int * val)511 get_uintval(const char *fname, unsigned int *val)
512 {
513     FILE *f;
514     char line[80];
515     size_t rv;
516 
517     f = fopen(fname, "r");
518     if (!f)
519        return errno;
520     rv = fread(line, 1, sizeof(line), f);
521     if (rv == 0) {
522         int retval = 0;
523         if (ferror(f)) {
524             retval = errno;
525         }
526 	fclose(f);
527 	return retval;
528     }
529     fclose(f);
530     *val = strtoul(line, NULL, 0);
531     return 0;
532 }
533 
534 /*
535  * Fetch a signed integer ASCII value from a file an convert it.
536  */
537 static int
get_intval(const char * fname,int * val)538 get_intval(const char *fname, int *val)
539 {
540     FILE *f;
541     char line[80];
542     size_t rv;
543 
544     f = fopen(fname, "r");
545     if (!f)
546        return errno;
547     rv = fread(line, 1, sizeof(line), f);
548     if (rv == 0) {
549         int retval = 0;
550         if (ferror(f)) {
551             retval = errno;
552         }
553 	fclose(f);
554 	return retval;
555     }
556     fclose(f);
557     *val = strtol(line, NULL, 0);
558     return 0;
559 }
560 
561 
562 /**************************************************************************
563  * Board power handling.
564  *
565  * This is kept as a list of boards waiting to power on.  Only one
566  * board may be waiting at a time, and the first thing in
567  * boards_waiting_power_on will be the next thing to power on.
568  *************************************************************************/
569 
570 static ipmi_timer_t *power_timer;
571 static unsigned int boards_waiting_power_on[NUM_BOARDS];
572 static unsigned int num_boards_waiting_power_on;
573 static enum {
574     PT_NOT_RUNNING,
575     PT_RUNNING,
576     PT_WAITING_RESET
577 } power_timer_running;
578 
579 /*
580  * Return true if the board is on, false if not.
581  */
582 static int
board_power_state(sys_data_t * sys,unsigned int num)583 board_power_state(sys_data_t *sys, unsigned int num)
584 {
585     int rv;
586     unsigned int rval;
587 
588     rv = get_uintval(trg_power[num], &rval);
589     if (rv) {
590 	sys->log(sys, OS_ERROR, NULL,
591 		 "Unable to read board %u power state: %s",
592 		 num + 1, strerror(rv));
593 	return 0;
594     }
595     return rval == BOARD_POWER_ON;
596 }
597 
598 /*
599  * Return true if the given board number is waiting to power on.
600  */
601 static int
board_waiting_power_on(unsigned int num)602 board_waiting_power_on(unsigned int num)
603 {
604     unsigned int i;
605 
606     for (i = 0; i < num_boards_waiting_power_on; i++) {
607 	if (boards_waiting_power_on[i] == num)
608 	    return 1;
609     }
610     return 0;
611 }
612 
613 /*
614  * Start the timer to power on the board.  The time will be
615  * mintime + rand[1-6].
616  */
617 static void
start_power_timer(sys_data_t * sys,unsigned int mintime)618 start_power_timer(sys_data_t *sys, unsigned int mintime)
619 {
620     struct timeval tv;
621     unsigned int to_add;
622 
623     sys->gen_rand(sys, &to_add, sizeof(to_add));
624     to_add %= 5;
625     to_add += 1 + mintime;
626     tv.tv_sec = to_add;
627     tv.tv_usec = 0;
628 
629     if (debug & 1)
630 	sys->log(sys, DEBUG, NULL, "Starting power timer on board %u for"
631 		 " %u seconds",
632 		 boards_waiting_power_on[0] + 1, to_add);
633     sys->start_timer(power_timer, &tv);
634     power_timer_running = PT_RUNNING;
635 }
636 
637 /*
638  * Set the given board number waiting to power up.
639  */
640 static void
board_add_power_wait(sys_data_t * sys,unsigned int num)641 board_add_power_wait(sys_data_t *sys, unsigned int num)
642 {
643     boards_waiting_power_on[num_boards_waiting_power_on] = num;
644     num_boards_waiting_power_on++;
645     if (num_boards_waiting_power_on == 1)
646 	start_power_timer(sys, 0);
647 }
648 
649 /*
650  * Remove the board from the power up wait list and start the next
651  * board, if there is one.
652  */
653 static void
board_remove_power_wait(sys_data_t * sys,unsigned int num)654 board_remove_power_wait(sys_data_t *sys, unsigned int num)
655 {
656     unsigned int i;
657 
658     for (i = 0; i < num_boards_waiting_power_on; i++) {
659 	if (boards_waiting_power_on[i] == num)
660 	    break;
661     }
662     if (i == num_boards_waiting_power_on)
663 	/* Not found */
664 	return;
665     for (; i < num_boards_waiting_power_on - 1; i++)
666 	boards_waiting_power_on[i] = boards_waiting_power_on[i + 1];
667     num_boards_waiting_power_on--;
668 
669     if (num_boards_waiting_power_on == 0) {
670 	sys->stop_timer(power_timer);
671 	if (!init_complete) {
672 	    set_intval(COLD_POWER_FILE, 0);
673 	    init_complete = 1;
674 	}
675     } else if (power_timer_running == PT_NOT_RUNNING)
676 	start_power_timer(sys, 5);
677 }
678 
679 static int
set_chassis_control(lmc_data_t * mc,int op,unsigned char * val,void * cb_data)680 set_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data)
681 {
682     struct board_info *board = cb_data;
683     sys_data_t *sys = board->sys;
684     unsigned int num = board->num;
685     int wval;
686     int rv, err;
687 
688     switch (op) {
689     case CHASSIS_CONTROL_POWER:
690 	if (debug & 1) {
691 	    struct timeval now;
692 	    board->sys->get_real_time(board->sys, &now);
693 	    sys->log(sys, DEBUG, NULL, "Power request for board %d,"
694 		     " val=%d, wait=%d last=%ld.%ld, now=%ld.%ld",
695 		     board->num + 1, *val, board->waiting_power_off,
696 		     last_board_power_on.tv_sec, last_board_power_on.tv_sec,
697 		     now.tv_sec, now.tv_sec);
698 	}
699 	if (debug & 1 && board->waiting_power_off)
700 	    sys->log(sys, DEBUG, NULL, "Canceling power off wait on"
701 		     "board power request for board %d", board->num + 1);
702 
703 	/* It's going to be forced on or off soon, just disable this. */
704 	board->waiting_power_off = 0;
705 	set_intval(pow_off_request[num], BOARD_OFF_REQUEST_OFF);
706 
707 	if (*val) {
708 	    if (!board->present) {
709 		if (debug & 1)
710 		    sys->log(sys, DEBUG, NULL, "Power on request while board"
711 			     " not present on %d", num + 1);
712 		return EAGAIN;
713 	    }
714 	    if (!board_power_state(sys, num) && !board_waiting_power_on(num))
715 		board_add_power_wait(sys, num);
716 	    else if (debug & 1)
717 		sys->log(sys, DEBUG, NULL, "Power on request, but board was"
718 			 " alread on or waiting power up on board %d", num + 1);
719 
720 	    /* We always delay for a power on. */
721 	    break;
722 	}
723 
724 	/* We are powering off. */
725 	if (board_waiting_power_on(num)) {
726 	    /* Don't power on later. */
727 	    if (debug & 1)
728 		sys->log(sys, DEBUG, NULL, "Stopping board power timer"
729 			 " on %d", num + 1);
730 	    board_remove_power_wait(sys, num);
731 	}
732 	if (debug & 1)
733 	    sys->log(sys, DEBUG, NULL, "Setting board power off on %d",
734 		     num + 1);
735 	rv = set_intval(trg_power[num], BOARD_POWER_OFF);
736 	if (rv) {
737 	    sys->log(sys, OS_ERROR, NULL, "Warning: Unable to set power off"
738 		     " for board %d: %s", board->num, strerror(rv));
739 	    return rv;
740 	}
741 
742 	/*
743 	 * We require a 0->1 transition for the power request to be
744 	 * honored, so start at 1 for the next time to avoid board
745 	 * insertion or startup issues.
746 	 */
747 	board->last_power_request = BOARD_OFF_READY;
748 	break;
749 
750     case CHASSIS_CONTROL_RESET:
751 	if (debug & 1)
752 	    sys->log(sys, DEBUG, NULL, "Resetting board %d", board->num + 1);
753 	set_intval(trg_reset[num], BOARD_RESET_ON);
754 	set_intval(trg_reset[num], BOARD_RESET_OFF);
755 	break;
756 
757     case CHASSIS_CONTROL_BOOT_INFO_ACK:
758 	/* Just ignore this for now */
759 	break;
760 
761     case CHASSIS_CONTROL_BOOT:
762 	if (debug & 1)
763 	    sys->log(sys, DEBUG, NULL, "Chassis control on %d present=%d, "
764 		     "fru_good=%d, val=%d",
765 		     board->num + 1, boards[num].present,
766 		     boards[num].fru_good, *val);
767 	if (!boards[num].present)
768 	    return EAGAIN;
769 	if (!boards[num].fru_good)
770 	    return EBADFD;
771 	switch (*val) {
772 	case 0: /* none */
773 	    return 0;
774 
775 	case 1: /* pxe */
776 	    wval = 1;
777 	    break;
778 
779 	case 2: /* default */
780 	    wval = 0;
781 	    break;
782 
783 	default:
784 	    return EINVAL;
785 	}
786 
787 	rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0);
788 	if (rv)
789 	    return rv;
790 
791 	boards[num].fru[11] = wval;
792 	rv = write_eeprom(&board_i2c[num].fru, boards[num].fru + 11, 11, 1);
793 	if (rv) {
794 	    sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d"
795 		     " PXE boot: %s", num + 1, strerror(rv));
796 	} else {
797 	    boards[num].fru[79] = -checksum(boards[num].fru + 8, 71);
798 	    rv = write_eeprom(&board_i2c[num].fru, boards[num].fru + 79, 79, 1);
799 	    if (rv) {
800 		sys->log(sys, OS_ERROR, NULL, "Warning: Error writing"
801 			 " board %d"
802 			 " PXE boot checksum: %s", num + 1, strerror(rv));
803 		rv = 0;
804 	    }
805 	}
806 	err = ipmi_mc_fru_sem_post(board->mc, 0);
807 	if (err)
808 	    sys->log(sys, OS_ERROR, NULL,
809 		     "Error posting board %d semaphore: %s", num + 1,
810 		     strerror(err));
811 	return rv;
812 
813     case CHASSIS_CONTROL_GRACEFUL_SHUTDOWN:
814 	if (board_waiting_power_on(num)) {
815 	    if (debug & 1)
816 		sys->log(sys, DEBUG, NULL, "Graceful shutdown requested on %d,"
817 			 " shutting down power on timer", board->num + 1);
818 	    board_remove_power_wait(sys, num);
819 	} else if (board->waiting_power_off) {
820 	    /* Nothing to do, already waiting. */
821 	} else if (board_power_state(sys, num)) {
822 	    if (debug & 1)
823 		sys->log(sys, DEBUG, NULL, "Graceful shutdown requested on %d,"
824 			 " requesting board power off", board->num + 1);
825 	    board->waiting_power_off = 1;
826 	    board->power_off_countdown = 30;
827 	    set_intval(pow_off_request[num], BOARD_OFF_REQUEST_ON);
828 	}
829 	break;
830 
831     default:
832 	return EINVAL;
833     }
834     return 0;
835 }
836 
837 static int
get_chassis_control(lmc_data_t * mc,int op,unsigned char * val,void * cb_data)838 get_chassis_control(lmc_data_t *mc, int op, unsigned char *val, void *cb_data)
839 {
840     struct board_info *board = cb_data;
841     sys_data_t *sys = board->sys;
842     unsigned int num = board->num;
843     unsigned char cval;
844     int rv, err;
845 
846     switch (op) {
847     case CHASSIS_CONTROL_POWER:
848 	*val = (board_power_state(board->sys, num) ||
849 		board_waiting_power_on(num));
850 	break;
851 
852     case CHASSIS_CONTROL_BOOT_INFO_ACK:
853 	val[0] = 0;
854 	val[1] = 0;
855 	break;
856 
857     case CHASSIS_CONTROL_BOOT:
858 	rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0);
859 	if (rv)
860 	    return rv;
861 	rv = read_eeprom(&board_i2c[num].fru, &cval, 11, 1);
862 	if (rv)
863 	    goto out_post;
864 	switch(cval) {
865 	case 0:
866 	    *val = 2; /* default disk */
867 	    break;
868 	case 1:
869 	    *val = 1; /* pxe */
870 	    break;
871 
872 	default:
873 	    *val = 0; /* Shouldn't happen */
874 	    break;
875 	}
876     out_post:
877 	err = ipmi_mc_fru_sem_post(board->mc, 0);
878 	if (err)
879 	    sys->log(sys, OS_ERROR, NULL,
880 		     "Error posting board %d semaphore: %s", num + 1,
881 		     strerror(err));
882 	return rv;
883 
884     default:
885 	return EINVAL;
886     }
887     return 0;
888 }
889 
890 /*
891  * Chassis control for the chassis.  This will perform the operation on
892  * all boards.
893  */
894 static int
bmc_set_chassis_control(lmc_data_t * mc,int op,unsigned char * val,void * cb_data)895 bmc_set_chassis_control(lmc_data_t *mc, int op, unsigned char *val,
896 			void *cb_data)
897 {
898     sys_data_t *sys = cb_data;
899     unsigned int i;
900 
901     switch (op) {
902     case CHASSIS_CONTROL_POWER:
903     case CHASSIS_CONTROL_RESET:
904     case CHASSIS_CONTROL_BOOT_INFO_ACK:
905     case CHASSIS_CONTROL_BOOT:
906     case CHASSIS_CONTROL_GRACEFUL_SHUTDOWN:
907 	break;
908     default:
909 	return EINVAL;
910     }
911 
912     if (debug & 1) {
913 	struct timeval now;
914 	sys->get_real_time(sys, &now);
915 	sys->log(sys, DEBUG, NULL, "Power request for all boards,"
916 		 " val=%d, now=%ld.%ld",
917 		 *val, now.tv_sec, now.tv_sec);
918     }
919 
920     for (i = 0; i < NUM_BOARDS; i++)
921 	set_chassis_control(NULL, op, val, &boards[i]);
922 
923     return 0;
924 }
925 
926 /*
927  * Chassis control get for the chassis.  This only works for the power
928  * control, and will return on if any board in the chassis is on, and
929  * off otherwise.
930  */
931 static int
bmc_get_chassis_control(lmc_data_t * mc,int op,unsigned char * val,void * cb_data)932 bmc_get_chassis_control(lmc_data_t *mc, int op, unsigned char *val,
933 			void *cb_data)
934 {
935     unsigned int i;
936 
937     if (op == CHASSIS_CONTROL_POWER) {
938 	unsigned char rval = 0, tval;
939 
940 	/* If any board is on, report power as on. */
941 	for (i = 0; i < NUM_BOARDS; i++) {
942 	    get_chassis_control(NULL, op, &tval, &boards[i]);
943 	    if (tval)
944 		rval = 1;
945 	}
946 	*val = rval;
947 	return 0;
948     }
949 
950     /* This doesn't make sense for anything else. */
951     return EINVAL;
952 }
953 
954 static void
board_power_timeout(void * cb_data)955 board_power_timeout(void *cb_data)
956 {
957     sys_data_t *sys = cb_data;
958     unsigned int num = boards_waiting_power_on[0];
959     struct board_info *board = &boards[num];
960     int rv;
961 
962     if (num_boards_waiting_power_on == 0) {
963 	sys->log(sys, SETUP_ERROR, NULL, "Warning: power timer went off"
964 		 " but no board waiting");
965 	return;
966     }
967 
968     if (power_timer_running == PT_RUNNING) {
969 	struct timeval tv;
970 
971 	if (debug & 1)
972 	    sys->log(sys, DEBUG, NULL, "Powering on board %d", num + 1);
973 
974 	/* Hold the reset on the board for 100ms while it powers on. */
975 	set_intval(trg_reset[num], BOARD_RESET_ON);
976 
977 	rv = set_intval(trg_power[num], BOARD_POWER_ON);
978 	if (rv)
979 	    sys->log(sys, OS_ERROR, NULL, "Warning: Unable to set power on"
980 		     " for board %d: %s", num, strerror(rv));
981 
982 	/* Start the 100ms reset timer */
983 	if (debug & 1)
984 	    sys->log(sys, DEBUG, NULL, "Starting reset timer on board %u",
985 		     num + 1);
986 	power_timer_running = PT_WAITING_RESET;
987 	tv.tv_sec = 0;
988 	tv.tv_usec = 100000;
989 	sys->start_timer(power_timer, &tv);
990     } else {
991 	/* Take the board out of reset. */
992 	set_intval(trg_reset[num], BOARD_RESET_OFF);
993 
994 	power_timer_running = PT_NOT_RUNNING;
995 
996 	/* Starts the next one if something is waiting. */
997 	board_remove_power_wait(sys, num);
998     }
999 }
1000 
1001 static void
power_down_system(sys_data_t * sys)1002 power_down_system(sys_data_t *sys)
1003 {
1004     unsigned int i;
1005     unsigned char val = 0;
1006 
1007     for (i = 0; i < NUM_BOARDS; i++)
1008 	set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, &boards[i]);
1009 }
1010 
1011 /*
1012  * Called at init time to make sure the board state is sane.
1013  */
1014 static void
check_chassis_state(sys_data_t * sys)1015 check_chassis_state(sys_data_t *sys)
1016 {
1017     unsigned int i;
1018 
1019     /*
1020      * Make sure the reset is off on all boards.  The power state will
1021      * be set later.
1022      */
1023     for (i = 0; i < NUM_BOARDS; i++)
1024 	set_intval(trg_reset[i], BOARD_RESET_OFF);
1025 }
1026 
1027 /**************************************************************************
1028  * Sensor handling
1029  *************************************************************************/
1030 
1031 /*
1032  * The DIMM and CPU error sensors will remain set until rearmed.  This
1033  * is the rearm handling to clear those bits.
1034  */
1035 struct eesense_rearm
1036 {
1037     unsigned int num;
1038     unsigned int offset;
1039     unsigned char mask;
1040 };
1041 
1042 static int
rearm_eesense_sensor(void * cb_data,uint16_t assert,uint16_t deassert)1043 rearm_eesense_sensor(void *cb_data,
1044 		     uint16_t assert,
1045 		     uint16_t deassert)
1046 {
1047     struct eesense_rearm *info = cb_data;
1048     unsigned int num = info->num;
1049     unsigned int off = info->offset;
1050     unsigned char mask = info->mask;
1051     struct board_info *board = &boards[num];
1052     sys_data_t *sys = board->sys;
1053     unsigned char data[72];
1054     unsigned int i;
1055     int rv, err;
1056 
1057     if (!(assert & mask))
1058 	return 0;
1059 
1060     rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0);
1061     if (rv)
1062 	return rv;
1063 
1064     rv = read_eeprom(&board_i2c[num].fru, data, 8, 72);
1065     if (rv) {
1066 	sys->log(sys, OS_ERROR, NULL,
1067 		 "Warning: Error reading board %d fru: %s",
1068 		 num + 1, strerror(rv));
1069 	goto out_post;
1070     }
1071 
1072     if (!(data[off] & mask))
1073 	goto out_post;
1074 
1075     data[off] &= ~mask;
1076     data[71] = -checksum(data, 71);
1077 
1078     rv = write_eeprom(&board_i2c[num].fru, data + off, 8 + off, 1);
1079     if (rv) {
1080 	sys->log(sys, OS_ERROR, NULL,
1081 		 "Warning: Error writing board %d"
1082 		 " sensor data: %s", num + 1, strerror(rv));
1083 	goto out_post;
1084     }
1085 
1086     for (i = 0; i < 8; i++)
1087 	ipmi_mc_sensor_set_bit(boards[num].mc, 0, 19 + off, i,
1088 			       ((data[off] >> i) & 1), 0);
1089 
1090     rv = write_eeprom(&board_i2c[num].fru, data + 71, 79, 1);
1091     if (rv) {
1092 	sys->log(sys, OS_ERROR, NULL,
1093 		 "Warning: Error writing board %d"
1094 		 " internal use checksum: %s", num + 1, strerror(rv));
1095 	rv = 0;
1096     }
1097 
1098   out_post:
1099     err = ipmi_mc_fru_sem_post(board->mc, 0);
1100     if (err)
1101 	sys->log(sys, OS_ERROR, NULL,
1102 		 "Error posting board %d semaphore: %s", num + 1,
1103 		 strerror(err));
1104 
1105     return rv;
1106 }
1107 
1108 /*
1109  * The rearm for the power supply sensor will set the clear fault flag
1110  * for the power supply, just to be sure it is clear.
1111  */
1112 static int
rearm_power_supply_sensor(void * cb_data,uint16_t assert,uint16_t deassert)1113 rearm_power_supply_sensor(void *cb_data,
1114 			  uint16_t assert,
1115 			  uint16_t deassert)
1116 {
1117     unsigned int num = (unsigned long) cb_data;
1118     sys_data_t *sys = boards[0].sys;
1119     int rv;
1120     char fname[100];
1121 
1122     if (!(assert & 2))
1123 	return 0;
1124 
1125     sprintf(fname, "/sys/class/wixpmbus/CLEAR_FAULT_%d", num);
1126     rv = set_intval(fname, 1);
1127     if (rv) {
1128 	sys->log(sys, OS_ERROR, NULL,
1129 		 "Error writing ps %d clear file: %s", num, strerror(rv));
1130 	return rv;
1131     }
1132     return 0;
1133 }
1134 
1135 
1136 /**************************************************************************
1137  * Board handling
1138  *************************************************************************/
1139 
1140 /*
1141  * Read the board's FRU and update anything that needs to be updated,
1142  * like the chassis information, the board's external MAC address, etc.
1143  */
1144 static int
handle_board_fru(sys_data_t * sys,int num)1145 handle_board_fru(sys_data_t *sys, int num)
1146 {
1147     int rv;
1148     unsigned int iuse;
1149     unsigned int iuse_len;
1150     unsigned int chinfo;
1151     unsigned int chinfo_len;
1152     unsigned int brdinfo;
1153     unsigned int brdinfo_len;
1154     unsigned int mac_offset;
1155     unsigned int brdchsernum_offset;
1156     unsigned int brdsernum_offset;
1157     int modified = 0;
1158     int fruversion2 = 0;
1159     unsigned char *fru;
1160 
1161     if (debug & 1)
1162 	sys->log(sys, DEBUG, NULL, "Checking board FRU on board %d", num + 1);
1163 
1164     /* Guilty until proven innocent */
1165     boards[num].fru_good = 0;
1166 
1167     rv = read_eeprom(&board_i2c[num].fru, boards[num].fru,
1168 		     0, board_i2c[num].fru.size);
1169     if (rv) {
1170 	sys->log(sys, SETUP_ERROR, NULL, "Can't read board %d eeprom: %s",
1171 		 num + 1, strerror(rv));
1172 	return 0;
1173     }
1174 
1175     fru = boards[num].fru;
1176 
1177     if (fru[0] != 1) {
1178 	sys->log(sys, SETUP_ERROR, NULL, "Invalid board %d FRU version: 0x%x",
1179 		 num + 1, fru[0]);
1180 	return 0;
1181     }
1182 
1183     if (checksum(fru + 0, 8) != 0) {
1184 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU header"
1185 		 " checksum fail", num + 1);
1186     }
1187 
1188     iuse = fru[1] * 8;
1189     iuse_len = 80 - 8;
1190     chinfo = fru[2] * 8;
1191     chinfo_len = 256 - 80;
1192     brdinfo = fru[3] * 8;
1193     brdinfo_len = 2048 - 256;
1194     brdchsernum_offset = 42;
1195     brdsernum_offset = 74;
1196     mac_offset = 95;
1197 
1198     if (iuse != 8) {
1199 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU internal use"
1200 		 "area is not at offset 8", num + 1);
1201 	return 0;
1202     }
1203     if (chinfo != 80) {
1204 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU chassis info"
1205 		 "area is not at offset 80", num + 1);
1206 	return 0;
1207     }
1208     if (brdinfo != 256) {
1209 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU board info"
1210 		 "area is not at offset 256", num + 1);
1211 	return 0;
1212     }
1213     if (checksum(fru + iuse, iuse_len) != 0) {
1214 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU internal use"
1215 		 " checksum fail", num + 1);
1216 	return 0;
1217     }
1218     if (checksum(fru + chinfo, chinfo_len) != 0) {
1219 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU chassis info"
1220 		 " checksum fail", num + 1);
1221 	return 0;
1222     }
1223     if (checksum(fru + brdinfo, brdinfo_len) != 0) {
1224 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU board info"
1225 		 " checksum fail", num + 1);
1226 	return 0;
1227     }
1228     boards[num].fru_good = 1;
1229 
1230     /* Set the chassis information if it is not correct. */
1231     if (chassis_fru[chinfo + brdchsernum_offset] != 0xd4) {
1232 	/* Try the version 2.0 of the FRU data */
1233 	brdchsernum_offset = 17;
1234     }
1235     if (sernum_len == 0) {
1236 	sys->log(sys, SETUP_ERROR, NULL, "Warning: FRU chassis serial number"
1237 		 " invalid, not setting board %d data", num + 1);
1238     } else if (chassis_chinfo == 0) {
1239 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis chassis info FRU"
1240 		 "invalid, not checking board %d FRU chassis data", num + 1);
1241     } else {
1242 	/*
1243 	 * If we have a different FRU version, or if the serial
1244 	 * numbers don't match, then update the chassis info area.
1245 	 */
1246 	if ((brdchsernum_offset != sernum_offset) ||
1247 	    memcmp(fru + chinfo + brdchsernum_offset,
1248 		   chassis_fru + chassis_chinfo + sernum_offset,
1249 		   sernum_len) != 0) {
1250 	    /* The chassis serial number has changed. */
1251 	    sys->log(sys, INFO, NULL, "Info: Updating board %d"
1252 		     " chassis info area", num + 1);
1253 	    memcpy(fru + chinfo, chassis_fru + chassis_chinfo,
1254 		   chassis_chinfo_len);
1255 	    rv = write_eeprom(&board_i2c[num].fru, fru + chinfo, chinfo,
1256 			      chassis_chinfo_len);
1257 	    if (rv) {
1258 		sys->log(sys, OS_ERROR, NULL,
1259 			 "Warning: Error writing board %d"
1260 			 " chassis info: %s", num + 1, strerror(rv));
1261 	    }
1262 	}
1263     }
1264 
1265     /* Set the board system serial number if it is not correct. */
1266     if (fru[brdinfo + brdsernum_offset] != 0xd4) {
1267 	/* FRU version 2.0 */
1268 	brdsernum_offset = 34;
1269 	fruversion2 = 1;
1270     }
1271     if (fru[brdinfo + brdsernum_offset] != 0xd4) {
1272 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU serial num"
1273 		 " data invalid", num + 1);
1274     } else if (!sernum[0]) {
1275 	sys->log(sys, SETUP_ERROR, NULL, "Warning: System serial num invalid,"
1276 		 " not checking board %d ser num", num + 1);
1277     } else {
1278 	char mysernum[21];
1279 
1280 	if (fruversion2) {
1281 	    int len;
1282 	    len = sprintf(mysernum, "%s-%c", sernum, num + 'A');
1283 	    memset(mysernum + len, ' ', 20 - len);
1284 	    mysernum[20] = '\0';
1285 	} else {
1286 	    memset(mysernum, 0, 21);
1287 	    sprintf(mysernum, "System SN %s-%c", sernum, num + 'A');
1288 	}
1289 
1290 	if (memcmp(mysernum, fru + brdinfo + brdsernum_offset + 1, 20) != 0) {
1291 	    sys->log(sys, INFO, NULL, "Info: Updating board %d"
1292 		     " serial number", num + 1);
1293 	    memcpy(fru + brdinfo + brdsernum_offset + 1, mysernum, 20);
1294 	    rv = write_eeprom(&board_i2c[num].fru,
1295 			      fru + brdinfo + brdsernum_offset + 1,
1296 			      brdinfo + brdsernum_offset + 1,
1297 			      20);
1298 	    if (rv) {
1299 		sys->log(sys, OS_ERROR, NULL,
1300 			 "Warning: Error writing board %d"
1301 			 " serial num: %s", num + 1, strerror(rv));
1302 	    }
1303 	    modified = 1;
1304 	}
1305     }
1306 
1307     /* Set the board MAC address if it is not correct. */
1308     if (fru[brdinfo + mac_offset] != 0xdc) {
1309 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Board %d FRU external MAC"
1310 		 " data invalid", num + 1);
1311     } else if (!sysmac[0]) {
1312 	sys->log(sys, SETUP_ERROR, NULL, "Warning: System MAC invalid, not"
1313 		 " checking board %d MAC", num + 1);
1314     } else {
1315 	char mac[29];
1316 
1317 	memset(mac, 0, 29);
1318 	sprintf(mac, "System MAC %s%d", sysmac, num + 1);
1319 	if (memcmp(mac, fru + brdinfo + mac_offset + 1, 28) != 0) {
1320 	    sys->log(sys, INFO, NULL, "Info: Updating board %d"
1321 		     " MAC address", num + 1);
1322 	    memcpy(fru + brdinfo + mac_offset + 1, mac, 28);
1323 	    rv = write_eeprom(&board_i2c[num].fru,
1324 			      fru + brdinfo + mac_offset + 1,
1325 			      brdinfo + mac_offset + 1,
1326 			      28);
1327 	    if (rv) {
1328 		sys->log(sys, OS_ERROR, NULL,
1329 			 "Warning: Error writing board %d"
1330 			 " MAC address: %s", num + 1, strerror(rv));
1331 	    }
1332 	    modified = 1;
1333 	}
1334     }
1335 
1336     if (modified) {
1337 	/* Recalculate the board checksum */
1338 	fru[brdinfo + brdinfo_len - 1] = -checksum(fru + brdinfo,
1339 						   brdinfo_len - 1);
1340 
1341 	rv = write_eeprom(&board_i2c[num].fru, fru + brdinfo + brdinfo_len - 1,
1342 			  brdinfo + brdinfo_len - 1, 1);
1343 	if (rv) {
1344 	    sys->log(sys, OS_ERROR, NULL, "Warning: Error writing board %d"
1345 		     " board info checksum: %s", num + 1, strerror(rv));
1346 	}
1347     }
1348     return 0;
1349 }
1350 
1351 /*
1352  * Check that the board has not changed states, and if it has then
1353  * handle the change.  Called on insertion/removal events and
1354  * periodically by a timer.
1355  */
1356 static int
check_board(sys_data_t * sys,int num,unsigned int since_last,int power_up_new_board)1357 check_board(sys_data_t *sys, int num, unsigned int since_last,
1358 	    int power_up_new_board)
1359 {
1360     int rv;
1361     unsigned int present;
1362     unsigned int rval;
1363     unsigned char val;
1364     struct board_info *board = &boards[num];
1365 
1366     if (board->present && board_power_state(sys, num)) {
1367 	rv = get_uintval(pow_off_ready[num], &rval);
1368 	if (rv) {
1369 	    sys->log(sys, OS_ERROR, NULL,
1370 		     "Unable to read board %u power off ready: %s",
1371 		     num, strerror(rv));
1372 	} else {
1373 	    if (board->last_power_request == BOARD_OFF_NOT_READY &&
1374 		rval == BOARD_OFF_READY) {
1375 		if (debug & 1) {
1376 		    if (board->waiting_power_off)
1377 			sys->log(sys, DEBUG, NULL, "Graceful power of finished"
1378 				 " on %d, setting power off", board->num + 1);
1379 		    else
1380 			sys->log(sys, DEBUG, NULL, "Board %d requested power"
1381 				 " off, setting power off", board->num + 1);
1382 		}
1383 		val = 0;
1384 		set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
1385 	    }
1386 	    board->last_power_request = rval;
1387 	}
1388     }
1389 
1390     if (board->waiting_power_off && since_last) {
1391 	if (board->power_off_countdown == 0) {
1392 	    unsigned char val;
1393 
1394 	    if (debug & 1)
1395 		    sys->log(sys, DEBUG, NULL, "Graceful power off timeout"
1396 			     " on %d, forcing power off", board->num + 1);
1397 	    val = 0;
1398 	    set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
1399 	} else {
1400 	    board->power_off_countdown--;
1401 	}
1402     }
1403 
1404     rv = get_uintval(trg_present[num], &present);
1405     if (rv) {
1406 	sys->log(sys, OS_ERROR, NULL, "Unable to read board %d presence: %s",
1407 		 num + 1, strerror(rv));
1408 	return rv;
1409     }
1410     present = (present == BOARD_PRESENT) && !simulate_board_absent[num];
1411     if (board->present == present)
1412 	return 0;
1413 
1414     board->present = present;
1415     if (!present) {
1416 	sys->log(sys, INFO, NULL, "Info: board %d has been removed", num + 1);
1417 
1418 	board->fru_good = 0;
1419 
1420 	/*
1421 	 * Turn off board power when not present, that way we can hold
1422 	 * off power on until we are done with messing with the board FRU
1423 	 * data.
1424 	 */
1425 	val = 0;
1426 	set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
1427 	return 0;
1428     }
1429 
1430     sys->log(sys, INFO, NULL, "Info: board %d is now present", num + 1);
1431 
1432     rv = create_eeprom(sys, board_i2c[num].add_dev, &board_i2c[num].fru);
1433     if (rv) {
1434 	/* Force a retry, perhaps the device hasn't been created yet */
1435 	board->present = 0;
1436 	sys->log(sys, SETUP_ERROR, NULL, "Can't create board %d eeprom: %s."
1437 		 "  Will retry in a second",
1438 		 num + 1, strerror(rv));
1439 	return 0;
1440     }
1441 
1442     rv = handle_board_fru(sys, num);
1443     if (rv)
1444 	return rv;
1445 
1446     if (power_up_new_board) {
1447 	/* If the board was not present and now it is, power it on. */
1448 	val = 1;
1449 	set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
1450     }
1451 
1452     return 0;
1453 }
1454 
1455 /*
1456  * If the board front-panel button is pressed, record the time, the
1457  * button will be handled on release.
1458  */
1459 static void
handle_button_press(sys_data_t * sys,unsigned int brdnum)1460 handle_button_press(sys_data_t *sys, unsigned int brdnum)
1461 {
1462     struct board_info *board = &boards[brdnum];
1463 
1464     if (debug & 1)
1465 	sys->log(sys, DEBUG, NULL, "Button press on %d", board->num + 1);
1466 
1467     board->button_pressed = 1;
1468     board->sys->get_monotonic_time(board->sys, &board->button_press_time);
1469 }
1470 
1471 /*
1472  * Handle the board's front-panel button.
1473  */
1474 static void
handle_button_release(sys_data_t * sys,unsigned int num)1475 handle_button_release(sys_data_t *sys, unsigned int num)
1476 {
1477     struct timeval now;
1478     unsigned char val;
1479     struct board_info *board = &boards[num];
1480     int power_state = board_power_state(sys, num);
1481 
1482     if (!board->button_pressed)
1483 	return;
1484 
1485     if (debug & 1)
1486 	sys->log(sys, DEBUG, NULL, "Button release on %d", num + 1);
1487 
1488     board->button_pressed = 0;
1489 
1490     board->sys->get_monotonic_time(board->sys, &now);
1491 
1492     /*
1493      * If the button is pressed more than 4 seconds, start a graceful
1494      * shutdown.
1495      */
1496     if (power_state &&
1497         (diff_timeval_ms(&now, &board->button_press_time) > 4000)) {
1498 	if (board_waiting_power_on(num)) {
1499 	    if (debug & 1)
1500 		sys->log(sys, DEBUG, NULL, "Button press on %d >4sec, stop"
1501 			 " power on timer", board->num + 1);
1502 	    board_remove_power_wait(sys, num);
1503 	} else {
1504 	    if (debug & 1)
1505 		sys->log(sys, DEBUG, NULL, "Button press on %d >4sec, start"
1506 			 " graceful shutdown", board->num + 1);
1507 	    val = 0;
1508 	    set_chassis_control(NULL, CHASSIS_CONTROL_GRACEFUL_SHUTDOWN,
1509 			        &val, board);
1510 	}
1511     }
1512 
1513     /*
1514      * If the button is pressed less than 4 seconds, start a power up
1515      * if the board is not already on.
1516      */
1517     if (!power_state &&
1518         (diff_timeval_ms(&now, &board->button_press_time) <= 4000)) {
1519 	if (debug & 1)
1520 	    sys->log(sys, DEBUG, NULL, "Button press on %d <4sec, power on",
1521 		board->num + 1);
1522 
1523 	val = 1;
1524 	set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
1525     }
1526 }
1527 
1528 /*
1529  * Read data from the chassis FRU.
1530  */
1531 static int
init_chassis(sys_data_t * sys)1532 init_chassis(sys_data_t *sys)
1533 {
1534     int rv;
1535 
1536     if (debug & 1)
1537 	sys->log(sys, DEBUG, NULL, "Reading chassis eeprom info");
1538 
1539     /* Detect which I2C channel to use for the chassis I2C. */
1540     rv = check_eeprom(sys, &chassis_i2c_new.fru);
1541     if (rv) {
1542 	rv = check_eeprom(sys, &chassis_i2c_old.fru);
1543 	if (rv) {
1544 	    sys->log(sys, SETUP_ERROR, NULL, "Can't find chassis eeprom: %s",
1545 		     strerror(rv));
1546 	    return rv;
1547 	}
1548 	chassis_i2c = &chassis_i2c_old;
1549     } else {
1550 	chassis_i2c = &chassis_i2c_new;
1551     }
1552 
1553     rv = read_eeprom(&chassis_i2c->fru, chassis_fru, 0, chassis_i2c->fru.size);
1554     if (rv) {
1555 	sys->log(sys, SETUP_ERROR, NULL, "Can't read chassis eeprom: %s",
1556 		 strerror(rv));
1557 	return rv;
1558     }
1559 
1560     if (chassis_fru[0] != 1) {
1561 	sys->log(sys, SETUP_ERROR, NULL, "Invalid Chassis FRU version: 0x%x",
1562 		 chassis_fru[0]);
1563 	return EINVAL;
1564     }
1565 
1566     if (checksum(chassis_fru + 0, 8) != 0) {
1567 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU header"
1568 		 " checksum fail");
1569     }
1570 
1571     chassis_iuse = chassis_fru[1] * 8;
1572     chassis_iuse_len = 80 - 8;
1573     chassis_chinfo = chassis_fru[2] * 8;
1574     chassis_chinfo_len = 256 - 80;
1575     chassis_brdinfo = chassis_fru[3] * 8;
1576     chassis_brdinfo_len = 1024 - 256;
1577     sernum_offset = 42;
1578     sernum_offset2 = 11;
1579     sernum_len = 20;
1580     sysmac_offset = 74;
1581 
1582     if (chassis_iuse != 8) {
1583 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU internal use"
1584 		 "area is not at offset 8");
1585     }
1586     if (chassis_chinfo != 80) {
1587 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU chassis info"
1588 		 "area is not at offset 80");
1589     }
1590     if (chassis_brdinfo != 256) {
1591 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU board info"
1592 		 "area is not at offset 256");
1593     }
1594     if (checksum(chassis_fru + chassis_iuse, chassis_iuse_len) != 0) {
1595 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU internal use"
1596 		 " checksum fail");
1597     }
1598     if (checksum(chassis_fru + chassis_chinfo, chassis_chinfo_len) != 0) {
1599 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU chassis info"
1600 		 " checksum fail");
1601     }
1602     if (checksum(chassis_fru + chassis_brdinfo, chassis_brdinfo_len) != 0) {
1603 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU board info"
1604 		 " checksum fail");
1605     }
1606 
1607     if (chassis_fru[chassis_chinfo + sernum_offset] != 0xd4) {
1608 	/* Try the version 2.0 of the FRU data */
1609 	sernum_offset = 17;
1610 	sernum_offset2 = 1;
1611     }
1612     if (chassis_fru[chassis_chinfo + sernum_offset] != 0xd4) {
1613 	sys->log(sys, SETUP_ERROR, NULL,
1614 		 "Warning: Chassis FRU system serial"
1615 		 " number data invalid");
1616 	sernum_len = 0;
1617     } else {
1618 	memcpy(sernum, chassis_fru + chassis_chinfo + sernum_offset
1619 	       + sernum_offset2, 8);
1620 	sernum[9] = '\0';
1621     }
1622 
1623     if (chassis_fru[chassis_brdinfo + sysmac_offset] != 0xe0) {
1624 	sys->log(sys, SETUP_ERROR, NULL, "Warning: Chassis FRU system MAC"
1625 		 " data invalid");
1626     } else {
1627 	/* Don't copy the last byte, we use that for the boards. */
1628 	memcpy(sysmac, chassis_fru + chassis_brdinfo + sysmac_offset + 14, 16);
1629 	sysmac[16] = '\0';
1630     }
1631 
1632     return 0;
1633 }
1634 
1635 /**************************************************************************
1636  * Event/timer handling
1637  *************************************************************************/
1638 
1639 static int ast_fd;
1640 static ipmi_io_t *ast_fd_id;
1641 static int fork_event_wait = 0;
1642 
1643 static void
ast_evt(int fd,void * cb_data)1644 ast_evt(int fd, void *cb_data)
1645 {
1646     int rv;
1647     int event;
1648     sys_data_t *sys = cb_data;
1649 
1650     if (!fork_event_wait) {
1651 	rv = ioctl(fd, READ_WIW_NONBLOCKING, &event);
1652 	if (rv == -1) {
1653 	    sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error reading"
1654 		     " AST event: %s", strerror(errno));
1655 	    return;
1656 	}
1657     } else {
1658 	unsigned char c;
1659 	rv = read(fd, &c, 1);
1660 	if (rv != 1) {
1661 	    sys->log(sys, OS_ERROR, NULL, "Warning: MV: AST1300 shim"
1662 		     " failed: %s", strerror(errno));
1663 	    exit(1);
1664 	}
1665 	event = c;
1666     }
1667 
1668     if (debug & 1)
1669 	sys->log(sys, DEBUG, NULL, "Got event %d", event);
1670 
1671     switch (event) {
1672     case WIW_NO_EVENT:
1673 	break;
1674 
1675     case WIW_NODE1_IN:
1676     case WIW_NODE1_OUT:
1677 	if (debug & 1)
1678 	    sys->log(sys, DEBUG, NULL, "Board %s on 1",
1679 		     event == WIW_NODE1_IN ? "insertion" : "removal");
1680 	check_board(sys, 0, 0, 1);
1681 	break;
1682 
1683     case WIW_NODE2_IN:
1684     case WIW_NODE2_OUT:
1685 	if (debug & 1)
1686 	    sys->log(sys, DEBUG, NULL, "Board %s on 2",
1687 		     event == WIW_NODE2_IN ? "insertion" : "removal");
1688 	check_board(sys, 1, 0, 1);
1689 	break;
1690 
1691     case WIW_NODE3_IN:
1692     case WIW_NODE3_OUT:
1693 	if (debug & 1)
1694 	    sys->log(sys, DEBUG, NULL, "Board %s on 3",
1695 		     event == WIW_NODE3_IN ? "insertion" : "removal");
1696 	check_board(sys, 2, 0, 1);
1697 	break;
1698 
1699     case WIW_NODE4_IN:
1700     case WIW_NODE4_OUT:
1701 	if (debug & 1)
1702 	    sys->log(sys, DEBUG, NULL, "Board %s on 4",
1703 		     event == WIW_NODE4_IN ? "insertion" : "removal");
1704 	check_board(sys, 3, 0, 1);
1705 	break;
1706 
1707     case WIW_NODE5_IN:
1708     case WIW_NODE5_OUT:
1709 	if (debug & 1)
1710 	    sys->log(sys, DEBUG, NULL, "Board %s on 5",
1711 		     event == WIW_NODE5_IN ? "insertion" : "removal");
1712 	check_board(sys, 4, 0, 1);
1713 	break;
1714 
1715     case WIW_NODE6_IN:
1716     case WIW_NODE6_OUT:
1717 	if (debug & 1)
1718 	    sys->log(sys, DEBUG, NULL, "Board %s on 6",
1719 		     event == WIW_NODE6_IN ? "insertion" : "removal");
1720 	check_board(sys, 5, 0, 1);
1721 	break;
1722 
1723     case WIW_NODE1_PBTN_P:
1724 	handle_button_press(sys, 0);
1725 	break;
1726 
1727     case WIW_NODE1_PBTN_R:
1728 	handle_button_release(sys, 0);
1729 	break;
1730 
1731     case WIW_NODE2_PBTN_P:
1732 	handle_button_press(sys, 1);
1733 	break;
1734 
1735     case WIW_NODE2_PBTN_R:
1736 	handle_button_release(sys, 1);
1737 	break;
1738 
1739     case WIW_NODE3_PBTN_P:
1740 	handle_button_press(sys, 2);
1741 	break;
1742 
1743     case WIW_NODE3_PBTN_R:
1744 	handle_button_release(sys, 2);
1745 	break;
1746 
1747     case WIW_NODE4_PBTN_P:
1748 	handle_button_press(sys, 3);
1749 	break;
1750 
1751     case WIW_NODE4_PBTN_R:
1752 	handle_button_release(sys, 3);
1753 	break;
1754 
1755     case WIW_NODE5_PBTN_P:
1756 	handle_button_press(sys, 4);
1757 	break;
1758 
1759     case WIW_NODE5_PBTN_R:
1760 	handle_button_release(sys, 4);
1761 	break;
1762 
1763     case WIW_NODE6_PBTN_P:
1764 	handle_button_press(sys, 5);
1765 	break;
1766 
1767     case WIW_NODE6_PBTN_R:
1768 	handle_button_release(sys, 5);
1769 	break;
1770 
1771     default:
1772 	break;
1773     }
1774 }
1775 
1776 
1777 /*
1778  * This timer is called periodically to check the boards.
1779  */
1780 static ipmi_timer_t *mv_timer;
1781 
1782 static void
mv_timeout(void * cb_data)1783 mv_timeout(void *cb_data)
1784 {
1785     int i;
1786     struct timeval tv;
1787     sys_data_t *sys = cb_data;
1788 
1789     for (i = 0; i < NUM_BOARDS; i++)
1790 	check_board(sys, i, 1, 1);
1791 
1792     tv.tv_sec = 1;
1793     tv.tv_usec = 0;
1794     sys->start_timer(mv_timer, &tv);
1795 }
1796 
1797 static void
shim_sig(int signr)1798 shim_sig(int signr)
1799 {
1800     exit(1);
1801 }
1802 
1803 /*
1804  * The ast1300 device doesn't support select() in older
1805  * implementations.  So add a small program that will wait for it
1806  * blocking and then feed it to the program through a pipe, which will
1807  * work as a select() device.
1808  */
1809 static void
ast1300_shim(sys_data_t * sys,int ast_fd,int writefd,int pid)1810 ast1300_shim(sys_data_t *sys, int ast_fd, int writefd, int pid)
1811 {
1812     unsigned char c;
1813     int rv;
1814     int event;
1815     struct sigaction act;
1816 
1817     /*
1818      * Make sure to terminate if the main program goes away.
1819      */
1820     memset(&act, 0, sizeof(act));
1821     act.sa_handler = shim_sig;
1822     rv = sigaction(SIGCHLD, &act, NULL);
1823     if (rv == -1) {
1824 	sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error settint up"
1825 		 " signal: %s", strerror(errno));
1826 	exit(1);
1827     }
1828 
1829     for (;;) {
1830 	rv = ioctl(ast_fd, READ_WIW_BLOCKING, &event);
1831 	if (rv == -1) {
1832 	    sys->log(sys, OS_ERROR, NULL, "Warning: MV: Error reading"
1833 		     " AST event: %s", strerror(errno));
1834 	    exit(1);
1835 	}
1836 	c = event;
1837 	rv = write(writefd, &c, 1);
1838 	if (rv != 1) {
1839 	    /* Other end of the pipe went away, just shut down. */
1840 	    exit(0);
1841 	}
1842     }
1843 }
1844 
1845 /**************************************************************************
1846  * General sensor handling
1847  *************************************************************************/
1848 
1849 struct sensor_info {
1850     char *filename;
1851     unsigned char sensor_number;
1852     char *create_file;
1853     char *create_data;
1854     int invalid_if_off;
1855     int mult;
1856     int div;
1857     int sub;
1858 };
1859 static struct sensor_info empty_sensors[] = { { NULL } };
1860 
1861 static int all_fans_duty = 0;
1862 
1863 struct fan_duty_table {
1864     int reading;
1865     int setting;
1866 };
1867 
1868 struct sensor_handling {
1869     struct sensor_info *switch_s;
1870     char *switch_valids;
1871     int *switch_last_values;
1872     struct sensor_info *board;
1873     char (*board_valids)[NUM_BOARDS];
1874     int (*board_last_values)[NUM_BOARDS];
1875     struct fan_duty_table *fan_duty;
1876 
1877     /* Modify the duty tables by this much. */
1878     int duty_offset;
1879 };
1880 
1881 static struct sensor_info switch_temp_sensors[] =
1882 {
1883     /* Switch Temp */
1884     { "/sys/class/i2c-adapter/i2c-0/0-0058/temp2_input", 1, .div = 1000 },
1885     /* Switch CPU Temp */
1886     { "/sys/class/i2c-adapter/i2c-0/0-0058/temp3_input", 2, .div = 1000 },
1887     { NULL }
1888 };
1889 static char switch_temp_sensor_valids[2];
1890 static int switch_temp_sensor_last_values[2];
1891 static struct sensor_info board_temp_sensors[] =
1892 {
1893     /* Board CPU Temp */
1894     { "/sys/class/i2c-adapter/i2c-%d/%d-0064/temp1_input", 2, .div = 1000,
1895       .invalid_if_off = 1,
1896       .create_file = "/sys/class/i2c-adapter/i2c-%d/new_device",
1897       .create_data = "axp 0x64" },
1898     /* Board DIMM Temp */
1899     { "/sys/class/i2c-adapter/i2c-%d/%d-001e/temp1_input", 3, .div = 1000,
1900       .invalid_if_off = 1,
1901       .create_file = "/sys/class/i2c-adapter/i2c-%d/new_device",
1902       .create_data = "dimm 0x1e" },
1903     { NULL }
1904 };
1905 static char board_temp_sensor_last_oor[NUM_BOARDS];
1906 static char board_temp_sensor_valids[2][NUM_BOARDS];
1907 static int board_temp_sensor_last_values[2][NUM_BOARDS];
1908 static struct fan_duty_table main_fan_duty_table[] =
1909 {
1910     { 0,  42 },
1911     { 60,  45 },
1912     { 65,  48 },
1913     { 70,  51 },
1914     { 75,  54 },
1915     { 80,  57 },
1916     { 85,  60 },
1917     { 95,  70 },
1918     { 100, 85 },
1919     { 105, 100 },
1920     { -1 }
1921 };
1922 static struct sensor_handling main_temp =
1923 {
1924     .switch_s = switch_temp_sensors,
1925     .switch_valids = switch_temp_sensor_valids,
1926     .switch_last_values = switch_temp_sensor_last_values,
1927     .board = board_temp_sensors,
1928     .board_valids = board_temp_sensor_valids,
1929     .board_last_values = board_temp_sensor_last_values,
1930     .fan_duty = main_fan_duty_table,
1931     .duty_offset = 10
1932 };
1933 
1934 static struct sensor_info board_mb_sensors[] =
1935 {
1936     /* Board MB Temp */
1937     { "/sys/class/i2c-adapter/i2c-%d/%d-004a/temp1_input", 1, .div = 1000 },
1938     { NULL }
1939 };
1940 static char board_mb_sensor_valids[1][NUM_BOARDS];
1941 static int board_mb_sensor_last_values[1][NUM_BOARDS];
1942 static struct fan_duty_table mb_fan_duty_table[] =
1943 {
1944     {  0, 42 },
1945     { 50, 45 },
1946     { 52, 48 },
1947     { 54, 51 },
1948     { 56, 54 },
1949     { 58, 57 },
1950     { 60, 60 },
1951     {  -1 }
1952 };
1953 static struct sensor_handling mb_temp =
1954 {
1955     .switch_s = empty_sensors,
1956     .board = board_mb_sensors,
1957     .board_valids = board_mb_sensor_valids,
1958     .board_last_values = board_mb_sensor_last_values,
1959     .fan_duty = mb_fan_duty_table,
1960     .duty_offset = 0
1961 };
1962 
1963 static struct sensor_info board_front_sensors[] =
1964 {
1965     /* Board Front Temp */
1966     { "/sys/class/i2c-adapter/i2c-%d/%d-004c/temp1_input", 4, .div = 1000 },
1967     { NULL }
1968 };
1969 static char board_front_sensor_valids[1][NUM_BOARDS];
1970 static int board_front_sensor_last_values[1][NUM_BOARDS];
1971 static struct fan_duty_table front_fan_duty_table[] =
1972 {
1973     {  0, 42 },
1974     { 37, 65 },
1975     { 39, 70 },
1976     { 41, 75 },
1977     { 43, 80 },
1978     { 45, 85 },
1979     {  -1 }
1980 };
1981 static struct sensor_handling front_temp =
1982 {
1983     .switch_s = empty_sensors,
1984     .board = board_front_sensors,
1985     .board_valids = board_front_sensor_valids,
1986     .board_last_values = board_front_sensor_last_values,
1987     .fan_duty = front_fan_duty_table,
1988     .duty_offset = 0
1989 };
1990 
1991 static struct sensor_info switch_sensors[] =
1992 {
1993     /* Switch 12v  */
1994     { "/sys/class/i2c-adapter/i2c-0/0-0058/in11_input", 3,
1995       .mult=8, .div=125, .sub=10000 },
1996     /* Switch 3.3v  */
1997     { "/sys/class/i2c-adapter/i2c-0/0-0058/in10_input", 4,
1998       .mult=8, .div=25, .sub=2900 },
1999     /* Switch 1.8v  */
2000     { "/sys/class/i2c-adapter/i2c-0/0-0058/in2_input", 5,
2001       .mult=16, .div=25, .sub=1600 },
2002     /* Fans */
2003     { "/sys/class/astfan/fan1_input", 0x70, .mult = 10, .div = 392 },
2004     { "/sys/class/astfan/fan2_input", 0x71, .mult = 10, .div = 392 },
2005     { "/sys/class/astfan/fan3_input", 0x72, .mult = 10, .div = 392 },
2006     { "/sys/class/astfan/fan4_input", 0x73, .mult = 10, .div = 392 },
2007     { "/sys/class/astfan/fan5_input", 0x74, .mult = 10, .div = 392 },
2008     { "/sys/class/astfan/fan6_input", 0x75, .mult = 10, .div = 392 },
2009     { "/sys/class/astfan/fan7_input", 0x76, .mult = 10, .div = 392 },
2010     { "/sys/class/astfan/fan8_input", 0x77, .mult = 10, .div = 392 },
2011     { NULL }
2012 };
2013 static char switch_sensor_valids[11];
2014 static int switch_sensor_last_values[11];
2015 static struct sensor_info board_sensors[] =
2016 {
2017     /* Board 1.0v */
2018     { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in3_input", 5,
2019       .mult=32, .div=25, .sub=900,
2020       .invalid_if_off = 1 },
2021     /* Board 1.8v */
2022     { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in2_input", 6,
2023       .mult=16, .div=25, .sub=1600,
2024       .invalid_if_off = 1 },
2025     /* Board 2.5v */
2026     { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in1_input", 7,
2027       .mult=32, .div=125, .sub=2000,
2028       .invalid_if_off = 1 },
2029     /* Board 3.3v */
2030     { "/sys/class/i2c-adapter/i2c-%d/%d-0048/in0_input", 8,
2031       .mult=8, .div=25, .sub=2900,
2032       .invalid_if_off = 1 },
2033     /* Board 1.05v */
2034     { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in2_input", 9,
2035       .mult=16, .div=25, .sub=800,
2036       .invalid_if_off = 1 },
2037     /* Board DIMMv */
2038     { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in1_input", 11,
2039       .mult=64, .div=75, .sub=1200,
2040       .invalid_if_off = 1 },
2041     /* Board 0.9v */
2042     { "/sys/class/i2c-adapter/i2c-%d/%d-0049/in0_input", 12,
2043       .mult=21, .div=50, .sub=700,
2044       .invalid_if_off = 1 },
2045     { NULL }
2046 };
2047 static char board_sensor_valids[8][NUM_BOARDS];
2048 static int board_sensor_last_values[8][NUM_BOARDS];
2049 static struct sensor_handling system_sensors =
2050 {
2051     .switch_s = switch_sensors,
2052     .switch_valids = switch_sensor_valids,
2053     .switch_last_values = switch_sensor_last_values,
2054     .board = board_sensors,
2055     .board_valids = board_sensor_valids,
2056     .board_last_values = board_sensor_last_values,
2057 };
2058 
2059 
2060 static int
get_readings(sys_data_t * sys,struct sensor_handling * h,int * rmax)2061 get_readings(sys_data_t *sys, struct sensor_handling *h, int *rmax)
2062 {
2063     int err;
2064     int success = 0;
2065     int max = 0;
2066     unsigned int i, j;
2067 
2068     for (i = 0; h->switch_s[i].filename; i++) {
2069 	int value;
2070 
2071 	err = get_intval(h->switch_s[i].filename, &value);
2072 	if (debug & 2)
2073 	    sys->log(sys, DEBUG, NULL, "Read value %s: %d %d",
2074 		     h->switch_s[i].filename, err, value);
2075 	if (err) {
2076 	    h->switch_valids[i] = 0;
2077 	} else {
2078 	    success = 1;
2079 	    h->switch_valids[i] = 1;
2080 	    h->switch_last_values[i] = value;
2081 	    if (value > max)
2082 		max = value;
2083 	}
2084     }
2085 
2086     for (i = 0; h->board[i].filename; i++) {
2087 	for (j = 0; j < NUM_BOARDS; j++) {
2088 	    int value;
2089 	    char filename[100];
2090 
2091 	    if (!boards[j].present ||
2092 		(h->board[i].invalid_if_off && !board_power_state(sys, j))) {
2093 		h->board_valids[i][j] = 0;
2094 		continue;
2095 	    }
2096 
2097 	    sprintf(filename, h->board[i].filename, j + 1, j + 1);
2098 
2099 	    err = get_intval(filename, &value);
2100 	    if ( err && h->board[i].create_file) {
2101 		/* The sysfs file doesn't exist, create it. */
2102 		char cfilename[100];
2103 		FILE *f;
2104 
2105 		sprintf(cfilename, h->board[i].create_file, j + 1);
2106 		f = fopen(cfilename, "w");
2107 		if (!f) {
2108 		    sys->log(sys, OS_ERROR, NULL, "Unable to create %s",
2109 			     filename);
2110 		} else {
2111 		    fprintf(f, "%s\n", h->board[i].create_data);
2112 		    fclose(f);
2113 		}
2114 		err = get_intval(filename, &value);
2115 	    }
2116 
2117 	    if (debug & 2)
2118 		sys->log(sys, DEBUG, NULL, "Read value %s: %d %d",
2119 			 filename, err, value);
2120 	    if (err) {
2121 		sys->log(sys, OS_ERROR, NULL, "Sensor read error of %s: %s",
2122 			 filename, strerror(err));
2123 		h->board_valids[i][j] = 0;
2124 	    } else {
2125 		success = 1;
2126 		h->board_valids[i][j] = 1;
2127 		h->board_last_values[i][j] = value;
2128 		if (value > max)
2129 		    max = value;
2130 	    }
2131 	}
2132     }
2133 
2134     if (rmax)
2135 	*rmax = max;
2136     return !success;
2137 }
2138 
2139 static int
calc_duty(struct fan_duty_table * t,int duty_offset,int v,int * last_v,int * last_duty)2140 calc_duty(struct fan_duty_table *t, int duty_offset,
2141 	  int v, int *last_v, int *last_duty)
2142 {
2143     unsigned int i;
2144     int duty = 0;
2145 
2146     /* Hysteresis when going down, and is two degress C. */
2147     if (v < *last_v)
2148 	v += 2000;
2149 
2150     /* Convert to degrees, rounding */
2151     v = (v + 500) / 1000;
2152 
2153     for (i = 1; t[i].reading != -1; i++) {
2154 	if (v < t[i].reading)
2155 	    break;
2156     }
2157     duty = t[i - 1].setting + duty_offset;
2158     if (duty > 100)
2159 	duty = 100;
2160     if (duty < 42)
2161 	duty = 42;
2162     if (duty != *last_duty) {
2163 	*last_duty = duty;
2164 	*last_v = v;
2165     } else if (v > *last_v) {
2166 	/*
2167 	 * This is subtle, but is required to correctly implement
2168 	 * hysteresis.  We don't want to get in a situation where the
2169 	 * temperature goes down, but is still in the hysteresis area,
2170 	 * then goes back up a little bit.  So we only set last_v when
2171 	 * going up.
2172 	 */
2173 	*last_v = v;
2174     }
2175 
2176     return duty;
2177 }
2178 
2179 static int last_main_v, last_mb_v, last_front_v;
2180 static int last_main_duty, last_mb_duty, last_front_duty;
2181 static int last_duty;
2182 
2183 static int scan_pipe[2];
2184 static pthread_mutex_t scan_mutex = PTHREAD_MUTEX_INITIALIZER;
2185 static pthread_cond_t scan_cond = PTHREAD_COND_INITIALIZER;
2186 static pthread_t scan_thread;
2187 static ipmi_io_t *scan_fd_id;
2188 
2189 static int eesense_data_ready[NUM_BOARDS];
2190 static unsigned char cpu_errors[NUM_BOARDS];
2191 static uint16_t dimm_errors[NUM_BOARDS];
2192 
2193 static int ps_status_good[2];
2194 static unsigned int ps_status_word[2];
2195 
2196 static void
scan_eeprom_sensors(sys_data_t * sys)2197 scan_eeprom_sensors(sys_data_t *sys)
2198 {
2199     int rv;
2200     unsigned int i;
2201 
2202     for (i = 0; i < NUM_BOARDS; i++) {
2203 	if (!boards[i].present) {
2204 	    eesense_data_ready[i] = 0;
2205 	} else {
2206 	    unsigned char data[2];
2207 
2208 	    rv = ipmi_mc_fru_sem_trywait(boards[i].mc, 0);
2209 	    if (rv)
2210 		continue;
2211 
2212 	    rv = read_eeprom(&board_i2c[i].fru, data, 9, 2);
2213 	    if (rv) {
2214 		eesense_data_ready[i] = 0;
2215 		sys->log(sys, OS_ERROR, NULL,
2216 			 "Error reading eeprom sensors for %d: %s",
2217 			 i + 1, strerror(rv));
2218 	    } else {
2219 		eesense_data_ready[i] = 1;
2220 		cpu_errors[i] = data[0];
2221 		dimm_errors[i] = data[1];
2222 	    }
2223 	    rv = ipmi_mc_fru_sem_post(boards[i].mc, 0);
2224 	    if (rv)
2225 		sys->log(sys, OS_ERROR, NULL,
2226 			 "Error posting board %d semaphore: %s", i + 1,
2227 			 strerror(rv));
2228 	}
2229     }
2230 }
2231 
2232 static void
scan_ps_sensors(sys_data_t * sys)2233 scan_ps_sensors(sys_data_t *sys)
2234 {
2235     int rv;
2236     unsigned int i;
2237 
2238     rv = get_uintval("/sys/class/wixpmbus/STATUS_1", &i);
2239     if (rv) {
2240 	/* Not present */
2241 	ps_status_good[0] = 0;
2242     } else {
2243 	ps_status_good[0] = 1;
2244 	ps_status_word[0] = i;
2245     }
2246     rv = get_uintval("/sys/class/wixpmbus/STATUS_2", &i);
2247     if (rv) {
2248 	/* Not present */
2249 	ps_status_good[1] = 0;
2250     } else {
2251 	ps_status_good[1] = 1;
2252 	ps_status_word[1] = i;
2253     }
2254 }
2255 
2256 static char *fan_fail_led[4]  =
2257 {
2258     "/sys/class/astgpio/GPIOP0",
2259     "/sys/class/astgpio/GPIOP1",
2260     "/sys/class/astgpio/GPIOP2",
2261     "/sys/class/astgpio/GPIOP3",
2262 };
2263 
2264 static void *
scan_sensors(void * cb_data)2265 scan_sensors(void *cb_data)
2266 {
2267     sys_data_t *sys = cb_data;
2268     int err;
2269     int duty;
2270     int max_temp = 0;
2271     int max_duty = 0;
2272     char dummy = 0;
2273     struct timeval next, now, wait;
2274     unsigned int i;
2275     char fan_fail[8];
2276 
2277     for (;;) {
2278 	sys->get_monotonic_time(sys, &next);
2279 	add_to_timeval(&next, poll_time);
2280 
2281 	err = get_readings(sys, &main_temp, &max_temp);
2282 	if (!err) {
2283 	    max_duty = calc_duty(main_temp.fan_duty, main_temp.duty_offset,
2284 				 max_temp, &last_main_v, &last_main_duty);
2285 	}
2286 	err = get_readings(sys, &mb_temp, &max_temp);
2287 	if (!err) {
2288 	    duty = calc_duty(mb_temp.fan_duty, mb_temp.duty_offset, max_temp,
2289 			     &last_mb_v, &last_mb_duty);
2290 	    if (duty > max_duty)
2291 		max_duty = duty;
2292 	}
2293 	err = get_readings(sys, &front_temp, &max_temp);
2294 	if (!err) {
2295 	    duty = calc_duty(front_temp.fan_duty, front_temp.duty_offset,
2296 			     max_temp, &last_front_v, &last_front_duty);
2297 	    if (duty > max_duty)
2298 		max_duty = duty;
2299 	}
2300 
2301 	duty = 0;
2302 	for (i = 1; i < 9; i++) {
2303 	    char filename[50];
2304 	    int val;
2305 
2306 	    sprintf(filename, "/sys/class/astfan/fan%u_input", i);
2307 	    err = get_intval(filename, &val);
2308 	    if (err) {
2309 		sys->log(sys, OS_ERROR, NULL,
2310 			 "Can't read fan speed for %s: %s", filename,
2311 			 strerror(err));
2312 		/* Can't read fan, better safe than sorry. */
2313 		duty = 90;
2314 		fan_fail[i - 1] = 1;
2315 	    } else {
2316 		/* A fan is failing. */
2317 		if (val < 1000) {
2318 		    fan_fail[i - 1] = 1;
2319 		    duty = 90;
2320 		} else
2321 		    fan_fail[i - 1] = 0;
2322 	    }
2323 	}
2324 
2325 	for (i = 0; i < 4; i++) {
2326 	    if (fan_fail[i * 2] || fan_fail[i * 2 + 1])
2327 		set_intval(fan_fail_led[i], 1);
2328 	    else
2329 		set_intval(fan_fail_led[i], 0);
2330 	}
2331 
2332 	if (duty > max_duty)
2333 	    max_duty = duty;
2334 
2335 	if (all_fans_duty)
2336 	    max_duty = all_fans_duty;
2337 
2338 	if (max_duty != last_duty) {
2339 	    if (debug & 8)
2340 		sys->log(sys, DEBUG, NULL, "Setting fan duty to %d",
2341 			 max_duty);
2342 
2343 	    for (i = 1; i < 5; i++) {
2344 		char filename[50];
2345 
2346 		sprintf(filename, "/sys/class/astfan/pwm%u", i);
2347 		err = set_intval(filename, max_duty * 256 / 100);
2348 		if (err)
2349 		    sys->log(sys, OS_ERROR, NULL,
2350 			     "Can't set fan duty %s to %d: %s",
2351 			     filename, max_duty, strerror(err));
2352 	    }
2353 	}
2354 
2355 	get_readings(sys, &system_sensors, NULL);
2356 
2357 	scan_eeprom_sensors(sys);
2358 
2359 	scan_ps_sensors(sys);
2360 
2361 	pthread_mutex_lock(&scan_mutex);
2362 	write(scan_pipe[1], &dummy, 1);
2363 	pthread_cond_wait(&scan_cond, &scan_mutex);
2364 	pthread_mutex_unlock(&scan_mutex);
2365 
2366 	if (wdt_test_timer_ran) {
2367 	    unsigned char data = 1;
2368 	    err = write(wdt_fd, &data, 1);
2369 	    if (err == -1) {
2370 		sys->log(sys, OS_ERROR, NULL,
2371 			 "Unable to write to watchdog timer: %s",
2372 			 strerror(err));
2373 	    }
2374 	    wdt_test_timer_ran = 0;
2375 	}
2376 
2377 	/* Wait until poll_time seconds after the last scan started */
2378 	sys->get_monotonic_time(sys, &now);
2379 	diff_timeval(&wait, &next, &now);
2380 	select(0, NULL, NULL, NULL, &wait);
2381     }
2382 
2383     return NULL;
2384 }
2385 
2386 static unsigned char
conv_value(struct sensor_info * info,int value)2387 conv_value(struct sensor_info *info, int value)
2388 {
2389     value -= info->sub;
2390     if (info->mult)
2391 	value *= info->mult;
2392     if (info->div) {
2393 	value += info->div / 2;
2394 	value /= info->div;
2395     }
2396     if (value < 0)
2397 	return 0;
2398     if (value > 255)
2399 	return 255;
2400     return value;
2401 }
2402 
2403 static void
set_sensors_from_table(sys_data_t * sys,struct sensor_handling * h)2404 set_sensors_from_table(sys_data_t *sys, struct sensor_handling *h)
2405 {
2406     unsigned int i, j;
2407 
2408     for (i = 0; h->switch_s[i].filename; i++) {
2409 	if (debug & 4)
2410 	    sys->log(sys, DEBUG, NULL, "process value %s: %d %d (%u)",
2411 		     h->switch_s[i].filename, h->switch_valids[i],
2412 		     h->switch_last_values[i],
2413 		     conv_value(&h->switch_s[i],
2414 				h->switch_last_values[i]));
2415 
2416 	ipmi_mc_sensor_set_enabled(bmc_mc, 0,
2417 				   h->switch_s[i].sensor_number,
2418 				   h->switch_valids[i]);
2419 	if (h->switch_valids[i]) {
2420 	    ipmi_mc_sensor_set_value(bmc_mc, 0,
2421 				     h->switch_s[i].sensor_number,
2422 				     conv_value(&h->switch_s[i],
2423 						h->switch_last_values[i]),
2424 				     1);
2425 	}
2426     }
2427 
2428     for (i = 0; h->board[i].filename; i++) {
2429 	for (j = 0; j < NUM_BOARDS; j++) {
2430 	    if (debug & 4)
2431 		sys->log(sys, DEBUG, NULL, "process value %s (%d): %d %d (%u)",
2432 			 h->board[i].filename, j + 1, h->board_valids[i][j],
2433 			 h->board_last_values[i][j],
2434 			 conv_value(&h->board[i],
2435 				    h->board_last_values[i][j]));
2436 
2437 	    ipmi_mc_sensor_set_enabled(boards[j].mc, 0,
2438 				       h->board[i].sensor_number,
2439 				       h->board_valids[i][j]);
2440 	    if (h->board_valids[i][j])
2441 		ipmi_mc_sensor_set_value(boards[j].mc, 0,
2442 					 h->board[i].sensor_number,
2443 					 conv_value(&h->board[i],
2444 						    h->board_last_values[i][j]),
2445 					 1);
2446 	}
2447     }
2448 }
2449 
2450 static void
handle_eesense_data(sys_data_t * sys)2451 handle_eesense_data(sys_data_t *sys)
2452 {
2453     unsigned int i, j;
2454 
2455     for (i = 0; i < NUM_BOARDS; i++) {
2456 
2457 	ipmi_mc_sensor_set_enabled(boards[i].mc, 0, 20,
2458 				   eesense_data_ready[i]);
2459 	ipmi_mc_sensor_set_enabled(boards[i].mc, 0, 21,
2460 				   eesense_data_ready[i]);
2461 	if (!eesense_data_ready[i])
2462 	    continue;
2463 	for (j = 0; j < 1; j++)
2464 	    ipmi_mc_sensor_set_bit(boards[i].mc, 0, 20, j,
2465 				   ((cpu_errors[i] >> j) & 1), 1);
2466 	for (j = 0; j < 8; j++)
2467 	    ipmi_mc_sensor_set_bit(boards[i].mc, 0, 21, j,
2468 				   ((dimm_errors[i] >> j) & 1), 1);
2469     }
2470 }
2471 
2472 #define PMBUS_NONE_BIT		(1 << 0)
2473 #define PMBUS_CML_BIT		(1 << 1)
2474 #define PMBUS_TEMP_BIT		(1 << 2)
2475 #define PMBUS_VIN_UV_BIT	(1 << 3)
2476 #define PMBUS_IOUT_OC_BIT	(1 << 4)
2477 #define PMBUS_VOUT_OV_BIT	(1 << 5)
2478 #define PMBUS_OFF_BIT		(1 << 6)
2479 #define PMBUS_BUSY_BIT		(1 << 7)
2480 #define PMBUS_UNKNOWN_BIT	(1 << 8)
2481 #define PMBUS_OTHER_BIT		(1 << 9)
2482 #define PMBUS_FANS_BIT		(1 << 10)
2483 #define PMBUS_NOT_POWER_GOOD_BIT (1 << 11)
2484 #define PMBUS_MRF_BIT		(1 << 12)
2485 #define PMBUS_INPUT_BIT		(1 << 13)
2486 #define PMBUS_I_P_OUT_BIT	(1 << 14)
2487 #define PMBUS_VOUT_BIT		(1 << 15)
2488 
2489 /*
2490  * This is a mask to convert the PMBus status work to the IPMI power
2491  * supply status bitmask.  Each entry in this array has a set of bits;
2492  * if one of those bits is set in the status work then the index of
2493  * the entry is a bit that should be set in the IPMI sensor.
2494  */
2495 static uint16_t pm_word_to_ipmi[7] =
2496 {
2497     0, /* presence is handled separately */
2498     0xffff, /* If anything is set we declare a fault */
2499     PMBUS_TEMP_BIT | PMBUS_FANS_BIT, /* Predictive failure */
2500     0, /* Input lost, nothing for this, only have "lost or out of range" */
2501     PMBUS_INPUT_BIT, /* Input lost or out of range */
2502     0, /* Out of range but present.  No bit for this, just previous. */
2503     0, /* Configuration error */
2504 };
2505 
2506 static void
handle_ps_status(int num)2507 handle_ps_status(int num)
2508 {
2509     uint16_t val;
2510     unsigned int i;
2511 
2512     if (ps_status_good[num]) {
2513 	val = 1; /* Present */
2514 	for (i = 1; i < 7; i++)
2515 	    val |= (!!(ps_status_word[num] & pm_word_to_ipmi[i])) << i;
2516     } else {
2517 	val = 0; /* Not present */
2518     }
2519 
2520     for (i = 0; i < 7; i++)
2521 	ipmi_mc_sensor_set_bit(bmc_mc, 0, 8 + num, i, (val >> i) & 1, 1);
2522 }
2523 
2524 static void
set_sensors_from_tables(int fd,void * cb_data)2525 set_sensors_from_tables(int fd, void *cb_data)
2526 {
2527     sys_data_t *sys = cb_data;
2528     unsigned int i;
2529     int temp = 0;
2530     unsigned char dummy;
2531     int rv;
2532 
2533     read(fd, &dummy, 1);
2534 
2535     set_sensors_from_table(sys, &main_temp);
2536     set_sensors_from_table(sys, &mb_temp);
2537     set_sensors_from_table(sys, &front_temp);
2538     set_sensors_from_table(sys, &system_sensors);
2539     handle_eesense_data(sys);
2540     handle_ps_status(0);
2541     handle_ps_status(1);
2542 
2543     /* Check for shutdown thresholds */
2544     if (switch_temp_sensor_valids[0])
2545 	temp = switch_temp_sensor_last_values[0];
2546     if (switch_temp_sensor_valids[1] &&
2547 	temp < switch_temp_sensor_last_values[1])
2548 	temp = switch_temp_sensor_last_values[1];
2549     if (temp >= SWITCH_TEMP_SHUTDOWN * 1000) {
2550 	sys->log(sys, INFO, NULL, "CRITICAL: Switch has exceeded temperature"
2551 		 " threshold, powering down system");
2552 	power_down_system(sys);
2553     }
2554     temp = 0;
2555     for (i = 0; i < NUM_BOARDS; i++) {
2556 	if (board_front_sensor_valids[0][i] &&
2557 	    board_front_sensor_last_values[0][i] > temp)
2558 	    temp = board_front_sensor_last_values[0][i];
2559     }
2560     if (temp >= FRONT_TEMP_SHUTDOWN * 1000) {
2561 	sys->log(sys, INFO, NULL, "CRITICAL: External environment exceeded"
2562 		 " temperature threshold, raw value is %d, powering down"
2563 		 " system", temp);
2564 	power_down_system(sys);
2565     }
2566 
2567     for (i = 0; i < NUM_BOARDS; i++) {
2568 	temp = 0;
2569 	if (board_temp_sensor_valids[0][i])
2570 	    temp = board_temp_sensor_last_values[0][i];
2571 	if (board_temp_sensor_valids[1][i] &&
2572 	    temp < board_temp_sensor_last_values[1][i])
2573 	    temp = board_temp_sensor_last_values[1][i];
2574 	if (temp >= BOARD_TEMP_SHUTDOWN * 1000) {
2575 	    unsigned char val = 0;
2576 	    if (board_temp_sensor_last_oor[i]) {
2577 		sys->log(sys, INFO, NULL, "CRITICAL: Board %d has exceeded"
2578 			 " temperature threshold, raw value is %d,"
2579 			 " powering down",
2580 			 i + 1, temp);
2581 		set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val,
2582 				    &boards[i]);
2583 	    } else {
2584 		sys->log(sys, INFO, NULL, "WARNING: Board %d has exceeded"
2585 			 " temperature threshold, raw value is %d,"
2586 			 " will check again before shutdown",
2587 			 i + 1, temp);
2588 		board_temp_sensor_last_oor[i]++;
2589 	    }
2590 	} else
2591 	    board_temp_sensor_last_oor[i] = 0;
2592 
2593 	if (boards[i].fru_data_ready_for_handling) {
2594 	    boards[i].fru_data_ready_for_handling = 0;
2595 	    handle_board_fru(sys, i);
2596 	    rv = ipmi_mc_fru_sem_post(boards[i].mc, 0);
2597 	    if (rv)
2598 		sys->log(sys, OS_ERROR, NULL,
2599 			 "Error posting board %d semaphore: %s", i + 1,
2600 			 strerror(rv));
2601 	}
2602     }
2603 
2604     pthread_mutex_lock(&scan_mutex);
2605     pthread_cond_signal(&scan_cond);
2606     pthread_mutex_unlock(&scan_mutex);
2607 }
2608 
2609 /**************************************************************************
2610  * Marvell OEM commands.
2611  *************************************************************************/
2612 
2613 struct fru_write_data {
2614     sys_data_t *sys;
2615     unsigned int num;
2616 };
2617 
2618 /*
2619  * Writing FRU data is too slow to do in the main thread, so do it in
2620  * another thread.
2621  */
2622 static void *
fru_write_thread(void * cb_data)2623 fru_write_thread(void *cb_data)
2624 {
2625     struct fru_write_data *info = cb_data;
2626     sys_data_t *sys = info->sys;
2627     unsigned int num = info->num;
2628     unsigned char board_fru_data[2048];
2629     int fd, rv;
2630 
2631     pthread_detach(pthread_self());
2632 
2633     free(info);
2634 
2635     fd = open(BOARD_FRU_FILE, O_RDONLY);
2636     if (fd == -1) {
2637 	sys->log(sys, OS_ERROR, NULL,
2638 		 "Unable to read board FRU file %s: %s",
2639 		 BOARD_FRU_FILE, strerror(errno));
2640     }
2641     rv = read(fd, board_fru_data, sizeof(board_fru_data));
2642     if (rv == -1) {
2643 	sys->log(sys, OS_ERROR, NULL,
2644 		 "Unable to read board FRU file %s: %s",
2645 		 BOARD_FRU_FILE, strerror(errno));
2646 	goto out_err;
2647     } else if (rv != sizeof(board_fru_data)) {
2648 	sys->log(sys, OS_ERROR, NULL,
2649 		 "board FRU file too small %s: %d",
2650 		 BOARD_FRU_FILE, rv);
2651 	goto out_err;
2652     }
2653     rv = write_eeprom(&board_i2c[num].fru, board_fru_data, 0,
2654 		      sizeof(board_fru_data));
2655     if (rv) {
2656 	sys->log(sys, OS_ERROR, NULL,
2657 		 "Error writing board %d fru: %d", num, rv);
2658 	goto out_err;
2659     }
2660 
2661     boards[num].fru_data_ready_for_handling = 1;
2662     return NULL;
2663 
2664   out_err:
2665     rv = ipmi_mc_fru_sem_post(boards[num].mc, 0);
2666     if (rv)
2667 	sys->log(sys, OS_ERROR, NULL,
2668 		 "Error posting board %d semaphore: %s", num + 1, strerror(rv));
2669     return NULL;
2670 }
2671 
2672 static void
handle_marvell_cmd(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)2673 handle_marvell_cmd(lmc_data_t    *mc,
2674 		   msg_t         *msg,
2675 		   unsigned char *rdata,
2676 		   unsigned int  *rdata_len,
2677 		   void          *cb_data)
2678 {
2679     sys_data_t *sys = cb_data;
2680     char cmd[100];
2681     int rv;
2682 
2683     /*
2684      * Note that the calling function remove the IANA from the message
2685      * and inserts the IANA in the return message, we handle this like
2686      * a normal command.
2687      *
2688      * Start assuming success.
2689      */
2690     rdata[0] = 0;
2691     *rdata_len = 1;
2692 
2693     switch (msg->cmd) {
2694     case DISABLE_NETWORK_SRVC_CMD:
2695 	if (check_msg_length(msg, 1, rdata, rdata_len))
2696 	    break;
2697 	snprintf(cmd, sizeof(cmd), "/etc/ipmi/netsrvc %d\n", msg->data[0]);
2698 	rv = system(cmd);
2699 	if (rv == -1) {
2700 	    rdata[0] = 0xff;
2701 	    rdata[1] = errno;
2702 	    rdata[2] = 0;
2703 	    *rdata_len = 3;
2704 	} else if (rv) {
2705 	    rdata[0] = 0xff;
2706 	    rdata[1] = 0;
2707 	    rdata[2] = rv;
2708 	    *rdata_len = 3;
2709 	}
2710 	break;
2711 
2712     case RELOAD_BOARD_FRU_CMD:
2713     {
2714 	struct fru_write_data *info;
2715 	pthread_t tid;
2716 	unsigned int num;
2717 
2718 	if (check_msg_length(msg, 1, rdata, rdata_len))
2719 	    return;
2720 
2721 	num = msg->data[0] - 1;
2722 	if (num >= NUM_BOARDS)
2723 	    goto out_err;
2724 
2725 	if (!boards[num].present)
2726 	    goto out_err;
2727 
2728 	rv = ipmi_mc_fru_sem_trywait(boards[num].mc, 0);
2729 	if (rv) {
2730 	    if (errno == EAGAIN)
2731 		/* Already in progress. */
2732 		goto out_good;
2733 
2734 	    sys->log(sys, OS_ERROR, NULL,
2735 		     "Unable to claim board %d FRU semaphore: %s",
2736 		     num + 1, strerror(errno));
2737 	    goto out_err;
2738 	}
2739 
2740 	info = malloc(sizeof(*info));
2741 	if (!info)
2742 	    goto out_err;
2743 	info->sys = sys;
2744 	info->num = num;
2745 
2746 	rv = pthread_create(&tid, NULL, fru_write_thread, info);
2747 	if (rv) {
2748 	    sys->log(sys, OS_ERROR, NULL,
2749 		     "MVMOD: Unable to create fru write thread: %s",
2750 		     strerror(rv));
2751 	    free(info);
2752 	    goto out_err;
2753 	}
2754     }
2755     break;
2756 
2757     case SET_ALL_FANS_DUTY_CMD:
2758     {
2759 	int duty;
2760 
2761 	if (check_msg_length(msg, 1, rdata, rdata_len))
2762 	    break;
2763 
2764 	duty = msg->data[0];
2765 	if (duty == 0)
2766 	    ; /* Disable the duty by setting to zero */
2767 	else if (duty < 30)
2768 	    duty = 30; /* Minimum allowed fan duty */
2769 	else if (duty > 100)
2770 	    duty = 100;
2771 	all_fans_duty = duty;
2772     }
2773     break;
2774 
2775     case GET_ALL_FANS_DUTY_CMD:
2776 	rdata[1] = all_fans_duty;
2777 	*rdata_len = 2;
2778 	break;
2779 
2780     default:
2781 	handle_invalid_cmd(mc, rdata, rdata_len);
2782 	break;
2783     }
2784 
2785   out_good:
2786     return;
2787 
2788   out_err:
2789     rdata[0] = 0xff;
2790 }
2791 
2792 int
ipmi_sim_module_print_version(sys_data_t * sys,char * initstr)2793 ipmi_sim_module_print_version(sys_data_t *sys, char *initstr)
2794 {
2795     printf("IPMI Simulator Marvell AXP module version %s\n", PVERSION);
2796     return 0;
2797 }
2798 
2799 /*
2800  * An emulator command for simulating a change in the board's presence.
2801  */
simulate_board_presence(emu_out_t * out,emu_data_t * emu,lmc_data_t * mc,char ** toks)2802 static int simulate_board_presence(emu_out_t  *out,
2803 				   emu_data_t *emu,
2804 				   lmc_data_t *mc,
2805 				   char       **toks)
2806 {
2807     int rv;
2808     unsigned int board, present;
2809     const char *err;
2810 
2811     rv = get_uint(toks, &board, &err);
2812     if (!rv && ((board == 0 || board > NUM_BOARDS))) {
2813 	err = "board number out of range";
2814 	rv = EINVAL;
2815     }
2816     if (rv) {
2817 	out->printf(out, "Invalid board number: %s\n", err);
2818 	return EINVAL;
2819     }
2820     board--;
2821     rv = get_bool(toks, &present, &err);
2822     if (rv) {
2823 	out->printf(out, "Invalid board presence value: %s\n", err);
2824 	return EINVAL;
2825     }
2826     simulate_board_absent[board] = !present;
2827 }
2828 
2829 
2830 /**************************************************************************
2831  * BMC reset handling
2832  *************************************************************************/
2833 
2834 static void
handle_cold_reset(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)2835 handle_cold_reset(lmc_data_t    *mc,
2836 		  msg_t         *msg,
2837 		  unsigned char *rdata,
2838 		  unsigned int  *rdata_len,
2839 		  void          *cb_data)
2840 {
2841     sys_data_t *sys = cb_data;
2842     int rv;
2843 
2844     rv = set_intval(RESET_REASON_FILE, RESET_REASON_COLD_BOOT);
2845     if (rv) {
2846 	sys->log(sys, OS_ERROR, NULL,
2847 		 "MVMOD: Unable to write cold reset reason: %s",
2848 		 strerror(rv));
2849     }
2850 
2851     system("reboot");
2852 }
2853 
2854 static void
handle_warm_reset(lmc_data_t * mc,msg_t * msg,unsigned char * rdata,unsigned int * rdata_len,void * cb_data)2855 handle_warm_reset(lmc_data_t    *mc,
2856 		  msg_t         *msg,
2857 		  unsigned char *rdata,
2858 		  unsigned int  *rdata_len,
2859 		  void          *cb_data)
2860 {
2861     sys_data_t *sys = cb_data;
2862     int rv;
2863 
2864     rv = set_intval(RESET_REASON_FILE, RESET_REASON_WARM_BOOT);
2865     if (rv) {
2866 	sys->log(sys, OS_ERROR, NULL,
2867 		 "MVMOD: Unable to write warm reset reason: %s",
2868 		 strerror(rv));
2869     }
2870 
2871     exit(1);
2872 }
2873 
2874 /*
2875  * This is a timer that is periodically called from the main thread,
2876  * it is basically used to tell if the main thread is running.
2877  */
2878 static void
wdt_test_timeout(void * cb_data)2879 wdt_test_timeout(void *cb_data)
2880 {
2881     struct timeval tv;
2882     sys_data_t *sys = cb_data;
2883 
2884     if (wdt_test_timer_ran)
2885 	sys->log(sys, OS_ERROR, NULL, "MVMOD: WDT test timer not cleared");
2886 
2887     wdt_test_timer_ran = 1;
2888     tv.tv_sec = 4;
2889     tv.tv_usec = 0;
2890     sys->start_timer(wdt_test_timer, &tv);
2891 }
2892 
2893 
2894 /**************************************************************************
2895  * Module initialization
2896  *************************************************************************/
2897 
2898 int
ipmi_sim_module_init(sys_data_t * sys,const char * initstr_i)2899 ipmi_sim_module_init(sys_data_t *sys, const char *initstr_i)
2900 {
2901     unsigned int num;
2902     int rv;
2903     const char *c;
2904     char *next;
2905     int use_events = 1;
2906     struct timeval tv;
2907     int power_up_force = 0;
2908     char *initstr = strdup(initstr_i);
2909     int val;
2910 
2911     printf("IPMI Simulator Marvell AXP module version %s\n", PVERSION);
2912 
2913     if (!initstr) {
2914 	sys->log(sys, SETUP_ERROR, NULL, "Error: MV: Out of memory");
2915 	return ENOMEM;
2916     }
2917 
2918     c = mystrtok(initstr, " \t\n", &next);
2919     while (c) {
2920 	if (strcmp(c, "noevents") == 0) {
2921 	    use_events = 0;
2922 	} else if (strcmp(c, "fork") == 0) {
2923 	    fork_event_wait = 1;
2924 	} else if (strncmp(c, "debug=", 6) == 0) {
2925 	    debug = strtoul(c + 6, NULL, 0);
2926 	} else if (strcmp(c, "forcecold") == 0) {
2927 	    power_up_force = 1;
2928 	} else if (strcmp(c, "forcewarm") == 0) {
2929 	    power_up_force = 1;
2930 	    cold_power_up = 0;
2931 	} else if (strcmp(c, "disablewdt") == 0) {
2932 	    disable_wdt = 1;
2933 	} else if (strncmp(c, "poll_time=", 10) == 0) {
2934 	    poll_time = strtoul(c + 10, NULL, 0);
2935 	} else {
2936 	    sys->log(sys, SETUP_ERROR, NULL, "Warning: MV: Unknown init"
2937 		     " string: %s", c);
2938 	}
2939 	c = mystrtok(NULL, " \t\n", &next);
2940     }
2941 
2942     free(initstr);
2943 
2944     check_chassis_state(sys);
2945 
2946     rv = init_chassis(sys);
2947     if (rv)
2948 	return rv;
2949 
2950     rv = pipe(scan_pipe);
2951     if (rv == -1) {
2952 	int errval = errno;
2953 	sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to open pipe");
2954 	return errval;
2955     }
2956     rv = sys->add_io_hnd(sys, scan_pipe[0], set_sensors_from_tables, sys,
2957 			 &scan_fd_id);
2958     if (rv) {
2959 	int errval = errno;
2960 	sys->log(sys, SETUP_ERROR, NULL,
2961 		 "MVMOD: Unable to add I/O handler");
2962 	close(scan_pipe[0]);
2963 	close(scan_pipe[1]);
2964 	return errval;
2965     }
2966 
2967     if (use_events) {
2968 	ast_fd = open("/dev/event", O_RDWR);
2969 	if (ast_fd == -1) {
2970 	    int errval = errno;
2971 	    sys->log(sys, SETUP_ERROR, NULL, "Unable to open /dev/event");
2972 	    return errval;
2973 	}
2974 	if (fork_event_wait) {
2975 	    int pipefds[2];
2976 	    rv = pipe(pipefds);
2977 	    if (rv == -1) {
2978 		int errval = errno;
2979 		close(ast_fd);
2980 		sys->log(sys, SETUP_ERROR, NULL, "Unable to open pipe");
2981 		return errval;
2982 	    }
2983 	    rv = fork();
2984 	    if (rv == -1) {
2985 		int errval = errno;
2986 		close(ast_fd);
2987 		close(pipefds[0]);
2988 		close(pipefds[1]);
2989 		sys->log(sys, SETUP_ERROR, NULL, "Unable to fork");
2990 		return errval;
2991 	    } else if (rv != 0) {
2992 		/*
2993 		 * Note that the main program runs as the child and
2994 		 * the shim program runs as the parent.  This allows
2995 		 * the shim program to catch the SIGCHLD and terminate
2996 		 * if the main program goes away.  Otherwise the shim
2997 		 * would be stuck waiting on an event and not
2998 		 * terminate properly.
2999 		 */
3000 		close(pipefds[0]);
3001 		ast1300_shim(sys, ast_fd, pipefds[1], rv);
3002 	    }
3003 	    close(ast_fd);
3004 	    close(pipefds[1]);
3005 	    ast_fd = pipefds[0];
3006 	}
3007 
3008 	rv = sys->add_io_hnd(sys, ast_fd, ast_evt, sys, &ast_fd_id);
3009 	if (rv) {
3010 	    int errval = errno;
3011 	    sys->log(sys, SETUP_ERROR, NULL,
3012 		     "MVMOD: Unable to add I/O handler");
3013 	    close(ast_fd);
3014 	    return errval;
3015 	}
3016     }
3017     rv = sys->alloc_timer(sys, mv_timeout, sys, &mv_timer);
3018     if (rv) {
3019 	int errval = errno;
3020 	sys->log(sys, SETUP_ERROR, NULL, "MVMOD: Unable to create timer");
3021 	return errval;
3022     } else {
3023 	tv.tv_sec = 1;
3024 	tv.tv_usec = 0;
3025 	sys->start_timer(mv_timer, &tv);
3026     }
3027 
3028     rv = sys->alloc_timer(sys, board_power_timeout, sys, &power_timer);
3029     if (rv) {
3030 	sys->log(sys, OS_ERROR, NULL,
3031 		 "Unable to allocate board power timer: %s", strerror(rv));
3032 	return rv;
3033     }
3034 
3035     if (!power_up_force) {
3036 	rv = get_uintval(COLD_POWER_UP_IO, &cold_power_up);
3037 	if (rv) {
3038 	    sys->log(sys, OS_ERROR, NULL, "Warning: MV: Could not read %s"
3039 		     " so assuming cold power up: %s", COLD_POWER_UP_IO,
3040 		     strerror(errno));
3041 	    cold_power_up = 1;
3042 	} else if (cold_power_up) {
3043 	    /* Save the setting in case we fail in startup */
3044 	    set_intval(COLD_POWER_FILE, 1);
3045 	} else {
3046 	    /*
3047 	     * Get the setting from the last startup.  If it's not
3048 	     * there, no big deal.
3049 	     */
3050 	    get_uintval(COLD_POWER_FILE, &cold_power_up);
3051 	}
3052     }
3053 
3054     rv = ipmi_mc_alloc_unconfigured(sys, 0x20, &bmc_mc);
3055     if (rv) {
3056 	sys->log(sys, OS_ERROR, NULL,
3057 		 "Unable to allocate an mc: %s", strerror(rv));
3058 	return rv;
3059     }
3060 
3061     for (num = 0; num < NUM_BOARDS; num++) {
3062 	lmc_data_t *mc;
3063 	unsigned int rval = 0;
3064 	struct board_info *board = &boards[num];
3065 
3066 	board->num = num;
3067 	board->sys = sys;
3068 
3069 	board->last_power_request = BOARD_OFF_READY;
3070 	if (!cold_power_up) {
3071 	    /*
3072 	     * On a cold power up, we bring everything up that is
3073 	     * present.  Otherwise we run this code to read the
3074 	     * current status and retain that.
3075 	     */
3076 	    rv = get_uintval(trg_present[num], &rval);
3077 	    if (rv) {
3078 		sys->log(sys, OS_ERROR, NULL,
3079 			 "Unable to read board %u presence state: %s",
3080 			 num, strerror(rv));
3081 		return rv;
3082 	    }
3083 	    if (rval != BOARD_PRESENT) {
3084 		unsigned char val = 0;
3085 		set_chassis_control(NULL, CHASSIS_CONTROL_POWER, &val, board);
3086 	    } else if (board_power_state(sys, num)) {
3087 		/*
3088 		 * This looks a bit unusual, so I will explain.  The
3089 		 * board power request is only handled on a off-to-on
3090 		 * transition, the raw values is not used directly.
3091 		 * But this presents an issue at startup: what if the
3092 		 * board requested a power off while this code wasn't
3093 		 * running?  To solve that, if it is not a cold power
3094 		 * up, assume that the request is off and then we will
3095 		 * power down if the request is asserted.
3096 		 */
3097 		board->last_power_request = BOARD_OFF_NOT_READY;
3098 	    }
3099 	}
3100 
3101 	rv = ipmi_mc_alloc_unconfigured(sys, board_ipmb[num], &mc);
3102 	if (rv) {
3103 	    sys->log(sys, OS_ERROR, NULL,
3104 		     "Unable to allocate an mc: %s", strerror(rv));
3105 	    return rv;
3106 	}
3107 	boards[num].mc = mc;
3108 
3109 	ipmi_mc_set_chassis_control_func(mc, set_chassis_control,
3110 					 get_chassis_control, board);
3111 
3112 	rv = check_board(sys, num, 0, cold_power_up);
3113 	if (rv) {
3114 	    if (ast_fd_id)
3115 		sys->remove_io_hnd(ast_fd_id);
3116 	    if (mv_timer)
3117 		sys->free_timer(mv_timer);
3118 	    return rv;
3119 	}
3120     }
3121 
3122     ipmi_mc_set_chassis_control_func(bmc_mc, bmc_set_chassis_control,
3123 				     bmc_get_chassis_control, sys);
3124 
3125 
3126     rv = ipmi_emu_register_iana_handler(MARVELL_SEMI_ISREAL_IANA,
3127 					handle_marvell_cmd, sys);
3128     if (rv) {
3129 	sys->log(sys, OS_ERROR, NULL,
3130 		 "Unable to register Marvell IANA handler: %s", strerror(rv));
3131     }
3132 
3133     rv = ipmi_emu_register_cmd_handler(IPMI_APP_NETFN, IPMI_COLD_RESET_CMD,
3134 				       handle_cold_reset, sys);
3135     if (rv) {
3136 	sys->log(sys, OS_ERROR, NULL,
3137 		 "Unable to register cold reset handler: %s", strerror(rv));
3138     }
3139 
3140     rv = ipmi_emu_register_cmd_handler(IPMI_APP_NETFN, IPMI_WARM_RESET_CMD,
3141 				       handle_warm_reset, sys);
3142     if (rv) {
3143 	sys->log(sys, OS_ERROR, NULL,
3144 		 "Unable to register cold reset handler: %s", strerror(rv));
3145     }
3146 
3147     if (!disable_wdt) {
3148 	wdt_fd = open("/dev/watchdog", O_WRONLY);
3149 	if (wdt_fd == -1) {
3150 	    sys->log(sys, OS_ERROR, NULL,
3151 		     "Unable to open wdt: %s", strerror(errno));
3152 	    return rv;
3153 	}
3154 
3155 	rv = sys->alloc_timer(sys, wdt_test_timeout, sys, &wdt_test_timer);
3156 	if (rv) {
3157 	    sys->log(sys, OS_ERROR, NULL,
3158 		     "Unable to allocate wdt test timer: %s", strerror(rv));
3159 	    return rv;
3160 	}
3161 	tv.tv_sec = 4;
3162 	tv.tv_usec = 0;
3163 	sys->start_timer(wdt_test_timer, &tv);
3164     }
3165 
3166     if (!cold_power_up)
3167 	init_complete = 1;
3168 
3169     ipmi_emu_add_cmd("simulate_board_presence", NOMC, simulate_board_presence);
3170 
3171     return 0;
3172 }
3173 
3174 int
ipmi_sim_module_post_init(sys_data_t * sys)3175 ipmi_sim_module_post_init(sys_data_t *sys)
3176 {
3177     int rv;
3178     const char *ver = get_lanserv_version();
3179     unsigned char lver[4];
3180     unsigned char omajor, ominor, orel;
3181     unsigned int i;
3182     int val;
3183 
3184     sscanf(ver, "%hhu.%hhu.%hhu", lver + 0, lver + 1, lver + 2);
3185     lver[3] = 0;
3186     sscanf(PVERSION, "%hhu.%hhu.%hhu", &omajor, &ominor, &orel);
3187     for (i = 0; i < NUM_BOARDS; i++) {
3188 	ipmi_mc_set_fw_revision(boards[i].mc, omajor, ominor << 4 | orel);
3189 	ipmi_mc_set_aux_fw_revision(boards[i].mc, lver);
3190     }
3191     ipmi_mc_set_fw_revision(bmc_mc, omajor, ominor << 4 | orel);
3192     ipmi_mc_set_aux_fw_revision(bmc_mc, lver);
3193 
3194     /*
3195      * Set the rearm handler for the CPU and DIMM sensors to clear
3196      * them on rearm.
3197      */
3198 
3199     for (i = 0; i < NUM_BOARDS; i++) {
3200 	struct eesense_rearm *info;
3201 
3202 	info = malloc(sizeof(*info));
3203 	if (!info) {
3204 	    sys->log(sys, OS_ERROR, NULL,
3205 		     "MVMOD: Unable to allocate eesense handler for board %d: "
3206 		     "Out of memory", i + 1);
3207 	    continue;
3208 	}
3209 	info->num = i;
3210 	info->offset = 1;
3211 	info->mask = 0x01;
3212 	rv = ipmi_mc_sensor_add_rearm_handler(boards[i].mc, 0, 20,
3213 					      rearm_eesense_sensor, info);
3214 	if (rv) {
3215 	    sys->log(sys, OS_ERROR, NULL,
3216 		     "MVMOD: Error adding eesense CPU rearm on %d: %s",
3217 		     i + 1, strerror(rv));
3218 	    continue;
3219 	}
3220 
3221 	info = malloc(sizeof(*info));
3222 	if (!info) {
3223 	    sys->log(sys, OS_ERROR, NULL,
3224 		     "MVMOD: Unable to allocate eesense handler for board %d: "
3225 		     "Out of memory", i + 1);
3226 	    continue;
3227 	}
3228 	info->num = i;
3229 	info->offset = 2;
3230 	info->mask = 0x87;
3231 	rv = ipmi_mc_sensor_add_rearm_handler(boards[i].mc, 0, 21,
3232 					      rearm_eesense_sensor, info);
3233 	if (rv) {
3234 	    sys->log(sys, OS_ERROR, NULL,
3235 		     "MVMOD: Error adding eesense DIMM rearm on %d: %s",
3236 		     i + 1, strerror(rv));
3237 	}
3238     }
3239 
3240     rv = ipmi_mc_sensor_add_rearm_handler(bmc_mc, 0, 8,
3241 					  rearm_power_supply_sensor,
3242 					  (void *) 1);
3243     if (rv) {
3244 	sys->log(sys, OS_ERROR, NULL,
3245 		 "MVMOD: Error adding power supply %d rearm: %s",
3246 		 1, strerror(rv));
3247     }
3248 
3249     rv = ipmi_mc_sensor_add_rearm_handler(bmc_mc, 0, 9,
3250 					  rearm_power_supply_sensor,
3251 					  (void *) 2);
3252     if (rv) {
3253 	sys->log(sys, OS_ERROR, NULL,
3254 		 "MVMOD: Error adding power supply %d rearm: %s",
3255 		 2, strerror(rv));
3256     }
3257 
3258     /* Initial state of the PSU sensor is with the present bit set */
3259     ipmi_mc_sensor_set_bit(bmc_mc, 0, 8, 0, 1, 0);
3260     ipmi_mc_sensor_set_bit(bmc_mc, 0, 9, 0, 1, 0);
3261 
3262     rv = pthread_create(&scan_thread, NULL, scan_sensors, sys);
3263     if (rv) {
3264 	sys->log(sys, OS_ERROR, NULL,
3265 		 "MVMOD: Unable to start scan thread: %s", strerror(rv));
3266     }
3267 
3268     rv = get_intval(RESET_REASON_FILE, &val);
3269     if (rv || cold_power_up) {
3270 	val = 0x00; /* Initiated by power up */
3271     } else if (val == RESET_REASON_COLD_BOOT ||
3272 	       rv || val == RESET_REASON_UNKNOWN) {
3273 	val = 0x01; /* Initiated by hard reset */
3274     } else if (val == RESET_REASON_WARM_BOOT) {
3275 	val = 0x02; /* Initiated by warm reset */
3276     } else {
3277 	sys->log(sys, OS_ERROR, NULL, "MVMOD: known reset reason: %d", val);
3278 	val = 0x01; /* Assume hard reset */
3279     }
3280     {
3281 	/*
3282 	 * We don't have an actual sensor for this, since it is
3283 	 * event-only, just send the event.
3284 	 */
3285 	unsigned char data[13];
3286 	memset(data, 0, sizeof(data));
3287 	data[4] = ipmi_mc_get_ipmb(bmc_mc);
3288 	data[5] = 0; /* LUN */
3289 	data[6] = 0x04; /* Event message revision for IPMI 1.5. */
3290 	data[7] = 0x1d; /* System boot initiated. */
3291 	data[8] = 20; /* Sensor num */
3292 	data[9] = (IPMI_ASSERTION << 7) | 0x6f;
3293 	data[10] = val;
3294 	rv = mc_new_event(bmc_mc, 0x02, data);
3295 	if (rv)
3296 	    sys->log(sys, OS_ERROR, NULL,
3297 		     "MVMOD: Unable to add reboot cause event: %s, "
3298 		     "event queue is probably full",
3299 		     strerror(rv));
3300 
3301     }
3302 
3303     rv = set_intval(RESET_REASON_FILE, 0);
3304     if (rv) {
3305 	sys->log(sys, OS_ERROR, NULL,
3306 		 "MVMOD: Unable to clear reset reason: %s",
3307 		 strerror(rv));
3308     }
3309 
3310     return rv;
3311 }
3312