/*
 *  This file is part of ixemul.library for the Amiga.
 *  Copyright (C) 1991, 1992  Markus M. Wild
 *
 *  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.
 */

#define KERNEL
#include "ixemul.h"
#include <signal.h>

#ifdef DEBUG
#define DP(a) kprintf a
#else
#define DP(a)
#endif

/* isn't defined when ifdef KERNEL */
void	(*signal())();

/*
 * ^F is a bail-out, if something really goes weird.. 
 */

#define SIGMASK ((1<<u.u_sync_mp->mp_SigBit) | SIGBREAKF_CTRL_F)

void
__wait_sync_packet(struct StandardPacket *sp)
{
  struct StandardPacket *prw;
  int omask;

  /* this is the synchronous way of dealing with packets that may
   * arrive at a port. */

  if (sp->sp_Msg.mn_Node.ln_Type != NT_MESSAGE) return;
 
  /* Have to guarantee, that a packet that we receive with GetPacket()
   * is set to NT_REPLYMSG before we allow interrupts again
   */
  omask = syscall (SYS_sigsetmask, ~0);

  for (;;)
    {
      if (prw = GetPacket(u.u_sync_mp))
        {
	   /* every application on the amiga sets the node-type of
	    * a reply-msg to NT_REPLYMSG, but DOS has its exception
	    * once again.. */
	  prw->sp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
          if (prw == sp) break;
        }
      else
        {
	  unsigned long res;

	  syscall (SYS_sigsetmask, omask);
	  res = Wait(SIGMASK);
	  omask = syscall (SYS_sigsetmask, ~0);
	  /* process our bail-out-signal */
	  if (res & SIGBREAKF_CTRL_F) break;
	}
    }
  
  syscall (SYS_sigsetmask, omask);
}


void
__wait_packet(struct StandardPacket *sp)
{
  /* have to make sure no interrupt is taken between we test and
   * call ix_sleep(), or ix_sleep() will never be awakend..
   * ix_sleep() calls Wait(), and thus breaks the Disable() */
  while (sp->sp_Msg.mn_Node.ln_Type == NT_MESSAGE)
    {
DP(("__wait_packet - "));
      Disable ();
      if (sp->sp_Msg.mn_Node.ln_Type == NT_MESSAGE)
        ix_sleep (sp);
      Enable ();
    }
}


int mp_interrupt (void) __attribute__ ((interrupt));

int
mp_interrupt (void)
{
  register struct MsgPort *_mp asm ("a1");
  register struct MsgPort *mp = _mp;
  register struct StandardPacket *prw;
  
  Disable ();
  while (prw = GetPacket (mp))
    {
      /* every application on the amiga sets the node-type of
       * a reply-msg to NT_REPLYMSG, but DOS has its exception
       * once again.. */
      prw->sp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
      
      /* wakeup any processes that might be interested in this packet */
      ix_wakeup (prw);
    }
  Enable ();

  return 0;
}
