/* $Id: lkst_mod_dmx.c,v 1.4 2002/10/16 04:18:16 ke-hata Exp $ */
/* addons/lkst_mod_maskset_dmx.c */

/************************************************************
 *
 * COPYRIGHT (C) HITACHI,LTD. 2002 ALL RIGHTS RESERVED.
 * WRITTEN BY HITACHI SYSTEMS DEVELOPMENT LABORATORY,
 *            HITACHI CENTRAL RESEARCH LABORATORY.
 *
 * Created by K.SERIZAWA <serizawa@sdl.hitachi.co.jp>
 *
 ************************************************************/

#error "lkst_mod_dmx is currently unsupported. (This function is obsolate.)"

/* includes */
#include<linux/version.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/string.h>	/* for memset() */
#include<linux/kernel.h>	/* for sscanf() */
#include <linux/sched.h>
#include<linux/lkst_private.h>

/* defines */

/* typedef, structs */

/* externals */

/* macros */

/* globals */

static lkst_maskset_id maskset_id_new = LKST_MASKSET_ID_RNOTHING;
static lkst_maskset_id maskset_id_orig = LKST_MASKSET_ID_RNOTHING;
static lkst_maskset_id maskset_id_base = LKST_MASKSET_ID_RALL;
static struct lkst_maskset_param	maskset_param;
static struct lkst_maskset_body 	body;

/* forward declarations */

static int	lkst_mod_init(void);
static void	lkst_mod_cleanup(void);

/* module init/cleanup */

module_init(lkst_mod_init);
module_exit(lkst_mod_cleanup);

MODULE_AUTHOR("K. Serizawa <serizawa@sdl.hitachi.co.jp>");
MODULE_DESCRIPTION("LKST module for dynamic maskset exchange.");
MODULE_LICENSE("GPL");
MODULE_PARM(maskset_id_base, "i");
MODULE_PARM_DESC(maskset_id_base, "ID of a maskset used as a template.");

/* inline functions */

/* functions */

int lkst_evhandler_test_ctrl(void *buf, size_t bufsize)
{
	int	i, ret=0;
	lkst_maskset_id maskset_id_toxchg;

	if ((buf)&&(1 == (ret = sscanf(buf, "%d", &i))))
		maskset_id_toxchg = i;
	else
		maskset_id_toxchg = maskset_id_orig;

	lkst_evhandler_maskset_xchg(NULL, 0, (lkst_arg_t)maskset_id_toxchg, 0, 0, 0);  //TODO: lkst_evhandlerprim_maskset_xchg()

	return (ret);
}

static int lkst_mod_init()
{
	int	retval;
	int	i;

	/* Register an event handler for panic dump. */
	retval = lkst_evhandler_register(LKST_EVHANDLER_ID_DMX,
					 LKST_EVHANDLER_NAME_DMX,
					 &lkst_entry_log,
					 &lkst_evhandler_test_ctrl);
	if (retval) {
		printk(KERN_ERR "cannot register event-handler function!\n");
		return (retval);
	}

	/* Initialize Maskset */
	body.len = LKST_MASKSET_TABLE_LEN_MAX;
				/* This ID can be defined as 
				   a module parameter. */
	maskset_param.id = maskset_id_base;
	maskset_param.maskset_size = LKST_MASKSET_SIZE(body.len);
	maskset_param.maskset = &body;

	/* copy from template. */
	if ((retval = lkst_maskset_read(&maskset_param)))
		return(retval);

	for (i = 0; i < body.len; i++) {
		if (body.entry[i].id == LKST_EVHANDLER_ID_DEFAULT) {
				/* replace handler */
			body.entry[i].id = 0;
		}
	}
	strcpy(body.name, "DynamicMasksetXchg");
	
	/* Write new maskset */
	maskset_param.id = LKST_MASKSET_ID_VOID;
	if ((retval = lkst_maskset_write(&maskset_param))) {
		lkst_mod_cleanup();
		return(retval);
	}
	maskset_id_new = maskset_param.id;

	/* Switch to the maskset. */
	maskset_id_orig = maskset_id_new;
	if ((retval = lkst_maskset_xchg(&maskset_id_orig))) {
		lkst_mod_cleanup();
		return(retval);
	}

	lkst_evhandler_maskset_xchg(NULL, 0, (lkst_arg_t)maskset_id_orig, 0, 0, 0);  //TODO: lkst_evhandlerprim_maskset_xchg()

	return (0);
}

static void lkst_mod_cleanup()
{
  		/* Switch to saved maskset. */
	if (maskset_id_orig != maskset_id_new)
		lkst_maskset_xchg(&maskset_id_orig);

		/* deregister the event handler. */
	lkst_evhandler_unregister((lkst_evhandler_id) LKST_EVHANDLER_ID_DMX);

	/* Clean up maskset */
	lkst_maskset_delete(maskset_id_new);

	/* Reset all hook */
	lkst_hook_reset_all();

	return;
}

/* END */
