/*
 *  This file is part of ixemul.library for the Amiga.
 *  Copyright (C) 1991, 1992  Markus M. Wild
 *  Portions Copyright (C) 1994 Rafael W. Luebbert
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  $Id: ix_init.c,v 1.12 1994/07/11 22:16:47 rluebbert Exp $
 *
 *  $Log: ix_init.c,v $
 *  Revision 1.12  1994/07/11  22:16:47  rluebbert
 *  Removed arp.library from source - no longer needed.
 *
 *  Revision 1.11  1994/07/07  15:08:21  rluebbert
 *  10*NOFILE -> NOFILE
 *
 *  Revision 1.10  1994/07/07  15:03:00  rluebbert
 *  Removed ttyport dummy routines
 *
 *  Revision 1.9  1994/07/07  12:21:55  rluebbert
 *  *** empty log message ***
 *
 *  Revision 1.8  1994/07/07  11:44:26  rluebbert
 *  *** empty log message ***
 *
 *  Revision 1.7  1994/06/22  15:31:17  rluebbert
 *  Re-enable global environment variables
 *
 *  Revision 1.6  1994/06/19  15:12:59  rluebbert
 *  *** empty log message ***
 *
 *  Revision 1.4  1992/08/09  20:52:38  amiga
 *  change to new way of remembering open libraries
 *  get prepared to deal with ttys
 *
 *  Revision 1.3  1992/05/22  01:43:46  mwild
 *  initialize buddy allocator
 *
 * Revision 1.2  1992/05/18  00:49:07  mwild
 * changed async mp to be global
 *
 * Revision 1.1  1992/05/14  19:55:40  mwild
 * Initial revision
 *
 */

#define KERNEL
#include "ixemul.h"
#include "kprintf.h"

#include <exec/memory.h>

/* not changed after the library is initialized */
struct ixemul_base *ixemulbase = 0;

/* used by gnulib.. I was too lazy to convert that library as well ;-) */
void *MathIeeeDoubBasBase, *MathIeeeDoubTransBase,
     *MathIeeeSingBasBase;

struct ExecBase *SysBase;

/* global port for asynchronous packet notification */
struct MsgPort *ix_async_mp;
extern int mp_interrupt ();

/* global port for tty handling */
struct MsgPort *ix_tty_mp;
extern int tty_interrupt ();

/* since gcc can now statically initialize unions, they're quite useful;-) */
union lib {
  char *name;
  struct Library *base;
};


void
open_libraries (union lib *libs)
{
  SysBase = *(struct ExecBase **)4;
  /* on input `libs' contains a pointer to the library name, on output it
     contains the library base pointer */
  do
    libs->base = (struct Library *) OpenLibrary (libs->name, 0) ? : (struct Library *) -1;
  while ((++libs)->name);
}

void
close_libraries (union lib *libs)
{
  do
    if (libs->base != (struct Library *) -1)
      CloseLibrary (libs->base);
  while ((++libs)->base);
}

/* these are the libraries we are potentially interested in. Not finding
   a certain library doesn't mean we can't continue. */
static union lib ix_libs[] = {
  "dos.library",
  "intuition.library",
  "graphics.library",
  "mathieeesingbas.library",
  "mathieeedoubbas.library",
  "mathieeedoubtrans.library",
  0,
};
enum { DOS_LIB=0, INTUI_LIB, GFX_LIB, SINGB_LIB, DOUBB_LIB, DOUBT_LIB };


struct ixemul_base *
ix_init (struct ixemul_base *ixbase)
{
  int i;
  ixemulbase = ixbase;
  if(! check_hardware()) return 0;
  open_libraries (ix_libs);

  /* these ones are necessary and are very (!) unlikely to be missing */
  if (   ! (ixbase->ix_dos_base = ix_libs[DOS_LIB].base)
      || ! (ixbase->ix_intui_base = (struct IntuitionBase *) ix_libs[INTUI_LIB].base)
      || ! (ixbase->ix_gfx_base = (struct GfxBase *) ix_libs[GFX_LIB].base))
    {
      close_libraries (ix_libs);
      return 0;
    }
  /* those are more or less optional, and if not available cause 
     ix_patch_functions() to replace functions that need them by aborting
     functions */
  	ixbase->ix_ms_base = 
		MathIeeeSingBasBase = ix_libs[SINGB_LIB].base;
	ixbase->ix_md_base =
    		MathIeeeDoubBasBase = ix_libs[DOUBB_LIB].base;
	ixbase->ix_mdt_base =
		MathIeeeDoubTransBase = ix_libs[DOUBT_LIB].base;
  ixbase->ix_file_tab = (struct file *)
    AllocMem (NOFILE * sizeof(struct file), MEMF_PUBLIC | MEMF_CLEAR);
  ixbase->ix_fileNFILE = ixbase->ix_file_tab + NOFILE;
  ixbase->ix_lastf = ixbase->ix_file_tab;
  ixbase->ix_red_zone_size = 0; /* not enabled by default */
  ixbase->ix_membuf_limit = 0;
  ixbase->ix_fs_buf_factor = 64;
  ixbase->ix_watch_stack = 0;
  ixbase->ix_translate_dots = 1;
  ixbase->ix_translate_slash = 1;
  ixbase->ix_translate_symlinks = 0;
  ixbase->ix_force_translation = 0;
  ixbase->ix_ignore_global_env = 0;
  ixbase->ix_no_ces_then_open_console = 0;
  ixbase->ix_unix_pattern_matching = 0;
  ixbase->ix_unix_pattern_matching_case_sensitive = 0;
  ixbase->ix_no_insert_disk_requester = 0;
  /* initialize the list structures for the allocator */
  init_buddy ();
  /* patch our library to optimally adapt to the given hardware */
  ix_patch_functions (ixbase);

  ix_async_mp = (struct MsgPort *) CreateInterruptPort (0, 0, mp_interrupt, 0);
  ix_tty_mp = 0; /* (struct MsgPort *) CreateInterruptPort (0, 0, tty_interrupt, 0);*/

  if (ixbase->ix_file_tab && ix_async_mp /* && ix_tty_mp */)
    {
      InitSemaphore (& ixbase->ix_semaph);


      configure_context_switch ();

      NewList ((struct List *) &ixbase->ix_socket_list);

      for (i = 0; i < IX_NUM_SLEEP_QUEUES; i++)
        NewList ((struct List *) &ixbase->ix_sleep_queues[i]);

      /* pass the array over to ix_expunge () */
      ixbase->ix_libs = ix_libs;

      return ixbase;
    }
  if (ix_async_mp)
    DeleteInterruptPort (ix_async_mp);

/*  if (ix_tty_mp)
    DeleteInterruptPort (ix_tty_mp);*/
/*rwl*/
/*This formerly was without the 10, leaving 630 sizeof(struct file) unfreed!*/
/* That's alot of memory to eat up and not free... :) */
  if (ixbase->ix_file_tab)
    FreeMem (ixbase->ix_file_tab, NOFILE * sizeof(struct file));
  else
    ix_panic ("out of memory");

  close_libraries (ix_libs);
  
  return 0;
}      


void
ix_lock_base ()
{
  u_save.u_oldmask = u_save.p_sigmask;
  u_save.p_sigmask = ~0;
  ObtainSemaphore (& ix.ix_semaph);
}

void
ix_unlock_base ()
{
  ReleaseSemaphore (& ix.ix_semaph);
  u_save.p_sigmask = u_save.u_oldmask;
}

