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

📄 lan91c.c

📁 老外的一个开源项目
💻 C
📖 第 1 页 / 共 2 页
字号:
    WRITE_REGISTER_USHORT(&g_pLAN91C->PTR, (PTR_AUTOINC | PTR_READ));
    OALStall(100);
    rc = READ_REGISTER_USHORT(&g_pLAN91C->DATA);

	// Release the packet
    switch (GET_CHIP_ID(g_chipRevision)) {
    case CHIP_ID_LAN91C111:
        WRITE_REGISTER_USHORT(&g_pLAN91C->MMUCR, MMUCR_111_RELEASE_TX);
        break;
    default:            
        WRITE_REGISTER_USHORT(&g_pLAN91C->MMUCR, MMUCR_REL_SPEC);
    }
    while ((READ_REGISTER_USHORT(&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
        WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 0);
        WRITE_REGISTER_USHORT(&g_pLAN91C->TCR, TCR_SWFDUP|TCR_PADEN|TCR_TXEN);

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

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

    // Set back bank 2
    WRITE_REGISTER_USHORT(&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
    WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 2);

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

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

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

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

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

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

            // Get control word (which can contain last byte)
            WRITE_REGISTER_USHORT(&g_pLAN91C->PTR, pointer);
            code = READ_REGISTER_USHORT(&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:
            WRITE_REGISTER_USHORT(&g_pLAN91C->MMUCR, MMUCR_111_REM_REL_RX);
            break;
        default:            
            WRITE_REGISTER_USHORT(&g_pLAN91C->MMUCR, MMUCR_REM_REL_TOP);
        }

        while ((READ_REGISTER_USHORT(&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)
    WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 2);
    WRITE_REGISTER_USHORT(&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
    WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 2);
    WRITE_REGISTER_USHORT(&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;

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

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

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

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

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

}

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

static void print_registers(void)
{
        UINT16 _temp;

        EdbgOutputDebugString("my2LAN91C111 registers:\r\n");
	    WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 0);
		EdbgOutputDebugString("0x%B- %x\r\n", 0, &g_pLAN91C->BANKSEL);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->TCR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->TCR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->EPHSR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->EPHSR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->RCR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->RCR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->ECR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->ECR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MIR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MIR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MCRPCR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MCRPCR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->DUMMY);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->DUMMY);

		WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 1);
		EdbgOutputDebugString("0x%B- %x\r\n", 1, &g_pLAN91C->BANKSEL);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->CFR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->CFR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->BAR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->BAR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->IAR0);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->IAR0);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->IAR1);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->IAR1);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->IAR2);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->IAR2);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->GPR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->GPR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->CTR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->CTR);

		WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 2);
		EdbgOutputDebugString("0x%B- %x\r\n", 1, &g_pLAN91C->BANKSEL);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MMUCR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MMUCR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->PNRARR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->PNRARR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->FIFO);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->FIFO);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->PTR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->PTR);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->DATA);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->DATA);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->DATAEX);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->DATAEX);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->INTR);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->INTR);

		WRITE_REGISTER_USHORT(&g_pLAN91C->BANKSEL, 3);
		EdbgOutputDebugString("0x%B- %x\r\n", 1, &g_pLAN91C->BANKSEL);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MT[0]);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MT[0]);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MT[1]);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MT[1]);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MT[2]);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MT[2]);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MT[3]);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MT[3]);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->MGMT);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->MGMT);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->REV);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->REV);
        _temp = READ_REGISTER_USHORT(&g_pLAN91C->ERDV);
        EdbgOutputDebugString("0x%B:\tat %x\r\n", _temp, &g_pLAN91C->ERDV);
}

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

⌨️ 快捷键说明

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