func: static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32_t val) int descriptor = txRegOffset / 4 ; if ( s -> cplus_enabled )  s -> TxStatus [ descriptor ] = val; if ( descriptor == 0 && ( val & 0x8 ) )  s -> TxStatus [ 0 ] &= ~0x8; val &= ~0xff00c000; val = SET_MASKED ( val , 0x00c00000 , s -> TxStatus [ descriptor ] ); s -> TxStatus [ descriptor ] = val; rtl8139_transmit ( s ); static void rtl8139_transmit(RTL8139State *s) int descriptor = s -> currTxDesc , txcount = 0 ; if ( rtl8139_transmit_one ( s , descriptor ) )  static int rtl8139_transmit_one(RTL8139State *s, int descriptor) if ( ! rtl8139_transmitter_enabled ( s ) )  static int rtl8139_transmitter_enabled(RTL8139State *s) return s -> bChipCmdState & CmdTxEnb ; if ( s -> TxStatus [ descriptor ] & TxHostOwns )  int txsize = s -> TxStatus [ descriptor ] & 0x1fff ; uint8_t txbuffer [ 0x2000 ] ; s -> TxStatus [ descriptor ] |= TxHostOwns; s -> TxStatus [ descriptor ] |= TxStatOK; rtl8139_transfer_frame ( s , txbuffer , txsize , 0 , NULL ); static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int int do_interrupt, const uint8_t *dot1q_buf) struct iovec * iov = NULL ; struct iovec vlan_iov [ 3 ] ; if ( ! size )  if ( dot1q_buf && size >= ETHER_ADDR_LEN * 2 )  iov = ( struct iovec [ 3 ] . iov_base = buf , . iov_len = ETHER_ADDR_LEN * 2 . iov_base = ( void * ) dot1q_buf , . iov_len = VLAN_HLEN . iov_base = buf + ETHER_ADDR_LEN * 2 . iov_len = size - ETHER_ADDR_LEN * 2 , memcpy ( vlan_iov , iov , sizeof ( vlan_iov ) ); iov = vlan_iov; if ( iov )  buf2_size = iov_size ( iov , 3 ); buf2 = g_malloc ( buf2_size ); iov_to_buf ( iov , 3 , 0 , buf2 , buf2_size ); buf = buf2; rtl8139_do_receive ( qemu_get_queue ( s -> nic ) , buf , size , do_interrupt ); static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt) RTL8139State * s = qemu_get_nic_opaque ( nc ) ; PCIDevice * d = PCI_DEVICE ( s ) ; int size = size_ ; DPRINTF ( ">>> received len=%d\n" , size ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) if ( ! s -> clock_enabled )  if ( ! rtl8139_receiver_enabled ( s ) )  static int rtl8139_receiver_enabled(RTL8139State *s) return s -> bChipCmdState & CmdRxEnb ; if ( s -> RxConfig & AcceptAllPhys )  if ( ! memcmp ( buf , broadcast_macaddr , 6 ) )  if ( ! ( s -> RxConfig & AcceptBroadcast ) )  ++ s -> tally_counters . RxERR; return size ; ++ s -> tally_counters . RxOkBrd; if ( buf [ 0 ] & 0x01 )  if ( ! ( s -> RxConfig & AcceptMulticast ) )  ++ s -> tally_counters . RxERR; return size ; int mcast_idx = compute_mcast_idx ( buf ) ; if ( ! ( s -> mult [ mcast_idx >> 3 ] & ( 1 << ( mcast_idx & 7 ) ) ) )  ++ s -> tally_counters . RxERR; return size ; ++ s -> tally_counters . RxOkMul; 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 ] )  if ( ! ( s -> RxConfig & AcceptMyPhys ) )  ++ s -> tally_counters . RxERR; return size ; ++ s -> tally_counters . RxOkPhy; ++ s -> tally_counters . RxERR; return size ; if ( size < MIN_BUF_SIZE + VLAN_HLEN )  memcpy ( buf1 , buf , size ); memset ( buf1 + size , 0 , MIN_BUF_SIZE + VLAN_HLEN - size ); buf = buf1; if ( size < MIN_BUF_SIZE )  if ( rtl8139_cp_receiver_enabled ( s ) )  static int rtl8139_cp_receiver_enabled(RTL8139State *s) return s -> CpCmd & CPlusRxEnb ; if ( ! rtl8139_cp_rx_valid ( s ) )  static bool rtl8139_cp_rx_valid(RTL8139State *s) return ! ( s -> RxRingAddrLO == 0 && s -> RxRingAddrHI == 0 ) ; return size ; int descriptor = s -> currCPlusRxDesc ; cplus_rx_ring_desc = rtl8139_addr64 ( s -> RxRingAddrLO , s -> RxRingAddrHI ); static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) return low | ( ( uint64_t ) high << 32 ) ; cplus_rx_ring_desc += 16 * descriptor; DPRINTF ( "+++ C+ mode reading RX descriptor %d from host memory at "%08x %08x = " DMA_ADDR_FMT "\n" , descriptor , s -> RxRingAddrHI s -> RxRingAddrLO , cplus_rx_ring_desc ) static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) pci_dma_read ( d , cplus_rx_ring_desc , & val , 4 ); pci_dma_read ( d , cplus_rx_ring_desc + 4 , & val , 4 ); pci_dma_read ( d , cplus_rx_ring_desc + 8 , & val , 4 ); pci_dma_read ( d , cplus_rx_ring_desc + 12 , & val , 4 ); DPRINTF ( "+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n" , descriptor , rxdw0 , rxdw1 , rxbufLO , rxbufHI ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) DPRINTF ( "C+ Rx mode : descriptor %d is owned by host\n" , descriptor ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) s -> IntrStatus |= RxOverflow; ++ s -> RxMissed; ++ s -> tally_counters . RxERR; ++ s -> tally_counters . MissPkt; rtl8139_update_irq ( s ); static void rtl8139_update_irq(RTL8139State *s) PCIDevice * d = PCI_DEVICE ( s ) ; isr = ( s -> IntrStatus & s -> IntrMask ) & 0xffff; DPRINTF ( "Set IRQ to %d (%04x %04x)\n" , isr ? 1 : 0 , s -> IntrStatus , s -> IntrMask ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) pci_set_irq ( d , ( isr != 0 ) ); return size_ ; if ( s -> CpCmd & CPlusRxVLAN && be16_to_cpup ( ( uint16_t * ) & buf [ ETHER_ADDR_LEN * 2 ] ) == ETH_P_8021Q )  dot1q_buf = & buf [ ETHER_ADDR_LEN * 2 ]; size -= VLAN_HLEN; if ( size < MIN_BUF_SIZE )  rxdw1 |= CP_RX_TAVA | le16_to_cpup ( ( uint16_t * ) & dot1q_buf [ ETHER_TYPE_LEN ] ); DPRINTF ( "C+ Rx mode : extracted vlan tag with tci: " "%u\n" be16_to_cpup ( ( uint16_t * ) & dot1q_buf [ ETHER_TYPE_LEN ] ) ) static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) rxdw1 &= ~CP_RX_TAVA; if ( size + 4 > rx_space )  DPRINTF ( "C+ Rx mode : descriptor %d size %d received %d + 4\n" , descriptor , rx_space , size ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) s -> IntrStatus |= RxOverflow; ++ s -> RxMissed; ++ s -> tally_counters . RxERR; ++ s -> tally_counters . MissPkt; rtl8139_update_irq ( s ); static void rtl8139_update_irq(RTL8139State *s) PCIDevice * d = PCI_DEVICE ( s ) ; isr = ( s -> IntrStatus & s -> IntrMask ) & 0xffff; DPRINTF ( "Set IRQ to %d (%04x %04x)\n" , isr ? 1 : 0 , s -> IntrStatus , s -> IntrMask ); pci_set_irq ( d , ( isr != 0 ) ); return size_ ; if ( dot1q_buf )  pci_dma_write ( d , rx_addr , buf , 2 * ETHER_ADDR_LEN ); pci_dma_write ( d , rx_addr + 2 * ETHER_ADDR_LEN , buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN , size - 2 * ETHER_ADDR_LEN ); pci_dma_write ( d , rx_addr , buf , size ); if ( s -> CpCmd & CPlusRxChkSum )  val = cpu_to_le32 ( crc32 ( 0 , buf , size_ ) ); pci_dma_write ( d , rx_addr + size , ( uint8_t * ) & val , 4 ); rxdw0 |= ( size + 4 ); val = cpu_to_le32 ( rxdw0 ); pci_dma_write ( d , cplus_rx_ring_desc , ( uint8_t * ) & val , 4 ); val = cpu_to_le32 ( rxdw1 ); pci_dma_write ( d , cplus_rx_ring_desc + 4 , ( uint8_t * ) & val , 4 ); ++ s -> tally_counters . RxOk; if ( rxdw0 & CP_RX_EOR )  s -> currCPlusRxDesc = 0; ++ s -> currCPlusRxDesc; int avail = MOD2 ( s -> RxBufferSize + s -> RxBufPtr - s -> RxBufAddr , s -> RxBufferSize ) ; if ( avail != 0 && size + 8 >= avail )  s -> IntrStatus |= RxOverflow; ++ s -> RxMissed; rtl8139_update_irq ( s ); static void rtl8139_update_irq(RTL8139State *s) PCIDevice * d = PCI_DEVICE ( s ) ; isr = ( s -> IntrStatus & s -> IntrMask ) & 0xffff; DPRINTF ( "Set IRQ to %d (%04x %04x)\n" , isr ? 1 : 0 , s -> IntrStatus , s -> IntrMask ); pci_set_irq ( d , ( isr != 0 ) ); return size_ ; packet_header |= ( ( ( size + 4 ) << 16 ) & 0xffff0000 ); uint32_t val = cpu_to_le32 ( packet_header ) ; rtl8139_write_buffer ( s , ( uint8_t * ) & val , 4 ); static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) PCIDevice * d = PCI_DEVICE ( s ) ; if ( s -> RxBufAddr + size > s -> RxBufferSize )  int wrapped = MOD2 ( s -> RxBufAddr + size , s -> RxBufferSize ) ; if ( wrapped && ! ( s -> RxBufferSize < 65536 && rtl8139_RxWrap ( s ) ) )  static int rtl8139_RxWrap(RTL8139State *s) return ( s -> RxConfig & ( 1 << 7 ) ) ; DPRINTF ( ">>> rx packet wrapped in buffer at %d\n" , size - wrapped ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) if ( size > wrapped )  pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size - wrapped ); s -> RxBufAddr = 0; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf + ( size - wrapped ) , wrapped ); s -> RxBufAddr = wrapped; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size ); s -> RxBufAddr += size; rtl8139_write_buffer ( s , buf , size ); static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) PCIDevice * d = PCI_DEVICE ( s ) ; if ( s -> RxBufAddr + size > s -> RxBufferSize )  int wrapped = MOD2 ( s -> RxBufAddr + size , s -> RxBufferSize ) ; if ( wrapped && ! ( s -> RxBufferSize < 65536 && rtl8139_RxWrap ( s ) ) )  DPRINTF ( ">>> rx packet wrapped in buffer at %d\n" , size - wrapped ); if ( size > wrapped )  pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size - wrapped ); s -> RxBufAddr = 0; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf + ( size - wrapped ) , wrapped ); s -> RxBufAddr = wrapped; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size ); s -> RxBufAddr += size; val = cpu_to_le32 ( crc32 ( 0 , buf , size ) ); rtl8139_write_buffer ( s , ( uint8_t * ) & val , 4 ); static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) PCIDevice * d = PCI_DEVICE ( s ) ; if ( s -> RxBufAddr + size > s -> RxBufferSize )  int wrapped = MOD2 ( s -> RxBufAddr + size , s -> RxBufferSize ) ; if ( wrapped && ! ( s -> RxBufferSize < 65536 && rtl8139_RxWrap ( s ) ) )  DPRINTF ( ">>> rx packet wrapped in buffer at %d\n" , size - wrapped ); if ( size > wrapped )  pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size - wrapped ); s -> RxBufAddr = 0; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf + ( size - wrapped ) , wrapped ); s -> RxBufAddr = wrapped; pci_dma_write ( d , s -> RxBuf + s -> RxBufAddr , buf , size ); s -> RxBufAddr += size; s -> RxBufAddr = MOD2 ( ( s -> RxBufAddr + 3 ) & ~0x3 , s -> RxBufferSize ); DPRINTF ( "received: rx buffer length %d head 0x%04x read 0x%04x\n" , s -> RxBufferSize , s -> RxBufAddr , s -> RxBufPtr ); static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...) s -> IntrStatus |= RxOK; if ( do_interrupt )  rtl8139_update_irq ( s ); static void rtl8139_update_irq(RTL8139State *s) PCIDevice * d = PCI_DEVICE ( s ) ; isr = ( s -> IntrStatus & s -> IntrMask ) & 0xffff; DPRINTF ( "Set IRQ to %d (%04x %04x)\n" , isr ? 1 : 0 , s -> IntrStatus , s -> IntrMask ); pci_set_irq ( d , ( isr != 0 ) ); return size_ ; if ( iov )  g_free ( buf2 ); if ( iov )  qemu_sendv_packet ( qemu_get_queue ( s -> nic ) , iov , 3 ); qemu_send_packet ( qemu_get_queue ( s -> nic ) , buf , size ); 