writehost.c 2.99 KB
/**************************************************************************
 *									  *
 *		 Copyright (C) 1995, Silicon Graphics, Inc.		  *
 *									  *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright law.  They  may  not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *									  *
 **************************************************************************/

#include <os.h>
#include <os_internal.h>
#include <rdb.h>
#include <ultraerror.h>

#ifndef _FINALROM

#ifndef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
#endif

static int		writeHostInitialized = 0;
static OSMesgQueue	writeHostMesgQueue;
static OSMesg		writeHostMesgBuf[1];


/*
 * Name:   osWriteHost
 *
 * Description:
 *	Send nbytes of data starting at dramAddr to the host.
 *
 * CAUTION: Application must insure that only one call to osWriteHost at a time!!!
 *          Application on host must have opened /dev/u64_data before osWriteHost
 *          is called!
 *
 * How it works:
 *   An application on the indy must open /dev/u64_data before osWriteHost is called.
 *   After the device is opened, either osWriteHost, or uhReadGame may be called in either
 *   order. When uhReadGame is called by the host application, it will block until data 
 *   begins to arrive. When osWriteHost is called, it will send a message indicating 
 *   how many bytes it will send, before expecting an ack back. It will follow this message
 *   with the data. Once the data has been read out of the kernel driver buffers, and into
 *   the host application buffers, the kernel will send a signal back, acknowledging the 
 *   transfer, and indicating it is ready for the next block.
 *
 */
void osWriteHost(void *dramAddr, u32 nbytes)
{
    u8     *tPtr = (u8*)dramAddr;
    u32    sent;
    u8     dCount[3];
    u32    count;

#ifdef _DEBUG
    /*
     * Size must be non-zero
     */
    if (nbytes == 0)
    {
	__osError(ERR_OSWRITEHOST_SIZE, 1, nbytes);
	return;
    }
#endif

    if(!writeHostInitialized)
    {
	osCreateMesgQueue(&writeHostMesgQueue, writeHostMesgBuf, 1);
	osSetEventMesg(OS_EVENT_RDB_DATA_DONE, &writeHostMesgQueue, NULL);
	writeHostInitialized = 1;
    }

    while(nbytes)  /* break into blocks of RDB_DATA_MAX_BLOCK_SIZE */
    {              /* this is to insure that kernal buffers don't overflow */

	count = MIN(nbytes,RDB_DATA_MAX_BLOCK_SIZE);
	dCount[0] = (u8)((count & 0x00FF0000) >> 16);
	dCount[1] = (u8)((count & 0x0000FF00) >> 8);
	dCount[2] = (u8)(count & 0x000000FF);
	
	sent = 0;
	while(sent < 3)
	    sent += __osRdbSend(&dCount[sent],3-sent,RDB_TYPE_GtoH_DATA_CT);
	
	sent = 0;
	while(sent < count)
	    sent += __osRdbSend(&tPtr[sent],count-sent,RDB_TYPE_GtoH_DATA);

	nbytes -= count;
	tPtr += count;

	osRecvMesg(&writeHostMesgQueue, NULL, OS_MESG_BLOCK);
    }

}

#endif /* ifndef _FINALROM */