/* daemon.c
   program that takes requests from dosemu and calls an interrupt
*/
/* 
 * Copyright (C) 1994, 1995 under GPL: Wayne Meissner
 * 
 * $Author: wayne $
 * $Date: 1995/01/17 13:50:22 $
 * $Source: /home/wayne/src/dosemu/daemon/RCS/daemon.c,v $
 * $Revision: 2.1 $
 * 
 */

#include <stdio.h>
/*#include "dosemu.h" */
#include "daemon.h"
/*
#define WANT_DEBUG 1
*/
/* used to save the ax register before altering it to call the dosemu func */
#define SAVE_AX daemon_comm.ax = _AX_
#define SAVE_FL asm  {\
  push ax\
  lahf\
  mov DGRP:_savfl, ah\
  pop ax\
}
#define RESTORE_FL asm {\
  push ax\
  mov ah, DGRP:_savfl\
  sahf\
  pop ax\
}

dump_regs () {
  printf ("ax = 0x%x \tbx = 0x%x \tcx = 0x%x \tdx = 0x%x\n si = 0x%x \tdi = 0x%x\n",
   _AX_, _BX_, _CX_, _DX_, _SI_, _DI_);
}
int i; /* misc var */
char savfl;
main() {
  struct daemon_comms daemon_comm;
  struct {
    char pad1[16384];
    char pad2[16384];
  } dosbuf;

  
  uint16 last_cmd; /* last command called */
  uint16 eseg;
  uint16 utmp16;
  
  printf ("ds = 0x%x\n", get_ds());
  printf ("&daemon_comm = 0x%x\n", daemon_comm);
  daemon_comm.seg = get_ds();
  daemon_comm.off = daemon_comm;
  sprintf (dosbuf, "DOSBUFFER ... testing 1 2 3%c", 0);
  
  /* init the dosemu side of the daemon */
  eseg = get_es();
  set_es (get_ds());
  _BX_ = daemon_comm;
  call_dosemu(DAEMON_FN(DAEMON_INIT));

  SAVE_FL;
  /* now start parsing command from dosemu and the client */
  for (;;) {
    switch (daemon_comm.command) {
     case DAEMON_EXIT:
      printf ("DAEMON_EXIT called\n");
      exit(-1);
      
      /* allocate some memory in the DS. Returns address in BX */
     case DAEMON_MALLOC:
      printf ("allocating %u bytes dos buffer memory\n", daemon_comm.arg);
      _BX_ = malloc (daemon_comm.arg);
      printf ("malloc memory = 0x%x\n", _BX_);
      daemon_comm.command = 0;
      break;

     case DAEMON_FREE:
      printf ("freeing memory: offset %x\n", daemon_comm.arg);
      free (daemon_comm.arg);
      daemon_comm.command = 0;
      break;
      
     case DAEMON_GETBUF:
      _BX_ = (int)dosbuf;
      _CX_ = sizeof (dosbuf);
      daemon_comm.command = 0;
      break;
      
     case DAEMON_SPAWN:
      system(daemon_comm.buf);
      daemon_comm.command = 0;
      break;
      
     case DAEMON_INT86:
#ifdef WANT_DEBUG
      printf ("calling irq 0x%x (%d)\n", daemon_comm.arg, daemon_comm.arg);
      dump_regs();
#endif
      int86(daemon_comm.arg);
      /* the next bit is a bit of screwing around to make sure flags
       * returned from the int86 call aren't overwritten later
       */
      SAVE_FL;
#ifdef WANT_DEBUG
      printf ("finished irq call\n");
      dump_regs();
#endif
      daemon_comm.command = 0;
      break;
      
     case DAEMON_DOCMD:
      daemon_comm.command = daemon_comm.arg;
#ifdef WANT_DEBUG
      printf ("DOCMD called: arg = %d\n", daemon_comm.arg);
#endif
      break;
      
     case DAEMON_RUNDOS:
      /* just busy loop */
#ifdef WANT_DEBUG
      printf ("running dos for %d cycles\n", daemon_comm.arg);
#endif
      while (daemon_comm.arg--)  {
	i = 10000;
	while (i--);
      }
      daemon_comm.command = 0;
      break;
      
     case DAEMON_RETRY:
      daemon_comm.command = last_cmd;
      break;
      
     default:
      daemon_comm.command = DAEMON_REPLY;
    }
    if (!daemon_comm.command)
      daemon_comm.command = DAEMON_REPLY;


    if (daemon_comm.command != DAEMON_RETRY)
      last_cmd = daemon_comm.command;
#ifdef WANT_DEBUG
    printf ("calling dosemu: cmd = %d, arg = %d\n",
	    daemon_comm.command, daemon_comm.arg);
    fflush(stdout);
#endif
    SAVE_AX;
    RESTORE_FL;
    call_dosemu(DAEMON_HELPER);
    SAVE_FL;
#ifdef WANT_DEBUG
    printf ("returned from dosemu: command = %d\n", daemon_comm.command);
#endif
  }
}
    
