/* Msg2 and Msg2PPC.elf
 * 
 * show how to send a Msg from the M68k to the PPC and from the PPC to the M68k.
 * It also shows how to use the StartupMsg and PPCTask`s msgport functions to
 * simplify the init and close phase.
 *
 */
#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>
#include "time.h"
#include "time_protos.h"

#define TEXT            "Text sent by M68k processor\n"

struct StartupData
{
	void	*MsgPort;
};

extern struct Library	*SysBase;

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

  printf("Opening ppc.library\n");
  if (PPCLibBase = OpenLibrary("ppc.library", 44))
  {
    if (MyTimerObject=TimerCreateObject())
    {
      printf("Loading PPC object\n");
      if (ElfObject=PPCLoadObject("PROGDIR:Msg2PPC.elf"))
      {
        printf("Creating reply port\n");
        MyTags[0].ti_Tag	=	TAG_DONE;
        if (ReplyPort = PPCCreatePort(MyTags))
        {
          printf("Creating M68k port\n");
          if (M68kPort = PPCCreatePort(MyTags))
          {
            if (StartupMsg = PPCCreateMessage(ReplyPort, sizeof(struct StartupData)))
            {
              printf("Allocating StartupData\n");
              if (StartupData = PPCAllocVec(sizeof(struct StartupData), MEMF_ANY))
              {
                StartupData->MsgPort	=	M68kPort;

                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	=(ULONG) StartupData;

                MyTags[2].ti_Tag	=	PPCTASKTAG_STARTUP_MSGLENGTH;
                MyTags[2].ti_Data	=	sizeof(StartupData);

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

                MyTags[4].ti_Tag	=	PPCTASKTAG_MSGPORT;
                MyTags[4].ti_Data	=	TRUE;

                MyTags[5].ti_Tag	=	TAG_DONE;

                if (Task = PPCCreateTask(ElfObject, MyTags))
                {

                  if (PPCPort=(void*) PPCGetTaskAttrsTags(Task,
                                                          PPCTASKINFOTAG_MSGPORT,0,
                                                          TAG_END))
                  {
                    printf("Allocating memory for message body\n");
                    if (Body = PPCAllocVec(sizeof(TEXT), MEMF_PUBLIC))
                    {
                      printf("Creating message...");
                      TimerSetAttr(MyTimerObject,TIMERTAG_START);
                      if (PPCMsg = PPCCreateMessage(ReplyPort, sizeof(TEXT)))
                      {
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);

                        printf("Sending message...");
                        strcpy(Body, TEXT);
                        TimerSetAttr(MyTimerObject,TIMERTAG_START);
                        PPCSendMessage(PPCPort,
                                       PPCMsg,
                                       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 (M68kMsg = PPCGetMessage(M68kPort))
                        {
                          TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                          TimerShow(MyTimerObject);
                          Printf("Message: %s", (char *) PPCGetMessageAttr(M68kMsg, PPCMSGTAG_DATA));
                          printf("Reply message...");
                          TimerSetAttr(MyTimerObject,TIMERTAG_START);
                          PPCReplyMessage(M68kMsg);
                          TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                          TimerShow(MyTimerObject);
                        }
                        else
                        {
                          Printf("Did not get PPC msg\n");
                        }

                        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(PPCMsg);
                        TimerSetAttr(MyTimerObject,TIMERTAG_STOP);
                        TimerShow(MyTimerObject);
                      }
                      else
                      {
                        Printf("Could not create message\n");
                      }
                    }
                    else
                    {
                      Printf("Could not alloc mem for msg body\n");
                    }
                    printf("Freeing message body memory\n");
                    PPCFreeVec(Body); 
                  }
                  else
                  {
                    Printf("Could not find the PPCTask's msgport\n");
                  }
                }
                else
                {
                  Printf("Could not create PPC task\n");
                }
                PPCFreeVec(StartupData);
              }
              else
              {
                Printf("Could not alloc Startup Data\n");
              }
              PPCDeleteMessage(StartupMsg);
            }
            else
            {
              Printf("Could not create Startup message\n");
            }
            printf("Deleting m68k msg port...");
            PPCDeletePort(M68kPort);
          }
          else
          {
            Printf("Could not create m68k msg port\n");
          }
          printf("Deleting m68k reply port...");
          PPCDeletePort(ReplyPort);
        }
        printf("Unloading PPC object\n");
        PPCUnLoadObject(ElfObject);
      }
      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");
  }
}

