/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "amigafork.h"

#include <exec/memory.h>
#include <exec/semaphores.h>
#include <exec/io.h>

#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/exall.h>


#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

#ifdef __GNUC__
extern void *SysBase;
extern void *DOSBase;

#include <inline/exec.h>
#include <inline/dos.h>
#endif /*__GNUC__*/

extern void newproc_code();

struct AFork
 {
  void *globalvector;
  void *ForkFunc;
  void *DeinitFunc;
  void *Structure;
 };

void *AmigaFork(void *ForkFunc,void *DeinitFunc,const void *Structure,
              unsigned long StructureSize,signed long priority,
              const unsigned char *procname)
 {
  struct AFork *afork;
  void *global;
  struct Process *proc;

  afork=AllocVec(sizeof(*afork),MEMF_PUBLIC);
  if (afork==NULL) return(NULL);

  __asm ("move.l A4,%0":"=r" (global):);

  afork->globalvector=global;
  afork->ForkFunc=ForkFunc;
  afork->DeinitFunc=DeinitFunc;

  afork->Structure=AllocVec(StructureSize,MEMF_PUBLIC);
  if (afork->Structure==NULL)
   {
    FreeVec(afork);
    return(NULL);
   }
   {
    const unsigned char *sptr;
    unsigned char *dptr;
    int i;
    sptr=Structure;
    dptr=afork->Structure;
    i=StructureSize;
    while (i>0)
     {
      --i;*(dptr++)=*(sptr++);
     }
   }

  Forbid();

  proc=CreateNewProcTags( NP_Entry, (unsigned long) newproc_code,
                 NP_StackSize,8192,
                 NP_Name,(unsigned long ) procname,
                 NP_Priority,priority,
                 TAG_DONE);

  if (proc==NULL)
   {
    Permit();
    FreeVec(afork->Structure);
    FreeVec(afork);
    return(NULL);
   }

  proc->pr_Task.tc_UserData=afork;
  Permit();

  return(proc);

 }
