#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 <proto/timer.h>
#include <stdio.h>
#include <string.h>
#include "time.h"
#include "time_protos.h"

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

extern struct Library	*SysBase;


int	main(void)
{
struct Library		*PPCLibBase;
struct Library		*TimerBase;
struct MsgPort		*timermp;
struct timerequest	*timerio;
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))
  {
    if (MyTimerObject=TimerCreateObject())
    {
      if ((timermp = CreatePort(NULL, 0)) != NULL)
      {
        if ((timerio = (struct timerequest*) CreateStdIO(timermp)) != NULL)
        {
          if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)timerio, 0) == 0L)
          {
            TimerBase	=	(struct Library*) timerio->tr_node.io_Device;

            printf("Loading PPC object\n");
            Object	=	PPCLoadObject("PROGDIR:Msg2oldPPC.elf");

            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	=	NULL;

                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...");
                    MyTags[0].ti_Tag	=	PPCPORTTAG_NAME;
                    MyTags[0].ti_Data	=(ULONG) "M68k port";
                    MyTags[1].ti_Tag	=	TAG_DONE;

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

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

                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

                        printf("Sending message...");
                        strcpy(Body, TEXT);
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCSendMessage(PPCPort,
                                       M68kMsg,
                                       Body,
                                       sizeof(TEXT),
                                       0x12345678);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

                        printf("Waiting for reply...");
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCWaitPort(ReplyPort);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

                        printf("Waiting for PPC message...");
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCWaitPort(M68kPort);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

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

                        printf("Releasing PPC port...");
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCReleasePort(PPCPort);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

                        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...");
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCDeleteMessage(M68kMsg);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);
                      }
                      else
                      {
                        Printf("Could not create msg\n");
                      }
                      printf("Deleting message port...");
                      TimerSetAttr(MyTimerObject,TIMERTAG_START);
                      while (PPCDeletePort(M68kPort) == FALSE);
                      TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                      TimerShow(MyTimerObject);
                    }
                    else
                    {
                      Printf("Could not create M68k msg port\n");
                    }
                    printf("Deleting reply port...");
                    TimerSetAttr(MyTimerObject,TIMERTAG_START);
                    while (PPCDeletePort(ReplyPort) == FALSE);
                    TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                    TimerShow(MyTimerObject);
                  }
                  else
                  {
                    Printf("Could not alloc mem for msg body\n");
                  }
                  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);
            CloseDevice((struct IORequest *)timerio);
          }
          DeleteStdIO((struct IOStdReq *)timerio);
        }
        DeletePort(timermp);
      }
      else
      {
        Printf("Could not load the elfobject\n");
      }
      TimerDeleteObject(MyTimerObject);
    }
    printf("Closing ppc.library\n");
    CloseLibrary(PPCLibBase);
  }
  else
  {
    Printf("Could not open ppc.library v44+\n");
  }
}

