/*
    Copyright 2001 (c) by Claudio Jeker,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/VMemory/Attic/vm_object.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#include "Error.h"
#include "Assert.h"
#include "Support.h"

#include "vm.h"
#include "vm_alloc.h"
#include "vm_region.h"

#include "vm_object.h"

/* vm_manager_[un]add and vm_object_connect are used for the object
	 manager registry. 
		vm_object_connect: used to initalize and connect an object.
		vm_manager_add: add a manager for a specific type.
		vm_manager_unadd: remove a manager form a specific type.
 */
struct vm_manager_queue
{
  TAILQ_ENTRY(vm_manager_queue) managerq;
  unsigned short type;
  struct vm_manager manager;
};

TAILQ_HEAD(vm_manager_head, vm_manager_queue) vm_manager_queue;

int (*vm_object_attach)(struct vm_oref*);

static void startmngr(unsigned short type, struct vm_manager* manager, char* name)
{
  int err;

  err = vm_manager_add(type, manager);
  switch(err)
  {
  case VM_OK:
    printf("vm_manager_init: %s loaded\n", name);
    return;
  default:
    printf("vm_manager_init: %s failed (%i)\n", name, err);
    PANIC("vm_manager_add failed");
  }
}

int vm_manager_init(void)
{
  TAILQ_INIT(&vm_manager_queue);

  startmngr(VM_MANAGER_ANON, &vm_anon_manager, "anonymous pager");
  startmngr(VM_MANAGER_FILE, &vm_file_manager, "file manager");
  startmngr(VM_MANAGER_STEAL, &steal_manager, "page stealer");
  startmngr(VM_MANAGER_LOAN, &loan_manager, "loan-out manager");
  startmngr(VM_MANAGER_DMAP, &dmap_manager, "direct mapped manager");

  ASSERT(vm_anon_manager.attach != NULL);
  vm_object_attach = vm_anon_manager.attach;

  return VM_OK;
}

int vm_manager_add(unsigned short type, struct vm_manager* manager)
{
  struct vm_manager_queue* m;

  ASSERT(manager != NULL);

  if (type == VM_FREE)
  {
    return VM_INVAL;
  }
  TAILQ_FOREACH(&vm_manager_queue, m, managerq)
  if (m->type == type)
    return VM_INVAL;

  m = (struct vm_manager_queue*)vm_alloc_desc(sizeof(struct vm_manager_queue));
  if ( m == NULL )
  {
    PANIC("Ups, no memory left");
    return VM_NOMEM;
  }
  byteCopy(&m->manager, manager, sizeof(struct vm_manager));
  m->type = type;
  TAILQ_ADDTAIL(&vm_manager_queue, m, managerq);

  if ( manager->init != NULL )
    return manager->init();

  return VM_OK;
}

int vm_manager_unadd(unsigned short type)
{
  struct vm_manager_queue* m;

  TAILQ_FOREACH(&vm_manager_queue, m, managerq)
  {
    if (m->type == type)
    {
      TAILQ_REMOVE(&vm_manager_queue, m, managerq);
      vm_free_desc(m);
      return VM_OK;
    }
  }
  return VM_INVAL;
}

int vm_object_connect(int type,
                      struct vm_object_arg* arg, struct vm_oref* oref)
{
  struct vm_manager_queue* m;

  //-CJ	printf("vm_object_connect: type %04hx\n", type);
  //-CJ	vm_manager_list();

  TAILQ_FOREACH(&vm_manager_queue, m, managerq)
  {
    if (m->type == type)
    {
      /* found corresponding entry, no connect */
      ASSERT(m->manager.connect != NULL);
      return m->manager.connect(oref, arg);
    }
  }
  WARNING("unknown manager");
  return VM_INVAL;
}

void vm_manager_list(void)
{
  struct vm_manager_queue* m;

  printf("vm_manager_list: loaded managers\n");
  TAILQ_FOREACH(&vm_manager_queue, m, managerq)
  printf("\tmanager: %04hx\n", m->type);
}

int default_disconnect(struct vm_oref* oref)
{
  return VM_NIMP;
}

int default_share(struct vm_oref* dest, struct vm_oref* src, int flag)
{
  return VM_NIMP;
}

int default_attach(struct vm_oref* oref)
{
  return VM_NIMP;
}

int default_extend(struct vm_oref* oref, size_t size)
{
  return VM_NIMP;
}

int default_loan_alloc(struct vm_oref* oref, offset_t* pagestartPtr,
                       struct vm_page** pagePtr, int flags)
{
  return VM_NIMP;
}

int default_loan_dealloc(struct vm_oref* oref, offset_t pagestart)
{
  return VM_NIMP;
}

int default_loan_out(struct vm_oref* oref, offset_t pagestart,
                     struct vm_page** pagePtr, int* remove)
{
  return VM_NIMP;
}

int default_loan_in(struct vm_oref* oref, offset_t* pagestartPtr,
                    struct vm_page* page)
{
  return VM_NIMP;
}

int default_lookup(struct vm_oref* oref, offset_t offset, int type,
                   struct vm_page** page)
{
  return VM_NIMP;
}

int default_map(struct vm_oref* oref, offset_t offset, address_t virt, address_t phys)
{
  return VM_NIMP;
}

int default_get_type(struct vm_oref* oref, unsigned short* type, char** s)
{
  return VM_NIMP;
}

int default_get_arg(struct vm_oref* oref, struct vm_object_arg* arg)
{
  return VM_NIMP;
}
