?? rtl8139.c
字號:
DEBUG_PRINT((">>> RTL8139: multicast address mismatch\n")); /* update tally counter */ ++s->tally_counters.RxERR; return; } packet_header |= RxMulticast; DEBUG_PRINT((">>> RTL8139: multicast packet received\n")); /* update tally counter */ ++s->tally_counters.RxOkMul; } else if (s->phys[0] == buf[0] && s->phys[1] == buf[1] && s->phys[2] == buf[2] && s->phys[3] == buf[3] && s->phys[4] == buf[4] && s->phys[5] == buf[5]) { /* match */ if (!(s->RxConfig & AcceptMyPhys)) { DEBUG_PRINT((">>> RTL8139: rejecting physical address matching packet\n")); /* update tally counter */ ++s->tally_counters.RxERR; return; } packet_header |= RxPhysical; DEBUG_PRINT((">>> RTL8139: physical address matching packet received\n")); /* update tally counter */ ++s->tally_counters.RxOkPhy; } else { DEBUG_PRINT((">>> RTL8139: unknown packet\n")); /* update tally counter */ ++s->tally_counters.RxERR; return; } } /* if too small buffer, then expand it */ if (size < MIN_BUF_SIZE) { memcpy(buf1, buf, size); memset(buf1 + size, 0, MIN_BUF_SIZE - size); buf = buf1; size = MIN_BUF_SIZE; } if (rtl8139_cp_receiver_enabled(s)) { DEBUG_PRINT(("RTL8139: in C+ Rx mode ================\n")); /* begin C+ receiver mode *//* w0 ownership flag */#define CP_RX_OWN (1<<31)/* w0 end of ring flag */#define CP_RX_EOR (1<<30)/* w0 bits 0...12 : buffer size */#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)/* w1 tag available flag */#define CP_RX_TAVA (1<<16)/* w1 bits 0...15 : VLAN tag */#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)/* w2 low 32bit of Rx buffer ptr *//* w3 high 32bit of Rx buffer ptr */ int descriptor = s->currCPlusRxDesc; target_phys_addr_t cplus_rx_ring_desc; cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor; DEBUG_PRINT(("RTL8139: +++ C+ mode reading RX descriptor %d from host memory at %08x %08x = %016" PRIx64 "\n", descriptor, s->RxRingAddrHI, s->RxRingAddrLO, (uint64_t)cplus_rx_ring_desc)); uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; cpu_physical_memory_read(cplus_rx_ring_desc, (uint8_t *)&val, 4); rxdw0 = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); rxdw1 = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+8, (uint8_t *)&val, 4); rxbufLO = le32_to_cpu(val); cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4); rxbufHI = le32_to_cpu(val); DEBUG_PRINT(("RTL8139: +++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI)); if (!(rxdw0 & CP_RX_OWN)) { DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d is owned by host\n", descriptor)); s->IntrStatus |= RxOverflow; ++s->RxMissed; /* update tally counter */ ++s->tally_counters.RxERR; ++s->tally_counters.MissPkt; rtl8139_update_irq(s); return; } uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; /* TODO: scatter the packet over available receive ring descriptors space */ if (size+4 > rx_space) { DEBUG_PRINT(("RTL8139: C+ Rx mode : descriptor %d size %d received %d + 4\n", descriptor, rx_space, size)); s->IntrStatus |= RxOverflow; ++s->RxMissed; /* update tally counter */ ++s->tally_counters.RxERR; ++s->tally_counters.MissPkt; rtl8139_update_irq(s); return; } target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); /* receive/copy to target memory */ cpu_physical_memory_write( rx_addr, buf, size ); if (s->CpCmd & CPlusRxChkSum) { /* do some packet checksumming */ } /* write checksum */#if defined (RTL8139_CALCULATE_RXCRC) val = cpu_to_le32(crc32(0, buf, size));#else val = 0;#endif cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4);/* first segment of received packet flag */#define CP_RX_STATUS_FS (1<<29)/* last segment of received packet flag */#define CP_RX_STATUS_LS (1<<28)/* multicast packet flag */#define CP_RX_STATUS_MAR (1<<26)/* physical-matching packet flag */#define CP_RX_STATUS_PAM (1<<25)/* broadcast packet flag */#define CP_RX_STATUS_BAR (1<<24)/* runt packet flag */#define CP_RX_STATUS_RUNT (1<<19)/* crc error flag */#define CP_RX_STATUS_CRC (1<<18)/* IP checksum error flag */#define CP_RX_STATUS_IPF (1<<15)/* UDP checksum error flag */#define CP_RX_STATUS_UDPF (1<<14)/* TCP checksum error flag */#define CP_RX_STATUS_TCPF (1<<13) /* transfer ownership to target */ rxdw0 &= ~CP_RX_OWN; /* set first segment bit */ rxdw0 |= CP_RX_STATUS_FS; /* set last segment bit */ rxdw0 |= CP_RX_STATUS_LS; /* set received packet type flags */ if (packet_header & RxBroadcast) rxdw0 |= CP_RX_STATUS_BAR; if (packet_header & RxMulticast) rxdw0 |= CP_RX_STATUS_MAR; if (packet_header & RxPhysical) rxdw0 |= CP_RX_STATUS_PAM; /* set received size */ rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; rxdw0 |= (size+4); /* reset VLAN tag flag */ rxdw1 &= ~CP_RX_TAVA; /* update ring data */ val = cpu_to_le32(rxdw0); cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4); val = cpu_to_le32(rxdw1); cpu_physical_memory_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); /* update tally counter */ ++s->tally_counters.RxOk; /* seek to next Rx descriptor */ if (rxdw0 & CP_RX_EOR) { s->currCPlusRxDesc = 0; } else { ++s->currCPlusRxDesc; } DEBUG_PRINT(("RTL8139: done C+ Rx mode ----------------\n")); } else { DEBUG_PRINT(("RTL8139: in ring Rx mode ================\n")); /* begin ring receiver mode */ int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); /* if receiver buffer is empty then avail == 0 */ if (avail != 0 && size + 8 >= avail) { DEBUG_PRINT(("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr, avail, size + 8)); s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); return; } packet_header |= RxStatusOK; packet_header |= (((size+4) << 16) & 0xffff0000); /* write header */ uint32_t val = cpu_to_le32(packet_header); rtl8139_write_buffer(s, (uint8_t *)&val, 4); rtl8139_write_buffer(s, buf, size); /* write checksum */#if defined (RTL8139_CALCULATE_RXCRC) val = cpu_to_le32(crc32(0, buf, size));#else val = 0;#endif rtl8139_write_buffer(s, (uint8_t *)&val, 4); /* correct buffer write pointer */ s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize); /* now we can signal we have received something */ DEBUG_PRINT((" received: rx buffer length %d head 0x%04x read 0x%04x\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr)); } s->IntrStatus |= RxOK; if (do_interrupt) { rtl8139_update_irq(s); }}static void rtl8139_receive(void *opaque, const uint8_t *buf, int size){ rtl8139_do_receive(opaque, buf, size, 1);}static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize){ s->RxBufferSize = bufferSize; s->RxBufPtr = 0; s->RxBufAddr = 0;}static void rtl8139_reset(RTL8139State *s){ int i; /* restore MAC address */ memcpy(s->phys, s->macaddr, 6); /* reset interrupt mask */ s->IntrStatus = 0; s->IntrMask = 0; rtl8139_update_irq(s); /* prepare eeprom */ s->eeprom.contents[0] = 0x8129;#if 1 // PCI vendor and device ID should be mirrored here s->eeprom.contents[1] = 0x10ec; s->eeprom.contents[2] = 0x8139;#endif s->eeprom.contents[7] = s->macaddr[0] | s->macaddr[1] << 8; s->eeprom.contents[8] = s->macaddr[2] | s->macaddr[3] << 8; s->eeprom.contents[9] = s->macaddr[4] | s->macaddr[5] << 8; /* mark all status registers as owned by host */ for (i = 0; i < 4; ++i) { s->TxStatus[i] = TxHostOwns; } s->currTxDesc = 0; s->currCPlusRxDesc = 0; s->currCPlusTxDesc = 0; s->RxRingAddrLO = 0; s->RxRingAddrHI = 0; s->RxBuf = 0; rtl8139_reset_rxring(s, 8192); /* ACK the reset */ s->TxConfig = 0;#if 0// s->TxConfig |= HW_REVID(1, 0, 0, 0, 0, 0, 0); // RTL-8139 HasHltClk s->clock_enabled = 0;#else s->TxConfig |= HW_REVID(1, 1, 1, 0, 1, 1, 0); // RTL-8139C+ HasLWake s->clock_enabled = 1;#endif s->bChipCmdState = CmdReset; /* RxBufEmpty bit is calculated on read from ChipCmd */; /* set initial state data */ s->Config0 = 0x0; /* No boot ROM */ s->Config1 = 0xC; /* IO mapped and MEM mapped registers available */ s->Config3 = 0x1; /* fast back-to-back compatible */ s->Config5 = 0x0; s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD; s->CpCmd = 0x0; /* reset C+ mode */// s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation// s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex s->BasicModeCtrl = 0x1000; // autonegotiation s->BasicModeStatus = 0x7809; //s->BasicModeStatus |= 0x0040; /* UTP medium */ s->BasicModeStatus |= 0x0020; /* autonegotiation completed */ s->BasicModeStatus |= 0x0004; /* link is up */ s->NWayAdvert = 0x05e1; /* all modes, full duplex */ s->NWayLPAR = 0x05e1; /* all modes, full duplex */ s->NWayExpansion = 0x0001; /* autonegotiation supported */ /* also reset timer and disable timer interrupt */ s->TCTR = 0; s->TimerInt = 0; s->TCTR_base = 0; /* reset tally counters */ RTL8139TallyCounters_clear(&s->tally_counters);}void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters){ counters->TxOk = 0; counters->RxOk = 0; counters->TxERR = 0; counters->RxERR = 0; counters->MissPkt = 0; counters->FAE = 0; counters->Tx1Col = 0; counters->TxMCol = 0; counters->RxOkPhy = 0; counters->RxOkBrd = 0; counters->RxOkMul = 0; counters->TxAbt = 0; counters->TxUndrn = 0;}static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* tally_counters){ uint16_t val16; uint32_t val32; uint64_t val64; val64 = cpu_to_le64(tally_counters->TxOk); cpu_physical_memory_write(tc_addr + 0, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->RxOk); cpu_physical_memory_write(tc_addr + 8, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->TxERR); cpu_physical_memory_write(tc_addr + 16, (uint8_t *)&val64, 8); val32 = cpu_to_le32(tally_counters->RxERR); cpu_physical_memory_write(tc_addr + 24, (uint8_t *)&val32, 4); val16 = cpu_to_le16(tally_counters->MissPkt); cpu_physical_memory_write(tc_addr + 28, (uint8_t *)&val16, 2); val16 = cpu_to_le16(tally_counters->FAE); cpu_physical_memory_write(tc_addr + 30, (uint8_t *)&val16, 2); val32 = cpu_to_le32(tally_counters->Tx1Col); cpu_physical_memory_write(tc_addr + 32, (uint8_t *)&val32, 4); val32 = cpu_to_le32(tally_counters->TxMCol); cpu_physical_memory_write(tc_addr + 36, (uint8_t *)&val32, 4); val64 = cpu_to_le64(tally_counters->RxOkPhy); cpu_physical_memory_write(tc_addr + 40, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->RxOkBrd); cpu_physical_memory_write(tc_addr + 48, (uint8_t *)&val64, 8); val32 = cpu_to_le32(tally_counters->RxOkMul); cpu_physical_memory_write(tc_addr + 56, (uint8_t *)&val32, 4); val16 = cpu_to_le16(tally_counters->TxAbt); cpu_physical_memory_write(tc_addr + 60, (uint8_t *)&val16, 2); val16 = cpu_to_le16(tally_counters->TxUndrn); cpu_physical_memory_write(tc_addr + 62, (uint8_t *)&val16, 2);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -