#define logMsg      printf

#include <stdio.h>
#include <string.h>
#include "dapi_define.h"
#include "dapi_parms.h"
#include "bme_app.h"
#include "bmehwapi.h"
                  
BYTE bDataAckPending;
BYTE bDataReadPending;
BYTE HostCpuEndianType;
int			host_dma_delay;

extern tBmeStruct Bme[5];

extern void InitDmaChannel15 (tBmeStruct *bmeStruct);
extern void doDmaRead_diag (int, int, char *, int);
extern void iposDelay (void);
int	hostWriteBMEMemories(char *, char *, int , int , int , int);

char bigdst [0x2000];
char bigdst1[0x2000];

void wrm (int address, int len, int which, int mode)
{
	int i;

        if (mode) {
                for (i = 0; i < 0x2000; i++) 
			bigdst [i] = 0;

        } else {
		UINT16 * pusBuf =  (UINT16 *)bigdst;

                for (i = 0; i < len; i++) {
                	pusBuf [i] = 2*i;
                }
                        pusBuf[0] = 22;
                        pusBuf[1] = 24;
                        pusBuf[2] = 26;
                        pusBuf[3] = 28;
                        pusBuf[4] = 30;
                        pusBuf[5] = 32;
                        pusBuf[6] = 34;
                        pusBuf[7] = 36;
        }

	// do host dma write to bme mem
	hostWriteBMEMemories( (char *)address, (char *)bigdst, len, 1, 0, 0); 
}


void 
initHostIO(int endianType, int baseAddr)
{
	
	HostCpuEndianType  = endianType;
	Bme[1].BMEbaseAddr = baseAddr; /* memory mapped BME interface base address */

	InitDmaChannel15 (&Bme[1]);
	return;
}

int	
hostPIO_read(int address)
{
	int	data;
	
	bmePioRead (&Bme[1], address, (BYTE *)&data);
	return(data);	
}

int	
hostPIO_write(int address, int data)
{

   	bmePioWrite (&Bme[1], address, (BYTE *)&data);
   	return(1);   
}

int 
waitforDMA_Done()
{
	BYTE bDmaStatus = 0;
	int iCount = 0; 
	UINT32 data = 0;


	while (1) {
		/* read DMA_STATUS_PORT */
		bDmaStatus = bmeRdStatus (&Bme[1]);
		
		/* check if it is DMA_WRITE_DONE interrupt */
		if (bDmaStatus & DW_H_DMA_WRITE_DONE) {
			/* if set, clear the status */
			bmeClrStatus (&Bme[1], CLR_DW_H_DMA_WRITE_DONE);
			data = 0x00000000;  
#ifdef BME_CPE_20
			bmePioWrite (&Bme[1], DMA_CCR(0, DMA_CH_15), (BYTE *)&data);
#else
			bmePioWrite (&Bme[1], DMA_CCR(0, DMA_CH_7), (BYTE *)&data);
#endif
			return(1);			
		} else {
			/* if not set, wait for sometime & then poll again */
			iCount++;
			if (iCount < 0x20 && iCount>0x10)
				iposDelay();	
			else if(iCount>=0x20){
				/* read DMA_CCR reg */
#ifdef BME_CPE_20
				bmePioRead (&Bme[1], DMA_CCR(0, DMA_CH_7), (BYTE *)&data);
#else
				bmePioRead (&Bme[1], DMA_CCR(0, DMA_CH_15), (BYTE *)&data);
#endif
				printf ("\nDMA_CCR 0x%08lx", data);
				printf ("\nDMA status : 0x%x failure", bDmaStatus);				
				return 0;
			}
		}	
	}

}


#define MAX_LEN_PER_XFER	(256)

int	
hostWriteBMEMemories(char *dst, char *src, int len, int write_mode, int isFifo, int bmeChNum)
// does host dma write to bme mem
//    dst : address in bme's accessible by dma 
//    src : address in host's mem 
//    len : num bytes to dma 
//    write_mode : if 1, then wait for dma to complete before returning 
//      NOTE: only write_mode = 1 has been tested. 
//    isFifo : if 1, then use fifo mode to access dst 
//    bmeChNum : if isFifo, then this chan num is used. 
{
	int		xfer_size;
	int		status;

	Bme[1].FifoFlag = isFifo;
	if (isFifo)
		dst = (char *)((int)dst + bmeChNum);
		
	while(1) {
		xfer_size = (len > MAX_LEN_PER_XFER) ? MAX_LEN_PER_XFER : len;
		bmeWrMemory (&Bme[1], (int)dst,  src, xfer_size);
		if (write_mode == 1) {
			status = waitforDMA_Done();
			if(status == 0)	 {
				printf("\n host write DMA took too long");	
				return(0);
			}
		}
		
		if (host_dma_delay > 0)
			iposDelay();
		len -= xfer_size;
		if (!isFifo)
			dst += xfer_size;
		src += xfer_size;
		if (len <= 0)
			break;				
	}

	return(1);	                                     
}


int	
hostReadBMEMemories(char *dst, char *src, int len, int read_mode, int isFifo, int bmeChNum)
// does host dma Read from bme mem
//    dst : address in host's mem 
//    src : address in bme's accessible by dma 
//    len : num bytes to dma 
//    read_mode : if 1, then wait for dma to complete before returning 
//      NOTE: only read_mode = 1 has been tested. 
//    isFifo : if 1, then use fifo mode to access src 
//    bmeChNum : if isFifo, then this chan num is used. 
{
	BYTE 	bDmaStatus = 0;
	int  	xfer_size, iCount = 0;
	UINT32 	data = 0;


	Bme[1].FifoFlag = isFifo;
	if (isFifo)
		src = (char *)((int)src+bmeChNum);
    	
	while (1) {
		xfer_size = (len > MAX_LEN_PER_XFER) ? MAX_LEN_PER_XFER : len;
		/* initiate data transfer from memory to HIC_FIFO */
		bmeTrMemory (&Bme[1], (int)src, xfer_size);
		
        /* poll for DMA_DONE bit / DW_H status bit to set */
#ifdef BME_CPE_20
		bmePioRead (&Bme[1], DMA_CCR(0, DMA_CH_7), (BYTE *)&data);
#else
		bmePioRead (&Bme[1], DMA_CCR(0, DMA_CH_15), (BYTE *)&data);
#endif

		/* check if it is DMA_WRITE_DONE interrupt */
		if (read_mode == 1) {			
			doDmaRead_diag ((unsigned int)src, xfer_size, dst, isFifo);
			if (host_dma_delay>0)
				iposDelay();
			len -= xfer_size;
			dst += xfer_size;
			if (!isFifo)
				src += xfer_size;
			if (len <= 0)
				break;
		}
		else
		{
			iCount++;
			if (iCount < 0x200)
				iposDelay();	
			else
			{
				logMsg ("\nDMA status in hostReadBMEMemories: 0x%x failure", bDmaStatus);
				return 0;
			
			}
			
		}	
	}

	return(1);
}



