📄 rtl8139.c
字号:
static uint32_t rtl8139_Config5_read(RTL8139State *s){ uint32_t ret = s->Config5;#ifdef DEBUG_RTL8139 printf("RTL8139: Config5 read val=0x%02x\n", ret);#endif return ret;}static void rtl8139_TxConfig_write(RTL8139State *s, uint32_t val){ if (!rtl8139_transmitter_enabled(s)) {#ifdef DEBUG_RTL8139 printf("RTL8139: transmitter disabled; no TxConfig write val=0x%08x\n", val);#endif return; }#ifdef DEBUG_RTL8139 printf("RTL8139: TxConfig write val=0x%08x\n", val);#endif val = SET_MASKED(val, TxVersionMask | 0x8070f80f, s->TxConfig); s->TxConfig = val;}static void rtl8139_TxConfig_writeb(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139C TxConfig via write(b) val=0x%02x\n", val);#endif uint32_t tc = s->TxConfig; tc &= 0xFFFFFF00; tc |= (val & 0x000000FF); rtl8139_TxConfig_write(s, tc);}static uint32_t rtl8139_TxConfig_read(RTL8139State *s){ uint32_t ret = s->TxConfig;#ifdef DEBUG_RTL8139 printf("RTL8139: TxConfig read val=0x%04x\n", ret);#endif return ret;}static void rtl8139_RxConfig_write(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: RxConfig write val=0x%08x\n", val);#endif /* mask unwriteable bits */ val = SET_MASKED(val, 0xf0fc0040, s->RxConfig); s->RxConfig = val; /* reset buffer size and read/write pointers */ rtl8139_reset_rxring(s, 8192 << ((s->RxConfig >> 11) & 0x3));#ifdef DEBUG_RTL8139 printf("RTL8139: RxConfig write reset buffer size to %d\n", s->RxBufferSize);#endif}static uint32_t rtl8139_RxConfig_read(RTL8139State *s){ uint32_t ret = s->RxConfig;#ifdef DEBUG_RTL8139 printf("RTL8139: RxConfig read val=0x%08x\n", ret);#endif return ret;}static int rtl8139_transmit_one(RTL8139State *s, int descriptor){ if (!rtl8139_transmitter_enabled(s)) {#ifdef DEBUG_RTL8139 printf("RTL8139: +++ cannot transmit from descriptor %d: transmitter disabled\n", descriptor);#endif return 0; } if (s->TxStatus[descriptor] & TxHostOwns) {#ifdef DEBUG_RTL8139 printf("RTL8139: +++ cannot transmit from descriptor %d: owned by host (%08x)\n", descriptor, s->TxStatus[descriptor]);#endif return 0; }#ifdef DEBUG_RTL8139 printf("RTL8139: +++ transmitting from descriptor %d\n", descriptor);#endif int txsize = s->TxStatus[descriptor] & 0x1fff; uint8_t txbuffer[0x2000];#ifdef DEBUG_RTL8139 printf("RTL8139: +++ transmit reading %d bytes from host memory at 0x%08x\n", txsize, s->TxAddr[descriptor]);#endif cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize); qemu_send_packet(s->vc, txbuffer, txsize); /* Mark descriptor as transferred */ s->TxStatus[descriptor] |= TxHostOwns; s->TxStatus[descriptor] |= TxStatOK;#ifdef DEBUG_RTL8139 printf("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor);#endif /* update interrupt */ s->IntrStatus |= TxOK; rtl8139_update_irq(s); return 1;}static int rtl8139_cplus_transmit_one(RTL8139State *s){ if (!rtl8139_transmitter_enabled(s)) {#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode: transmitter disabled\n");#endif return 0; } if (!rtl8139_cp_transmitter_enabled(s)) {#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode: C+ transmitter disabled\n");#endif return 0 ; } int descriptor = s->currCPlusTxDesc; target_phys_addr_t cplus_tx_ring_desc = rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]); /* Normal priority ring */ cplus_tx_ring_desc += 16 * descriptor;#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode reading TX descriptor %d from host memory at %08x0x%08x = 0x%8lx\n", descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc);#endif uint32_t val, txdw0,txdw1,txbufLO,txbufHI; cpu_physical_memory_read(cplus_tx_ring_desc, (uint8_t *)&val, 4); txdw0 = le32_to_cpu(val); cpu_physical_memory_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4); txdw1 = le32_to_cpu(val); cpu_physical_memory_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4); txbufLO = le32_to_cpu(val); cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4); txbufHI = le32_to_cpu(val);#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, txdw0, txdw1, txbufLO, txbufHI);#endif/* w0 ownership flag */#define CP_TX_OWN (1<<31)/* w0 end of ring flag */#define CP_TX_EOR (1<<30)/* first segment of received packet flag */#define CP_TX_FS (1<<29)/* last segment of received packet flag */#define CP_TX_LS (1<<28)/* large send packet flag */#define CP_TX_LGSEN (1<<27)/* IP checksum offload flag */#define CP_TX_IPCS (1<<18)/* UDP checksum offload flag */#define CP_TX_UDPCS (1<<17)/* TCP checksum offload flag */#define CP_TX_TCPCS (1<<16)/* w0 bits 0...15 : buffer size */#define CP_TX_BUFFER_SIZE (1<<16)#define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1)/* w1 tag available flag */#define CP_RX_TAGC (1<<17)/* w1 bits 0...15 : VLAN tag */#define CP_TX_VLAN_TAG_MASK ((1<<16) - 1)/* w2 low 32bit of Rx buffer ptr *//* w3 high 32bit of Rx buffer ptr *//* set after transmission *//* FIFO underrun flag */#define CP_TX_STATUS_UNF (1<<25)/* transmit error summary flag, valid if set any of three below */#define CP_TX_STATUS_TES (1<<23)/* out-of-window collision flag */#define CP_TX_STATUS_OWC (1<<22)/* link failure flag */#define CP_TX_STATUS_LNKF (1<<21)/* excessive collisions flag */#define CP_TX_STATUS_EXC (1<<20) if (!(txdw0 & CP_TX_OWN)) {#if defined(DEBUG_RTL8139) printf("RTL8139: C+ Tx mode : descriptor %d is owned by host\n", descriptor);#endif return 0 ; }#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ Tx mode : transmitting from descriptor %d\n", descriptor);#endif int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); uint8_t txbuffer[CP_TX_BUFFER_SIZE];#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode transmit reading %d bytes from host memory at 0x%08x\n", txsize, tx_addr);#endif cpu_physical_memory_read(tx_addr, txbuffer, txsize); /* transmit the packet */ qemu_send_packet(s->vc, txbuffer, txsize); /* transfer ownership to target */ txdw0 &= ~CP_RX_OWN; /* reset error indicator bits */ txdw0 &= ~CP_TX_STATUS_UNF; txdw0 &= ~CP_TX_STATUS_TES; txdw0 &= ~CP_TX_STATUS_OWC; txdw0 &= ~CP_TX_STATUS_LNKF; txdw0 &= ~CP_TX_STATUS_EXC; /* update ring data */ val = cpu_to_le32(txdw0); cpu_physical_memory_write(cplus_tx_ring_desc, (uint8_t *)&val, 4);// val = cpu_to_le32(txdw1);// cpu_physical_memory_write(cplus_tx_ring_desc+4, &val, 4); /* seek to next Rx descriptor */ if (txdw0 & CP_TX_EOR) { s->currCPlusTxDesc = 0; } else { ++s->currCPlusTxDesc; }#ifdef DEBUG_RTL8139 printf("RTL8139: +++ C+ mode transmitted %d bytes from descriptor %d\n", txsize, descriptor);#endif return 1;}static void rtl8139_cplus_transmit(RTL8139State *s){ int txcount = 0; while (rtl8139_cplus_transmit_one(s)) { ++txcount; } /* Mark transfer completed */ if (!txcount) {#ifdef DEBUG_RTL8139 printf("RTL8139: C+ mode : transmitter queue stalled, current TxDesc = %d\n", s->currCPlusTxDesc);#endif } else { /* update interrupt status */ s->IntrStatus |= TxOK; rtl8139_update_irq(s); }}static void rtl8139_transmit(RTL8139State *s){ int descriptor = s->currTxDesc, txcount = 0; /*while*/ if (rtl8139_transmit_one(s, descriptor)) { ++s->currTxDesc; s->currTxDesc %= 4; ++txcount; } /* Mark transfer completed */ if (!txcount) {#ifdef DEBUG_RTL8139 printf("RTL8139: transmitter queue stalled, current TxDesc = %d\n", s->currTxDesc);#endif }}static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val){ int descriptor = txRegOffset/4;#ifdef DEBUG_RTL8139 printf("RTL8139: TxStatus write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor);#endif /* mask only reserved bits */ val &= ~0xff00c000; /* these bits are reset on write */ val = SET_MASKED(val, 0x00c00000, s->TxStatus[descriptor]); s->TxStatus[descriptor] = val; /* attempt to start transmission */ rtl8139_transmit(s);}static uint32_t rtl8139_TxStatus_read(RTL8139State *s, uint32_t txRegOffset){ uint32_t ret = s->TxStatus[txRegOffset/4];#ifdef DEBUG_RTL8139 printf("RTL8139: TxStatus read offset=0x%x val=0x%08x\n", txRegOffset, ret);#endif return ret;}static uint16_t rtl8139_TSAD_read(RTL8139State *s){ uint16_t ret = 0; /* Simulate TSAD, it is read only anyway */ ret = ((s->TxStatus[3] & TxStatOK )?TSAD_TOK3:0) |((s->TxStatus[2] & TxStatOK )?TSAD_TOK2:0) |((s->TxStatus[1] & TxStatOK )?TSAD_TOK1:0) |((s->TxStatus[0] & TxStatOK )?TSAD_TOK0:0) |((s->TxStatus[3] & TxUnderrun)?TSAD_TUN3:0) |((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0) |((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0) |((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0) |((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0) |((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0) |((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0) |((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0) |((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0) |((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0) |((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0) |((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; #ifdef DEBUG_RTL8139 printf("RTL8139: TSAD read val=0x%04x\n", ret);#endif return ret;}static uint16_t rtl8139_CSCR_read(RTL8139State *s){ uint16_t ret = s->CSCR;#ifdef DEBUG_RTL8139 printf("RTL8139: CSCR read val=0x%04x\n", ret);#endif return ret;}static void rtl8139_TxAddr_write(RTL8139State *s, uint32_t txAddrOffset, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: TxAddr write offset=0x%x val=0x%08x\n", txAddrOffset, val);#endif s->TxAddr[txAddrOffset/4] = le32_to_cpu(val);}static uint32_t rtl8139_TxAddr_read(RTL8139State *s, uint32_t txAddrOffset){ uint32_t ret = cpu_to_le32(s->TxAddr[txAddrOffset/4]);#ifdef DEBUG_RTL8139 printf("RTL8139: TxAddr read offset=0x%x val=0x%08x\n", txAddrOffset, ret);#endif return ret;}static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: RxBufPtr write val=0x%04x\n", val);#endif /* this value is off by 16 */ s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);#if defined(DEBUG_RTL8139) printf(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n", s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);#endif}static uint32_t rtl8139_RxBufPtr_read(RTL8139State *s){ /* this value is off by 16 */ uint32_t ret = s->RxBufPtr - 0x10;#ifdef DEBUG_RTL8139 printf("RTL8139: RxBufPtr read val=0x%04x\n", ret);#endif return ret;}static void rtl8139_RxBuf_write(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: RxBuf write val=0x%08x\n", val);#endif s->RxBuf = val; /* may need to reset rxring here */}static uint32_t rtl8139_RxBuf_read(RTL8139State *s){ uint32_t ret = s->RxBuf;#ifdef DEBUG_RTL8139 printf("RTL8139: RxBuf read val=0x%08x\n", ret);#endif return ret;}static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: IntrMask write(w) val=0x%04x\n", val);#endif /* mask unwriteable bits */ val = SET_MASKED(val, 0x1e00, s->IntrMask); s->IntrMask = val; rtl8139_update_irq(s);}static uint32_t rtl8139_IntrMask_read(RTL8139State *s){ uint32_t ret = s->IntrMask;#ifdef DEBUG_RTL8139 printf("RTL8139: IntrMask read(w) val=0x%04x\n", ret);#endif return ret;}static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val){#ifdef DEBUG_RTL8139 printf("RTL8139: IntrStatus write(w) val=0x%04x\n", val);#endif#if 0 /* writing to ISR has no effect */ return;#else uint16_t newStatus = s->IntrStatus & ~val; /* mask unwriteable bits */ newStatus = SET_MASKED(newStatus, 0x1e00, s->IntrStatus);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -