/*
 *   kstat() interface
 *     e.g. Solaris
 */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/hardware/cpu.h>

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

#include <kstat.h>
#include <sys/sysinfo.h>

extern kstat_ctl_t  *kstat_fd;
extern int           cpu_num;
int _cpu_status(char *state);

    /*
     * Initialise the list of CPUs on the system
     *   (including descriptions)
     */
void init_cpu_kstat( void ) {
    int               i, n=0, clock, state_begin;
    char              ctype[15], ftype[15], state[10];
    kstat_t          *ksp;
    kstat_named_t    *ks_data;
    netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 1 );
    strcpy(cpu->name, "Overall CPU statistics");

    if (kstat_fd == NULL)
        kstat_fd = kstat_open();
    kstat_chain_update( kstat_fd );

    DEBUGMSGTL(("cpu", "cpu_kstat init\n "));
    for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
        if (ksp->ks_flags & KSTAT_FLAG_INVALID)
            continue;
        if ((strcmp(ksp->ks_module, "cpu_info") == 0) &&
            (strcmp(ksp->ks_class,  "misc"    ) == 0)) {
            kstat_read(kstat_fd, ksp, NULL );
            n++;
            clock = 999999;
            memset(ctype, 0, sizeof(ctype));
            memset(ftype, 0, sizeof(ftype));
            memset(state, 0, sizeof(state));
            for (i=0, ks_data = ksp->ks_data; i < ksp->ks_ndata; i++, ks_data++) {
                if ( strcmp( ks_data->name, "state" ) == 0 ) {
                    strlcpy(state, ks_data->value.c, sizeof(state));
                } else if ( strcmp( ks_data->name, "state_begin" ) == 0 ) {
                    state_begin = ks_data->value.i32;
                } else if ( strcmp( ks_data->name, "cpu_type" ) == 0 ) {
                    strlcpy(ctype, ks_data->value.c, sizeof(ctype));
                } else if ( strcmp( ks_data->name, "fpu_type" ) == 0 ) {
                    strlcpy(ftype, ks_data->value.c, sizeof(ftype));
                } else if ( strcmp( ks_data->name, "clock_MHz" ) == 0 ) {
                    clock = ks_data->value.i32;
                }
            }
            i   = ksp->ks_instance;
            cpu = netsnmp_cpu_get_byIdx( i, 1 );
            sprintf( cpu->name,  "cpu%d", i );
            sprintf( cpu->descr, "CPU %d Sun %d MHz %s with %s FPU %s",
                                 i, clock, ctype, ftype, state  );
            cpu->status = _cpu_status(state); /* XXX - or in 'n_c_a_load' ? */
        }
    }
    cpu_num = i;
}


    /*
     * Load the latest CPU usage statistics
     */
int netsnmp_cpu_arch_load( netsnmp_cache *cache, void *magic ) {
    int               i=1;
    kstat_t          *ksp;
    cpu_stat_t        cs;
    netsnmp_cpu_info *cpu = netsnmp_cpu_get_byIdx( -1, 0 );
    netsnmp_cpu_info *cpu2;

        /* Clear overall stats, ready for summing individual CPUs */
    cpu->user_ticks = 0;
    cpu->idle_ticks = 0;
    cpu->kern_ticks = 0;
    cpu->wait_ticks = 0;
    cpu->sys2_ticks = 0;
    cpu->swapIn       = 0;
    cpu->swapOut      = 0;
    cpu->nInterrupts  = 0;
    cpu->nCtxSwitches = 0;

    kstat_chain_update( kstat_fd );
    DEBUGMSGTL(("cpu", "cpu_kstat load\n "));
    for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
        if (ksp->ks_flags & KSTAT_FLAG_INVALID)
            continue;
        if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
            i    = ksp->ks_instance;
            cpu2 = netsnmp_cpu_get_byIdx( i, 0 );
            if ( !cpu2 )  
                break;   /* or continue ? */    /* Skip new CPUs */
            if ((ksp->ks_type != KSTAT_TYPE_RAW) ||
                (ksp->ks_data_size != sizeof(cs))||
                (kstat_read(kstat_fd, ksp, &cs) == -1)) {
                DEBUGMSGTL(("cpu", "cpu_kstat load failed (%d)\n ", i));
                break;   /* or continue ? */
            }

            cpu2->user_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_USER];
            cpu2->idle_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_IDLE];
            cpu2->kern_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_KERNEL];
            cpu2->wait_ticks = (unsigned long long)cs.cpu_sysinfo.cpu[CPU_WAIT];
              /* or cs.cpu_sysinfo.wait[W_IO]+cs.cpu_sysinfo.wait[W_PIO] */
            cpu2->sys2_ticks = (unsigned long long)cpu2->kern_ticks+cpu2->wait_ticks;
                /* nice_ticks, intrpt_ticks, sirq_ticks unused */

                /* sum these for the overall stats */
            cpu->user_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_USER];
            cpu->idle_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_IDLE];
            cpu->kern_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_KERNEL];
            cpu->wait_ticks += (unsigned long long)cs.cpu_sysinfo.cpu[CPU_WAIT];
              /* or cs.cpu_sysinfo.wait[W_IO]+cs.cpu_sysinfo.wait[W_PIO] */
            cpu->sys2_ticks += (unsigned long long)cpu2->kern_ticks+cpu2->wait_ticks;

                /*
                 * Interrupt/Context Switch statistics
                 *   XXX - Do these really belong here ?
                 */
            cpu->swapIn       += (unsigned long long)cs.cpu_vminfo.swapin;
            cpu->swapOut      += (unsigned long long)cs.cpu_vminfo.swapout;
            cpu->pageIn       += (unsigned long long)cs.cpu_sysinfo.bread;
            cpu->pageOut      += (unsigned long long)cs.cpu_sysinfo.bwrite;
            cpu->nInterrupts  += (unsigned long long)cs.cpu_sysinfo.intr;
            cpu->nCtxSwitches += (unsigned long long)cs.cpu_sysinfo.pswitch;
        }
    }
    return 0;
}

int
_cpu_status( char *state)
{
    /*
     * hrDeviceStatus OBJECT-TYPE
     * SYNTAX     INTEGER {
     * unknown(1), running(2), warning(3), testing(4), down(5)
     * }
     */
    if (strcmp(state,"on-line")==0)
        { return 2; /* running */ } 
    else if (strcmp(state,"off-line")==0)
        { return 5; /* down */ }
    else if (strcmp(state,"missing")==0)
        { return 3; /* warning, went missing */ }
    else if (strcmp(state,"testing")==0)
        { return 4; /* somebody must be testing code somewhere */ }
    else
        { return 1; /* unknown */ }
}

