/*
**    Name: rmameminit.c
**
**    Date: Sun Jan  5 16:30:54 2003
**
*/

#include "rmamem.h"
#include "osmodule.h"
#include "osheap.h"
#include "kernel.h"

int rmamem_status    = RMAMEM_UNITIALISED;
int rmamem_limit     = 1024 * 1024 * 16;
int rmamem_size      = 16384;
char rmamem_name[64] = "Heap";

RMAMemDetails rmamem_details;

void rmamem_init(int status)
    {
    _kernel_swi_regs regs;

    char *ptr;
/*
#ifdef __MemCheck_MemCheck_h
    MemCheck_Init();
    MemCheck_InterceptSCLStringFunctions();
    MemCheck_RedirectToFilenamef("ram::0.$.d");
    MemCheck_SetQuitting(0,0);
#endif

    rmamem_details.count = 0;
            rmamem_details.da   = -1;
            rmamem_details.base = -1;
            rmamem_details.add  = 0;
            rmamem_status = RMAMEM_MALLOC;
return;*/
/* If status is 3 force use of RMA if dynamic areas are not
** available to us */

/* Determine whether to use RMA or dynamic area */

    regs.r[0] = OSDynamicArea_Create;
    regs.r[1] = (os_dynamic_area_no)-1;
    regs.r[2] = rmamem_size;
    regs.r[3] = -1;
    regs.r[4] = 0x80;
    regs.r[5] = rmamem_limit;
    regs.r[6] = NULL;
    regs.r[7] = NULL;
    regs.r[8] = (int)rmamem_name;

    if (_kernel_swi(XOS_DynamicArea,&regs,&regs) == NULL)
        {
        rmamem_status       = RMAMEM_DYNAMICAREA;
        rmamem_details.da   = regs.r[1];
        rmamem_details.base = regs.r[3];
        }
    else
        {
        if (status == RMAMEM_RMA)
            {
            rmamem_status = RMAMEM_RMA;

            regs.r[0] = OSModule_Alloc;
            regs.r[3] = rmamem_size;
            _kernel_swi(XOS_Module,&regs,&regs);

            rmamem_details.da   = -1;
            rmamem_details.base = regs.r[2];
            rmamem_details.add  = 0;
            }
        else
            {
            rmamem_details.da   = -1;
            rmamem_details.base = -1;
            rmamem_details.add  = 0;
            rmamem_status = RMAMEM_MALLOC;
            }
        }

/* Initialise heap if necessary */

    if (rmamem_status == RMAMEM_DYNAMICAREA)
        {
        rmamem_details.heap_size = rmamem_size;

        regs.r[0] = OSHeap_Initialise;
        regs.r[1] = rmamem_details.base;
        regs.r[3] = rmamem_size;
        if (_kernel_swi(XOS_Heap,&regs,&regs) == NULL)
            {
/* Grab a dummy 8 byte block */

            regs.r[0] = OSHeap_Alloc;
            regs.r[1] = rmamem_details.base;
            regs.r[3] = 8;
            if (_kernel_swi(XOS_Heap,&regs,&regs) == NULL)
                {
/* Now read the size */

                ptr = (char *)regs.r[2];

                regs.r[0] = OSHeap_ReadSize;
                regs.r[1] = rmamem_details.base;
                regs.r[2] = (int)ptr;

                if (_kernel_swi(XOS_Heap,&regs,&regs) == NULL)
                    {
/* Calculate offset */

                    rmamem_details.add = regs.r[3] - 8;

                    if (rmamem_details.add < 0 )
                        {
                        rmamem_details.add = 0;
                        }
                    }

                rmafree(ptr);
                }
            }
        }

    atexit(rmamem_tidy);

    return;
    }


/* Free up memory */

void rmamem_tidy(void)
    {
    _kernel_swi_regs regs;

    if (rmamem_status == RMAMEM_DYNAMICAREA)
        {
        regs.r[0] = OSDynamicArea_Delete;
        regs.r[1] = rmamem_details.da;
        _kernel_swi(XOS_DynamicArea,&regs,&regs);
        }
    else if (rmamem_status == RMAMEM_RMA)
        {
        regs.r[0] = OSModule_Free;
        regs.r[2] = rmamem_details.base;
        _kernel_swi(XOS_Module,&regs,&regs);
        }

    rmamem_status = RMAMEM_UNITIALISED;
    }
