/* $Id: timer.c,v 1.1 93/02/15 23:29:54 tf Exp $ © 1992,93 by Tobias Ferber */

#include "timer.h"

/*
 * FUNCTION
 *
 *   open_timer -- open the timer.device
 *
 * SYNOPSIS
 *
 *   treq= open_timer(portname, portpri);
 *
 *   struct timerequest *open_timer(STRPTR, LONG);
 *
 * DESCRIPTION
 *
 *   This function opens the timer.device and returns a fully initialized
 *   timerequest structure (treq).
 *   open_timer() allocates both, a message port (replyport) including a
 *   signal bit and the timerequest structure.  The replyport will then be
 *   linked to treq in treq->tr_node.io_Message.mn_ReplyPort.
 *
 *   You *must* use close_timer() to free all this.
 *
 * INPUTS
 *
 *   portname - public name of the message port, or NULL if the port
 *              is not named. (ports should not be named if they're not
 *              used for rendez-vous between tasks)
 *   portpri  - Priority used for insertion into the public port list,
 *              normally 0.
 *
 * RESULT
 *
 *   treq     - a new timerequest structure ready for use, or NULL if
 *              either the port or the treq structure could not be
 *              created due to not enough memory or no available signal
 *              bit.
 */

struct timerequest *open_timer(STRPTR portname, long portpri)
{ struct timerequest *treq= (struct timerequest *)NULL;
  struct MsgPort *replyport= (struct MsgPort *)
    CreatePort(portname, portpri);
  if(replyport != (struct MsgPort *)NULL)
  { treq= (struct timerequest *)
      CreateExtIO(replyport,sizeof(struct timerequest));
    if(treq != (struct timerequest *)NULL)
    { long err= OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)treq,0L);
      if(err!=0)
      { DeleteExtIO((struct IOStdReq *)treq,sizeof(struct timerequest));
        treq= (struct timerequest *)NULL;
      }
    }
    if(treq == (struct timerequest *)NULL) /* not 'else' */
      DeletePort(replyport);
  }
  return(treq);
}

/*
 * FUNCTION
 *
 *   close_timer -- close the timer.device if opened via open_timer()
 *
 * SYNOPSIS
 *
 *   close_timer(treq);
 *
 *   VOID close_timer(struct timerequest *);
 *
 * DESCRIPTION
 *
 *   Frees up the timerequest structure and replyport as allocated by
 *   open_timer().
 *
 * INPUTS
 *
 *   treq - pointer to the timerequest structure which was returned
 *          from open_timer()
 */

void close_timer(struct timerequest *treq)
{ if(treq != (struct timerequest *)NULL)
  { struct MsgPort *mp= treq->tr_node.io_Message.mn_ReplyPort;
    if(AbortIO((struct IORequest *)treq) == 0)
      WaitIO((struct IORequest *)treq);
    CloseDevice((struct IORequest *)treq);
    DeleteExtIO((struct IOStdReq *)treq, sizeof(struct timerequest));
    if(mp != (struct MsgPort *)NULL)
      DeletePort(mp);
  }
}

/*
 * FUNCTION
 *
 *   queue_timer -- queue a timer request
 *
 * SYNOPSIS
 *
 *   queue_timer(treq, secs, micro);
 *
 *   VOID queue_timer(struct timerequest *, long, long);
 *
 * DESCRIPTION
 *
 *   Tells the timer device to signal after <secs> seconds and <micro>
 *   micro seconds.  This request is sent using SendIO() i.e. this
 *   function returns immediately.
 *
 * INPUTS
 *
 *   treq  - pointer to the timerequest structure
 *   secs  - #of seconds until timer.device signals treq's replyport
 *   micro - #of micro seconds until doom ;)
 */

void queue_timer(struct timerequest *treq, long secs, long micro)
{ if(treq != (struct timerequest *)NULL)
  { /*if(CheckIO((struct IORequest *)&treq->tr_node))*/
    { treq->tr_node.io_Command= TR_ADDREQUEST;
      treq->tr_node.io_Flags= 0;     /* not used (yet) */
      treq->tr_time.tv_secs  = secs;
      treq->tr_time.tv_micro = micro;
      SendIO((struct IORequest *)treq);
    }
  }
}

void purge_timer(struct timerequest *treq)
{ if(treq != (struct timerequest *)NULL)
  { if(AbortIO((struct IORequest *)treq) == 0)
      WaitIO((struct IORequest *)treq);
  }
}
