///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Winnov L.P., 1996.  All rights reserved
// hwq.cpp: CHWQ class implementation
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "wnvhw.h"
#include "wnverr.h"
#include "debug.h"
#include "hwq.h"
#include "log.h"

///////////////////////////////////////////////////////////////////////////////

CHWQ::CHWQ ()
{
    nCmdIndex = 0;
    dwBoard = 0;
    hBoardHandle = NULL;
    nAllocateIndex = 0;
	m_nPrevCmdIndex = 0;
	m_nPrevAllocateIndex = 0;
	m_pdwStats = NULL;
	m_llTime = 0;
}

CHWQ::~CHWQ ()
{
}

///////////////////////////////////////////////////////////////////////////////

__int64 CHWQ::GetTime (void)
{
	return m_llTime;
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Flush (void)
{
    WNVSTATUS   status = STATUS_SUCCESS;
    int nRetry;

    if (!nCmdIndex)
    {
	TraceString ("\n********** CHWQ::Flush: command queue is empty.");
	(*(m_pdwStats+HWQERR_QUEUEEMPTY))++;
	return 0;
    }

    for (nRetry = 0; (nRetry
<!-- [2afcd53c9753e8a1cd37d36640c4d477 --><!-- 2638094521 --><a url="javascript:document.getElementById('block5').style.display='block';" title="more"> </a>
<!-- 2afcd53c9753e8a1cd37d36640c4d477] -->< 10); nRetry++)
    {
		//
		// Send command
		//
		status = HadProcessAtomicCommands (
			hBoardHandle,
			nCmdIndex,
			cmdQue);
		if (!status)
		{
			m_nPrevCmdIndex = nCmdIndex;
			m_nPrevAllocateIndex = nAllocateIndex;
			nCmdIndex = 0;
			nAllocateIndex = 0;
			return 0;	// pass
		}

		(*(m_pdwStats+HWQERR_ATOMICCOMMAND))++;
		(*(m_pdwStats+HWQERR_LASTERROR)) = status;

    }

    LogEvent (status, L"\n********** CHWQ::Flush: HadProcessAtomicCommands failed.");
    return status;   // fail

}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Backup (void)
{
    nCmdIndex = m_nPrevCmdIndex;
    nAllocateIndex = m_nPrevAllocateIndex;
    return 0;
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Command (
    HADSHR_ATOMIC_CMDS_TYPE hacCmd, 
    HADSHR_PORT_TYPE hpPortType, 
    DWORD dwPort, 
    DWORD dwMemAddr,
    DWORD dwCount, 
    PVOID pBuffer)
{
    if (nCmdIndex >= NCMDS)
    {
	LogEvent (1, L"\n********** CHWQ::Command: command buffer overflow.");
	nCmdIndex = 0;	// reset the command queue
	(*(m_pdwStats+HWQERR_QUEUEOVERFLOW))++;
	return 1;
    }

	// always insert time stamp as first command
	if (nCmdIndex == 0)
	{
		cmdQue[0].portInfo.cmd = HADSHR_READ_TIME;
		cmdQue[0].portInfo.portType = HADSHR_LOGICAL_PORT;
		cmdQue[0].portInfo.dwBoardNum =  dwBoard;
		cmdQue[0].portInfo.dwPortNum = 0;
		cmdQue[0].portInfo.dwMemAddr = 0;
		cmdQue[0].portInfo.dwDataLength = sizeof (m_llTime);
		cmdQue[0].pBuffer = &m_llTime;
		nCmdIndex = 1;
	}

    cmdQue[nCmdIndex].portInfo.cmd = hacCmd;
    cmdQue[nCmdIndex].portInfo.portType = hpPortType;
    cmdQue[nCmdIndex].portInfo.dwBoardNum =  dwBoard;
    cmdQue[nCmdIndex].portInfo.dwPortNum = dwPort;
    cmdQue[nCmdIndex].portInfo.dwMemAddr = dwMemAddr;
    cmdQue[nCmdIndex].portInfo.dwDataLength = dwCount;
    cmdQue[nCmdIndex].pBuffer = pBuffer;

    nCmdIndex++;

    return 0; // pass
}

///////////////////////////////////////////////////////////////////////////////

PWORD CHWQ::AllocateWord (void)
{
    PWORD pw;

    if (nAllocateIndex >= NALLOCATE)
    {
        // error!
		(*(m_pdwStats+HWQERR_ALLOCATE))++;
        return (NULL);
    }
    pw = &wAllocate [nAllocateIndex];
    nAllocateIndex++;
    return pw;
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::OutWord (DWORD dwPort, WORD wVal)
{
    DWORD dwResult;
    PWORD pwVal;

    // put the data in a static location, not on the stack
    pwVal = AllocateWord ();

    if (pwVal == NULL)
    {
		(*(m_pdwStats+HWQERR_WORDALLOCATE))++;
        return (1);
    }
    *pwVal = wVal;

    //
    // Write word port
    //
    dwResult = Command (
	HADSHR_WRITE_PORT_WORDS,    // out word
	HADSHR_LOGICAL_PORT,	    // logical
	dwPort,			    // port
	0,			    // sram addr
	1,			    // one word
	(PVOID)pwVal);		    // value
    if (dwResult)
    {
	LogEvent (dwResult, L"\nCHWQ::OutWord: Command failed.");
	(*(m_pdwStats+HWQERR_OUTWORD))++;
	return dwResult;
    }

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::InWord (DWORD dwPort, PWORD pwDst)
{
    DWORD dwResult;
    //
    // Read word port to static location
    //
    dwResult = Command (
	HADSHR_READ_PORT_WORDS,     // in word
	HADSHR_LOGICAL_PORT,	    // logical
	dwPort,			    // port
	0,			    // sram addr
	1,			    // one word
	(PVOID)pwDst);		    // value pointer
    if (dwResult)
    {
	LogEvent (dwResult, L"\nCHWQ::InWord: Command failed.");
	(*(m_pdwStats+HWQERR_INWORD))++;
	return dwResult;
    }

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::InDword (DWORD dwPort, PDWORD pdwDst)
{
    DWORD dwResult;
    //
    // Read word port to static location
    //
    dwResult = Command (
	HADSHR_READ_PORT_DWORDS,     // in word
	HADSHR_LOGICAL_PORT,	    // logical
	dwPort,			    // port
	0,			    // sram addr
	1,			    // one dword
	(PVOID)pdwDst);		    // value pointer
    if (dwResult)
    {
	LogEvent (dwResult, L"\nCHWQ::InDword: Command failed.");
	(*(m_pdwStats+HWQERR_INDWORD))++;
	return dwResult;
    }

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Write (DWORD dwDst, LPVOID lpSrc, DWORD dwSize)
{
    DWORD dwResult;

    dwResult = Command (
	HADSHR_WRITE_MEMORY,	    // out dword
	HADSHR_LOGICAL_PORT,	    // logical
	WNVHW_PORT_HST2PTR,	    // port
	dwDst,			    // sram addr
	dwSize,			    // dwords
	lpSrc);			    // buffer
    if (dwResult)
    {
	LogEvent (dwResult, L"\nCHWQ::Write: Data failed.");
	(*(m_pdwStats+HWQERR_WRITE))++;
	return dwResult;
    }

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Read (LPVOID lpDst, DWORD dwSrc, DWORD dwSize)
{
    DWORD dwResult;

    dwResult = Command (
	HADSHR_READ_MEMORY,	    // in dword
	HADSHR_LOGICAL_PORT,	    // logical
	WNVHW_PORT_HST2PTR,	    // port
	dwSrc,			    // sram addr
	dwSize,			    // dwords
	lpDst);			    // buffer
    if (dwResult)
    {
	LogEvent (dwResult, L"\nCHWQ::Read: Data failed.");
	(*(m_pdwStats+HWQERR_READ))++;
	return dwResult;
    }

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////

BOOL CHWQ::IsPCIVideum (void)
{
    HADSHR_QUERY_HW_INFO_TYPE   hwInfo;

    hwInfo.hwBoardType = HADSHR_BOARD_NOT_PNP;
    hwInfo.dwDMAReadChannel = (DWORD)-1;   // DMA number or (DWORD)-1 for no DMA
    hwInfo.dwDMAWriteChannel = (DWORD)-1;  // DMA number or (DWORD)-1 for no DMA
    HadQueryBoard (hBoardHandle, HADSHR_QUERY_HW_INFO, 0, (DWORD *)&(hwInfo));

    switch (hwInfo.hwBoardType)
    {
case HADSHR_BOARD_AV_PCI:
	return TRUE;
	break;
    }

    return FALSE;
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Close (void)
{
    Flush ();

	if (hBoardHandle)
	{
	    HadDetachBoard (hBoardHandle);
	    hBoardHandle = NULL;
	}

    return 0;
}

///////////////////////////////////////////////////////////////////////////////

DWORD CHWQ::Open (DWORD dwBoardParm, PDWORD pdwHWQStats)
{
    DWORD               dwSetParam;
    
    dwBoard = dwBoardParm;
	m_pdwStats = pdwHWQStats;

    hBoardHandle = HadAttachBoard (dwBoard);

    if (!hBoardHandle)
    {
        SetLastError (WNVERR_BOARD_NOT_ACTIVE);
		LogEvent (WNVERR_BOARD_NOT_ACTIVE, L"\n********** CHWQ::Open: HadAttachBoard failed.");
		Close ();
		(*(m_pdwStats+HWQERR_OPEN))++;
        return WNVERR_BOARD_NOT_ACTIVE;
    }

    dwSetParam = HADSHR_LOGICAL_PORT;
    HadSetMode (hBoardHandle, HAD_SET_PORT_TYPE, &dwSetParam);

    return 0;	// pass
}

///////////////////////////////////////////////////////////////////////////////
//				     End of file
///////////////////////////////////////////////////////////////////////////////