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

📄 lan91c.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 2 页
字号:

    if ((INPORT16(&g_pLAN91C->INTR) & INTR_TX) == 0)
    {
        OALMSGS(OAL_ERROR, (L"ERROR: LAN91CSendFrame: Timed out waiting for the transfer to complete.\r\n"));
        return(1);
    }

	// Read TXDONE Pkt# from FIFO Port Register
    OUTPORT16(&g_pLAN91C->BANKSEL, 2);
    packetNumber = (INPORT16(&g_pLAN91C->FIFO) & 0x3F);

	// Write to Packet Number Register
    OUTPORT16(&g_pLAN91C->PNRARR, packetNumber);

	// Retrieve packet status
    OUTPORT16(&g_pLAN91C->PTR, (PTR_AUTOINC | PTR_READ));
    OALStall(100);

    rc = INPORT16(&g_pLAN91C->DATA);
    // SQET bit always set on lan91c111 and lan100FD (so mask it) on all plats
    rc &= ~EPH_STAT_SQET;

	// Release the packet
    switch (GET_CHIP_ID(g_chipRevision)) {
    case CHIP_ID_LAN91C111:
        OUTPORT16(&g_pLAN91C->MMUCR, MMUCR_111_RELEASE_TX);
        break;
    default:            
        OUTPORT16(&g_pLAN91C->MMUCR, MMUCR_REL_SPEC);
    }
    while ((INPORT16(&g_pLAN91C->MMUCR) & MMUCR_BUSY) != 0);

	// Clear the tx interrupt status
    SETPORT16(&g_pLAN91C->INTR, INTR_TX);

    // Tx error?
    if (rc & (EPH_STAT_TXUNRN | EPH_STAT_SQET | EPH_STAT_LOSTCARR | EPH_STAT_LATCOL | EPH_STAT_16COL))
    {
        // Display error status.
        OALMSGS(OAL_ERROR, (L"ERROR: LAN91CSendFrame: status = ( "));
        if (rc & EPH_STAT_TXUNRN)
        {
            OALMSGS(OAL_ERROR, (L"TXUNRN "));
        }
        if (rc & EPH_STAT_SQET)
        {
            OALMSGS(OAL_ERROR, (L"SQET "));
        }
        if (rc & EPH_STAT_LOSTCARR)
        {
            OALMSGS(OAL_ERROR, (L"LOSTCARR "));
        }
        if (rc & EPH_STAT_LATCOL)
        {
            OALMSGS(OAL_ERROR, (L"LATCOL "));
        }
        if (rc & EPH_STAT_16COL)
        {
            OALMSGS(OAL_ERROR, (L"16COL "));
        }
        OALMSGS(OAL_ERROR, (L")\r\n"));
            
        // Re-enable TXENA
        OUTPORT16(&g_pLAN91C->BANKSEL, 0);
        OUTPORT16(&g_pLAN91C->TCR, TCR_PADEN|TCR_TXEN);

        // Failure.
        rc = 1;
    }
    else
    {
        // Success.
        rc = 0;
    }

    // Clear the statistics registers
    OUTPORT16(&g_pLAN91C->BANKSEL, 0);
    INPORT16(&g_pLAN91C->ECR);

    // Set back bank 2
    OUTPORT16(&g_pLAN91C->BANKSEL, 2);

    return rc;
}

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

UINT16 LAN91CGetFrame(UINT8 *pBuffer, UINT16 *pLength)
{
    UINT8 *pos = pBuffer;
    UINT16 code, pointer;
    UINT32 length, count;
    BOOL   bErr = FALSE; 

    // Make sure that bank 2 is actual
    OUTPORT16(&g_pLAN91C->BANKSEL, 2);

    length = 0;
    while ((INPORT16(&g_pLAN91C->INTR) & INTR_RX) != 0) {

        // Setup pointer address register
        pointer = PTR_RCV | PTR_READ;

        // Read status
        OUTPORT16(&g_pLAN91C->PTR, pointer);
        code = INPORT16(&g_pLAN91C->DATA);
        pointer += sizeof(UINT16);

        if ((code & (STAT_ALGNERR|STAT_BADCRC|STAT_LONG|STAT_SHORT)) == 0) {
        

            // Get packet size
            OUTPORT16(&g_pLAN91C->PTR, pointer);
            length = (INPORT16(&g_pLAN91C->DATA) & 0x07FF) - 6;
            pointer += sizeof(UINT16);

            //  Check packet size
            if( length <= *pLength )
            {
                // Copy packet
                count = length;
                while (count > 1) {
                    OUTPORT16(&g_pLAN91C->PTR, pointer);
                    *(UINT16*)pos = INPORT16(&g_pLAN91C->DATA);
                    pointer += sizeof(UINT16);
                    pos += sizeof(UINT16);
                    count -= sizeof(UINT16);
                }


                // Get control word (which can contain last byte)
                OUTPORT16(&g_pLAN91C->PTR, pointer);
                code = INPORT16(&g_pLAN91C->DATA);
                pointer += sizeof(UINT16);
                if ((code & CTRL_ODD) != 0) {
                    length++;
                    *pos = (UINT8)code;
                }
            }
            else
            {
                //  Error getting the packet size
                OALMSGS(OAL_ERROR, (L"ERROR: LAN91CGetFrame: packet size (%d) > than buf len (%d)\r\n", length, *pLength ));
                length = 0;
                bErr = TRUE;
            }
        }

        // Release the memory for the received frame
        switch (GET_CHIP_ID(g_chipRevision)) {

            case CHIP_ID_LAN91C111:
                OUTPORT16(&g_pLAN91C->MMUCR, MMUCR_111_REM_REL_RX);
                break;

            default:            
                OUTPORT16(&g_pLAN91C->MMUCR, MMUCR_REM_REL_TOP);
        }

        while ((INPORT16(&g_pLAN91C->MMUCR) & MMUCR_BUSY) != 0);


        // If error, break
        if( bErr ) break;

        // If length is non zero we get a packet
        if (length > 0) break;

    }        

    *pLength = (UINT16)length;
    return (*pLength);
}


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

VOID LAN91CEnableInts()
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+LAN91CEnableInts\r\n"));

    // Only enable receive interrupts (we poll for Tx completion)
    OUTPORT16(&g_pLAN91C->BANKSEL, 2);
    OUTPORT16(&g_pLAN91C->INTR, INTR_RX_MASK);

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

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

VOID LAN91CDisableInts()
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+LAN91CDisableInts\r\n"));

    // Disable all interrupts
    OUTPORT16(&g_pLAN91C->BANKSEL, 2);
    OUTPORT16(&g_pLAN91C->INTR, 0);

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

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

VOID LAN91CCurrentPacketFilter(UINT32 filter)
{
    UINT16 rcr = RCR_RXEN|RCR_STRIP_CRC;

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

    if ((filter & PACKET_TYPE_ALL_MULTICAST) != 0) rcr |= RCR_ALMUL;
    if ((filter & PACKET_TYPE_PROMISCUOUS) != 0) rcr |= RCR_PRMS;

    OUTPORT16(&g_pLAN91C->BANKSEL, 0);
    OUTPORT16(&g_pLAN91C->RCR, rcr);

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

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

BOOL LAN91CMulticastList(UINT8 *pAddresses, UINT32 count)
{
    UINT32 crc, i;
    UINT16 h[4];

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

    // Calculate hash bits       
    h[0] = h[1] = h[2] = h[3] = 0;
    for (i = 0; i < count; i++) {
        crc = Crc(pAddresses);
        h[crc >> 30] |= 1 << ((crc >> 26) & 0x0F);
        pAddresses += 6;
    }

    // Write it to hardware
    OUTPORT16(&g_pLAN91C->BANKSEL, 3);
    OUTPORT16(&g_pLAN91C->MT[0], h[0]);
    OUTPORT16(&g_pLAN91C->MT[1], h[1]);
    OUTPORT16(&g_pLAN91C->MT[2], h[2]);
    OUTPORT16(&g_pLAN91C->MT[3], h[3]);

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

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

UINT32 Crc(UINT8 *pAddress)
{
    UINT32 crc, carry;
    UINT32 i, j;
    UINT8 uc;

    crc = 0xFFFFFFFF;
    for (i = 0; i < 6; i++) {
        uc = pAddress[i];
        for (j = 0; j < 8; j++) {
            carry = ((crc & 0x80000000) ? 1 : 0) ^ (uc & 0x01);
            crc <<= 1;
            uc >>= 1;
            if (carry) crc = (crc ^ 0x04c11db6) | carry;
        }
    }
    return crc;
}

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

static VOID PhyWrite(UINT8 PHYaddr, UINT8 PHYreg, UINT16 PHYdata)
{
    INT32 i;
    UINT16 mask;
    UINT16 mii_reg;
    UINT8 bits[65];
    INT32 clk_idx = 0;

    // 32 consecutive ones on MDO to establish sync.
    //
    for (i = 0; i < 32; ++i)
    {
        bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
    }

    // Start code <01>.
    //
    bits[clk_idx++] = MGMT_MDOE;
    bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;

    // Write command <01>.
    //
    bits[clk_idx++] = MGMT_MDOE;
    bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;

    // Output the PHY address, msb first.
    //
    mask = (UINT8)0x10;
    for (i = 0; i < 5; ++i)
    {
        if (PHYaddr & mask)
            bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
        else
            bits[clk_idx++] = MGMT_MDOE;

        // Shift to next lowest bit.
        mask >>= 1;
    }

    // Output the PHY register number, msb first.
    //
    mask = (UINT8)0x10;
    for (i = 0; i < 5; ++i)
    {
        if (PHYreg & mask)
            bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
        else
            bits[clk_idx++] = MGMT_MDOE;

        // Shift to next lowest bit.
        mask >>= 1;
    }

    // Tristate and turnaround (2 bit times).
    //
    bits[clk_idx++] = 0;
    bits[clk_idx++] = 0;

    // Write out 16 bits of data, msb first.
    //
    mask = 0x8000;
    for (i = 0; i < 16; ++i)
    {
        if (PHYdata & mask)
            bits[clk_idx++] = MGMT_MDOE | MGMT_MDO;
        else
            bits[clk_idx++] = MGMT_MDOE;

        // Shift to next lowest bit.
        mask >>= 1;
    }

    // Final clock bit (tristate).
    //
    bits[clk_idx++] = 0;

    // Select bank 3.
    //
    OUTPORT16(&g_pLAN91C->BANKSEL, 3);

    // Get the current MII register value.
    //
    mii_reg = INPORT16(&g_pLAN91C->MGMT);

    // Turn off all MII Interface bits.
    //
    mii_reg &= ~(MGMT_MDOE | MGMT_MCLK | 
                 MGMT_MDI  | MGMT_MDO);

    // Clock all cycles.
    //
    for (i = 0; i < sizeof bits; ++i)
    {
        // Clock Low - output data.
        //
        OUTPORT16(&g_pLAN91C->MGMT, mii_reg | bits[i]);
        OALStall(50);

        // Clock Hi - input data.
        //
        OUTPORT16(&g_pLAN91C->MGMT, (UINT16)(mii_reg | bits[i] | MGMT_MCLK));
        OALStall(50);

        bits[i] |= INPORT16(&g_pLAN91C->MGMT) & MGMT_MDI;
    }

    // Return to idle state.  Set clock to low, data to low, and output tristated.
    //
    OUTPORT16(&g_pLAN91C->MGMT, mii_reg);
    OALStall(50);

}

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

⌨️ 快捷键说明

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