/*
 * DANG_BEGIN_MODULE
 *
 * Description:
 *   Initializes the environment modules
 *
 * DANG_END_MODULE
 *
 * $Date: $
 * $Source: $
 * $Revision: $
 * $State: $
 *
 * $Log: $
 */

#include "dosemu.h"
#include "env/setup.h"

struct env_info_struct {
  const char *name;
  Boolean    (*detect)(void);
  void       (*phase0_init)(void);
  void       (*phase1_init)(void);
  void       (*phase1_reset)(void);
  void       (*terminate)(void);
};

#define ENV_STRUCT(e) \
  { \
    #e, \
    env_##e##_detect, \
    env_##e##_phase0_init, \
    env_##e##_phase1_init, \
    env_##e##_phase1_reset, \
    env_##e##_term \
  }

/*
 * Setup the array of operating environments
 */

static struct env_info_struct env_devices[] = {
#ifdef CONFIG_ENV_X
  ENV_STRUCT(X),
#endif
#ifdef CONFIG_ENV_VGA
  ENV_STRUCT(vga),
#endif
  ENV_STRUCT(generic),
  { NULL, NULL, NULL, NULL, NULL, NULL }
};

/*
 * Pointer to the current environment
 */

static struct env_info_struct *cur_environ = NULL;


void env_phase0_init(void)
{
  c_printf("ENV: searching for current environment\n");
  for (cur_environ = env_devices; cur_environ->name; cur_environ++) {
    c_printf("ENV: checking for environment '%s'\n", cur_environ->name);
    if (cur_environ->detect && cur_environ->detect())
      break;
  }

  if (!cur_environ || !cur_environ->name) {
    error("ENV: unable to locate a valid environment!\n");
    leavedos(1);
  }

  c_printf("ENV: doing env_%s_phase0_init()\n", cur_environ->name);
  if (cur_environ->phase0_init)
    cur_environ->phase0_init();
}

void env_phase1_init(void)
{
  c_printf("ENV: doing env_%s_phase1_init()\n", cur_environ->name);
  if (cur_environ->phase1_init)
    cur_environ->phase1_init();

  c_printf("ENV: doing env_%s_phase1_reset()\n", cur_environ->name);
  if (cur_environ->phase1_reset)
    cur_environ->phase1_reset();
}

void env_phase1_reset(void)
{
  c_printf("ENV: doing env_%s_phase1_reset()\n", cur_environ->name);
  if (cur_environ->phase1_reset)
    cur_environ->phase1_reset();
}

void env_terminate(void)
{
  c_printf("ENV: doing env_%s_term()\n", cur_environ->name);
  if (cur_environ && cur_environ->terminate)
    cur_environ->terminate();
}
