/*
**	Timer.c
**
**	Timer I/O support routines
**
**	Copyright © 1990-1997 by Olaf `Olsen' Barthel
**		All Rights Reserved
**
**	:ts=4
*/

#ifndef _GLOBAL_H
#include "Global.h"
#endif

/****************************************************************************/

	/* Current timer state. */

STATIC BOOL TimerRunning;

	/* DelayTime(LONG Secs,LONG Micros):
	 *
	 *	Delay for a given period of time.
	 */

VOID
DelayTime(
	ULONG Secs,
	ULONG Micros)
{
	ASSERT(Secs > 0 || Micros > 0);

	StopTime();

	if(Secs > 0 || Micros > 0)
	{
		StartTime(Secs,Micros);

		WaitTime();
	}
}

	/* WaitTime():
	 *
	 *	Wait for a pending time request to finish.
	 */

VOID
WaitTime(VOID)
{
	if(TimerRunning)
	{
		TimerRunning = FALSE;

		WaitIO((struct IORequest *)TimeRequest);
	}
}

	/* StopTime():
	 *
	 *	Stop the running timer.
	 */

VOID
StopTime(VOID)
{
	if(TimerRunning)
	{
		if(!CheckIO((struct IORequest *)TimeRequest))
			AbortIO((struct IORequest *)TimeRequest);
	}

	WaitTime();
}

	/* StartTime(LONG Secs,LONG Micros):
	 *
	 *	Start the timer asynchronously.
	 */

VOID
StartTime(
	ULONG Secs,
	ULONG Micros)
{
	ASSERT(Secs > 0 || Micros > 0);

	StopTime();

	if(Secs > 0 || Micros > 0)
	{
		TimeRequest->tr_node.io_Command	= TR_ADDREQUEST;
		TimeRequest->tr_time.tv_secs	= Secs;
		TimeRequest->tr_time.tv_micro	= Micros;

		ClrSignal(SIG_TIMER);

		SendIO((struct IORequest *)TimeRequest);

		TimerRunning = TRUE;
	}
}

/****************************************************************************/

VOID
DeleteTimeRequest(
	struct timerequest *	pTimeRequest,
	struct MsgPort *		pTimePort)
{
	if(pTimeRequest != NULL)
	{
		if(pTimeRequest->tr_node.io_Device != NULL)
			CloseDevice((struct IORequest *)pTimeRequest);

		DeleteIORequest((struct IORequest *)pTimeRequest);
	}

	DeleteMsgPort(pTimePort);
}

BOOL
CreateTimeRequest(
	LONG					lUnit,
	struct timerequest **	ppTimeRequest,
	struct MsgPort **		ppTimePort)
{
	struct MsgPort *TimePort;
	BOOL success = FALSE;

	ASSERT((lUnit == UNIT_VBLANK || lUnit == UNIT_MICROHZ) && ppTimeRequest != NULL && ppTimePort != NULL);

	TimePort = CreateMsgPort();
	if(TimePort != NULL)
	{
		struct timerequest *TimeRequest;

		TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(*TimeRequest));
		if(TimeRequest != NULL)
		{
			if(OpenDevice(TIMERNAME,lUnit,(struct IORequest *)TimeRequest,NULL) == OK)
			{
				*ppTimeRequest	= TimeRequest;
				*ppTimePort		= TimePort;

				success = TRUE;
			}

			if(NO success)
				DeleteIORequest((struct IORequest *)TimeRequest);
		}

		if(NO success)
			DeleteMsgPort(TimePort);
	}

	return(success);
}
