/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/samples/ahafs/samplePrograms/kextEvProd/testKext.c 1.1.1.1 */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2009,2010              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* FUNCTIONS in this file testKext.c:
 *    init_kext
 *    ahafs_sampleKextEvProd_register
 *    chk_event
 *    mon_event
 *    _trigger_event
 *     trigger_event
 * PURPOSE: This set of functions consistutes an example of how one can code
 *     a kernel extension AHAFS event-producer.
 * COMPONENT of AHAFS v0.75b  2008/11/17.  N.Dubey, J.Jann
 */
#include <sys/types.h>
#include <stdlib.h>
#include <sys/m_types.h>
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/malloc.h>
#include <sys/uprintf.h>
#include <sys/syspest.h>
#include <sys/thread.h>
#include <sys/user.h>
#include <sys/pseg.h>
#include <sys/uthread.h>
#include <sys/cred.h>
#include <sys/lockl.h>
#include <sys/lock_alloc.h>
#include <sys/syspest.h>
#include <sys/kerrno.h>
#include <sys/ahafs_evProds.h>

char  *evProdName = "sampleKextEvProd";
int   AHAFS_EVPRODKEXT_ID=0;
int   TEST_EVMON_ON = 0;
int   TEST_EVMON_ID = 1;

/* Function prototypes */
int   init_kext (int, struct uio *);
kerrno_t  ahafs_sampleKextEvProd_register(int , ahafs_evMon_info_t *);
static int chk_event (char *name);
static int mon_event ();
static int _trigger_event();
int         trigger_event();

/*----------------------------------------------------------------------------
 * NAME:  init_kext(cmd, uio)
 * PURPOSE:
 *    This is the entry point of the kernel extension.
 * PARAMETERS: The input parameters "cmd" and "uio" are intialized by the
 *    function sysconfig(...) of the kernel-extension loading function "kexload"
 */
int
init_kext (int cmd, struct uio *uio)
{
    int          rc =0;
    kerrno_t     kern_rc;

    ahafs_evProd_info_t  evprod={0};

    if (cmd == CFG_INIT)
    {
        strncpy(evprod.evp_name, evProdName, strlen(evProdName)+1);
        evprod.evp_size =1;
        evprod.evp_caps = AHAFS_THRESHOLD_STATE|AHAFS_STKTRACE_AVAILABLE;
        evprod.evp_func = ahafs_sampleKextEvProd_register;
        evprod.evp_version = AHAFS_EVPROD_INFO_VERSION;

        kern_rc = ahafs_evprods(AHAFS_EVPROD_REG, (void *) &evprod, NULL);
        rc = KERROR2ERRNO(kern_rc);
        if (!rc)
        {
            AHAFS_EVPRODKEXT_ID = evprod.evp_id;
            uprintf ("AHAFS_EVPRODKEXT_ID : %d\n", AHAFS_EVPRODKEXT_ID);
        }
        uprintf ("CFG_INIT completed :rc = %d\n", rc);
    }
    else if (cmd == CFG_TERM)
    {
        uprintf ("AHAFS_EVPRODKEXT_ID : %d\n", AHAFS_EVPRODKEXT_ID);
        if (AHAFS_EVPRODKEXT_ID)
        {
            evprod.evp_id = AHAFS_EVPRODKEXT_ID;
            evprod.evp_version = AHAFS_EVPROD_INFO_VERSION;
            kern_rc = ahafs_evprods(AHAFS_EVPROD_UNREG, (void *) &evprod, NULL);
            rc = KERROR2ERRNO(kern_rc);
        }
        uprintf ("CFG_TERM completed :rc = %d\n", rc);
    }

  end:
    return (rc);
}

/*----------------------------------------------------------------------------
 * NAME:  ahafs_sampleKextEvProd_register( cmd, *evMonInfo)
 */
kerrno_t
ahafs_sampleKextEvProd_register(int cmd , ahafs_evMon_info_t *evMonInfo)
{
    int id;
    int rc = 0;
 
    switch (cmd)
    {

        /* Unregister monitoring all the events */
        case AHAFS_EVMON_DISABLE_ALL:
  
            BUGLPR(1, 1, ("Unregister monitoring all the events. \n"));
            TEST_EVMON_ON = 0;
            break;

        /* Unregister one particular event */
        case AHAFS_EVMON_DISABLE:
            if (! evMonInfo->evm_opqId)
            {
                rc = EINVAL;
                goto out;
            }
            BUGLPR(1, 1, ("Unregister monitoring the event with id = %d. \n",
                          evMonInfo->evm_opqId));
            TEST_EVMON_ON = 0;
            break;

        /* Validation of specified threshold */
        case AHAFS_EVMON_CHK_THRESH:
            rc = EINVAL;
            goto out;

        /* Allow the access to monitor the event */
        case AHAFS_EVMON_CHK_ACCESS:
            goto out;


        /* Get the id if the event is being monitored. */
        case AHAFS_EVMON_GET_ID:
            /* See whether event is being monitored */
            if ( ! TEST_EVMON_ON)
            {
                rc = ENOENT;
                goto out;
            }
            /* Verify the pathname of the event */
            id = chk_event(evMonInfo->evm_pathName);
            if (!id)
            {
                rc = ENOENT;
                goto out;
            }
           
            evMonInfo->evm_opqId = (ulong) TEST_EVMON_ID;
            BUGLPR(1, 1, ("opqId = %d .\n", id));
            break;

        /* Register the event */
        case AHAFS_EVMON_ENABLE:
            BUGLPR(1, 1, ("Register the event \n"));
            evMonInfo->evm_opqId = (ulong)TEST_EVMON_ID;
            evMonInfo->evm_curValue = -1;
            TEST_EVMON_ON = 1;
            break;
        default:
            rc = EINVAL;
            goto out;
    }
    
 out:
    return ( (kerrno_t) rc);
}

/*----------------------------------------------------------------------------
 * NAME:  chk_event (*name)
 */
static int
chk_event (char *name)
{
    int i;

    /* Remove the first character if it is '/' */
    if (*name == '/')
    {
            name++;
    }

    if (! strncmp(name, "sampleKextEvent", strlen(name)+1))
    {
            return ( TEST_EVMON_ID);
    }
    return (0);
}

/*----------------------------------------------------------------------------
 * NAME:    mon_event
 *
 * NOTE:  This is a dummy function which gives an idea how a section
 *        of code in the kernel extension can monitor the event and
 *        notify the AHAFS.
 */
static int
mon_event()
{
        int rc=0;
        int event_occurred = 0;
        
        if (TEST_EVMON_ON)  /* If event monitoring is required */
        {
            /* Start monitoring the event
             * ............
             */
            if (event_occurred)
            {
                /* Notify the AHAFS */
                rc=_trigger_event();
            }
        }
        return (rc);
}

/*----------------------------------------------------------------------------
 * NAME:    _trigger_event
 * PURPOSE: Sample Code to trigger the event
 */
static int
_trigger_event()
{
    ahafs_cbFn_info_t  cbFnInfo={0};
    int rc = ENOENT;
    kerrno_t  kern_rc;
    if (TEST_EVMON_ON)
    {
        cbFnInfo.cb_evProdId = AHAFS_EVPRODKEXT_ID;
        cbFnInfo.cb_opqId = (ulong) TEST_EVMON_ID;
        cbFnInfo.cb_version = AHAFS_CBFN_INFO_VERSION;

        BUGLPR(1, 1, ("Inform AHAFS about occurrence of the event. \n"));
        kern_rc = ahafs_evprods(AHAFS_EVPROD_CALLBACK, (void *) &cbFnInfo, NULL);
        rc = KERROR2ERRNO(kern_rc);      
    }
    return (rc);
}

/*----------------------------------------------------------------------------
 * NAME:    trigger_event
 * PURPOSE: Syscall to test ahafs_evprods(AHAFS_EVPROD_CALLBACK,..)
 */
int
trigger_event()
{
        int rc = 0;
        rc = _trigger_event();
        return (rc);
}

