/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*---------------------------------------------------------------------------
 *		
 * MODULE NAME:	noticeBuf
 *
 * DESCRIPTION:	Routines to queue and dequeue notices of messages 
 *		being passed between RCI tasks. These are used by the RCI
 *		message passing functions.
 *
 * AUTHOR/DATE:	John Lloyd, Fall 1987
 *
 * MODIFICATION HISTORY:
 *
 *--------------------------------------------------------------------------*/

#include "messageDefs.h"
#include "maskInterrupts.h"

#ifdef VXWORKS_CFG
#include "vxwCtrlTask.h"
extern int rciTaskId;
extern int rciSignalRefCount;	
#endif

#ifdef SGI_CFG
extern int rciTaskId;
extern int rciSignalRefCount;	
extern int rciCtrlTaskPid;
#endif

putNoticeAux (arg0, arg1)
int arg0, arg1;
{
	MSG_NOTICE *n = (MSG_NOTICE*)arg0;
	NOTICE_BUF *nb = (NOTICE_BUF*)arg1;
	int s, code, newFirst;

#ifdef vax
	s = splhigh();
#endif
	mutexBegin (&nb->mutex);

#if NOTICE_BUF_SIZE & (NOTICE_BUF_SIZE-1)
	newFirst = (nb->first + 1) % (NOTICE_BUF_SIZE);
#else
	newFirst = (nb->first + 1) & (NOTICE_BUF_SIZE-1);
#endif
	if (newFirst == nb->last)
	 { code = 0;
	 }
	else
	 { nb->buf[nb->first] = *n;
	   nb->first = newFirst;
	   code = 1;
	 }

	mutexEnd (&nb->mutex);
#ifdef vax
	splx (s);
#endif
	return (code);
}

putNotice (n, nb)
MSG_NOTICE *n;
NOTICE_BUF *nb;
{
	/* Puts a notice (of either a message delivered or of an
	   acknowledge that a message was received) into a ring
	   buffer.
	*/
	char *fxnName = "putNotice()";
	int code;

	if (!(MUTEX_VALID(&nb->mutex)))
	 { mutexAbort(fxnName, &nb->mutex);
	   return(-1);
	 }
/* IRIX: acheive mutex by blocking RCI task from running */
#ifdef VXWORKS_CFG
	 { int s;

	   if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { blockRciSignals();
	    }
	   s = VXINT_LOCK();
	   code = putNoticeAux ((int)n, (int)nb);
	   VXINT_UNLOCK(s);
	   if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { unblockRciSignals();
	    }
	 }
#else
#if defined(SGI_CFG)
	if (rciInKernelMode())
	 { code = putNoticeAux ((int)n, (int)nb);
	 }
	else
	 { if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { blockRciSignals();
	    }
	   blockproc (rciCtrlTaskPid);
	   code = putNoticeAux ((int)n, (int)nb);
	   unblockproc (rciCtrlTaskPid);
	   if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { unblockRciSignals();
	    }
	 }
#elif defined(LINUX_CFG)
	/* MS This needs to be added for Linux */
	if (rciInKernelMode())
	 { code = putNoticeAux ((int)n, (int)nb);
	 }
	else
	 { /* if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { blockRciSignals();
	    }
	   blockproc (rciCtrlTaskPid);
	   code = putNoticeAux ((int)n, (int)nb);
	   unblockproc (rciCtrlTaskPid);
	   if (rciTaskId == 0 && rciSignalRefCount > 0)
	    { unblockRciSignals();
	    } */
	 }

#else
	if (!rciInKernelMode())
	 { return (rciKrnlExec (putNoticeAux, (int)n, (int)nb));
	 }
	else
	 { MASK_INTERRUPTS;
	   code = putNoticeAux ((int)n, (int)nb);
	   UNMASK_INTERRUPTS;
	 }
#endif
#endif
	return (code);
}

getNotice (n, nb)
MSG_NOTICE *n;
NOTICE_BUF *nb;
{
	/* Retrieves an notice (of either an incoming message or
	   the acknowledgement of a message received) from a ring
	   buffer.
	*/

	int last;


	if ((last = nb->last) == nb->first)
  	 { return (0);
	 }
 	else
 	 { *n = nb->buf[last];
#if NOTICE_BUF_SIZE & (NOTICE_BUF_SIZE-1)
	   nb->last = (last + 1) % (NOTICE_BUF_SIZE);
#else
	   nb->last = (last + 1) & (NOTICE_BUF_SIZE-1);
#endif
	   return (1);
	 }
}
