/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*---------------------------------------------------------------------------
 *		
 * MODULE NAME:	download
 *
 * DESCRIPTION:	Routines to download the control portion of an RCI
 *		program into a slave CPU, and start the program executing.
 * 
 * AUTHOR/DATE:	John Lloyd, Fall 1987.
 *
 * MODIFICATION HISTORY:
 *
 *--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------

	    Routines to download programs and control execution.

	sendText (kafd, addr, size) -- sends 'size' bytes of text starting at
		'addr' to the cpu referenced by file descriptor 'kafd'.

	sendData (kafd, addr, size) -- sends 'size' bytes of data starting at
		'addr' to the cpu referenced by file descriptor 'kafd'.

	sendExec (kafd, entry, arg) -- tells the cpu referenced by the file
		descriptor  'kafd' to start executing function 'entry' with 
		argument 'arg'.	

	sendClear (kafd) -- tells the cpu referenced bu the file descriptor
		'kafd' to stop program execution and frees all memory
		resources.

  --------------------------------------------------------------------------*/

#include <sys/types.h>
#include <errno.h>

#include "../h/cdefs.h"
#include "../h/rciConfig.h"
#include "../h/errorCodes.h"

#if defined(uVAX_CFG)
#include "../sys.uVAX/rciext/kaioctl.h"		/* UNIX auxiliary CPU ioctls */
#endif

extern int errno;
static int pagesize;

/* ----- Error Messages. Defined externally to save space ----- */

static char *badIoctlMsg	= "%s -- %s ioctl failed, errno %d\n";
static char *badSegSizeMsg	= "%s -- bad segment size (%d) specified\n";
static char *noAuxCpusMsg	= "%s -- aux cpus not implemented\n";

sendText (kafd, addr, size)
int kafd;
void *addr;
int size;
{
	char *fxnName = "sendText()";

#if defined(uVAX_CFG)
       	struct blkadesc blad;
	struct blkdesc bld;

	if (pagesize == 0)
	 { pagesize = getpagesize();
	 }
	if (size <= 0)
	 { errorMsg (EInternal, badSegSizeMsg, fxnName, size);
	   return (-1);
	 }
	addr -= (int)addr%pagesize;
	size += (int)addr%pagesize + pagesize - ((int)addr+size)%pagesize;

	blad.size = size;
	blad.haddr = (char*)addr;
	blad.saddr = (char*)addr;
	if (ioctl (kafd, KAIOC_DOWNLOAD, &blad) < 0)
	 { errorMsg (errno == ENOMEM ? EMemory : EInternal, 	/* EAuxMem */
		     badIoctlMsg, fxnName, "DOWNLOAD", errno);
	   return (-1);
	 }
	bld.size = (int) size;
	bld.addr = (char*)addr;
	if (ioctl (kafd, KAIOC_READONLY, &bld) < 0)
	 { errorMsg (EInternal,
		     badIoctlMsg, fxnName, "READONLY", errno);
	   return (-1);
	 }
	return (1);
#else
	errorMsg (EInternal, noAuxCpusMsg, fxnName);
	return (-1);
#endif
}

sendData (kafd, addr, size)
int kafd;
void *addr;
int size;
{
	char *fxnName = "sendData()";

#if defined(uVAX_CFG)
	struct blkadesc blad;

	if (pagesize == 0)
	 { pagesize = getpagesize();
	 }
	if (size <= 0)
	 { errorMsg (EInternal, badSegSizeMsg, fxnName, size);
	   return (-1);
	 }
	addr -= (int)addr%pagesize;
	size += (int)addr%pagesize + pagesize - ((int)addr+size)%pagesize;

	blad.size = size;
	blad.haddr = (char*)addr;
	blad.saddr = (char*)addr;
	if (ioctl (kafd, KAIOC_DOWNLOAD, &blad) < 0)
	 { errorMsg (errno == ENOMEM ? EMemory : EInternal,	/* EAuxMem */
		     badIoctlMsg, fxnName, "DOWNLOAD", errno);
	   return (-1);
	 }
	return (1);
#else
	errorMsg (EInternal, noAuxCpusMsg, fxnName);
	return (-1);
#endif
}

sendExec (kafd, entrypt, arg)
int kafd;
int (*entrypt)();
int arg;
{
	int ep[2];
	char *fxnName = "sendExec()";

#if defined(uVAX_CFG)
	ep[0] = ((int)entrypt) + 2;
	ep[1] = arg;

	if (ioctl (kafd, KAIOC_START, ep) < 0)
	 { errorMsg (EInternal,
		     badIoctlMsg, fxnName, "START", errno);
	   return (-1);
	 }
	return (1);
#else
	errorMsg (EInternal, noAuxCpusMsg, fxnName);
	return (-1);
#endif

}

sendClear (kafd)
int kafd;
{
	char *fxnName = "sendClear()";

#if defined(uVAX_CFG)
	if (ioctl(kafd, KAIOC_CLEAR, 0) < 0)
	 { errorMsg (EInternal,
		     badIoctlMsg, fxnName, "CLEAR", errno);
	   return (-1);
	 }
	return (1);
#else
	errorMsg (EInternal, noAuxCpusMsg, fxnName);
	return (-1);
#endif
}
