/* x-files main program */

#include "module.h"

#include "kernel.h"
#include "swis.h"
#include "chunks.h"
#include "fshook.h"

#include <stdio.h>
#include <stdlib.h>

static BOOL declared;
void *wsp;

extern void entry_Open(void);
extern void entry_GetBytes(void);
extern void entry_PutBytes(void);
extern void entry_Args(void);
extern void entry_Close(void);
extern void entry_File(void);
extern void entry_Func(void);
extern void entry_Ticker(void);
extern int  Image_RO_Base;

static void xFiles__finalise(void)
{
   if (declared)
   {
      _kernel_swi_regs regs;
   
      regs.r[0] = 36;
      regs.r[1] = xFiles_TYPE;
   
      (void) _kernel_swi(OS_FSControl, &regs, &regs);

      regs.r[0] = 0x1c;     /* TickerV */
      regs.r[1] = (int) entry_Ticker;
      regs.r[2] = (int) wsp;
      (void) _kernel_swi(OS_Release, &regs, &regs);

      xFiles_Tidy();
   }
}

static _kernel_oserror *xFiles__declareFS(void)
{
   _kernel_swi_regs regs;
   _kernel_oserror *err;
   static int fsInfoBlock[10];

   fsInfoBlock[ 0] = 0;
   fsInfoBlock[ 1] = xFiles_TYPE;
   fsInfoBlock[ 2] = (int) entry_Open         - Image_RO_Base;
   fsInfoBlock[ 3] = (int) entry_GetBytes     - Image_RO_Base;
   fsInfoBlock[ 4] = (int) entry_PutBytes     - Image_RO_Base;
   fsInfoBlock[ 5] = (int) entry_Args         - Image_RO_Base;
   fsInfoBlock[ 6] = (int) entry_Close        - Image_RO_Base;
   fsInfoBlock[ 7] = (int) entry_File         - Image_RO_Base;

   /* Next item duplicated because of worrying discrepency on crap
    * green PRM page 4-5.
    */

   fsInfoBlock[ 8] = (int) &entry_Func         - Image_RO_Base;
   fsInfoBlock[ 9] = (int) &entry_Func         - Image_RO_Base;

   regs.r[0] = 35;
   regs.r[1] = Image_RO_Base;
   regs.r[2] = (int) &fsInfoBlock - Image_RO_Base;
   regs.r[3] = (int) wsp;

   if (err = _kernel_swi(OS_FSControl, &regs, &regs), err)
      return err;

   regs.r[0] = 0x1c;     /* TickerV */
   regs.r[1] = (int) entry_Ticker;
   regs.r[2] = (int) wsp;
   if (err = _kernel_swi(OS_Claim, &regs, &regs), err)
      return err;

   declared = TRUE;

   return NULL;
}

void xFiles_service(int nService, _kernel_swi_regs *regs, void *ws)
{
   (void) regs;
   (void) ws;

   switch (nService)
   {
      case 0x00040:     /* Service_FSRedeclare */
         (void) xFiles__declareFS();
         break;
   }
}

_kernel_oserror *xFiles_initialise(char *cmd, int pod, void *ws)
{
   _kernel_oserror *err;
   (void) cmd;
   (void) pod;

   wsp = ws;

   atexit(xFiles__finalise);

#if 0
   if (err = InstallFSHook(), err)
      return err;
#endif      

   if (err = xFiles__declareFS(), err)
      return err;

   return xFiles_InitCache(16384);
}
