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

📄 cs8900a.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (length > 0)
        memcpy(pData, g_recvbuffer[g_recvdata].pdata, length);

    // Release buffer
    g_recvbuffer[g_recvdata].len = 0;
    g_recvdata++;
    if(g_recvdata >= CS8900A_RECV_BUFFER_COUNT)
        g_recvdata = 0;

    *pLength = length;

    // Read any pending frames, so they don't get lost
    CS8900AQueueGetFrame();

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

    return length;
}

//------------------------------------------------------------------------------
//
// Function: CS8900AEnableInts
//
VOID CS8900AEnableInts()
{
    UINT16 data;

    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+CS8900AEnableInts\r\n"));
    data = ReadPacketPage(BUS_CTL);
    WritePacketPage(BUS_CTL, data | BUS_CTL_ENABLE_IRQ);
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-CS8900AEnableInts\r\n"));
}

//------------------------------------------------------------------------------
//
// Function: CS8900ADisableInts
//
VOID CS8900ADisableInts()
{
    UINT16 data;

    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+CS8900ADisableInts\r\n"));
    data = ReadPacketPage(BUS_CTL);
    WritePacketPage(BUS_CTL, data & ~BUS_CTL_ENABLE_IRQ);
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-CS8900ADisableInts\r\n"));
}

//------------------------------------------------------------------------------
//
// Function: CS8900ACurrentPacketFilter
//
VOID CS8900ACurrentPacketFilter(UINT32 filter)
{
    UINT16 rxCtl;

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

    // Read current filter
    rxCtl = ReadPacketPage(RX_CTL);

    if ((filter & PACKET_TYPE_ALL_MULTICAST) != 0) {
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 0, 0xFFFF);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 2, 0xFFFF);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 4, 0xFFFF);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 6, 0xFFFF);
    } else {
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 0, g_hash[0]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 2, g_hash[1]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 4, g_hash[2]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 6, g_hash[3]);
    }

    if (
        (filter & PACKET_TYPE_MULTICAST) != 0 ||
        (filter & PACKET_TYPE_ALL_MULTICAST) != 0
    ) {
        rxCtl |= RX_CTL_MULTICAST;
    } else {
        rxCtl &= ~RX_CTL_MULTICAST;
    }

    if ((filter & PACKET_TYPE_PROMISCUOUS) != 0) {
        rxCtl |= RX_CTL_PROMISCUOUS;
    } else {
        rxCtl &= ~RX_CTL_PROMISCUOUS;
    }

    WritePacketPage(RX_CTL, rxCtl);

    // Save actual filter
    g_filter = filter;

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

//------------------------------------------------------------------------------
//
// Function: CS8900AMulticastList
//
BOOL CS8900AMulticastList(UINT8 *pAddresses, UINT32 count)
{
    UINT32 i, j, crc, data, bit;

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

    g_hash[0] = g_hash[1] = g_hash[2] = g_hash[3] = 0;
    for (i = 0; i < count; i++) {
        data = crc = ComputeCRC(pAddresses, 6);
        for (j = 0, bit = 0; j < 6; j++) {
            bit <<= 1;
            bit |= (data & 1);
            data >>= 1;
        }
        g_hash[bit >> 4] |= 1 << (bit & 0x0f);
        pAddresses += 6;
    }

    // But update only if all multicast mode isn't active
    if ((g_filter & PACKET_TYPE_ALL_MULTICAST) == 0) {        
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 0, g_hash[0]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 2, g_hash[1]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 4, g_hash[2]);
        WritePacketPage(LOGICAL_ADDR_FILTER_BASE + 6, g_hash[3]);
    }

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

//------------------------------------------------------------------------------
//
// Function: IOReadPacketPage
//
static UINT16 IOReadPacketPage(UINT16 address)
{
    OUTREG16(&g_pCS8900->PAGEIX, address);
    return INREG16(&g_pCS8900->PAGE0);
}

//------------------------------------------------------------------------------
//
// Function: IOWritePacketPage
//
static VOID IOWritePacketPage(UINT16 address, UINT16 data)
{
    OUTREG16(&g_pCS8900->PAGEIX, address);
    OUTREG16(&g_pCS8900->PAGE0, data);
}

//------------------------------------------------------------------------------
//
// Function: ComputeCRC
//
static UINT32 ComputeCRC(UINT8 *pBuffer, UINT32 length)
{
    UINT32 crc, carry, i, j;
    UINT8 byte;

    crc = 0xffffffff;
    for (i = 0; i < length; i++) {
        byte = pBuffer[i];
        for (j = 0; j < 8; j++) {
            carry = ((crc & 0x80000000) ? 1 : 0) ^ (byte & 0x01);
            crc <<= 1;
            byte >>= 1;
            if (carry) crc = (crc ^ 0x04c11db6) | carry;
        }
    }
    return crc;
}

//------------------------------------------------------------------------------
#ifdef CS8900_EEPROM_SUPPORT
//------------------------------------------------------------------------------
//
// Function: CS8900EEPROMWait
//
// The read and write EEPROM routines access the EEPROM that is attached to the
// CS8900. There are extra locations within the EEPROM that can be used to store
// other important information. The reset configuration accepted by the CS8900
// is given in the CS8900 spec. 
//
// Parameters:
//      timeOut
//          [in] Specifies the number of seconds to wait before the EEPROM
//          operation to complete.
//
// Returns:  
//      TRUE/FALSE for success.
//
//------------------------------------------------------------------------------
static BOOL CS8900EEPROMWait(UINT32 timeOut)
{
    BOOL rc = TRUE;
    DWORD dwCurSec;
    
    // Start time for timeout
    dwCurSec = OEMEthGetSecs();
        
    // SIBUSY is set when EEPROM is currently busy
    while (IOReadPacketPage(SELF_ST) & SELF_ST_SIBUSY) {
        // Check if we have exceeded timeout
        if ((OEMEthGetSecs() - dwCurSec) > timeOut) {
            OALMSGS(OAL_ERROR, (TEXT("+CS8900EEPROMWait: CS8900 busy timeout.\r\n")));
            rc = FALSE;
            break;
        }
    }

    return rc;
}

//------------------------------------------------------------------------------
//
// Function: CS8900ReadEEPROM
//
// The read and write EEPROM routines access the EEPROM that is attached to the
// CS8900. There are extra locations within the EEPROM that can be used to store
// other important information. The reset configuration accepted by the CS8900
// is given in the CS8900 spec. 
//
// Parameters:
//      EEPROMAddress
//          [in] EEPROM word address.
//      pwVal
//          [out] Storage for data read.
//
// Returns:
//      TRUE/FALSE for success.
//
//------------------------------------------------------------------------------
BOOL CS8900ReadEEPROM(UINT16 EEPROMAddress, UINT16 *pwVal)
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (
        L"+CS8900ReadEEPROM(0x%04x, 0x%08x)\r\n", EEPROMAddress, pwVal));

    if (pwVal == NULL || !(IOReadPacketPage(SELF_ST) & SELF_ST_EEPROM_PRESENT)) {
        OALMSGS(OAL_ERROR, (
            TEXT("+CS8900ReadEEPROM: EEPROM not present or invalid param.\r\n")));
        return FALSE;
    }
    
    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;

    // Issue read EEPROM command 
    IOWritePacketPage(EEPROM_COMMAND, (EEPROM_READ_REGISTER | (EEPROMAddress & 0xFF))); 
        
    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;
                                   
    *pwVal = IOReadPacketPage(EEPROM_DATA);

    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"-CS8900ReadEEPROM(*pwVal = 0x%04x)\r\n", *pwVal));
    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: CS8900WriteEEPROM
//
// The read and write EEPROM routines access the EEPROM that is attached to the
// CS8900. There are extra locations within the EEPROM that can be used to store
// other important information. The reset configuration accepted by the CS8900
// is given in the CS8900 spec. 
//
// Parameters:
//      EEPROMAddress
//          [in] EEPROM address.
//      data
//          [in] Data to write.
//
// Returns:
//      TRUE/FALSE for success.
//
//------------------------------------------------------------------------------
BOOL CS8900WriteEEPROM(UINT16 EEPROMAddress, UINT16 data)
{

    OALMSGS(OAL_ETHER&&OAL_FUNC, (
        L"+CS8900WriteEEPROM(0x%04x, 0x%08x)\r\n", EEPROMAddress, data));

    if (!(IOReadPacketPage(SELF_ST) & SELF_ST_EEPROM_PRESENT)) {
        OALMSGS(OAL_ERROR, (
            TEXT("+CS8900WriteEEPROM: EEPROM not present.")));
        return FALSE;
    }

    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;

    // Issue enable write enable EEPROM command & data
    IOWritePacketPage(EEPROM_COMMAND, EEPROM_ERASE_WRITE_ENABLE); 

    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;
    
    IOWritePacketPage(EEPROM_DATA, data); 
            
    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;

    // Issue write EEPROM command
    IOWritePacketPage(EEPROM_COMMAND, (EEPROM_WRITE_REGISTER | (EEPROMAddress & 0xFF))); 
    
    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;
                                           
    // Issue enable write disable EEPROM command & data
    IOWritePacketPage(EEPROM_COMMAND, EEPROM_ERASE_WRITE_DISABLE); 
    
    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;
    
    OALMSGS(OAL_ETHER&&OAL_VERBOSE, (L"-CS8900WriteEEPROM\r\n"));
    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: CS8900EEPROMDetect
//
// Checks that the CS8900 and EEPROM chips are present. Note: MUST be called
// before any other EEPROM access functions.
//
// Parameters:
//      pAddress
//          [in] CS8900 IO base address.
//
// Returns:  
//      FALSE for if no EEPROM or CS8900 device detected.
//
//------------------------------------------------------------------------------
BOOL CS8900EEPROMDetect(BYTE *pAddress)
{
    OALMSGS(OAL_ETHER&&OAL_FUNC, (
        L"+CS8900EEPROMDetect(0x%08x)\r\n", pAddress));

    // Save address
    g_pCS8900 = (CS8900A_REGS*)pAddress;

    // Wait for the Ethernet controller to become ready
    if (!CS8900EEPROMWait(5)) {
        OALMSG(OAL_INFO, (L"INFO: CS8900EEPROMDetect failed!\r\n"));
        return FALSE;
    }

    // First check if there is chip
    if (IOReadPacketPage(EISA_NUMBER) != CS8900A_EISA_NUMBER) {
        OALMSG(OAL_INFO, (L"INFO: Failed to detect CS8900 chip.\r\n"));
        return FALSE;
    }

    if(!(IOReadPacketPage(SELF_ST) & SELF_ST_EEPROM_PRESENT))
    {
        OALMSG(OAL_INFO, (L"INFO: No EEPROM detected with CS8900.\r\n"));
        return FALSE;
    }
    OALMSG(OAL_INFO, (L"INFO: EEPROM chip detected with CS8900. SELF_ST(0x%04x)\r\n", IOReadPacketPage(SELF_ST)));


    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"-CS8900EEPROMDetect\r\n"));
    return TRUE;
}

//------------------------------------------------------------------------------
//
// Function: CS8900EEPROMResetCfgStatus
//
// The function returns CS8900 reset configuration load status from EEPROM. 
//
// Parameters:
//      bReset
//          [in] Reset the chip or not.
//
// Returns:  
//      TRUE if reset configuration is loaded successfully on chip reset.
//
//------------------------------------------------------------------------------
BOOL CS8900EEPROMResetCfgValid(BOOL bReset)
{
    BOOL rc = FALSE;
    UINT32 count;
    
    OALMSGS(OAL_ETHER&&OAL_FUNC, (L"+CS8900EEPROMResetCfgValid\r\n"));

    // Reset the chip if neccessary
    if (bReset) {
        IOWritePacketPage(SELF_CTL, SELF_CTL_RESET);

        count = RETRY_COUNT;
        while (count-- > 0) {
            if ((IOReadPacketPage(SELF_ST) & SELF_ST_INITD) != 0)
                break;
        }        
        if (count == 0) {
            OALMSGS(OAL_ERROR, (L"ERROR: CS8900EEPROMResetCfgValid: Failed to reset card\r\n"));
            goto cleanUp;
        }
        
        count = RETRY_COUNT;
        while (count-- > 0) {
            if ((IOReadPacketPage(SELF_ST) & SELF_ST_SIBUSY) != 0)
                break;
        }
        if (count == 0) {
            OALMSGS(OAL_ERROR, (L"ERROR: CS8900EEPROMResetCfgValid: Failed to reset card\r\n"));
            goto cleanUp;
        }
    }

    // Wait for pending EEPROM operations to complete
    if (!CS8900EEPROMWait(5)) return FALSE;

    // Check if EEPROM is present and status is OK
    if ((IOReadPacketPage(SELF_ST) & (SELF_ST_EEPROM_PRESENT | SELF_ST_EEPROM_OK))
        == (SELF_ST_EEPROM_PRESENT | SELF_ST_EEPROM_OK)) {
        OALMSGS(OAL_INFO, (L"CS8900EEPROMResetCfgValid: EEPROM present & OK.\r\n"));
        rc  = TRUE;
    }

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

#endif // CS8900_EEPROM_SUPPORT

⌨️ 快捷键说明

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