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

📄 bcm11dbg.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
📖 第 1 页 / 共 2 页
字号:

    // Stop the DMA channel
    SETPORT32(&g_bcm11.pRxDmaRegs->CFG, DMA_CFG_STALL);
    while ((INPORT32(&g_bcm11.pRxDmaRegs->CFG) & DMA_CFG_STALL) == 0); 
    OUTPORT32(&g_bcm11.pRxDmaRegs->CFG, DMA_CFG_HALT);
    while ((INPORT32(&g_bcm11.pRxDmaRegs->CFG) & DMA_CFG_ENABLE) != 0);

    // Disable interrupts
    CLRPORT32(&g_bcm11.pIntcRegs->MASK, 1 << IRQ_DMA_EMAC_RX);

    // Operate in chaining mode with wrapping controlled by length register
    OUTPORT32(&g_bcm11.pRxDmaRegs->CFG, DMA_CFG_CHAIN);

    // Set max burst length
    OUTPORT32(&g_bcm11.pRxDmaRegs->MAXBURST, RX_BURST_MAX);

    // Set descriptor info
    OUTPORT32(&g_bcm11.pRxDmaRegs->ADDRESS, OALVAtoPA(g_bcm11.pRxDescFirst));
    OUTPORT32(&g_bcm11.pRxDmaRegs->LENGTH, g_bcm11.rxBuffers);

    // Interested in packet interrupts
    OUTPORT32(&g_bcm11.pRxDmaRegs->INTMASK, DMA_INT_PDONE);
    OUTPORT32(&g_bcm11.pRxDmaRegs->INTSTAT, DMA_INT_PDONE);

    // Set misc info
    OUTPORT32(&g_bcm11.pRxDmaRegs->STATUS, 0);
    OUTPORT32(&g_bcm11.pRxDmaRegs->FLOW_CTRL_TH, 0);
    OUTPORT32(&g_bcm11.pRxDmaRegs->FLOW_CTRL_LEN, 0);

    // Enable operation
    SETPORT32(&g_bcm11.pRxDmaRegs->CFG, DMA_CFG_ENABLE);

    rc = TRUE;
    
cleanUp:
    CHECKCOOKIE(3);
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-BCM11EdbgInit(rc = %d)\r\n", rc));
    return rc;
}

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

UINT16 BCM11EdbgSendFrame(UINT8 *pData, UINT32 length)
{
    UINT16 status;
    
    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (
        L"+BCM11EdbgSendFrame(0x%08x, %d)\r\n", pData, length
    ));

    CHECKCOOKIE(4);

    // Wait until actual position is busy
    while ((INREG32(&g_bcm11.pTxDescPos->status) & SWAP16(DMA_DESC_OWN)) != 0);
    
    // Check if packet has minimal size
    if (
        length < MAC_TYPE_OFFSET || length >= (TX_BUFFER_SIZE - MAC_TYPE_SIZE)
     ) {
        OALMSGS(OAL_ERROR, (L"ERROR: BCM11EdbgSendFrame: "
            L"Incorrect packet length %d\r\n", length
        ));
        return 1;
    }
    
    memcpy(g_bcm11.pTxBufferPos, pData, MAC_TYPE_OFFSET);
    memcpy(
        g_bcm11.pTxBufferPos + MAC_TYPE_OFFSET + MAC_TYPE_SIZE, 
        pData + MAC_TYPE_OFFSET, length - MAC_TYPE_OFFSET
    );
    if (length < 64) {
        memset(g_bcm11.pTxBufferPos + MAC_TYPE_SIZE + length, 0xff, 64 - length);
        length = 64;
    }
    
    // Set TX DMA descriptor
    length += MAC_TYPE_SIZE;
    status = DMA_DESC_OWN|DMA_DESC_SOP|DMA_DESC_EOP|DMA_DESC_ETHCRC;
    g_bcm11.pTxDescPos->length = SWAP16(length);
    g_bcm11.pTxDescPos->status = SWAP16(status);        

    //  Start transmission
    SETREG32(&g_bcm11.pTxDmaRegs->CFG, DMA_CFG_ENABLE);

    // Move to next buffer position
    g_bcm11.pTxDescPos++;
    g_bcm11.pTxBufferPos += TX_BUFFER_SIZE;
    if (g_bcm11.pTxDescPos > g_bcm11.pTxDescLast) {
        g_bcm11.pTxDescPos = g_bcm11.pTxDescFirst;
        g_bcm11.pTxBufferPos  = g_bcm11.pTxBuffers;
    }

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

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

UINT16 BCM11EdbgGetFrame(UINT8 *pData, UINT16 *pLength)
{
    UINT32 length;

    CHECKCOOKIE(6);
    
    length = 0;
    while ((INREG32(&g_bcm11.pRxDescPos->status) & SWAP16(DMA_DESC_OWN)) == 0) {

        length = SWAP16(g_bcm11.pRxDescPos->length);
        if (length > 2 * MAC_CRC_SIZE + MAC_TYPE_SIZE) {
            // Fix length
            length -= 2 * MAC_CRC_SIZE + MAC_TYPE_SIZE;
            // When packet fits to buffer copy it, else skip
            if (length <= *pLength) {
                memcpy(pData, g_bcm11.pRxBufferPos, MAC_TYPE_OFFSET);
                memcpy(
                    pData + MAC_TYPE_OFFSET, 
                    g_bcm11.pRxBufferPos + MAC_TYPE_OFFSET + MAC_TYPE_SIZE,
                    length - MAC_TYPE_OFFSET
                );
            } else {
                length = 0;
            }                    
        } else {
            length = 0;
        }

        // Return descriptor to ring
        g_bcm11.pRxDescPos->length = SWAP16(RX_BUFFER_SIZE);
        g_bcm11.pRxDescPos->status = SWAP16(DMA_DESC_OWN);
        // Start DMA in case it is stopped
        SETREG32(&g_bcm11.pRxDmaRegs->CFG, DMA_CFG_ENABLE);

        // Move to next descriptor
        if (++g_bcm11.pRxDescPos <= g_bcm11.pRxDescLast) {
            g_bcm11.pRxBufferPos += RX_BUFFER_SIZE;
        } else {            
            g_bcm11.pRxDescPos = g_bcm11.pRxDescFirst;
            g_bcm11.pRxBufferPos = g_bcm11.pRxBuffers;
        }

        // Clear interrupt
        OUTREG32(&g_bcm11.pRxDmaRegs->INTSTAT, DMA_INT_PDONE);
        
        // If length is non zero we get a packet
        if (length > 0) break;        
    }        

    CHECKCOOKIE(7);
    *pLength = (USHORT)length;
    return *pLength;
}

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

VOID BCM11EdbgEnableInts()
{
    SETPORT32(&g_bcm11.pIntcRegs->MASK, 1 << IRQ_DMA_EMAC_RX);
}

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

VOID BCM11EdbgDisableInts()
{
    CLRPORT32(&g_bcm11.pIntcRegs->MASK, 1 << IRQ_DMA_EMAC_RX);
}

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

VOID BCM11EdbgCurrentPacketFilter(UINT32 filter)
{
    // Disable multicast & broadcast
    CLRREG32(&g_bcm11.pEthRegs->CTRL_SMP, CTRL_SMP_BCST|CTRL_SMP_MCST);

    if ((filter & PACKET_TYPE_ALL_MULTICAST) != 0) {
        // Enable multicast flooding
        SETREG32(&g_bcm11.pEthRegs->CTRL_SMP, CTRL_SMP_MCST);
    }
    if ((filter & PACKET_TYPE_BROADCAST) != 0) {
        // Enable broadcast flooding
        SETREG32(&g_bcm11.pEthRegs->CTRL_SMP, CTRL_SMP_BCST);
    }
}

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

BOOL BCM11EdbgMulticastList(UINT8 *pAddresses, UINT32 count)
{
    UINT32 i;

    // Add multicast address as static entry to ARL table
    for (i = 0; i < count; i++) {
        arlWrite((UINT16*)pAddresses, 10, TRUE, TRUE, FALSE);
        pAddresses += MAC_ADDR_SIZE;
    }
    return TRUE;
}

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

static UINT8 reverseByte(UINT8 data)
{
    UINT8 result, mask;

    result = 0;
    for (mask = 0x80; mask != 0; mask >>= 1) {
        result >>= 1;
        if ((data & mask) != 0) result |= 0x80;
    }
    return result;    
}

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

static VOID ssramWrite(UINT32 address, UINT32 hiData, UINT32 loData)
{
    BCM11_ETH_REGS *pEthRegs = OALPAtoUA(BCM11_ETH_REGS_PA);

    // make sure that address isn't too big
    address &= 0x1FFF;

    // set data
    OUTREG32(&pEthRegs->SSRAM_DATA_LSW, loData);
    OUTREG32(&pEthRegs->SSRAM_DATA_MSW, hiData);
    
    // put SSRAM into read mode
    OUTREG32(&pEthRegs->SSRAM_ADDR, 0);

    // set SSRAM address
    OUTREG32(&pEthRegs->SSRAM_ADDR, address);

    // start read
    OUTREG32(&pEthRegs->SSRAM_ADDR, SSRAM_START|address);
    
    // wait for read done
    while ((INREG32(&pEthRegs->SSRAM_ADDR) & SSRAM_START) != 0);
}

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

static VOID ssramRead(UINT32 address, UINT32 *pHiData, UINT32 *pLoData)
{
    BCM11_ETH_REGS *pEthRegs = OALPAtoUA(BCM11_ETH_REGS_PA);

    // make sure that address isn't too big
    address &= 0x1FFF;
    
    // put SSRAM into read mode
    OUTREG32(&pEthRegs->SSRAM_ADDR, SSRAM_READ);

    // set SSRAM address
    OUTREG32(&pEthRegs->SSRAM_ADDR, SSRAM_READ|address);

    // start read
    OUTREG32(&pEthRegs->SSRAM_ADDR, SSRAM_READ|SSRAM_START|address);
    
    // wait for read done
    while ((INREG32(&pEthRegs->SSRAM_ADDR) & SSRAM_START) != 0);

    // read data
    *pLoData = INREG32(&pEthRegs->SSRAM_DATA_LSW);
    *pHiData = INREG32(&pEthRegs->SSRAM_DATA_MSW);
}

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

static VOID arlInit()
{
    UINT32 i, address;
    
    // Clear ARL
    for (i = 0; i < SSRAM_ARL_ENTRIES; i++) {
        address = ((i & 0x03E0) << 3)|0x00E0|(i & 0x001F);
        ssramWrite(address, 0, 0);
    }
}

//------------------------------------------------------------------------------
//
//  This function write to entry 0 only, entry 1 is cleared....
//
static VOID arlWrite(
    UINT16 mac[3], UINT32 port, BOOL valid, BOOL stat, BOOL learn
) {
    BCM11_ETH_REGS *pEthRegs = OALPAtoUA(BCM11_ETH_REGS_PA);
    UINT32 hi, lo, opt;
    UINT32 i;
    UINT16 mcx[3];

    // First reverse MAC address bits & swap half words
    for (i = 0; i < 3; i++) {
        mcx[i]  = reverseByte(mac[i] & 0xFF) << 8;
        mcx[i] |= reverseByte(mac[i] >> 8) & 0xFF;
    }
    
    // Then prepare values for write
    hi = mcx[0];
    lo = (mcx[1] << 16) | mcx[2];

    // Calculate options
    opt = ARLA_VALID|((port & 0xF) << 16);
    if (stat) opt |= ARLA_STATIC;
    if (learn) opt |= ARLA_AGE;

    // Write it to entry 0
    OUTREG32(&pEthRegs->ARLA_ENTRY0_LSW, lo);
    OUTREG32(&pEthRegs->ARLA_ENTRY0_MSW, hi | opt);
    OUTREG32(&pEthRegs->ARLA_ENTRY1_LSW, 0);
    OUTREG32(&pEthRegs->ARLA_ENTRY1_MSW, 0);
    OUTREG32(&pEthRegs->ARLA_ADDR_LSW, lo);
    OUTREG32(&pEthRegs->ARLA_ADDR_MSW, hi);

    // Start write
    OUTREG32(&pEthRegs->ARLA_RW, ARLA_RW_START|ARLA_RW_WRITE);

    // Wait until finished    
    while ((INREG32(&pEthRegs->ARLA_RW) & ARLA_RW_START) != 0);
}

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

⌨️ 快捷键说明

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