
/*
 *  LIB.C
 *
 *  Basic Library Resource Handling
 *
 *  NOTE: all data declarations should be initialized since we skip
 *	  normal C startup code (unless initial value is don't care)
 */

#include "defs.h"

Prototype __geta4 __stkargs long LibExpunge(long, Library *);


extern long ALibExpunge(), ALibClose(), ALibOpen();
extern long AOpenFifo(), ACloseFifo(), AReadFifo(), AWriteFifo();
extern long ARequestFifo(), ABufSizeFifo();

Library *LibBase = NULL;	/*  Library Base pointer    */
long	SegList  = 0;
ExecBase *SysBase  = NULL;
List	FifoList;
/* Iot	   Iot0;		   /*  timer request	       */

/*
 *    The Initialization routine is given only a seglist pointer.  Since
 *    we are NOT AUTOINIT we must construct and add the library ourselves
 *    and return either NULL or the library pointer.  Exec has Forbid()
 *    for us during the call.
 *
 *    If you have an extended library structure you must specify the size
 *    of the extended structure in MakeLibrary().
 */

__geta4 __stkargs Library *
LibInit(segment)
long segment;
{
    Library *lib;
    static const long (*Vectors[])() = {
	ALibOpen,
	ALibClose,
	ALibExpunge,
	NULL,
	AOpenFifo,
	ACloseFifo,
	AReadFifo,
	AWriteFifo,
	ARequestFifo,
	ABufSizeFifo,
	(long (*)())-1
    };

    SysBase = *(ExecBase **)4;

#ifdef NOTDEF
    Iot0.tr_node.io_Device = NULL;
    if (OpenDevice("timer.device", UNIT_MICROHZ, &Iot0, 0))
	return(NULL);
    Iot0.tr_node.io_Command = TR_ADDREQUEST;
    Iot0.tr_time.tv_secs = 0;
    Iot0.tr_time.tv_micro= 0;
#endif

    LibBase = lib = MakeLibrary(Vectors,NULL,NULL,sizeof(Library),NULL);
    lib->lib_Node.ln_Type = NT_LIBRARY;
    lib->lib_Node.ln_Name = LibName;
    lib->lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
    lib->lib_Version  = 37;
    lib->lib_Revision = 3;
    lib->lib_IdString = (APTR)LibId;
    SegList = segment;
    AddLibrary(lib);

    NewList((MaxList *)&FifoList);

    return(lib);
}

/*
 *    Open is given the library pointer and the version request.  Either
 *    return the library pointer or NULL.  Remove the DELAYED-EXPUNGE flag.
 *    Exec has Forbid() for us during the call.
 */

__geta4 __stkargs Library *
LibOpen(version, lib)
Library *lib;
long version;
{
    ++lib->lib_OpenCnt;
    lib->lib_Flags &= ~LIBF_DELEXP;
    return(lib);
}

/*
 *    Close is given the library pointer and the version request.  Be sure
 *    not to decrement the open count if already zero.	If the open count
 *    is or becomes zero AND there is a LIBF_DELEXP, we expunge the library
 *    and return the seglist.  Otherwise we return NULL.
 *
 *    Note that this routine never sets LIBF_DELEXP on its own.
 *
 *    Exec has Forbid() for us during the call.
 */

__geta4 __stkargs Library *
LibClose(dummy, lib)
long dummy;
Library *lib;
{
    if (lib->lib_OpenCnt && --lib->lib_OpenCnt)
	return(NULL);
    if (lib->lib_Flags & LIBF_DELEXP)
	return(LibExpunge(0, lib));
    return(NULL);
}

/*
 *    We expunge the library and return the Seglist ONLY if the open count
 *    is zero.	If the open count is not zero we set the DELAYED-EXPUNGE
 *    flag and return NULL.
 *
 *    Exec has Forbid() for us during the call.  NOTE ALSO that Expunge
 *    might be called from the memory allocator and thus we CANNOT DO A
 *    Wait() or otherwise take a long time to complete (straight from RKM).
 *
 *    Apparently RemLibrary(lib) calls our expunge routine and would
 *    therefore freeze if we called it ourselves.  As far as I can tell
 *    from RKM, LibExpunge(lib) must remove the library itself as shown
 *    below.
 */

__geta4 __stkargs long
LibExpunge(dummy, lib)
long dummy;
Library *lib;
{
    if (lib->lib_OpenCnt) {
	lib->lib_Flags |= LIBF_DELEXP;
	return(NULL);
    }
    Remove((MaxNode *)lib);
    FreeMem((char *)lib-lib->lib_NegSize, lib->lib_NegSize+lib->lib_PosSize);

#ifdef NOTDEF
    if (Iot0.tr_node.io_Device) {
	CloseDevice(&Iot0);
	Iot0.tr_node.io_Device = NULL;
    }
#endif

    return(SegList);
}

