#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/wait.h>
#include <linux/proc_fs.h>
#include <linux/vmalloc.h>

#include "led_platform.h"
#include <asm/mips-boards/hardware_error.h>
#include <asm/mach-ohio/led_config.h>
#include "led_hal.h"

#define MAX_HARDWARE_ERRORS     20

static char *hardware_errors[MAX_HARDWARE_ERRORS];
static unsigned int hardware_errors_count = 0;
static void *hardware_error_led;
static unsigned int hardware_error_init_done = 0;


/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
static int hardware_error_info(char *buf, char **start, off_t offset, int count, int *eof, void *data)        {                                                                                              
	int len = 0;                                                                                 
    int i;
    for ( i = 0 ; i < hardware_errors_count ; i++) {
	    len += sprintf(buf + len, "%s ", hardware_errors[i]);
    }
	return len;                                                                                
}                                                                                              

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void hardware_error_init(void) {
    printk("[hardware_error_init]\n");
    create_proc_read_entry("hardware_errors", 0, NULL, hardware_error_info, NULL);
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
void hardware_error_log(char *error_msg, unsigned int blink_code) {
    unsigned int len = strlen(error_msg) + 1;
    if(hardware_error_init_done == 0) {
        hardware_error_led = avalanche_led_register("error", 0);
    }

    if(blink_code)
        avalanche_led_action (hardware_error_led, blink_code + 1);

    if(hardware_errors_count >= MAX_HARDWARE_ERRORS)
        return;
    hardware_errors[hardware_errors_count] = vmalloc(len);
    if(hardware_errors[hardware_errors_count]) {
        memcpy(hardware_errors[hardware_errors_count], error_msg, len);
        hardware_errors_count++;
    }
}

/*------------------------------------------------------------------------------------------*\
\*------------------------------------------------------------------------------------------*/
EXPORT_SYMBOL(hardware_error_log);
