/*
 * nasd_linux_common.c
 *
 * NASD Common API Linux Kernel Module
 *
 * Authors: Sean Levy, Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#if defined(LINUX) && defined(KERNEL) && defined(MODULE) /* should always be */

#include <nasd/nasd_options.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_sys.h>
#include <linux/module.h>

#define NASD_EXPORT_SYMBOL(_symname_) EXPORT_SYMBOL(_symname_)

#include <nasd/nasd_linux_common_syms.ver.h>


int test = 0;
int loglvl = 3;
int test_delta = 10;
int syscall_no = NASD_LINUX_SYSCALL_NO;

MODULE_AUTHOR("Sean Levy <snl+@cs.cmu.edu>");
MODULE_DESCRIPTION("NASD Common API");
MODULE_PARM(loglvl, "i");
MODULE_PARM(syscall_no, "i");

extern void *sys_call_table[];
int (*old_syscall)(void *) = (int (*)(void *))0;

int init_module(void)
{
  extern int nasd_linux_kernel_default_log_lvl;
  extern void *sys_call_table[];
  extern int sys_ni_syscall(void); /* XXX ??? ? where the XXXX does this get */
					/* exported? it's in System.map, but */
					/* i can't find the header file that */
					/* declares it. */

  nasd_linux_kernel_default_log_lvl = loglvl;
#if 0
  /* We'd like to do it this way, but sys_ni_syscall is not exported by
     the kernel, so we can't.  Instead, we blindly replace the system
     call entry for the number we get passed in, which defaults to
     our standard 247.  If this is not right, then the system will
     surely crash in a horrible way. */
  if (sys_call_table[NASD_LINUX_SYSCALL_NO] == sys_ni_syscall) {
    printk(KERN_ERR "nasd_common: syscall %d taken by %p - bugging out!\n",
	   NASD_LINUX_SYSCALL_NO, sys_call_table[NASD_LINUX_SYSCALL_NO]);
    return -EBUSY;
  }
#else /* !0 */
  /* Yeah, baby!  You go, girl! */
  old_syscall = sys_call_table[syscall_no];
  sys_call_table[syscall_no] = (void *)nasd_srv;
  printk(KERN_INFO "nasd_common: took over syscall %d (was %p, is now %p)\n",
	 syscall_no, old_syscall, sys_call_table[syscall_no]);
#endif /* 0 */
  /* We are now wired in to the kernel via our syscall. */

  nasd_linux_kinit_once();

  return 0;
}

void cleanup_module(void)
{
  /* We know that we're ok blowing away our syscall because the module's
     use count gets incremented/decremented properly. */
  sys_call_table[syscall_no] = old_syscall;
  printk(KERN_INFO "nasd_common: syscall %d released, is now %p\n",
	 syscall_no, old_syscall);
}

#endif /* LINUX && KERNEL && MODULE */
