/*                          TaskRTimer.c                                  */
/* This Module Handles the Timer device interface for TaskTool's          */
/*                     Timed Refresh feature.                             */

#include <exec/types.h>
#include <devices/timer.h>
#include <proto/all.h>
#include <stdlib.h>
#include <stdio.h>

#include "TaskTool.h"

/*- Structures for this module. Static So Limited _just_ to this module-*/
static struct timerequest *tr = NULL;
static struct MsgPort *tport = NULL;
static BOOL IORSent = FALSE; /* Keeps track of if there is a pending message */


/*------------------------------------------------------------------------*/
VOID AbortTimer(VOID)
/*  Reset Timer Device- IORSent tells us if we have infact sent a request
 *  so we only AbortIO() if TRUE, we then wait for a reply.
 */

{
    if (IORSent) {
        AbortIO(&(tr->tr_node)); /* ...Abort request */
        WaitIO(&(tr->tr_node));

        while(GetMsg(tport));
    }
}

/*------------------------------------------------------------------------*/
VOID CloseTimer(VOID)
/* Closes Timer */
{
    AbortTimer();

    if (tport) DeletePort(tport);
    CloseDevice((struct IORequest *)tr);
    DeleteExtIO((struct IORequest *)tr);
    IORSent=FALSE;
}

/*------------------------------------------------------------------------*/
struct MsgPort *
OpenTimer(VOID)
/*  Opens timer device ready for Timer Requests. If successful Returns
 *  pointer to the MsgPort that the timer.device will reply to.
 */
{
    LONG error;

    tport=CreatePort(0,0);

    if (tport == NULL)  return(NULL);

    tr = (struct timerequest *)
        CreateExtIO( tport, sizeof( struct timerequest ) );

    if (tr == NULL)  return(NULL);

    error = OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)tr,0L);

    if (error) {
        CloseTimer();
        return(NULL);
    }

    return(tport);
}

/*------------------------------------------------------------------------*/
VOID SendTimerRequest(struct TimeInfo *TimerInfo)
/* Sends an asynchronous timer request to the timer device */
{
    AbortTimer();   /* Abort any pending IORequest */

    tr->tr_node.io_Command = TR_ADDREQUEST;
    tr->tr_time.tv_secs  = TISECONDS(TimerInfo);
    tr->tr_time.tv_micro = TIMICROS(TimerInfo);

                                    /* Note: if we were using the MICRO_HZ
                                     * Unit we would have to check that the
                                     * request was not for <2 uS
                                     */
    SendIO(&(tr->tr_node));
    IORSent=TRUE;
}