//------------------------------------------------------------------------------ // // Function: CS8900AGetFrame // UINT16 CS8900AGetFrame(UINT8 *pData, UINT16 *pLength) { UINT16 isq, length, status, count, data; OALMSGS(OAL_ETHER&&OAL_VERBOSE, ( L"+CS8900AGetFrame(0x%08x, %d)\r\n", pData, *pLength )); 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); count -= sizeof(UINT16); } // Read last one byte if (count > 0) { data = INPORT16(&g_pCS8900->DATA0); *pData = (UINT8)data; } } } // Return packet size *pLength = length; OALMSGS(OAL_ETHER&&OAL_VERBOSE, ( L"-CS8900AGetFrame(length = %d)\r\n", length )); return length; }
//------------------------------------------------------------------------------ // // 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); }