/* Original code (c) Acorn Computers Ltd, 1992-3 */

/* $Id: c.ModuleWrap 3.1 93/03/09 20:08:52 brian Exp $ */
/*
     Module wrapping for FS

*/

#include "FS.h"

/* Define for FS with interactive freespace support */
#define XFree_Register          0x644c0
#define XFree_DeRegister        0x644c1

/* Define TRACESERVICE in order to output trace of service calls */
/* #define TRACESERVICE */


/*
        This is the finalisation code
*/
static void fs_finalise
( void )
{
        _kernel_swi_regs r;

        /*
                Close your filing system down here and free up all your memory NOW.
                If you do not then all your filing system's junk is going to be left
                cluttering up the RMA as this module is just about to be killed.
        */
        fs_terminate();
        Terminate_FileEntrys();
#ifdef XFree_Register
        r.r[0] = FilingSystemInformationWord & 0xFF; /* Filing system numbe */
        _kernel_swi( XFree_DeRegister, &r, &r );
#endif
        r.r[0] = FSControl_RemoveFilingSystem;
        r.r[1] = (int)FilingSystemName;

        _kernel_swi( XOS_Bit | OS_FSControl, &r, &r );
}

/*
        Declare FS to FileSwitch
*/
static _kernel_oserror *declare_fs
( void *private_word )
{
        _kernel_oserror *err;
        _kernel_swi_regs r;
        int information_block[ Information_Block_Size ];

        information_block[0] = (int)FilingSystemName                    - (int)Image_RO_Base;
        information_block[1] = (int)ModuleName                          - (int)Image_RO_Base;
        information_block[2] = (int)&veneer_fsentry_open                - (int)Image_RO_Base;
        information_block[3] = (int)&veneer_fsentry_getbytes            - (int)Image_RO_Base;
        information_block[4] = (int)&veneer_fsentry_putbytes            - (int)Image_RO_Base;
        information_block[5] = (int)&veneer_fsentry_args                - (int)Image_RO_Base;
        information_block[6] = (int)&veneer_fsentry_close               - (int)Image_RO_Base;
        information_block[7] = (int)&veneer_fsentry_file                - (int)Image_RO_Base;
        information_block[8] = FilingSystemInformationWord;
        information_block[9] = (int)&veneer_fsentry_func                - (int)Image_RO_Base;
        information_block[10] = (int)&veneer_fsentry_gbpb               - (int)Image_RO_Base;

        r.r[0] = FSControl_AddFilingSystem;
        r.r[1] = (int)Image_RO_Base;
        r.r[2] = (int)information_block - (int)Image_RO_Base;
        r.r[3] = (int)private_word;

        err = _kernel_swi( XOS_Bit | OS_FSControl, &r, &r );
#ifdef XFree_Register
        if ( !err )
        { r.r[0] = FilingSystemInformationWord & 0xFF; /* Filing system numbe */
          r.r[1] = (int)&veneer_fsentry_free;
          r.r[2] = (int)private_word;
          _kernel_swi( XFree_Register, &r, &r );
        }
#endif
        return err;
}

/*
        This is the initialisation code
*/
_kernel_oserror *fs_initialise
( char *cmd_tail, int podule_base, void *private_word )
{
        _kernel_oserror *err;
        /*
                These keep the compiler quiet.
        */
        cmd_tail = cmd_tail;
        podule_base = podule_base;

        /*
                Place your filing system's initialisation here. If an error occurs then
                you can skip the 'declaring yourself to FileSwitch' bit.
        */
        err = Initialise_FileEntrys( private_word );

        if ( !err )
          err = declare_fs( private_word );

        if ( !err )
          atexit( fs_finalise );

        return err;
}

/*
        Service call handler
*/

#ifdef TRACESERVICE
static struct {int svc; char *name;} svcs[] =
{
 {0x00,"Serviced"},
 {0x04,"UKCommand"},
 {0x06,"Error"},
 {0x07,"UKByte"},
 {0x08,"UKWord"},
 {0x09,"Help"},
 {0x0b,"ReleaseFIQ"},
 {0x0c,"ClaimFIQ"},
 {0x11,"Memory"},
 {0x12,"StartUpFS"},
 {0x27,"Reset"},
 {0x28,"UKConfig"},
 {0x29,"UKStatus"},
 {0x2a,"NewApplication"},
 {0x40,"FSRedclare"},
 {0x41,"Print"},
 {0x42,"LookupFileType"},
 {0x43,"International"},
 {0x44,"Keyhandler"},
 {0x45,"PreReset"},
 {0x46,"ModeChange"},
 {0x47,"ClaimFIQinBackground"},
 {0x48,"ReAllocatePorts"},
 {0x49,"StartWimp"},
 {0x4a,"StartedWimp"},
 {0x4b,"StartFiler"},
 {0x4c,"StartedFiler"},
 {0x4d,"PreModeChange"},
 {0x4e,"MemoryMoved"},
 {0x4f,"FilerDying"},
 {0x50,"ModeExtension"},
 {0x51,"ModeTranslation"},
 {0x52,"MouseTrap"},
 {0x53,"WimpCloseDown"},
 {0x54,"Sound"},
 {0x55,"NetFS"},
 {0x56,"EconetDying"},
 {0x57,"WimpReportError"},
 {-1,"Something else"}
};
#endif

void fs_service
( int service_number, _kernel_swi_regs *r, void *private_word )
{
#ifdef TRACESERVICE
{ int i;
 for (i=0;svcs[i].svc>=0;i++) if (svcs[i].svc==service_number)break;
 printf("Service_%s (%#x)%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\r\n",svcs[i].name,service_number,*r);
}
#endif
        r=r;
        switch( service_number )
        {
        case Service_FSRedeclare:
                declare_fs( private_word );
                break;
        /*
                Handle other service calls here
        */
        }
}
