/* **********************************************************
 * Copyright (C) 1998-2000 VMware, Inc.
 * All Rights Reserved
 * **********************************************************/

#include "driver-config.h"

#ifdef KERNEL_2_1
#  define EXPORT_SYMTAB
#  ifndef __KERNEL__
#    define __KERNEL__
#  endif
#endif

#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#ifdef KERNEL_2_1
#include <linux/poll.h>
#include <asm/uaccess.h>
#endif

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/mm.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/sockios.h>
#include <net/sock.h>

#define __KERNEL_SYSCALLS__
#include <asm/io.h>

#include <linux/proc_fs.h>
#include <linux/file.h>

#include <linux/config.h>

#include "vm_oui.h"
#include "vnet.h"
#include "vnetInt.h"


#if defined(CONFIG_PROC_FS) && defined(KERNEL_2_1)

#ifndef KERNEL_2_3_25
static void VNetProcModCount(struct inode *inode, int fill);
#endif

static VNetProcEntry *base = NULL;


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_Init --
 *
 *      Initialize the vnets procfs entries.
 *
 * Results: 
 *      errno.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

int
VNetProc_Init(void)
{
   int retval;

   retval = VNetProc_MakeEntry(&proc_root, "vmnet", S_IFDIR, &base);
   if (retval) {
      return retval;
   }

#ifndef KERNEL_2_3_25
   base->fill_inode = VNetProcModCount;
#endif

   return 0;
}


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_Cleanup --
 *
 *      Cleanup the vnets proc filesystem entries.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
VNetProc_Cleanup(void)
{
   VNetProc_RemoveEntry(base, &proc_root);
   base = NULL;
}

#ifndef KERNEL_2_3_25
/*
 *----------------------------------------------------------------------
 *
 * VNetProcModCount --
 *
 *      Callback for the vnets proc filesystem. This gets called when
 *      the inode goes into or out of service. For example when someone
 *      cd's to the vmnet directory. We must put a use count on the module
 *      so that its doesn't go away.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
void
VNetProcModCount(struct inode *inode,
                 int           fill)
{
   VNetIncrModCount((fill) ? 1 : -1);
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * VNetProc_MakeEntry --
 *
 *      Make an entry in the vnets proc file system.
 *
 * Results: 
 *      errno. If errno is 0 and ret is non NULL then ret is filled
 *      in with the resulting proc entry.
 *      
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

int
VNetProc_MakeEntry(VNetProcEntry  *parent,
                  char            *name,
                  int              mode,
                  VNetProcEntry  **ret)
{
   VNetProcEntry *ent;
#ifndef KERNEL_2_3_29
   int retval;

   if (ret) {
      *ret = NULL;
   }
   
   ent = kmalloc(sizeof(VNetProcEntry), GFP_KERNEL);
   if (!ent) {
      return -ENOMEM;
   }
   
   memset(ent, 0, sizeof(VNetProcEntry));

   if (mode == S_IFDIR) {
      mode |= S_IRUGO | S_IXUGO;
   } else if (mode == S_IFREG) {
      mode |= S_IRUGO;
   }
   
   ent->low_ino = 0;
   ent->name = name;
   ent->namelen = strlen(name);
   ent->mode = mode;

   if (S_ISDIR(mode)) {
      ent->nlink = 2;
   } else {
      ent->nlink = 1;
   }

   if (!parent) {
      parent = base;
   }
   
   retval = proc_register(parent, ent);
   if (retval) {
      kfree(ent);
      return retval;
   }

   if (ret) {
      *ret = ent;
   }
#else
   if (!parent) {
      parent = base;
   }
   ent = create_proc_entry(name, mode, parent);
   *ret = ent;
   if (!ent)
      return -ENOMEM;
#endif
   return 0;
}


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_RemoveEntry --
 *
 *      Remove a previously installed proc entry.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
VNetProc_RemoveEntry(VNetProcEntry *node,
                     VNetProcEntry *parent)
{
   if (!parent) {
      parent = base;
   }
   
   if (node) {
#ifndef KERNEL_2_3_29
      proc_unregister(parent, node->low_ino);
      kfree(node);
#else
      remove_proc_entry(node->name, parent);
#endif
   }
}


#else


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_Init --
 *
 *      Initialize the vnets procfs entries.
 *
 * Results: 
 *      errno.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

int
VNetProc_Init(void)
{
   return 0;
}


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_Cleanup --
 *
 *      Cleanup the vnets proc filesystem entries.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
VNetProc_Cleanup(void)
{
}


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_MakeEntry --
 *
 *      Make an entry in the vnets proc file system.
 *
 * Results: 
 *      errno. If errno is 0 and ret is non NULL then ret is filled
 *      in with the resulting proc entry.
 *      
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

int
VNetProc_MakeEntry(VNetProcEntry  *parent,
                  char            *name,
                  int              mode,
                  VNetProcEntry  **ret)
{
   return -ENXIO;
}


/*
 *----------------------------------------------------------------------
 *
 * VNetProc_RemoveEntry --
 *
 *      Remove a previously installed proc entry.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */

void
VNetProc_RemoveEntry(VNetProcEntry *node,
                     VNetProcEntry *parent)
{
}

#endif
