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

📄 rtl8139.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
    OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), 0);
    OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), 0);

    // Configure RX
    if (g_rtl8139.rxSize >= 64 * 1024) {
        u32 = RCR_RBLEN64;
    } else if (g_rtl8139.rxSize >= 32 * 1024) {
        u32 = RCR_RBLEN32;
    } else if (g_rtl8139.rxSize >= 16 * 1024) {
        u32 = RCR_RBLEN16;
    } else {
        u32 = RCR_RBLEN8;
    }
    u32 |= RCR_RXFTH16 | RCR_MXDMA16 | RCR_AR | RCR_AB | RCR_APM;
    OUTPORT32((UINT32*)(g_rtl8139.address + RTL_RCR),  u32);
    OUTPORT32(
        (UINT32*)(g_rtl8139.address + RTL_RBSTART),
        OALVAtoPA((VOID*)g_rtl8139.rxBuffer)
    );

    // Actual filter 
    g_rtl8139.filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
    
    // Clear all interrupts
    OUTPORT16((UINT16*)(g_rtl8139.address + RTL_ISR), 0xFFFF);

    // Done
    rc = TRUE;

clean:
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139Init(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  RTL8139SendFrame
//
UINT16 RTL8139SendFrame(UINT8 *pData, UINT32 length)
{
    UINT32 *pTsd;
    UINT32 buffer, start;
    

    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
        L"+RTL8139SendFrame(0x%08x, %d)\r\n", pData, length
    ));

    // Wait until buffer is released by hardware
    pTsd = (UINT32*)(g_rtl8139.address + RTL_TSD0 + (g_rtl8139.txPos << 2));
    start = OALGetTickCount();
    while ((INPORT32(pTsd) & TSR_OWN) == 0) {
        if ((OALGetTickCount() - start) > 2000) {
            OALMSGS(OAL_ERROR, (L"ERROR: RTL8139SendFrame: Send timeout\r\n"));
            return 1;
        }
    }

    // Copy data to buffer
    buffer = g_rtl8139.txBuffer + g_rtl8139.txPos * MAC_TX_BUFFER_SIZE;
    memcpy((VOID*)buffer, pData, length);
    if (length < 60) {
        memset((VOID*)(buffer + length), 0, 60 - length);
        length = 60;
    }

    // Write TSD register to start send
    OUTPORT32(pTsd, length);

    // Move to next position
    if (++g_rtl8139.txPos >= MAC_TX_BUFFERS) g_rtl8139.txPos = 0;

    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"-RTL8139SendFrame(rc = 0)\r\n"));
    return 0;
}

//------------------------------------------------------------------------------
//
//  Function:  RTL8139GetFrame
//
UINT16 RTL8139GetFrame(UINT8 *pData, UINT16 *pLength)
{
    UINT16 offset, length, status, len1;
    BOOL ok;
    
    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
        L"+RTL8139GetFrame(0x%08x, %d)\r\n", pData, *pLength
    ));

    length = 0;
    ok = FALSE;
    while ((INPORT8((UINT8*)(g_rtl8139.address + RTL_CR)) & CR_BUFE) == 0) {

        // Get read offset
        offset = INPORT16((UINT16*)(g_rtl8139.address + RTL_CAPR)) + 0x10;

        // Read packet status and length
        status = *(UINT16*)(g_rtl8139.rxBuffer + offset);
        length = *(UINT16*)(g_rtl8139.rxBuffer + offset + 2) - 4;

        offset += 4;
        if (offset >= g_rtl8139.rxSize) offset = 0;

        // When packet is OK copy it to buffer
        if ((status & RSR_ROK) != 0 && length <= *pLength) {
            len1 = g_rtl8139.rxSize - offset;
            if (length <= len1) {
                memcpy(pData, (VOID*)(g_rtl8139.rxBuffer + offset), length);
            } else {
                memcpy(pData, (VOID*)(g_rtl8139.rxBuffer + offset), len1);
                memcpy(pData + len1, (VOID*)g_rtl8139.rxBuffer, length - len1);
            }
            ok = TRUE;
        }

        // Update read offset
        offset += (length + 7) & ~3;
        if (offset >= g_rtl8139.rxSize) offset -= g_rtl8139.rxSize;
        OUTPORT16((UINT16*)(g_rtl8139.address + RTL_CAPR), offset - 0x10);

        // If packet is ok, we have all we need
        if (ok) break;

        length = 0;
    }

    // If there isn't a packet ack the interrupt
    if (length == 0) OUTPORT16((UINT16*)(g_rtl8139.address + RTL_ISR), 0xFFFF);

    // Return packet size
    *pLength = length;

    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
        L"-RTL8139GetFrame(length = %d)\r\n", length
    ));
    return length;
}

//------------------------------------------------------------------------------
//
//  Function:  RTL8139EnableInts
//
VOID RTL8139EnableInts()
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+RTL8139EnableInts\r\n"));
    // We are only interested in RX interrupts
    OUTPORT16((UINT16*)(g_rtl8139.address + RTL_IMR), IR_ROK);
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139EnableInts\r\n"));
}


//------------------------------------------------------------------------------
//
//  Function:  RTL8139DisableInts
//
VOID RTL8139DisableInts()
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+RTL8139DisableInts\r\n"));
    OUTPORT16((UINT16*)(g_rtl8139.address + RTL_IMR), 0);
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139DisableInts\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  RTL8139CurrentPacketFiler
//

VOID RTL8139CurrentPacketFilter(UINT32 filter)
{
    UINT32 ctrl;

    OALMSGS(OAL_ETHER&&OAL_FUNC, (
        L"+RTL8139CurrentPacketFilter(0x%08x)\r\n", filter
    ));

    ctrl = INPORT32((UINT32*)(g_rtl8139.address + RTL_RCR));

    // First set hash functions
    if (
        (filter & PACKET_TYPE_PROMISCUOUS) != 0 ||
        (filter & PACKET_TYPE_ALL_MULTICAST) != 0
    ) {
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), 0xFFFFFFFF);
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), 0xFFFFFFFF);
    } else {
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), g_rtl8139.hash[0]);
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), g_rtl8139.hash[1]);
    }

    // Then global 
    if (
        (filter & PACKET_TYPE_PROMISCUOUS) != 0 ||
        (filter & PACKET_TYPE_ALL_MULTICAST) != 0 ||
        (filter & PACKET_TYPE_MULTICAST) != 0
    ) {
        ctrl |= RCR_AM;
    } else {
        ctrl &= ~RCR_AM;
    }
    
    if ((filter & PACKET_TYPE_PROMISCUOUS) != 0) {
        ctrl |= RCR_AAP;
    } else {
        ctrl &= ~RCR_AAP;
    }

    // Set filter to hardware
    OUTPORT32((UINT32*)(g_rtl8139.address + RTL_RCR), ctrl);

    // Save actual filter
    g_rtl8139.filter = filter;

    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139CurrentPacketFilter\r\n"));
}

//------------------------------------------------------------------------------
//
//  Function:  RTL8139MulticastList
//
BOOL RTL8139MulticastList(UINT8 *pAddresses, UINT32 count)
{
    UINT32 i, crc, bit;
    UINT8 hash[8];

    OALMSGS(OAL_ETHER&&OAL_FUNC, (
        L"+RTL8139MulticastList(0x%08x, %d)\r\n", pAddresses, count
    ));

    memset(hash, 0, sizeof(hash));
    for (i = 0; i < count; i++) {
        crc = ComputeCRC(pAddresses, 6);
        bit = (crc >> 26) & 0x3f;
        hash[bit >> 3] |= 1 << (bit & 0x07);
        pAddresses += 6;
    }
    g_rtl8139.hash[0] = (hash[3] << 24)|(hash[2] << 16)|(hash[1] << 8)|hash[0];
    g_rtl8139.hash[1] = (hash[7] << 24)|(hash[6] << 16)|(hash[5] << 8)|hash[4];

    // But update only if all multicast and promiscuous mode aren't active
    if (
        (g_rtl8139.filter & PACKET_TYPE_ALL_MULTICAST) == 0 &&
        (g_rtl8139.filter & PACKET_TYPE_PROMISCUOUS) == 0
    ) {        
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR0), g_rtl8139.hash[0]);
        OUTPORT32((UINT32*)(g_rtl8139.address + RTL_MAR4), g_rtl8139.hash[1]);
    }

    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-RTL8139MulticastList(rc = 1)\r\n"));
    return TRUE;
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

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