fir24a0.c

来自「S3C24A0的完整BSP包,对开发此芯片的开发者很有用.」· C语言 代码 · 共 1,319 行 · 第 1/3 页

C
1,319
字号
}



/* 	This is the function which sets up the DMA channel for transmission
	and sends the packet thru it.
*/	
BOOLEAN Irda_DMA_Tx(IrDevice *thisDev)
{
    NDIS_STATUS stat;
    PNDIS_PACKET Packet;
    PNDIS_IRDA_PACKET_INFO packetInfo;
    int ret_val;

    DEBUGMSG(DBGIRDA, (TEXT("==> Irda_DMA_Tx(0x%x)\r\n"), (UINT) thisDev));

    thisDev->HangChk = 0;

    if (IsListEmpty(&thisDev->SendQueue)) {
        ret_val = FALSE;
    } else {

        thisDev->portInfo.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;

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

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


            NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);

          //  RETAILMSG(DBGIRDA, (TEXT("Irda_DMA_Tx:- Do min TAT wait\r\n")));
            return TRUE; // Say we're successful.  We'll come back here.
#endif
        }

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


        DEBUGFIR(DBGIRDA, (TEXT("Irda_DMA_Tx: Sending packet 0x%x, len = %d\r\n"), Packet, thisDev->portInfo.writeBufLen));

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

        if (stat != NDIS_STATUS_SUCCESS) {
            DBGERR( (TEXT("Irda_DMA_Tx: NdisMSetupDmaTransfer(Tx)failed\r\n")));

            DbgBreakPoint();
            ret_val = FALSE;
        }
        else {
            ret_val = TRUE;
        }


    }

//    RETAILMSG(DBGIRDA, (TEXT("<== Irda_DMA_Tx\r\n")));

    return ret_val;
}



// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID 
NdisMSetupIntTransfer(
    PNDIS_STATUS            pStatus,
    PNDIS_BUFFER            pBuffer,
    ULONG                   Offset,
    ULONG                   Length,
    BOOLEAN                 WriteToDevice
    )
{
	PVOID	VirtualAddress;
	UINT	BufferLength;

    DEBUGFIR(DBGIRDA, (TEXT("+NdisMSetupIntransfer %s: buf = 0x%x, offset = %d, len = %d"),
        (WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
        pBuffer, Offset, Length));

#if 0
    RETAILMSG(1, (TEXT("+NdisMSetupDmaTransfer %s: buf = 0x%x, offset = %d, len = %d"),
        (WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
        pBuffer, Offset, Length));
#endif
    if(Length <1000)
        RETAILMSG(1, (TEXT("%x "),Length));
    *pStatus = NDIS_STATUS_SUCCESS;


	NdisQueryBuffer(pBuffer, &VirtualAddress, &BufferLength);

    if (Offset + Length > BufferLength)
    {
        DBGERR( (TEXT("Whoa! The offset+length is greater than the buffer length!")));
        *pStatus = NDIS_STATUS_RESOURCES;
        goto done;
    }
    
    DEBUGFIR(DBGIRDA, (TEXT("Address = 0x%X\r\n"), (PBYTE)VirtualAddress + Offset));
    DEBUGFIR(DBGIRDA, (TEXT("Length  = 0x%X\r\n"), BufferLength));

	Init_Irda_Rx(Length,S24A0_IRDA_RXMODEINT);

done:

//    RETAILMSG(DBGIRDA, (TEXT("-NdisMSetupDmaTransfer [%s]"), DBG_NDIS_RESULT_STR(*pStatus)));
    return;
}

#ifdef  DEBUG
void DumpFrame(PUCHAR pStart, UINT len) 
{
	UINT i;

	for(i=0;i<len;i++) {
		RETAILMSG(DBGIRDA, (TEXT(" 0x%x"),*pStart++));
		if((len %16 ) == 15)
			RETAILMSG(DBGIRDA, (TEXT(" \r\n")));
	}

}
#else
#define DumpFrame(pStart,len) 
#endif


#if 0
VOID FIR_HandleDMARxFrame(IN PVOID SystemSpecific1,
                  IN PVOID FunctionContext,
                  IN PVOID SystemSpecific2,
                  IN PVOID SystemSpecific3)
{
    IrDevice *thisDev = FunctionContext;

    DEBUGMSG(DBGIRDA, (TEXT("==> FIR_HandleDMARxFrame\r\n")));

    NdisAcquireSpinLock(&thisDev->Lock);

    Read the DMA cnt.

    if the DMA cnt is not changed

    restart the timer..

    
 
    NdisReleaseSpinLock(&thisDev->Lock);
    DEBUGMSG(DBGIRDA, (TEXT("<== DelayedWrite\r\n")));
}
#endif
void FIR_HandleRxFrame(IrDevice *thisDev)
{
    UCHAR frameStat,frameLSR;
//    NDIS_STATUS stat;
    ULONG rcvFrameSize = 0,i;
    PUCHAR FrameStart,readPtr;
    BOOLEAN bDoSetupAgain = TRUE;


	g_pINTregs->INTSUBMSK |= BIT_SUB_IRDA;

    //   g_pIRDAregs->IRDA_IER = 0x1<<6|1<<4|1<<3|1; // Enable the interrupts

    // RETAILMSG(1, (TEXT("FIR_HandleRxFrame \r\n")));
   
    frameStat = thisDev->InterruptStatus;
    frameLSR = thisDev->FrameStatus;

    while(1){

  

//    RETAILMSG(1, (TEXT("FS (0x%x) LSR(0x%x) \r\n"), frameStat,frameLSR));
//	DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> FrameStat (0x%x)"), frameStat));
//	DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> FrameLSR (0x%x)"), frameLSR));
    	if((frameStat & 0x40) || (frameLSR & 0x1c)) {
	        DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Error Indication")));
	        if(frameLSR & 0x04) {
	    	    RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> CRC Error")));
    	    	RegStats.ReceiveCRCErrors++;
	        }
	        if(frameLSR & 0x08) {
	    	    RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> PHY Error")));
    	    	RegStats.ReceiveCRCErrors++;
	        }	
	        if(frameLSR & 0x10) {
	    	    RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> FL Error, len LL%x LH%x"),g_pIRDAregs->IRDA_RXFLL,g_pIRDAregs->IRDA_RXFLH));
    	    	RegStats.ReceiveCRCErrors++;
	        }	
	        break;
        }else if(frameStat & 0x08) {
	      //  RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> Rx Over Run error")));
	        RegStats.ReceiveFIFOOverflows++;
	        break;
        //      }else if(frameLSR & 0x01) {
        //	    DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Rx Empty")));
        //	    RegStats.ReceiveFIFOOverflows++;
    #if 0      
        }
   
        else if (frameLSR & 0x01) {
    	    Sleep(1);
            
       
	    
	    //    RETAILMSG(1, (TEXT("FIR_HandleRxFrame: ==> Rx Fifo Empty\r\n)")));   

	    
	        bDoSetupAgain = FALSE;
	        NdisMSetupIntTransfer(&stat,thisDev->rcvDmaBuffer, 
                          thisDev->rcvDmaOffset,
                          thisDev->rcvDmaSize, FALSE);

	        if (stat != NDIS_STATUS_SUCCESS) {
      		    LOG(TEXT("Error: NdisMSetupDmaTransfer failed in SetupRecv"), stat);
        	    DBGERR((TEXT("NdisMSetupDmaTransfer failed (0x%x) in SetupRecv"), 
                (UINT)stat));
	   	    }

	        break; 
     #endif   
    	} else if(((frameStat & 0x10) || (frameStat & 0x80))){
	        DEBUGFIR(DBG_RX, (TEXT("Last Byte Detected\r\n")));

	        // 
	        // Half Duplex, received last byte, so disable Rx
	        //
    		g_pIRDAregs->IRDA_CNT &= ~(3<<6); //Resest Tx and Rx bits
	
	    	g_pIRDAregs->IRDA_CNF = 0x0; // Disable Interrupt & DMA

		    // Interrupt Enable Register
    		g_pIRDAregs->IRDA_IER = 0x0; // Disable All interrupts


	        FrameStart = readPtr = thisDev->portInfo.dmaReadBuf + thisDev->rcvPktOffset;
	    

    		while(!(g_pIRDAregs->IRDA_LSR & 0x20)) {
	    		*readPtr++ = g_pIRDAregs->IRDA_RBR;
		    }

    		DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Completed")));

        	rcvFrameSize = readPtr -FrameStart; 
		    thisDev->rcvdFrameLen += rcvFrameSize;

        	DumpFrame(FrameStart,rcvFrameSize);
		
		    FrameStart = thisDev->portInfo.dmaReadBuf + thisDev->rcvdFrameStart;

            thisDev->rcvPktOffset += rcvFrameSize;


            if (thisDev->rcvdFrameLen <= MAX_NDIS_DATA_SIZE && 
                thisDev->rcvdFrameLen>= IR_ADDR_SIZE + IR_CONTROL_SIZE) {
 	           //
               // Queue this rcv packet.  Move Newframe pointer 
               // into RxDMA buffer.
               //
               RegStats.ReceivedPackets++;
               RegStats.RxWindow++;
               QueueReceivePacket(thisDev, FrameStart, thisDev->rcvdFrameLen, TRUE);
               thisDev->bRcvdFullFrame = TRUE;   
            }
            else {
                LOG(TEXT("Error: invalid packet size in FIR_DeliverFrames"), 
                rcvFrameSize);
                DEBUGFIR(DBG_RX|DBG_ERR, 
                    (TEXT("Invalid packet size in FIR_DeliverFrames; %xh > %xh"), 
                    rcvFrameSize, MAX_RCV_DATA_SIZE));
                thisDev->DiscardNextPacketSet = TRUE;
            }
            break;
	    }else if(frameStat & 0x01) {
	        DEBUGFIR(DBG_RX, (TEXT("FIR_HandleRxFrame: ==> Rx Fifo is full (0x%x)"), (UINT) thisDev));
     //     RETAILMSG(1, (TEXT("RxF\r\n")));  
	        FrameStart = readPtr = thisDev->portInfo.dmaReadBuf + thisDev->rcvPktOffset;

            for(i=0; i <16;i++)
                *readPtr++ = g_pIRDAregs->IRDA_RBR;   

	 //     rcvFrameSize = readPtr -FrameStart; 
           	rcvFrameSize = 16; 
            /* Step offset for next buffer.  */
            thisDev->rcvPktOffset += rcvFrameSize;
	    	thisDev->rcvdFrameLen += rcvFrameSize;
		    DumpFrame(FrameStart,rcvFrameSize);

	    }else if (frameLSR & 0x01) {  // Rx Fifo empty
    	    Sleep(1);
        }
//        thisDev->InterruptStatus = g_pIRDAregs->IRDA_IIR;
//        thisDev->FrameStatus = g_pIRDAregs->IRDA_LSR;

          frameStat = g_pIRDAregs->IRDA_IIR;
          frameLSR = g_pIRDAregs->IRDA_LSR;

    }	    

	if(bDoSetupAgain)
	    FirSetupIntRecv(thisDev);
    LOG(TEXT("<== FIR_DeliverFrames"), 1);
    DEBUGFIR(DBG_RX|DBG_OUT, (TEXT("<== FIR_DeliverFrames")));
}



BOOLEAN IR24A0_Setup(IrDevice *thisDev)
{
    NDIS_DMA_DESCRIPTION DMAChannelDcr;
    NDIS_STATUS stat;

    thisDev->rcvDmaOffset = 0;

    /*
     *  Because we enable rcv DMA while SIR receives may still be
     *  going on, we need to keep a separate receive buffer for DMA.
     *  This buffer gets swapped with the rcvBuffer data pointer
     *  and must be the same size.
     */
#ifdef UNDER_CE
    // Windows CE. We get a chunk of memory from our contiguous physical
    // buffer. See externs.h for detailed information.

    ASSERT(g_pvDmaVirtualBase);
    thisDev->portInfo.dmaReadBuf = (PUCHAR)g_pvDmaVirtualBase + RCVDMA_OFFSET;
#else // UNDER_CE
    thisDev->portInfo.dmaReadBuf = MyMemAlloc(RCV_DMA_SIZE, TRUE);
    if (!thisDev->portInfo.dmaReadBuf){
        return FALSE;
    }
#endif //!UNDER_CE

    NdisAllocateBufferPool(&stat, &thisDev->dmaBufferPoolHandle, 2);
    if (stat != NDIS_STATUS_SUCCESS){
        RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBufferPool failed in IR24A0_setup\r\n")));
        return FALSE;
    }

    NdisAllocateBuffer(&stat, &thisDev->rcvDmaBuffer, 
                       thisDev->dmaBufferPoolHandle, 
                       thisDev->portInfo.dmaReadBuf,
                       RCV_DMA_SIZE);
    if (stat != NDIS_STATUS_SUCCESS) {
        RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBuffer failed (rcv) in IRDA24A0_Setup\r\n")));
        return FALSE;
    }

    NdisAllocateBuffer(&stat, &thisDev->xmitDmaBuffer, 
                       thisDev->dmaBufferPoolHandle, 
                       thisDev->portInfo.writeBuf,
                       MAX_IRDA_DATA_SIZE);
    if (stat != NDIS_STATUS_SUCCESS) {
        RETAILMSG(DBGIRDA, (TEXT("24A0: NdisAllocateBuffer failed (xmit) in IRDA24A0_Setup\r\n")));
        return FALSE;
    }


    /*
     *  Initialize rcv DMA channel
     */
    DMAChannelDcr.DemandMode = TRUE;
    DMAChannelDcr.AutoInitialize = FALSE;
    DMAChannelDcr.DmaChannelSpecified = FALSE;
    DMAChannelDcr.DmaWidth = Width8Bits;
    DMAChannelDcr.DmaSpeed = Compatible;
    DMAChannelDcr.DmaPort = 0;
    DMAChannelDcr.DmaChannel = thisDev->DMAChannel;

    stat = NdisMRegisterDmaChannel(&thisDev->DmaHandle,
                                   thisDev->ndisAdapterHandle,
                                   thisDev->DMAChannel,
                                   FALSE, &DMAChannelDcr, RCV_DMA_SIZE);

    if (stat != NDIS_STATUS_SUCCESS) {
        RETAILMSG(DBGIRDA, (TEXT("24A0: NdisMRegisterDmaChannel failed\r\n")));
        return FALSE;
    }

    return TRUE;
}


void IR24A0_Shutdown(IrDevice *thisDev)
{
    if (thisDev->DmaHandle){
        NdisMDeregisterDmaChannel(thisDev->DmaHandle);
        thisDev->DmaHandle = NULL;
    }

    if (thisDev->xmitDmaBuffer){
        NdisFreeBuffer(   thisDev->xmitDmaBuffer);
        thisDev->xmitDmaBuffer = NULL;
    }

    if (thisDev->rcvDmaBuffer){
        NdisFreeBuffer(thisDev->rcvDmaBuffer);
        thisDev->rcvDmaBuffer = NULL;
    }

    if (thisDev->dmaBufferPoolHandle){
        NdisFreeBufferPool(thisDev->dmaBufferPoolHandle);
        thisDev->dmaBufferPoolHandle = NULL;
    }
}





⌨️ 快捷键说明

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