//==============================================================================
// Copyright 2006 Mistral Software Pvt Ltd.
//
// Use of this software is controlled by the terms and conditions found
// in the license agreement under which this software has been supplied.
//==============================================================================
// \file Dm644xSpiMdd.c
// \brief This file contains the Hardware independent function implementation
// which calls the PDD layer to do hardware specific things
// \version
// Includes
#include "Dm644xSpi.h"
// Debug Zones.
#ifdef DEBUG
#define DBG_INIT 0x0001
#define DBG_OPEN 0x0002
#define DBG_READ 0x0004
#define DBG_WRITE 0x0008
#define DBG_CLOSE 0x0010
#define DBG_IOCTL 0x0020
#define DBG_THREAD 0x0040
#define DBG_EVENTS 0x0080
#define DBG_CRITSEC 0x0100
#define DBG_FLOW 0x0200
#define DBG_IR 0x0400
#define DBG_NOTHING 0x0800
#define DBG_ALLOC 0x1000
#define DBG_FUNCTION 0x2000
#define DBG_WARNING 0x4000
#define DBG_ERROR 0x8000
DBGPARAM dpCurSettings = {
TEXT("Serial"), {
TEXT("Init"),TEXT("Open"),TEXT("Read"),TEXT("Write"),
TEXT("Close"),TEXT("Ioctl"),TEXT("Thread"),TEXT("Events"),
TEXT("CritSec"),TEXT("FlowCtrl"),TEXT("Infrared"),TEXT("User Read"),
TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error")},
0
};
#endif
// Define some internally used functions
BOOL SPI_Close(PSPI_OPEN_INFO pOpenHead);
BOOL SPI_Deinit(PSPI_INFO pSerialHead);
VOID EvaluateEventFlag(PVOID pHead, ULONG fdwEventMask);
//==============================================================================
//! \fn BOOL
//! DllEntry(
//! HINSTANCE hinstDll,
//! DWORD dwReason,
//! LPVOID lpReserved
//! )
//! \brief SPI Dllentry Function
//! \param HINSTANCE hinstDll,
//! DWORD dwReason,
//! LPVOID lpReserved
//! \return Boolean
//==============================================================================
BOOL
DllEntry(
HINSTANCE hinstDll,
DWORD dwReason,
LPVOID lpReserved
)
{
if ( dwReason == DLL_PROCESS_ATTACH )
{
DEBUGREGISTER(hinstDll);
DEBUGMSG (ZONE_INIT, (TEXT("SPI process attach\r\n")));
DisableThreadLibraryCalls((HMODULE) hinstDll);
}
if ( dwReason == DLL_PROCESS_DETACH )
{
DEBUGMSG (ZONE_INIT, (TEXT("process detach called\r\n")));
}
return TRUE;
}
//==============================================================================
//! \fn ULONG
//! DoTxData(
//! PSPI_INFO pSerialHead
//! )
//! \brief Transmits the next available data
//! \param PSPI_INFO pSerialHead
//! \return No of Bytes Transmitted
//==============================================================================
ULONG
DoTxData(
PSPI_INFO pSerialHead
)
{
// Number of bytes to be transmitted
ULONG Len;
ULONG BytesWritten;
DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes waiting for CritSec %x.\r\n"),
&(pSerialHead->TxBufferInfo.CS)));
TxEnterCS(pSerialHead);
DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes got CritSec %x.\r\n"),
&(pSerialHead->TxBufferInfo.CS)));
// If device was closed from under us, stop transmitting
if (!pSerialHead->OpenCnt)
{
DEBUGMSG (ZONE_THREAD|ZONE_WRITE ,
(TEXT("Device closed! Quit transmission!\r\n")));
DEBUGMSG (ZONE_WRITE,
(TEXT("SerialEventHandler: %d sent up-to-now.\n\r"),
pSerialHead->TxBytesSent));
pSerialHead->TxBufferInfo.Permissions = 0;
pSerialHead->TxBufferInfo.TxCharBuffer = NULL;
pSerialHead->TxBufferInfo.Length = 0;
TxRead(pSerialHead) = 0;
}
if (pSerialHead->TxBufferInfo.TxCharBuffer && TxBytesAvail(pSerialHead))
{
// Copy the present permissions
//DWORD oldPerm = SetProcPermissions(pSerialHead->TxBufferInfo.Permissions);
DEBUGMSG (ZONE_WRITE,
(TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
TxRead(pSerialHead), TxLength(pSerialHead),
TxBytesAvail(pSerialHead)));
// Number of bytes to be transmitted
Len = TxBytesAvail(pSerialHead);
DEBUGMSG (ZONE_WRITE, (TEXT("About to copy %d bytes\r\n"), Len));
// Tranfer data
BytesWritten = HWTxHandler(pSerialHead,
TxBuffRead(pSerialHead),
&Len);
DEBUGMSG (ZONE_WRITE, (TEXT("%d bytes actually copied.\r\n"), Len));
// Update Fifo info
pSerialHead->TxBytes += Len;
pSerialHead->TxBytesSent += Len;
TxRead(pSerialHead) += Len;
//SetProcPermissions(oldPerm);
SetEvent(pSerialHead->hTransmitEvent);
}
else
{
Len = 0;
BytesWritten = HWTxHandler(pSerialHead,
TxBuffRead(pSerialHead),
&Len);
DEBUGMSG (ZONE_WRITE, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
pSerialHead->TxBufferInfo.Permissions = 0;
pSerialHead->TxBufferInfo.TxCharBuffer = NULL;
pSerialHead->TxBufferInfo.Length = 0;
TxRead(pSerialHead) = 0;
SetEvent(pSerialHead->hTransmitEvent);
}
TxLeaveCS(pSerialHead);
DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
(TEXT("DoPutBytes released CritSec: %x.\r\n"),
&(pSerialHead->TxBufferInfo.CS)));
return BytesWritten;
}
//==============================================================================
//! \fn VOID
//! SerialEventHandler(
//! PSPI_INFO pSerialHead
//! )
//! \brief Handles all the serial events
//! \param PSPI_INFO pSerialHead
//! \return None
//==============================================================================
VOID
SerialEventHandler(
PSPI_INFO pSerialHead
)
{
ULONG RoomLeft = 0;
ULONG TotalLeft = 0;
DWORD it = SPI_INTR_NONE;
BOOL RxDataAvail = FALSE;
DEBUGMSG (ZONE_THREAD, (TEXT("+SPIEventHandler, pHead 0x%X\r\n"),
pSerialHead));
// We should not be here with Killthread flag asserted or
// without a serialevent
if (pSerialHead->KillRxThread ||
!pSerialHead->hSerialEvent)
{
DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread\r\n")));
SetEvent(pSerialHead->hKillDispatchThread);
ExitThread(0);
}
if (pSerialHead->pAccessOwner)
{
SPI_INC_USAGE_CNT(pSerialHead->pAccessOwner);
}
while (TRUE)
{
// Get the Interrupt type
if (!(it = HWGetIntrType (pSerialHead)))
{
DEBUGMSG (ZONE_THREAD,
(TEXT("SPIEventHandler, No Interrupt.\r\n")));
break;
}
DEBUGMSG (ZONE_THREAD,
(TEXT("SPIEventHandler, Interrupts 0x%X\r\n"), it));
if (it & SPI_INTR_RXOVR)
{
DEBUGMSG (ZONE_THREAD, (TEXT("Rx Overrun Interrupt, it:%x\r\n"), it));
SpiRxOverrunIntrHandler(pSerialHead);
}
if (it & SPI_INTR_RX)
{
// Get the index for Read and Write
register DWORD RxWIndex=RxWrite(pSerialHead);