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

📄 rtl8139.c

📁 三星2410的BSP开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
    //  Caller ** MUST HAVE ** called RTL8139InitDMABuffer()
    //
    sRTL8139.pucTxBuffer     = (PUCHAR)(dwTxStartAddress);
    sRTL8139.pucRxBuffer     = (PUCHAR)(dwRxStartAddress);  
    sRTL8139.puLastRxAddress = sRTL8139.pucRxBuffer + dwRxLength - 1;

    PRINTF (1, ("RTL8139Init():: TxBuff[0x%x] - RxBuff[0x%x] - LastRx[0x%x]\r\n",
        sRTL8139.pucTxBuffer,
        sRTL8139.pucRxBuffer,
        sRTL8139.puLastRxAddress));


    ////////////////////////////////////////////////////////////////////////////
    //  First stop, soft reset the NIC, and fill up the MacAddr.
    //      
    if( NULL != MacAddr ) {
	    WRITE_PORT_UCHAR(RTL_CR, RTL8139_COMMAND_RESET);
	    while(READ_PORT_UCHAR(RTL_CR) & RTL8139_COMMAND_RESET)
	        ;

	    WRITE_PORT_UCHAR(
	        RTL_CR,
	        (RTL8139_COMMAND_TX_ENABLE | RTL8139_COMMAND_RX_ENABLE));
	    
	    dwScrap = READ_PORT_ULONG(RTL_IDR0);
	    sRTL8139.usMacAddr[0] = (USHORT)(dwScrap);
	    sRTL8139.usMacAddr[1] = (USHORT)(dwScrap >> 16);
	    
	    dwScrap = READ_PORT_ULONG(RTL_IDR4);
	    sRTL8139.usMacAddr[2] = (USHORT)(dwScrap);  
	    
	    PRINTF (1, ("RTL8139Init:: MAC = %B-%B-%B-%B-%B-%B\r\n",
	        sRTL8139.usMacAddr[0] & 0x00FF, 
	        sRTL8139.usMacAddr[0] >> 8,
	        sRTL8139.usMacAddr[1] & 0x00FF, 
	        sRTL8139.usMacAddr[1] >> 8,
	        sRTL8139.usMacAddr[2] & 0x00FF, 
	        sRTL8139.usMacAddr[2] >> 8));

	    memcpy(
	        &(MacAddr[0]), 
	        &(sRTL8139.usMacAddr[0]),
	        6);
    }
    
#ifndef AUTO_NEGOTIATE

    ////////////////////////////////////////////////////////////////////////////
    //  Currently hardcode to:
    //  -  10Mbps
    //  -  Auto negotiation disabled.
    //  -  Simplex
    //  

	PRINTF (1, ("Hardcoded to 10Mbps..\r\n"));

    usScrap = READ_PORT_USHORT(RTL_BMCR);
    usScrap &= ~(RTL_100MBPS | RTL_FULL_DUPLEX | RTL_AUTO_NEGOTIATE_ENABLE);
    WRITE_PORT_USHORT(RTL_BMCR, usScrap);

#else

	//
	//	Auto Negotiate!!
	//

	PRINTF (1, ("RTL8139 ethdbg library: AutoNegotiate..\r\n"));

	WRITE_PORT_USHORT(RTL_BMCR, 0x1000);

#endif

    
    ////////////////////////////////////////////////////////////////////////////
    //  Prepare the TX buffers & descriptors.
    //
    for (i = 0x00 ; i < NUM_TX_DESC ; i++)
    {   
        WRITE_PORT_ULONG(
            RTL_TSAD_X(i), 
            TO_REAL((DWORD)(sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE)));
    }

    ////////////////////////////////////////////////////////////////////////////
    //  TX DMA burst size per TX DMA burst.
    //
    WRITE_PORT_ULONG(
        RTL_TCR, 
        (TX_DMA_BURST_SIZE) | 0x03000000);


	//
	//	Init multicast registers to 0
	//

	memset(
		g_pucMulticastList,
		0x00,
		MAX_MULTICAST_LIST * 6);

	g_dwMulticastListInUse = 0x00;

	RTL8139HWSetMCRegs(NULL, FALSE);	
    
    ////////////////////////////////////////////////////////////////////////////
    //  Now, prepare the RX buffers & descriptors and RX Mode.  
    //  Hardcode to accept only broadcast and myself.
    //
    
	g_dwRCR = RX_BROADCAST		|	 
			  RX_UNICAST		|	 
			  dwRxLengthBit		| 
			  RX_DMA_BURST_SIZE |
			  RX_ACCEPT_RUNT;

	WRITE_PORT_ULONG (RTL_RCR, g_dwRCR);	

    WRITE_PORT_ULONG(
        RTL_RBSTART, 
        TO_REAL((DWORD)(sRTL8139.pucRxBuffer)));
    
    WRITE_PORT_USHORT(
        RTL_ANAR,
        0x21);  

    WRITE_PORT_USHORT(
        RTL_ISR,
        0xffff);

#if 0
    DumpAll8139Regs();  
#endif

    return TRUE;

}   //  RTL8139Init()



////////////////////////////////////////////////////////////////////////////////
//  RTL8139EnableInts()
//  
void    
RTL8139EnableInts(void)
{
    PRINTF (1, ("+RTL8139EnableInts()..\r\n"));

    ////////////////////////////////////////////////////////////////////////////
    //  We are only interested in RX interrupts.
    //  Also turn on TX interrupts for quick purge of TX descriptors..
    //
    WRITE_PORT_USHORT(
        RTL_IMR,
        0x05);


    PRINTF (1, ("-RTL8139EnableInts()..\r\n"));
}   // RTL8139EnableInts()



////////////////////////////////////////////////////////////////////////////////
//  RTL8139DisableInts()
//
void    
RTL8139DisableInts(void)
{    
    PRINTF (0, ("RTL8139DisableInts()..\r\n"));

    WRITE_PORT_USHORT(
        RTL_IMR,
        0x00);


}   //  RTL8139DisableInts()



#define RX_ERR_ISE      (1 << 5)
#define RX_ERR_RUNT     (1 << 4)
#define RX_ERR_LONG     (1 << 3)
#define RX_ERR_CRC      (1 << 2)
#define RX_ERR_FAE      (1 << 1)

#define BAD_RX_PACKET       \
            (RX_ERR_ISE | RX_ERR_RUNT | RX_ERR_LONG | RX_ERR_CRC | RX_ERR_FAE)

////////////////////////////////////////////////////////////////////////////////
//  ExtractData()
//  This function will take the buffer pointer and it's start and end address.
//  It will extract dwSize amount of bytes and handle the wrap around case.
//
UCHAR *
ExtractData(
    UCHAR   *pucSource, 
    UCHAR   *pucSourceHead,
    UCHAR   *pucSourceTail, 
    UCHAR   *pucDest,
    DWORD   dwSize)
{

    PRINTF (0, ("Extracting fr [0x%x] - to [0x%x] - H[0x%x] - T[0x%x] - tot [%d]\r\n",
        pucSource,
        pucDest,
        pucSourceHead,
        pucSourceTail,
        dwSize));

    if (pucSource + dwSize <= pucSourceTail)
    {
        ////////////////////////////////////////////////////////////////////////
        //  No problem, straight copy.
        //
        memcpy(
            pucDest,
            pucSource,
            dwSize);

        PRINTF (0, ("Returning: [0x%x]\r\n",
            (pucSource + dwSize)));

        return (pucSource + dwSize);
    }
    else
    {
        DWORD   dwFirstCopySize;

        ////////////////////////////////////////////////////////////////////////
        //  Wrap around copy..
        //
        dwFirstCopySize = pucSourceTail - pucSource + 1;
        memcpy(
            pucDest,
            pucSource,
            dwFirstCopySize);

        memcpy(
            pucDest + dwFirstCopySize,
            pucSourceHead,
            dwSize - dwFirstCopySize);

        PRINTF (0, ("ReturningWrap: [0x%x]\r\n",
            (pucSource + (dwSize - dwFirstCopySize))));

        return (pucSourceHead + (dwSize - dwFirstCopySize));
    }


}   //  ExtractData()



////////////////////////////////////////////////////////////////////////////////
//  RTL8139GetFrame()
//  Fill up pbData with the next availabe packet in the RX FIFO.    
//
UINT16    
RTL8139GetFrame(BYTE *pbData, UINT16 *pwLength)
{   
    PACKET_HEADER   PacketHeader;
    UCHAR           *pucRxBuffer;   

    PRINTF (0, ("RTL8139GetFrame()..\r\n"));

    *pwLength = 0x00;

    if (!(READ_PORT_UCHAR(RTL_CR) & RTL8139_COMMAND_BUFFER_EMPTY))
    {
        pucRxBuffer = sRTL8139.pucRxBuffer + sRTL8139.dwCurrentRxOffset;        

        PRINTF (0, ("$ "));

        PRINTF (0, ("[a] [0x%x]\r\n", pucRxBuffer));

        
        ////////////////////////////////////////////////////////////////////////
        //  Now, the first 4 bytes form the PACKET_HEADER.      
        //
        pucRxBuffer = ExtractData(
                        pucRxBuffer,
                        sRTL8139.pucRxBuffer,
                        sRTL8139.puLastRxAddress,
                        (PUCHAR)&PacketHeader,
                        sizeof(PACKET_HEADER));

        PRINTF (0, ("[b] [0x%x]\r\n", pucRxBuffer));

        PRINTF (0, (">> One RX packet:: Offset = [0x%x] - Header = [0x%x] - Length = [%d] bytes.\r\n",
                sRTL8139.dwCurrentRxOffset,
                PacketHeader.usPacketHeader,
                PacketHeader.usPacketLength));

        if (PacketHeader.usPacketHeader & BAD_RX_PACKET)
        {
            PRINTF (1, ("Bad RX packet [Header: 0x%x -- Length : [%d]]...\r\n",
                PacketHeader.usPacketHeader,
                PacketHeader.usPacketLength));

            pucRxBuffer = ExtractData(
                            pucRxBuffer,
                            sRTL8139.pucRxBuffer,
                            sRTL8139.puLastRxAddress,
                            pbData,
                            PacketHeader.usPacketLength);

            sRTL8139.dwCurrentRxOffset = 
                (pucRxBuffer - sRTL8139.pucRxBuffer + 3) & ~3;

            WRITE_PORT_USHORT(
                RTL_CAPR,
                (USHORT)(sRTL8139.dwCurrentRxOffset - 0x10));

            // ack the interrupt so we can get interrupted again
            WRITE_PORT_USHORT(
                RTL_ISR,
                0xffff);
    
            return 0x00;
        }
        else
        {
            pucRxBuffer = ExtractData(
                            pucRxBuffer,
                            sRTL8139.pucRxBuffer,
                            sRTL8139.puLastRxAddress,
                            pbData,
                            PacketHeader.usPacketLength);

            PRINTF (0, ("[c] [0x%x]\r\n", pucRxBuffer));

            *pwLength = (PacketHeader.usPacketLength - 4);


            //  DumpMemory(
            //      pbData,
            //      48);

            sRTL8139.dwCurrentRxOffset = 
                (pucRxBuffer - sRTL8139.pucRxBuffer + 3) & ~3;

            PRINTF (0, ("[d] Offset = [0x%x]\r\n",
                sRTL8139.dwCurrentRxOffset));
        }

        WRITE_PORT_USHORT(
            RTL_CAPR,
            (USHORT)(sRTL8139.dwCurrentRxOffset - 0x10));

        return *pwLength;
    }
    else
    {
        PRINTF (0, ("# "));

        // ack the interrupt so we can get interrupted again
        WRITE_PORT_USHORT(
            RTL_ISR,
            0xffff);
    
        return 0x00;
    }
    
    
}    // RTL8139GetFrame()



////////////////////////////////////////////////////////////////////////////////
//  RTL8139SendFrame()
//      This routine should be called with a pointer to the ethernet frame data.  
//      It is the caller's responsibility to fill in all information including 
//      the destination and source addresses and the frame type.  
//      The length parameter gives the number of bytes in the ethernet frame.
//      The routine will return immediately regardless of whether transmission 
//      has successfully been performed.
//


#define TX_OWN_BIT              (1 << 13)
#define TX_TOK_BIT              (1 << 15)
#define TX_ABORT                (1 << 30)
#define FREE_TX_DESCRIPTOR      (TX_TOK_BIT)
#define GET_TSD(x)  \
            (READ_PORT_ULONG(RTL_TSD_X(x)) & FREE_TX_DESCRIPTOR)

void
PurgeTxDescriptors()
{       
    int     i     = 0x00;

    while((sRTL8139.dwFreeTxDescriptors < NUM_TX_DESC) &&
          (GET_TSD(sRTL8139.dwCurrentHwTxDescriptor) & FREE_TX_DESCRIPTOR))
    {
        i++;
        NEXT(sRTL8139.dwCurrentHwTxDescriptor, NUM_TX_DESC);
        sRTL8139.dwFreeTxDescriptors++;
    }

    ////////////////////////////////////////////////////////////////////////////
    //  If it was transmit abort in any of the TX desc, restart it.
    //  
    if (!i)
    {
        for (i = 0 ; i < 4 ; i++)
        {
            if (READ_PORT_ULONG(RTL_TSD_X(i)) & TX_ABORT)
            {
                PRINTF (1, ("* "));
                WRITE_PORT_ULONG(
                    RTL_TCR, 
                    TX_DMA_BURST_SIZE | TX_CLEAR_ABORT | 0x03000000);
                break;
            }
        }
    }
        

}   //  PurgeTxDescriptors()



UINT16    
RTL8139SendFrame(BYTE *pbData, DWORD dwLength)
{       
    DWORD   i;
    DWORD   dwWaitTime;
    BOOL    bLastTry = FALSE;
    

    PRINTF (0, ("RTL8139SendFrame()..\r\n"));   

    PRINTF (0, ("[0x%x] ",
            READ_PORT_USHORT(RTL_ISR)));

    ////////////////////////////////////////////////////////////////////////////
    //  Check if the current TX descriptor is available.
    //  If not then we loop wait till it is available.
    //
    dwWaitTime = 100000;
    
    while (sRTL8139.dwFreeTxDescriptors == 0)
    {       
        PurgeTxDescriptors();
        
        PRINTF (0, ("![%d, %x - %x - %x - %x] [0x%x]",
            sRTL8139.dwCurrentHwTxDescriptor,
            READ_PORT_ULONG(RTL_TSD_X(0)),
            READ_PORT_ULONG(RTL_TSD_X(1)),
            READ_PORT_ULONG(RTL_TSD_X(2)),
            READ_PORT_ULONG(RTL_TSD_X(3)),
            READ_PORT_USHORT(RTL_ISR)));

        ////////////////////////////////////////////////////////////////////////
        //  Oh well, chip is toasted... SOFT RESET it.
        //
        if (!--dwWaitTime)
        {   
            USHORT  usDummy[3];

            PRINTF (1, ("@ "));
            dwWaitTime = 100000;        

            PRINTF (1, ("< TX Reset >\r\n"));
            PRINTF (1, ("HW Descriptor [%d] :: SW Descriptor [%d] :: Free = [%d]",
                    sRTL8139.dwCurrentHwTxDescriptor,
                    sRTL8139.dwCurrentTxDescriptor,
                    sRTL8139.dwFreeTxDescriptors));
            DumpAll8139Regs();

            WRITE_PORT_UCHAR(
                RTL_CR,
                (RTL8139_COMMAND_RX_ENABLE));

            WRITE_PORT_UCHAR(
                RTL_CR,
                (RTL8139_COMMAND_TX_ENABLE | RTL8139_COMMAND_RX_ENABLE));

            RTL8139DisableInts();
            RTL8139Init(
                (PBYTE)sRTL8139.dwBaseIO,
                sRTL8139.dwMemOffset,
                usDummy);
            RTL8139EnableInts();
        }
    }

    sRTL8139.dwFreeTxDescriptors--;
    
    ////////////////////////////////////////////////////////////////////////////
    //  So we are definitely using this descriptor.
    //  Advance it for the next call.
    //
    i = sRTL8139.dwCurrentTxDescriptor;
    NEXT(sRTL8139.dwCurrentTxDescriptor, NUM_TX_DESC);

    PRINTF (0, ("RTL8139SendFrame() using index: [%d] :: Size = [%d]\r\n",
        i,
        dwLength)); 

    
    ////////////////////////////////////////////////////////////////////////////
    //  Copy the user data and set it to go.
    //
    memcpy(
        sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE,
        pbData,
        dwLength);

#if 0
    DumpMemory(
        pbData,
        dwLength);

    DumpMemory(
        sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE,
        dwLength);
#endif

    
    WRITE_PORT_ULONG(
        RTL_TSAD_X(i), 
        TO_REAL((DWORD)(sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE)));  


    ////////////////////////////////////////////////////////////////////////////
    //  Minimum packet size required by RTL 
    //
    if (dwLength < 60)
    {
        memset(
          (sRTL8139.pucTxBuffer + i * ONE_BUFFER_SIZE) + dwLength,
            0x00,
            60 - dwLength);

        dwLength = 60;
    }


    ////////////////////////////////////////////////////////////////////////////
    //  Send it out now..
    //  8 bytes threshold.

⌨️ 快捷键说明

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