/*
 *  FILE: timer.c
 *  Support routines for dealing with the timer device.
 *
 *  Public Domain, but keep my name in it as the original author.
 *  31-Aug-88	Jan Sven Trabandt   first release version
 *  31-Oct-88	Jan Sven Trabandt   most routines moved to timerstuff.c
 *				      so that minimal routines need to be
 *				      linked in when using stdstuff.c
 */


#define I_AM_TIMER
#include "gimmelib/gimmefuncs.h"

extern struct Device *TimerBase;


struct timerequest *accessTimer( unit, portptr )
    ULONG	    unit;
    struct MsgPort  **portptr;
{
    struct MsgPort	*timerport = NULL;
    struct timerequest	*tr;

#ifdef GIMME_WIMPY
    if( unit != UNIT_VBLANK && unit != UNIT_MICROHZ ) {
	return( NULL );
    }
#endif
    if( portptr && *portptr ) {
	timerport = *portptr;
    } else {
	timerport = CreatePort( NULL, 0L );
	if( portptr ) {
	    *portptr = timerport;
	}
    }
    if( !timerport ) {
	return( NULL );
    }
    tr = CreateExtIO( timerport, (ULONG)sizeof(struct timerequest) );
    if( !tr ) {
	DeletePort( timerport );
    } else {
	if( OpenDevice(TIMERNAME, unit, tr, 0L) ) {
	    DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
	    DeletePort( timerport );
	    return( NULL );
	}
    }
    TimerBase = tr->tr_node.io_Device;
    tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
    return( tr );
} /* accessTimer */


LONG releaseTimer( tr, saveport )
    register struct timerequest *tr;
    struct MsgPort  *saveport;
{
    struct MsgPort  *tport;
    LONG	    err;

#ifdef GIMME_WIMPY
    if( !tr ) {
	return( 0L );
    }
#endif
    tport = tr->tr_node.io_Message.mn_ReplyPort;
    if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
	if( err = AbortIO(tr) ) {
	    return( err );
	}
	Remove( tr );
    }
    CloseDevice( tr );
    DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
    if( !saveport && tport ) {
	DeletePort( tport );
    }
    return( 0L );
} /* releaseTimer */


struct timerequest *gimmeTimeRequest( trmaster )
    struct timerequest	*trmaster;
{
    register struct timerequest *tr;

#ifdef GIMME_WIMPY
    if( !trmaster ) {
	return( NULL );
    }
#endif
    tr = CreateExtIO( trmaster->tr_node.io_Message.mn_ReplyPort,
			(ULONG)sizeof(struct timerequest) );
    if( tr ) {
	tr->tr_node.io_Device = trmaster->tr_node.io_Device;
	tr->tr_node.io_Unit   = trmaster->tr_node.io_Unit;
	tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
    }
    return( tr );
} /* gimmeTimeRequest */


LONG getRidOfTimeRequest( tr )
    register struct timerequest *tr;
{
    LONG    err;

#ifdef GIMME_WIMPY
    if( !tr ) {
	return( 0L );
    }
#endif
    Forbid();
    tr->tr_node.io_Message.mn_ReplyPort = NULL;
    if( tr->tr_node.io_Message.mn_Node.ln_Type == NT_MESSAGE ) {
	if( err = AbortIO(tr) ) {
	    Permit();
	    return( err );
	}
	Remove( tr );
	tr->tr_node.io_Message.mn_Node.ln_Type = NT_FREEMSG;
    }
    Permit();
    DeleteExtIO( tr, (ULONG)sizeof(struct timerequest) );
    return( 0L );
} /* getRidOfTimeRequest */
