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

📄 lan91c.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    switch (GET_CHIP_ID(g_chipRevision)) {
    case CHIP_ID_LAN91C111:
        OUTREG16(&g_pLAN91C->MMUCR, MMUCR_111_RELEASE_TX);
        break;
    default:            
        OUTREG16(&g_pLAN91C->MMUCR, MMUCR_REL_SPEC);
    }
    while ((INREG16(&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
        OUTREG16(&g_pLAN91C->BANKSEL, 0);
        OUTREG16(&g_pLAN91C->TCR, TCR_SWFDUP|TCR_PADEN|TCR_TXEN);

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

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

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

    return rc;
}

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

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

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

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

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

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

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

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

            // Copy packet
            count = length;
            while (count > 1) {
                OUTREG16(&g_pLAN91C->PTR, pointer);
                *(UINT16*)pos = INREG16(&g_pLAN91C->DATA);
                pointer += sizeof(UINT16);
                pos += sizeof(UINT16);
                count -= sizeof(UINT16);
            }

            // Get control word (which can contain last byte)
            OUTREG16(&g_pLAN91C->PTR, pointer);
            code = INREG16(&g_pLAN91C->DATA);
            pointer += sizeof(UINT16);
            if ((code & CTRL_ODD) != 0) {
                length++;
                *pos = (UINT8)code;
            }
        }

        // Release the memory for the received frame
        switch (GET_CHIP_ID(g_chipRevision)) {
        case CHIP_ID_LAN91C111:
            OUTREG16(&g_pLAN91C->MMUCR, MMUCR_111_REM_REL_RX);
            break;
        default:            
            OUTREG16(&g_pLAN91C->MMUCR, MMUCR_REM_REL_TOP);
        }

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

        // 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)
    OUTREG16(&g_pLAN91C->BANKSEL, 2);
    OUTREG16(&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
    OUTREG16(&g_pLAN91C->BANKSEL, 2);
    OUTREG16(&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;

    OUTREG16(&g_pLAN91C->BANKSEL, 0);
    OUTREG16(&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
    OUTREG16(&g_pLAN91C->BANKSEL, 3);
    OUTREG16(&g_pLAN91C->MT[0], h[0]);
    OUTREG16(&g_pLAN91C->MT[1], h[1]);
    OUTREG16(&g_pLAN91C->MT[2], h[2]);
    OUTREG16(&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.
    //
    OUTREG16(&g_pLAN91C->BANKSEL, 3);

    // Get the current MII register value.
    //
    mii_reg = INREG16(&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.
        //
        OUTREG16(&g_pLAN91C->MGMT, mii_reg | bits[i]);
        OALStall(50);

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

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

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

}

BOOL LAN91CsetMAC(UINT8 *pAddress, UINT16 mac[3])
{
    BOOL rc = FALSE;

    // Save address
    g_pLAN91C = (LAN91C_REGS*)pAddress;

    // Verify that network chip can be detected
    if ((INREG16(&g_pLAN91C->BANKSEL) & 0xFF00) != 0x3300) {

        OALMSGS(OAL_ERROR, (
            L"ERROR: LAN91CInit: Network Chip not found at 0x%08x\r\n", pAddress
        ));
        goto cleanUp;
    }

    // Select bank 1
    OUTREG16(&g_pLAN91C->BANKSEL, 1);
    OUTREG16(&g_pLAN91C->IAR0, mac[0]);
    OUTREG16(&g_pLAN91C->IAR1, mac[1]);
    OUTREG16(&g_pLAN91C->IAR2, mac[2]);

    // Write the MAC address into EEPROM
    SMCWriteEEPROM(0x20, mac[0]);
    SMCWriteEEPROM(0x21, mac[1]);
    SMCWriteEEPROM(0x22, mac[2]);

    // We are done
    rc = TRUE;

cleanUp:
    OALMSGS(TRUE, (
        L"\r\nSetting MAC Address(%02x:%02x:%02x:%02x:%02x:%02x)\r\n",
        mac[0]&0xFF, mac[0]>>8, mac[1]&0xFF, mac[1]>>8, mac[2]&0xFF, mac[2]>>8
    ));

    return rc;
}

BOOL SMCWriteEEPROM( UINT16 EEPROMAddress, UINT16 Data )
{
    DWORD dwCurTime;
    BOOL writeComplete;
    UINT16 controlRegister;

    OUTREG16(&g_pLAN91C->BANKSEL, 2);
    OUTREG16(&g_pLAN91C->PTR, (USHORT)(EEPROMAddress & 0x003F | 0x6000));
    OUTREG16(&g_pLAN91C->BANKSEL, 1);
    OUTREG16(&g_pLAN91C->GPR, Data);

    OUTREG16(&g_pLAN91C->BANKSEL, 1);
    controlRegister = INREG16(&g_pLAN91C->CTR);
    OUTREG16(&g_pLAN91C->BANKSEL, 1);
    OUTREG16(&g_pLAN91C->CTR, (USHORT)(controlRegister | 0x0005));

    // Loop until EEPROM data is written
    dwCurTime = OEMEthGetSecs();
    writeComplete = 1;
    while(writeComplete)
    {
        OUTREG16(&g_pLAN91C->BANKSEL, 1);
        writeComplete = INREG16(&g_pLAN91C->CTR) & 0x0003;

        if ((OEMEthGetSecs() - dwCurTime) > 5) {
            EdbgOutputDebugString("!SMCWriteEEPROM read timed out\n");
            return FALSE;
        }
    }
    return TRUE;
}

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

⌨️ 快捷键说明

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