#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <utility/tagitem.h>
#include <powerup/ppclib/interface.h>
#include <powerup/ppclib/message.h>
#include <powerup/ppclib/tasks.h>
#include <powerup/proto/ppc.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdio.h>
#include <string.h>

#define TEXT            "Text sent by M68k processor\n"
#define KILL_ID         0x4b494c4c

struct Library    *PPCLibBase;


int main(void)
{
  struct TagItem    MyTags[10];
  void              *PPCPort;
  void              *M68kPort;
  void              *ReplyPort;
  void              *StartupMsg;
  void              *M68kMsg;
  void              *PPCMsg;
  void              *Object;
  void              *Task;
  UBYTE             *Body;
  void              *MyTimerObject;

  printf("Opening ppc.library\n");
  if (PPCLibBase = OpenLibrary("ppc.library", 44))
  {
    printf("Loading PPC object\n");
    if (!(Object  = PPCLoadObject("msgtest.elf"))) {
      printf("Can't load msgtest.elf!\n");
      CloseLibrary(PPCLibBase);
      exit(15);
    }

    printf("Creating reply port\n");
    MyTags[0].ti_Tag  = TAG_DONE;
    if (ReplyPort = PPCCreatePort(MyTags))
    {
      if (StartupMsg = PPCCreateMessage(ReplyPort, 0))
      {
        printf("Creating PPC task\n");
        MyTags[0].ti_Tag  = PPCTASKTAG_STARTUP_MSG;
        MyTags[0].ti_Data =(ULONG) StartupMsg;

        MyTags[1].ti_Tag  = PPCTASKTAG_STARTUP_MSGDATA;
        MyTags[1].ti_Data = 0;

        MyTags[2].ti_Tag  = PPCTASKTAG_STARTUP_MSGLENGTH;
        MyTags[2].ti_Data = 0;

        MyTags[3].ti_Tag  = PPCTASKTAG_STARTUP_MSGID;
        MyTags[3].ti_Data = 0;

        MyTags[4].ti_Tag  = TAG_DONE;

        if (Task = PPCCreateTask(Object, MyTags))
        {
          printf("Allocating memory for message body\n");
          if (Body = PPCAllocVec(sizeof(TEXT), MEMF_PUBLIC))
          {
            printf("Creating message port...\n");
            MyTags[0].ti_Tag  = PPCPORTTAG_NAME;
            MyTags[0].ti_Data =(ULONG) "M68k port";
            MyTags[1].ti_Tag  = TAG_DONE;

            if (M68kPort = PPCCreatePort(MyTags))
            {
              printf("Creating message...\n");
              if (M68kMsg = PPCCreateMessage(ReplyPort, sizeof(TEXT)))
              {
                printf("Obtaining PPC port...\n");
                MyTags[0].ti_Tag  = PPCPORTTAG_NAME;
                MyTags[0].ti_Data =(ULONG) "PPC port";
                MyTags[1].ti_Tag  = TAG_DONE;

                while (!(PPCPort = PPCObtainPort(MyTags)));

                printf("Sending message...\n");
                strcpy((char *)Body, TEXT);
                PPCSendMessage(PPCPort,
                               M68kMsg,
                               Body,
                               sizeof(TEXT),
                               0x12345678);

                printf("Waiting for reply...\n");
                PPCWaitPort(ReplyPort);

                printf("Waiting for PPC message...\n");
                PPCWaitPort(M68kPort);

                printf("Getting message...\n");
                if (PPCMsg = PPCGetMessage(M68kPort))
                {
                  printf("Message: %s", (char *) PPCGetMessageAttr(PPCMsg, PPCMSGTAG_DATA));
                  printf("Reply message...\n");
                  PPCReplyMessage(PPCMsg);
                }
                else
                {
                  printf("Did not get PPC msg\n");
                }

                printf("Releasing PPC port...\n");
                PPCReleasePort(PPCPort);

                printf("Waiting for Task Finish Msg...\n");
                for (;;)
                {
                  if ((M68kMsg=PPCGetMessage(ReplyPort)) == StartupMsg)
                  {
                    printf("Ahh..the expected Startup=Finish Msg was received.\nNow we can savely free all resources.\n");
                    break;
                  }
                  else
                  {
                    printf("Some non replied Msg 0x%lx was found..wait\n",
                           M68kMsg);
                    PPCWaitPort(ReplyPort);
                  }
                }

                printf("Deleting message...\n");
                PPCDeleteMessage(M68kMsg);
              }
              else
              {
                printf("Could not create msg\n");
                PPCDeleteTask(Task);
              }
              printf("Deleting message port...\n");
              while (PPCDeletePort(M68kPort) == FALSE);
            }
            else
            {
              printf("Could not create M68k msg port\n");
              PPCDeleteTask(Task);
            }
            printf("Deleting reply port...\n");
            while (PPCDeletePort(ReplyPort) == FALSE);
          }
          else
          {
            printf("Could not alloc mem for msg body\n");
            PPCDeleteTask(Task);
          }
          printf("Freeing message body memory\n");
          PPCFreeVec(Body);
        }
        else
        {
          printf("Could not create PPC task\n");
        }
      }
      else
      {
        printf("Could not create PPC message\n");
      }
    }
    else
    {
      printf("Could not create reply port\n");
    }
    printf("Unloading PPC object\n");
    PPCUnLoadObject(Object);
    printf("Closing ppc.library\n");
    CloseLibrary(PPCLibBase);
  }
  else
  {
    printf("Could not open ppc.library v44+\n");
  }
}
