⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nscfir.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
/*

  Copyright(c) 1998,1999 SIC/Hitachi,Ltd.

	Module Name:

		nscfir.c

	Revision History:

		26th May   1999		Released

*/
//#define OUTMSG

#include "nsc.h"
#include "nsctypes.h"
#include "firregs.h"

#include "cc.h"
/******************************************************************************
 * Modification Done by Maneesh Gupta
 *
 * S1.h has been replaced by platform.h 
 * Mobytel.h has been removed as it is no longer needed.
 *****************************************************************************/
//#include "mobytel.h"
/******************************************************************************
 * End of modification Done by Maneesh Gupta
 *****************************************************************************/

//#include "dma.h"


VOID NSC_FIR_ISR(IrDevice *thisDev, BOOLEAN *claimingInterrupt,
                 BOOLEAN *requireDeferredCallback)
{
USHORT IrsrVal;
UCHAR itsr;

    DBGISR((TEXT("==> NSC_FIR_ISR(0x%x)"), thisDev));

	if(READ_REGISTER_UCHAR(pISIRR) & CC_FIR_ISIRR_SIRMOD){
		*claimingInterrupt = FALSE;
		*requireDeferredCallback = FALSE;
		return;
	}
	WRITE_REGISTER_UCHAR(pIMSTCR, READ_REGISTER_UCHAR(pIMSTCR) & (CC_FIR_IMSTCR_TXEN|CC_FIR_IMSTCR_RXEN));

	if(READ_REGISTER_UCHAR(pIMSTSR) & (CC_FIR_IMSTSR_TMI|CC_FIR_IMSTSR_TXI|CC_FIR_IMSTSR_RXI)){
		if((READ_REGISTER_UCHAR(pIMSTSR) & CC_FIR_IMSTSR_RXI) && thisDev->portInfo.writePending==FALSE){
			IrsrVal = READ_REGISTER_UCHAR(pIRSR);


			if(IrsrVal & CC_FIR_IRSR_RFOVF){
				WRITE_REGISTER_UCHAR(pIRSTCR,CC_FIR_IRSTCR_RSTC_RXFIFO);
				RETAILMSG(1, (TEXT("ERROR NSC_FI_ISR1. Overrun.\r\n")));
			}else{
				if(IrsrVal & CC_FIR_IRSR_CRCER){
					RETAILMSG(1, (TEXT("ERROR NSC_FIR_ISR2. Frame Error.\r\n")));
				}
				if(IrsrVal & CC_FIR_IRSR_ABORT){
					RETAILMSG(1, (TEXT("ERROR NSC_FIR_ISR3. RxAbort.\r\n")));
				}
			}
			WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK1);
			thisDev->ReadRFPCount = READ_REGISTER_UCHAR(pIRRFPLR);
			thisDev->ReadRFPCount |= ((USHORT)READ_REGISTER_UCHAR(pIRRFPHR) << 8);
			WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK0);
			WRITE_REGISTER_UCHAR(pIRSTCR, CC_FIR_IRSTCR_RSTC_RXSCI);
			WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK2);
			WRITE_REGISTER_UCHAR(pITMR, 0xA0);
			WRITE_REGISTER_UCHAR(pIIRC3R, (CC_FIR_IIRC3R_TMIEN|CC_FIR_IIRC3R_TMI));
		}
		WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK0);
		if(READ_REGISTER_UCHAR(pIMSTSR) & CC_FIR_IMSTSR_TMI){
			WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK2);
			WRITE_REGISTER_UCHAR(pIIRC3R,CC_FIR_IIRC3R_TMI);
		}

		*claimingInterrupt = TRUE;
		*requireDeferredCallback = TRUE;

		// Disable Interrupts
		WRITE_REGISTER_UCHAR(pIMSTCR,READ_REGISTER_UCHAR(pIMSTCR) & ~CC_FIR_IMSTCR_IEN);

		WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK) | CC_FIR_IMSTCR_BANK0);
		if((READ_REGISTER_UCHAR(pIMSTSR) & CC_FIR_IMSTSR_TXI) &&
			thisDev->portInfo.writePending == TRUE){

			itsr = READ_REGISTER_UCHAR(pITSR);


			if(itsr & CC_FIR_ITSR_TFUR){
				// TxFIFO Underrun
#ifdef OUTMSG
				RETAILMSG(1, (TEXT("ERROR NSC_FI_ISR1. Underrun.\r\n")));
#endif
			}
		}

	}else{
		*claimingInterrupt = FALSE;
		*requireDeferredCallback = FALSE;
	}

    DBGISR((TEXT("<== NSC_FIR_ISR [int recognized = %s, dpc = %s]"),
            *claimingInterrupt ?        TEXT("TRUE") : TEXT("FALSE"),
            *requireDeferredCallback ?  TEXT("TRUE") : TEXT("FALSE")));
}


typedef struct {
    IrDevice *thisDev;
    ULONG Offset;      // This is a PUCHAR so we can do math on it.
    ULONG Length;
} DMASPACE;

//
// We have two lists of buffers which occupy our DMA space.  We
// want to walk this list and find the largest space for putting
// new packets.
//
rcvBuffer *GetNextPacket(DMASPACE *Space,
                         PLIST_ENTRY *CurrFull,
                         PLIST_ENTRY *CurrPend)
{
    rcvBuffer *Result = NULL;

    DBGOUT((TEXT("==>GetNextPacket")));

    if (*CurrFull==&Space->thisDev->rcvBufFull)
    {
        // Full list is finished.
        if (*CurrPend!=&Space->thisDev->rcvBufPend)
        {
            // Any entry on the pend list is valid.  Take the
            // next one and advance the pointer.

            Result = CONTAINING_RECORD(*CurrPend,
                                       rcvBuffer,
                                       listEntry);

            *CurrPend = (*CurrPend)->Flink;
        }
        else
        {
            // Both lists are finished.  We will return NULL.
        }
    }
    else 
    {
        if (*CurrPend==&Space->thisDev->rcvBufPend)
        {
            // Pend list is finished.  Take anything from the 
            // Full list, advance the pointer.
            Result = CONTAINING_RECORD(*CurrFull,
                                       rcvBuffer,
                                       listEntry);

            *CurrFull = (*CurrFull)->Flink;
        }
        else
        {
            // Both list have valid entries.  Compare the two and take the 
            // one that appears in the buffer first.
            rcvBuffer *Full, *Pend;

            Full = CONTAINING_RECORD(*CurrFull,
                                     rcvBuffer,
                                     listEntry);
            Pend = CONTAINING_RECORD(*CurrPend,
                                     rcvBuffer,
                                     listEntry);

            if (Full->dataBuf < Pend->dataBuf)
            {
                // Full is the winner.  Take it.

                Result = Full;
                *CurrFull = (*CurrFull)->Flink;
            }
            else
            {
                // Pend is the winner.  Take it.

                Result = Pend;
                *CurrPend = (*CurrPend)->Flink;
            }
        }
    }

    if (Result)
    {
        ASSERT(Result->isDmaBuf);
    }

    DBGOUT((TEXT("<==GetNextPacket")));
    return Result;
}

BOOLEAN SynchronizedFindLargestSpace(IN PVOID Context)
{
    DMASPACE *Space = Context;
    IrDevice *thisDev = Space->thisDev;
    BOOLEAN Result;
    PLIST_ENTRY Full, Pend;
    rcvBuffer *Current = NULL;

    DBGOUT((TEXT("==>SynchronizedFindLargestSpace")));
    ASSERT(sizeof(ULONG)==sizeof(PVOID));

    if (IsListEmpty(&thisDev->rcvBufFull) && IsListEmpty(&thisDev->rcvBufPend))
    {
        Space->Offset = (ULONG)thisDev->portInfo.dmaReadBuf;        
        Space->Length = RCV_DMA_SIZE;
    }
    else
    {
        ULONG EndOfLast;
        ULONG ThisSpace;

        Full = thisDev->rcvBufFull.Flink;
        Pend = thisDev->rcvBufPend.Flink;

        Space->Length = 0;

        EndOfLast = Space->Offset = (ULONG)thisDev->portInfo.dmaReadBuf;
        
        Current = GetNextPacket(Space, &Full, &Pend);
        while (Current)
        {
            // It's possible to get a packet that is from SIR.  If so, skip it.
                
            if (Current->isDmaBuf)
            {
                ASSERT((ULONG)Current->dataBuf >= EndOfLast);
    
                ThisSpace = (ULONG)Current->dataBuf - EndOfLast;
    
                // ASSERT the pointer is actually in our DMA buffer.
                ASSERT(Current->dataBuf >= thisDev->portInfo.dmaReadBuf ||
                       Current->dataBuf < thisDev->portInfo.dmaReadBuf+RCV_DMA_SIZE);
    
                if (ThisSpace > Space->Length)
                {
                    Space->Offset = EndOfLast;
                    Space->Length = ThisSpace;
                }
    
                EndOfLast = (ULONG)Current->dataBuf + Current->dataLen;
            }

            Current = GetNextPacket(Space, &Full, &Pend);
        }

        // Now we do one more calculation for the space after the end of the list.

        ThisSpace = (ULONG)thisDev->portInfo.dmaReadBuf + RCV_DMA_SIZE - (ULONG)EndOfLast;

        if (ThisSpace > Space->Length)
        {
            Space->Offset = EndOfLast;
            Space->Length = ThisSpace;
        }

        // Round off to start DMA on 4 byte boundary
        Space->Length -= 4 - (Space->Offset & 3);
        Space->Offset = (Space->Offset+3) & (~3);
    }

    // We want space relative to start of buffer.
    Space->Offset -= (ULONG)thisDev->portInfo.dmaReadBuf;

    Result = (Space->Length >= MAX_RCV_DATA_SIZE + FAST_IR_FCS_SIZE);

    if (!Result)
    {
        DEBUGFIR(DBG_ERR, (TEXT("NSC: ERROR: Not enough space to DMA full packet %x"), 
                 thisDev));
    }

    DBGOUT((TEXT("<==SynchronizedFindLargestSpace")));
    return Result;
}

BOOLEAN FindLargestSpace(IN IrDevice *thisDev, 
                         OUT PULONG pOffset, 
                         OUT PULONG pLength)
{
    DMASPACE Space;
    BOOLEAN Result;

    DBGOUT((TEXT("<==FindLargestSpace")));

    Space.Offset = 0;
    Space.Length = 0;
    Space.thisDev = thisDev;
    
    NdisAcquireSpinLock(&thisDev->QueueLock);
    Result = NdisMSynchronizeWithInterrupt(&thisDev->interruptObj, 
                                           SynchronizedFindLargestSpace,
                                           &Space);
    NdisReleaseSpinLock(&thisDev->QueueLock);

    *pOffset = Space.Offset;
    *pLength = Space.Length;

    DBGOUT((TEXT("<==FindLargestSpace")));

    return Result;
}



BOOLEAN FIR_MegaSend(IrDevice *thisDev)
{
    NDIS_STATUS stat;
    PNDIS_PACKET Packet;
    PNDIS_IRDA_PACKET_INFO packetInfo;
    int ret_val;


    DBGOUT((TEXT("==>FIR_MegaSend")));
    LOG(TEXT("==> FIR_MegaSend"), 0);
    DEBUGFIR(DBG_TX|DBG_OUT, (TEXT("NSC: ==> FIR_MegaSend(0x%x)"), 
                              (UINT) thisDev));

    NdisAcquireSpinLock(&thisDev->QueueLock);

    if (IsListEmpty(&thisDev->SendQueue))
    {
        NdisReleaseSpinLock(&thisDev->QueueLock);
        ret_val = FALSE;
    }
    else
    {
        /*
         * Update statistics.
         */
        RegStats.TxPacketsStarted++;

        thisDev->portInfo.writePending = TRUE;
		DBGOUT((TEXT("writePending = TRUE")));

        Packet = HEAD_SEND_PACKET(thisDev);

        // Check for min turnaround time set.

        packetInfo = GetPacketInfo(Packet);

        //
        // NOTE: Don't use NdisStallExecution for turnaround delay since
        //       you shouldn't stall for more than 60 us. Calling
        //       NdisStallExecution for large times will degrade system
        //       performance.
        //

        if (packetInfo->MinTurnAroundTime)
        {
            UINT usecToWait = packetInfo->MinTurnAroundTime;
            UINT msecToWait;
            packetInfo->MinTurnAroundTime = 0;

            NdisReleaseSpinLock(&thisDev->QueueLock);

            // Ndis timer has a 1ms granularity (in theory).  Let's round off.

            msecToWait = (usecToWait<=1000) ? 1 : (usecToWait+500)/1000;

        #ifdef UNDER_CE
            NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);
        #else //  UNDER_CE
            NdisSetTimer(&thisDev->TurnaroundTimer, msecToWait);
        #endif // !UNDER_CE

            DEBUGFIR(DBG_TX|DBG_OUT, (TEXT("NSC: MegaSend - do min TAT wait")));

            return TRUE; // Say we're successful.  We'll come back here.

        }

        if (thisDev->lastPacketAtOldSpeed==Packet)
        {
            thisDev->setSpeedAfterCurrentSendPacket = TRUE;
        }

        NdisToFirPacket(thisDev, 
                        Packet, (UCHAR *) thisDev->portInfo.writeBuf,
                        MAX_IRDA_DATA_SIZE, &thisDev->portInfo.writeBufLen);


        DEBUGFIR(DBG_PKT|DBG_TX, (TEXT("NSC: Sending packet 0x%x, len = %d"), 
                                  Packet, thisDev->portInfo.writeBufLen));
        DBGPRINTBUF(thisDev->portInfo.writeBuf, thisDev->portInfo.writeBufLen);

        NdisReleaseSpinLock(&thisDev->QueueLock);

#if 0
        NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 4, (UCHAR)(thisDev->portInfo.writeBufLen & 0xff));

        NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 5, (UCHAR)((thisDev->portInfo.writeBufLen >> 8) & 0x1f));
#endif


        /* Setup Transmit DMA. */
        NdisMSetupDmaTransfer(&stat, thisDev->DmaHandle,
                              thisDev->xmitDmaBuffer, 0,
                              thisDev->portInfo.writeBufLen, TRUE);

        if (stat != NDIS_STATUS_SUCCESS) {
            LOG(TEXT("NdisMSetupDmaTransfer(Tx)failed"), 0);
            DbgBreakPoint();
            ret_val = FALSE;
        }
        else {
            ret_val = TRUE;

            LOG(TEXT("FIR_MegaSend number of data bytes sent: "),
                thisDev->portInfo.writeBufLen);
            DEBUGFIR(DBG_TX|DBG_OUT, 
                (TEXT("NSC: FIR_MegaSend sent 0x%x bytes of data."),
                 thisDev->portInfo.writeBufLen));
        }
    }


    LOG(TEXT("<== FIR_MegaSend"), 0);
    DEBUGFIR(DBG_TX|DBG_OUT, (TEXT("NSC: <== FIR_MegaSend")));

    DBGOUT((TEXT("<==FIR_MegaSend")));
    return ret_val;
}


void FIR_MegaSendComplete(IrDevice *thisDev)
{
    NDIS_STATUS status;
    PLIST_ENTRY ListEntry;
    PNDIS_PACKET Packet;

    DBGOUT((TEXT("==>FIR_MegaSendComplete")));
    LOG(TEXT("==> FIR_MegaSendComplete"), 0);
    DEBUGFIR(DBG_TX|DBG_OUT, (TEXT("NSC: ==> FIR_MegaSendComplete(0x%x)"), 
                              (UINT) thisDev));

    ListEntry = MyInterlockedRemoveHeadList(&thisDev->SendQueue,
                                              &thisDev->QueueLock);

    if (!ListEntry)
    {
        ASSERT(0);
    }
    else
    {
        Packet = CONTAINING_RECORD(ListEntry,
                                   NDIS_PACKET,
                                   MiniportReserved);

        RegStats.TxPacketsCompleted++;      

        NdisMCompleteDmaTransfer(&status, thisDev->DmaHandle,
                                 thisDev->xmitDmaBuffer, 0,
                                 thisDev->portInfo.writeBufLen, TRUE);

        if (status != NDIS_STATUS_SUCCESS) {
            DbgBreakPoint();
        }

        /*
         * Check for Tx underrun.
         */
        WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK)|CC_FIR_IMSTCR_BANK0);/* Set to Bank 0 */ 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -