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

📄 cs8900a.c

📁 我自己编译的armv4i wince60模拟器的bps源文件,已经验证可以使用,欢迎下载
💻 C
📖 第 1 页 / 共 2 页
字号:
    {
        OUTPORT16(&g_pCS8900->DATA0, *(UINT16*)pData);
        pData += sizeof *(UINT16*)pData;
    }

    rc = FALSE;		// Success

Exit:
    OALMSGS(OAL_ETHER && OAL_VERBOSE, (L"-CS8900ASendFrame(rc = %d)\r\n", rc));
    return (rc);
}

//------------------------------------------------------------------------------
//
//  Function:  CS8900AGetFrame
//
UINT16
CS8900AGetFrame(UINT8 *pData, UINT16 *pLength)
{
    UINT16 isq, length, status, count, data;
    UINT16 DeviceInterrupt;
    BOOL   GlobalInterrupt;

    OALMSGS(OAL_ETHER && OAL_VERBOSE, (
        L"+CS8900AGetFrame(0x%08x, %d)\r\n", pData, *pLength
    ));

    //
    // This routine could be interrupt driven, or polled.
    // When polled, it keeps the emulator so busy that it
    // starves other threads. The emulator already has the
    // ability to recognize the polling in the bootloader
    // by noting whether the interrupt for this device is
    // disabled. In order to make the emulator recognize it
    // here as well, we need to detect the polling by noting
    // that *global* interrupts are disabled, then disable at
    // the device level as well if so.
    //
    GlobalInterrupt = INTERRUPTS_ENABLE(FALSE);	// Disable to obtain state
    INTERRUPTS_ENABLE(GlobalInterrupt);          // Immediately restore it.

    // Mimic the global interrupt state at the device level too.
    if (!GlobalInterrupt)	// If polled
    {
        // Disable at the device level too so the emulator knows we're polling.
        // Now it can yeild to other threads on the host side.
        DeviceInterrupt = ReadPacketPage(BUS_CTL);
        WritePacketPage(BUS_CTL, DeviceInterrupt & ~BUS_CTL_ENABLE_IRQ);
        DeviceInterrupt &= BUS_CTL_ENABLE_IRQ;
    }
        
    length = 0;
    isq = INPORT16(&g_pCS8900->ISQ);

    if ((isq & ISQ_ID_MASK) == RX_EVENT_ID
    &&  (isq & RX_EVENT_RX_OK) != 0)
    {
        // Get RxStatus and length
        status = INPORT16(&g_pCS8900->DATA0);
        length = INPORT16(&g_pCS8900->DATA0);

        if (length > *pLength)
        {
            // If packet doesn't fit in buffer, skip it
            data = ReadPacketPage(RX_CFG);
            WritePacketPage(RX_CFG, data | RX_CFG_SKIP_1);
            length = 0;
        } else {
            // Read packet data
            count = length;
            while (count > 1)
            {
                data = INPORT16(&g_pCS8900->DATA0);
                *(UINT16*)pData = data;
                pData += sizeof *(UINT16*)pData;
                count -= sizeof *(UINT16*)pData;
            }

            // Read last one byte
            if (count > 0)
            {
                data = INPORT16(&g_pCS8900->DATA0);
                *pData = (UINT8)data;
            }
        }
    }

    if (!GlobalInterrupt)	// If polled
    {
        if (DeviceInterrupt)    // If it was enabled at the device level,
        {
            // Re-enable at the device level.
            CS8900AEnableInts();
        }
    }

    // Return packet size
    *pLength = length;

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

    return (length);
}

//------------------------------------------------------------------------------
//
//  Function:  CS8900AEnableInts
//
VOID
CS8900AEnableInts(VOID)
{
    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(VOID)
{
    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)
    ||  (filter & PACKET_TYPE_ALL_MULTICAST))
    {
        rxCtl |= RX_CTL_MULTICAST;
    } else {
        rxCtl &= ~RX_CTL_MULTICAST;
    }

    if (filter & PACKET_TYPE_PROMISCUOUS)
    {
        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);
}

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

static UINT16
ReadPacketPage(UINT16 address)
{
    OUTREG16(&g_pCS8900->PAGEIX, address);
    return (INREG16(&g_pCS8900->PAGE0));
}

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

static VOID
WritePacketPage(UINT16 address, UINT16 data)
{
    OUTREG16(&g_pCS8900->PAGEIX, address);
    OUTREG16(&g_pCS8900->PAGE0, data);
}

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

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);
}

⌨️ 快捷键说明

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