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

    /* size is the length of the buffer passed to the driver */

    int size = size_;

    const uint8_t *dot1q_buf = NULL;



    uint32_t packet_header = 0;



    uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];

    static const uint8_t broadcast_macaddr[6] =

        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };



    DPRINTF(">>> received len=%d\n", size);



    /* test if board clock is stopped */

    if (!s->clock_enabled)

    {

        DPRINTF("stopped ==========================\n");

        return -1;

    }



    /* first check if receiver is enabled */



    if (!rtl8139_receiver_enabled(s))

    {

        DPRINTF("receiver disabled ================\n");

        return -1;

    }



    /* XXX: check this */

    if (s->RxConfig & AcceptAllPhys) {

        /* promiscuous: receive all */

        DPRINTF(">>> packet received in promiscuous mode\n");



    } else {

        if (!memcmp(buf,  broadcast_macaddr, 6)) {

            /* broadcast address */

            if (!(s->RxConfig & AcceptBroadcast))

            {

                DPRINTF(">>> broadcast packet rejected\n");



                /* update tally counter */

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxBroadcast;



            DPRINTF(">>> broadcast packet received\n");



            /* update tally counter */

            ++s->tally_counters.RxOkBrd;



        } else if (buf[0] & 0x01) {

            /* multicast */

            if (!(s->RxConfig & AcceptMulticast))

            {

                DPRINTF(">>> multicast packet rejected\n");



                /* update tally counter */

                ++s->tally_counters.RxERR;



                return size;

            }



            int mcast_idx = compute_mcast_idx(buf);



            if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))

            {

                DPRINTF(">>> multicast address mismatch\n");



                /* update tally counter */

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxMulticast;



            DPRINTF(">>> 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))

            {

                DPRINTF(">>> rejecting physical address matching packet\n");



                /* update tally counter */

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxPhysical;



            DPRINTF(">>> physical address matching packet received\n");



            /* update tally counter */

            ++s->tally_counters.RxOkPhy;



        } else {



            DPRINTF(">>> unknown packet\n");



            /* update tally counter */

            ++s->tally_counters.RxERR;



            return size;

        }

    }



    /* if too small buffer, then expand it

     * Include some tailroom in case a vlan tag is later removed. */

    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) {

            size = MIN_BUF_SIZE;

        }

    }



    if (rtl8139_cp_receiver_enabled(s))

    {

        if (!rtl8139_cp_rx_valid(s)) {

            return size;

        }



        DPRINTF("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;

        dma_addr_t cplus_rx_ring_desc;



        cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);

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



        uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;



        pci_dma_read(d, cplus_rx_ring_desc, &val, 4);

        rxdw0 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+4, &val, 4);

        rxdw1 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+8, &val, 4);

        rxbufLO = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+12, &val, 4);

        rxbufHI = le32_to_cpu(val);



        DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",

            descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI);



        if (!(rxdw0 & CP_RX_OWN))

        {

            DPRINTF("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 size_;

        }



        uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;



        /* write VLAN info to descriptor variables. */

        if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)

                &buf[ETH_ALEN * 2]) == ETH_P_VLAN) {

            dot1q_buf = &buf[ETH_ALEN * 2];

            size -= VLAN_HLEN;

            /* if too small buffer, use the tailroom added duing expansion */

            if (size < MIN_BUF_SIZE) {

                size = MIN_BUF_SIZE;

            }



            rxdw1 &= ~CP_RX_VLAN_TAG_MASK;

            /* BE + ~le_to_cpu()~ + cpu_to_le() = BE */

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

        } else {

            /* reset VLAN tag flag */

            rxdw1 &= ~CP_RX_TAVA;

        }



        /* TODO: scatter the packet over available receive ring descriptors space */



        if (size+4 > rx_space)

        {

            DPRINTF("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 size_;

        }



        dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);



        /* receive/copy to target memory */

        if (dot1q_buf) {

            pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN);

            pci_dma_write(d, rx_addr + 2 * ETH_ALEN,

                          buf + 2 * ETH_ALEN + VLAN_HLEN,

                          size - 2 * ETH_ALEN);

        } else {

            pci_dma_write(d, rx_addr, buf, size);

        }



        if (s->CpCmd & CPlusRxChkSum)

        {

            /* do some packet checksumming */

        }



        /* write checksum */

        val = cpu_to_le32(crc32(0, buf, size_));

        pci_dma_write(d, 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);



        /* update ring data */

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



        /* update tally counter */

        ++s->tally_counters.RxOk;



        /* seek to next Rx descriptor */

        if (rxdw0 & CP_RX_EOR)

        {

            s->currCPlusRxDesc = 0;

        }

        else

        {

            ++s->currCPlusRxDesc;

        }



        DPRINTF("done C+ Rx mode ----------------\n");



    }

    else

    {

        DPRINTF("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 */



#define RX_ALIGN(x) (((x) + 3) & ~0x3)



        if (avail != 0 && RX_ALIGN(size + 8) >= avail)

        {

            DPRINTF("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 size_;

        }



        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 */

        val = cpu_to_le32(crc32(0, buf, size));

        rtl8139_write_buffer(s, (uint8_t *)&val, 4);



        /* correct buffer write pointer */

        s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);



        /* now we can signal we have received something */



        DPRINTF("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);

    }



    return size_;

}

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_;

    const uint8_t *dot1q_buf = NULL;



    uint32_t packet_header = 0;



    uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];

    static const uint8_t broadcast_macaddr[6] =

        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };



    DPRINTF(">>> received len=%d\n", size);



    

    if (!s->clock_enabled)

    {

        DPRINTF("stopped ==========================\n");

        return -1;

    }



    



    if (!rtl8139_receiver_enabled(s))

    {

        DPRINTF("receiver disabled ================\n");

        return -1;

    }



    

    if (s->RxConfig & AcceptAllPhys) {

        

        DPRINTF(">>> packet received in promiscuous mode\n");



    } else {

        if (!memcmp(buf,  broadcast_macaddr, 6)) {

            

            if (!(s->RxConfig & AcceptBroadcast))

            {

                DPRINTF(">>> broadcast packet rejected\n");



                

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxBroadcast;



            DPRINTF(">>> broadcast packet received\n");



            

            ++s->tally_counters.RxOkBrd;



        } else if (buf[0] & 0x01) {

            

            if (!(s->RxConfig & AcceptMulticast))

            {

                DPRINTF(">>> multicast packet rejected\n");



                

                ++s->tally_counters.RxERR;



                return size;

            }



            int mcast_idx = compute_mcast_idx(buf);



            if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))

            {

                DPRINTF(">>> multicast address mismatch\n");



                

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxMulticast;



            DPRINTF(">>> multicast packet received\n");



            

            ++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]) {

            

            if (!(s->RxConfig & AcceptMyPhys))

            {

                DPRINTF(">>> rejecting physical address matching packet\n");



                

                ++s->tally_counters.RxERR;



                return size;

            }



            packet_header |= RxPhysical;



            DPRINTF(">>> physical address matching packet received\n");



            

            ++s->tally_counters.RxOkPhy;



        } else {



            DPRINTF(">>> unknown packet\n");



            

            ++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) {

            size = MIN_BUF_SIZE;

        }

    }



    if (rtl8139_cp_receiver_enabled(s))

    {

        if (!rtl8139_cp_rx_valid(s)) {

            return size;

        }



        DPRINTF("in C+ Rx mode ================\n");



        





#define CP_RX_OWN (1<<31)



#define CP_RX_EOR (1<<30)



#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)



#define CP_RX_TAVA (1<<16)



#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)







        int descriptor = s->currCPlusRxDesc;

        dma_addr_t cplus_rx_ring_desc;



        cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);

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



        uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;



        pci_dma_read(d, cplus_rx_ring_desc, &val, 4);

        rxdw0 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+4, &val, 4);

        rxdw1 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+8, &val, 4);

        rxbufLO = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+12, &val, 4);

        rxbufHI = le32_to_cpu(val);



        DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n",

            descriptor, rxdw0, rxdw1, rxbufLO, rxbufHI);



        if (!(rxdw0 & CP_RX_OWN))

        {

            DPRINTF("C+ Rx mode : descriptor %d is owned by host\n",

                descriptor);



            s->IntrStatus |= RxOverflow;

            ++s->RxMissed;



            

            ++s->tally_counters.RxERR;

            ++s->tally_counters.MissPkt;



            rtl8139_update_irq(s);

            return size_;

        }



        uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;



        

        if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)

                &buf[ETH_ALEN * 2]) == ETH_P_VLAN) {

            dot1q_buf = &buf[ETH_ALEN * 2];

            size -= VLAN_HLEN;

            

            if (size < MIN_BUF_SIZE) {

                size = MIN_BUF_SIZE;

            }



            rxdw1 &= ~CP_RX_VLAN_TAG_MASK;

            

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

        } else {

            

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



            s->IntrStatus |= RxOverflow;

            ++s->RxMissed;



            

            ++s->tally_counters.RxERR;

            ++s->tally_counters.MissPkt;



            rtl8139_update_irq(s);

            return size_;

        }



        dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);



        

        if (dot1q_buf) {

            pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN);

            pci_dma_write(d, rx_addr + 2 * ETH_ALEN,

                          buf + 2 * ETH_ALEN + VLAN_HLEN,

                          size - 2 * ETH_ALEN);

        } else {

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





#define CP_RX_STATUS_FS (1<<29)



#define CP_RX_STATUS_LS (1<<28)



#define CP_RX_STATUS_MAR (1<<26)



#define CP_RX_STATUS_PAM (1<<25)



#define CP_RX_STATUS_BAR (1<<24)



#define CP_RX_STATUS_RUNT (1<<19)



#define CP_RX_STATUS_CRC (1<<18)



#define CP_RX_STATUS_IPF (1<<15)



#define CP_RX_STATUS_UDPF (1<<14)



#define CP_RX_STATUS_TCPF (1<<13)



        

        rxdw0 &= ~CP_RX_OWN;



        

        rxdw0 |= CP_RX_STATUS_FS;



        

        rxdw0 |= CP_RX_STATUS_LS;



        

        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;



        

        rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK;

        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;

        }

        else

        {

            ++s->currCPlusRxDesc;

        }



        DPRINTF("done C+ Rx mode ----------------\n");



    }

    else

    {

        DPRINTF("in ring Rx mode ================\n");



        

        int avail = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize);



        



#define RX_ALIGN(x) (((x) + 3) & ~0x3)



        if (avail != 0 && RX_ALIGN(size + 8) >= avail)

        {

            DPRINTF("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 size_;

        }



        packet_header |= RxStatusOK;



        packet_header |= (((size+4) << 16) & 0xffff0000);



        

        uint32_t val = cpu_to_le32(packet_header);



        rtl8139_write_buffer(s, (uint8_t *)&val, 4);



        rtl8139_write_buffer(s, buf, size);



        

        val = cpu_to_le32(crc32(0, buf, size));

        rtl8139_write_buffer(s, (uint8_t *)&val, 4);



        

        s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);



        



        DPRINTF("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);

    }



    return size_;

}

            return size_;
static ssize_t FUNC_0(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 VAR_0 = size_;

    const uint8_t *VAR_1 = NULL;



    uint32_t packet_header = 0;



    uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN];

    static const uint8_t VAR_2[6] =

        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };



    DPRINTF(">>> received len=%d\n", VAR_0);



    

    if (!s->clock_enabled)

    {

        DPRINTF("stopped ==========================\n");

        return -1;

    }



    



    if (!rtl8139_receiver_enabled(s))

    {

        DPRINTF("receiver disabled ================\n");

        return -1;

    }



    

    if (s->RxConfig & AcceptAllPhys) {

        

        DPRINTF(">>> packet received in promiscuous mode\n");



    } else {

        if (!memcmp(buf,  VAR_2, 6)) {

            

            if (!(s->RxConfig & AcceptBroadcast))

            {

                DPRINTF(">>> broadcast packet rejected\n");



                

                ++s->tally_counters.RxERR;



                return VAR_0;

            }



            packet_header |= RxBroadcast;



            DPRINTF(">>> broadcast packet received\n");



            

            ++s->tally_counters.RxOkBrd;



        } else if (buf[0] & 0x01) {

            

            if (!(s->RxConfig & AcceptMulticast))

            {

                DPRINTF(">>> multicast packet rejected\n");



                

                ++s->tally_counters.RxERR;



                return VAR_0;

            }



            int VAR_3 = compute_mcast_idx(buf);



            if (!(s->mult[VAR_3 >> 3] & (1 << (VAR_3 & 7))))

            {

                DPRINTF(">>> multicast address mismatch\n");



                

                ++s->tally_counters.RxERR;



                return VAR_0;

            }



            packet_header |= RxMulticast;



            DPRINTF(">>> multicast packet received\n");



            

            ++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]) {

            

            if (!(s->RxConfig & AcceptMyPhys))

            {

                DPRINTF(">>> rejecting physical address matching packet\n");



                

                ++s->tally_counters.RxERR;



                return VAR_0;

            }



            packet_header |= RxPhysical;



            DPRINTF(">>> physical address matching packet received\n");



            

            ++s->tally_counters.RxOkPhy;



        } else {



            DPRINTF(">>> unknown packet\n");



            

            ++s->tally_counters.RxERR;



            return VAR_0;

        }

    }



    



    if (VAR_0 < MIN_BUF_SIZE + VLAN_HLEN) {

        memcpy(buf1, buf, VAR_0);

        memset(buf1 + VAR_0, 0, MIN_BUF_SIZE + VLAN_HLEN - VAR_0);

        buf = buf1;

        if (VAR_0 < MIN_BUF_SIZE) {

            VAR_0 = MIN_BUF_SIZE;

        }

    }



    if (rtl8139_cp_receiver_enabled(s))

    {

        if (!rtl8139_cp_rx_valid(s)) {

            return VAR_0;

        }



        DPRINTF("in C+ Rx mode ================\n");



        





#define CP_RX_OWN (1<<31)



#define CP_RX_EOR (1<<30)



#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)



#define CP_RX_TAVA (1<<16)



#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)







        int VAR_4 = s->currCPlusRxDesc;

        dma_addr_t cplus_rx_ring_desc;



        cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI);

        cplus_rx_ring_desc += 16 * VAR_4;



        DPRINTF("+++ C+ mode reading RX VAR_4 %d from host memory at "

            "%08x %08x = "DMA_ADDR_FMT"\n", VAR_4, s->RxRingAddrHI,

            s->RxRingAddrLO, cplus_rx_ring_desc);



        uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI;



        pci_dma_read(d, cplus_rx_ring_desc, &val, 4);

        rxdw0 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+4, &val, 4);

        rxdw1 = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+8, &val, 4);

        rxbufLO = le32_to_cpu(val);

        pci_dma_read(d, cplus_rx_ring_desc+12, &val, 4);

        rxbufHI = le32_to_cpu(val);



        DPRINTF("+++ C+ mode RX VAR_4 %d %08x %08x %08x %08x\n",

            VAR_4, rxdw0, rxdw1, rxbufLO, rxbufHI);



        if (!(rxdw0 & CP_RX_OWN))

        {

            DPRINTF("C+ Rx mode : VAR_4 %d is owned by host\n",

                VAR_4);



            s->IntrStatus |= RxOverflow;

            ++s->RxMissed;



            

            ++s->tally_counters.RxERR;

            ++s->tally_counters.MissPkt;



            rtl8139_update_irq(s);

            return size_;

        }



        uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK;



        

        if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)

                &buf[ETH_ALEN * 2]) == ETH_P_VLAN) {

            VAR_1 = &buf[ETH_ALEN * 2];

            VAR_0 -= VLAN_HLEN;

            

            if (VAR_0 < MIN_BUF_SIZE) {

                VAR_0 = MIN_BUF_SIZE;

            }



            rxdw1 &= ~CP_RX_VLAN_TAG_MASK;

            

            rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)

                &VAR_1[ETHER_TYPE_LEN]);



            DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n",

                be16_to_cpup((uint16_t *)&VAR_1[ETHER_TYPE_LEN]));

        } else {

            

            rxdw1 &= ~CP_RX_TAVA;

        }



        



        if (VAR_0+4 > rx_space)

        {

            DPRINTF("C+ Rx mode : VAR_4 %d VAR_0 %d received %d + 4\n",

                VAR_4, rx_space, VAR_0);



            s->IntrStatus |= RxOverflow;

            ++s->RxMissed;



            

            ++s->tally_counters.RxERR;

            ++s->tally_counters.MissPkt;



            rtl8139_update_irq(s);

            return size_;

        }



        dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI);



        

        if (VAR_1) {

            pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN);

            pci_dma_write(d, rx_addr + 2 * ETH_ALEN,

                          buf + 2 * ETH_ALEN + VLAN_HLEN,

                          VAR_0 - 2 * ETH_ALEN);

        } else {

            pci_dma_write(d, rx_addr, buf, VAR_0);

        }



        if (s->CpCmd & CPlusRxChkSum)

        {

            

        }



        

        val = cpu_to_le32(crc32(0, buf, size_));

        pci_dma_write(d, rx_addr+VAR_0, (uint8_t *)&val, 4);





#define CP_RX_STATUS_FS (1<<29)



#define CP_RX_STATUS_LS (1<<28)



#define CP_RX_STATUS_MAR (1<<26)



#define CP_RX_STATUS_PAM (1<<25)



#define CP_RX_STATUS_BAR (1<<24)



#define CP_RX_STATUS_RUNT (1<<19)



#define CP_RX_STATUS_CRC (1<<18)



#define CP_RX_STATUS_IPF (1<<15)



#define CP_RX_STATUS_UDPF (1<<14)



#define CP_RX_STATUS_TCPF (1<<13)



        

        rxdw0 &= ~CP_RX_OWN;



        

        rxdw0 |= CP_RX_STATUS_FS;



        

        rxdw0 |= CP_RX_STATUS_LS;



        

        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;



        

        rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK;

        rxdw0 |= (VAR_0+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;

        }

        else

        {

            ++s->currCPlusRxDesc;

        }



        DPRINTF("done C+ Rx mode ----------------\n");



    }

    else

    {

        DPRINTF("in ring Rx mode ================\n");



        

        int VAR_5 = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize);



        



#define RX_ALIGN(x) (((x) + 3) & ~0x3)



        if (VAR_5 != 0 && RX_ALIGN(VAR_0 + 8) >= VAR_5)

        {

            DPRINTF("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, VAR_5, VAR_0 + 8);



            s->IntrStatus |= RxOverflow;

            ++s->RxMissed;

            rtl8139_update_irq(s);

            return size_;

        }



        packet_header |= RxStatusOK;



        packet_header |= (((VAR_0+4) << 16) & 0xffff0000);



        

        uint32_t val = cpu_to_le32(packet_header);



        rtl8139_write_buffer(s, (uint8_t *)&val, 4);



        rtl8139_write_buffer(s, buf, VAR_0);



        

        val = cpu_to_le32(crc32(0, buf, VAR_0));

        rtl8139_write_buffer(s, (uint8_t *)&val, 4);



        

        s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize);



        



        DPRINTF("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);

    }



    return size_;

}

static ssize_t FUNC_0(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 VAR_0 = size_; const uint8_t *VAR_1 = NULL; uint32_t packet_header = 0; uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN]; static const uint8_t VAR_2[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; DPRINTF(">>> received len=%d\n", VAR_0); if (!s->clock_enabled)
{ DPRINTF("stopped ==========================\n"); return -1; } if (!rtl8139_receiver_enabled(s))
{ DPRINTF("receiver disabled ================\n"); return -1; } if (s->RxConfig & AcceptAllPhys) { DPRINTF(">>> packet received in promiscuous mode\n"); } else { if (!memcmp(buf,  VAR_2, 6)) { if (!(s->RxConfig & AcceptBroadcast))
{ DPRINTF(">>> broadcast packet rejected\n"); ++s->tally_counters.RxERR; return VAR_0; } packet_header |= RxBroadcast; DPRINTF(">>> broadcast packet received\n"); ++s->tally_counters.RxOkBrd; } else if (buf[0] & 0x01) { if (!(s->RxConfig & AcceptMulticast))
{ DPRINTF(">>> multicast packet rejected\n"); ++s->tally_counters.RxERR; return VAR_0; } int VAR_3 = compute_mcast_idx(buf); if (!(s->mult[VAR_3 >> 3] & (1 << (VAR_3 & 7))))
{ DPRINTF(">>> multicast address mismatch\n"); ++s->tally_counters.RxERR; return VAR_0; } packet_header |= RxMulticast; DPRINTF(">>> multicast packet received\n"); ++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]) { if (!(s->RxConfig & AcceptMyPhys))
{ DPRINTF(">>> rejecting physical address matching packet\n"); ++s->tally_counters.RxERR; return VAR_0; } packet_header |= RxPhysical; DPRINTF(">>> physical address matching packet received\n"); ++s->tally_counters.RxOkPhy; } else { DPRINTF(">>> unknown packet\n"); ++s->tally_counters.RxERR; return VAR_0; } } if (VAR_0 < MIN_BUF_SIZE + VLAN_HLEN) { memcpy(buf1, buf, VAR_0); memset(buf1 + VAR_0, 0, MIN_BUF_SIZE + VLAN_HLEN - VAR_0); buf = buf1; if (VAR_0 < MIN_BUF_SIZE) { VAR_0 = MIN_BUF_SIZE; } } if (rtl8139_cp_receiver_enabled(s))
{ if (!rtl8139_cp_rx_valid(s)) { return VAR_0; } DPRINTF("in C+ Rx mode ================\n"); #define CP_RX_OWN (1<<31)
#define CP_RX_EOR (1<<30)
#define CP_RX_BUFFER_SIZE_MASK ((1<<13) - 1)
#define CP_RX_TAVA (1<<16)
#define CP_RX_VLAN_TAG_MASK ((1<<16) - 1)
int VAR_4 = s->currCPlusRxDesc; dma_addr_t cplus_rx_ring_desc; cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * VAR_4; DPRINTF("+++ C+ mode reading RX VAR_4 %d from host memory at "
"%08x %08x = "DMA_ADDR_FMT"\n", VAR_4, s->RxRingAddrHI,
s->RxRingAddrLO, cplus_rx_ring_desc); uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; pci_dma_read(d, cplus_rx_ring_desc, &val, 4); rxdw0 = le32_to_cpu(val); pci_dma_read(d, cplus_rx_ring_desc+4, &val, 4); rxdw1 = le32_to_cpu(val); pci_dma_read(d, cplus_rx_ring_desc+8, &val, 4); rxbufLO = le32_to_cpu(val); pci_dma_read(d, cplus_rx_ring_desc+12, &val, 4); rxbufHI = le32_to_cpu(val); DPRINTF("+++ C+ mode RX VAR_4 %d %08x %08x %08x %08x\n",
VAR_4, rxdw0, rxdw1, rxbufLO, rxbufHI); if (!(rxdw0 & CP_RX_OWN))
{ DPRINTF("C+ Rx mode : VAR_4 %d is owned by host\n",
VAR_4); s->IntrStatus |= RxOverflow; ++s->RxMissed; ++s->tally_counters.RxERR; ++s->tally_counters.MissPkt; rtl8139_update_irq(s); return size_; } uint32_t rx_space = rxdw0 & CP_RX_BUFFER_SIZE_MASK; if (s->CpCmd & CPlusRxVLAN && be16_to_cpup((uint16_t *)
&buf[ETH_ALEN * 2]) == ETH_P_VLAN) { VAR_1 = &buf[ETH_ALEN * 2]; VAR_0 -= VLAN_HLEN; if (VAR_0 < MIN_BUF_SIZE) { VAR_0 = MIN_BUF_SIZE; } rxdw1 &= ~CP_RX_VLAN_TAG_MASK; rxdw1 |= CP_RX_TAVA | le16_to_cpup((uint16_t *)
&VAR_1[ETHER_TYPE_LEN]); DPRINTF("C+ Rx mode : extracted vlan tag with tci: ""%u\n",
be16_to_cpup((uint16_t *)&VAR_1[ETHER_TYPE_LEN])); } else { rxdw1 &= ~CP_RX_TAVA; } if (VAR_0+4 > rx_space)
{ DPRINTF("C+ Rx mode : VAR_4 %d VAR_0 %d received %d + 4\n",
VAR_4, rx_space, VAR_0); s->IntrStatus |= RxOverflow; ++s->RxMissed; ++s->tally_counters.RxERR; ++s->tally_counters.MissPkt; rtl8139_update_irq(s); return size_; } dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); if (VAR_1) { pci_dma_write(d, rx_addr, buf, 2 * ETH_ALEN); pci_dma_write(d, rx_addr + 2 * ETH_ALEN,
buf + 2 * ETH_ALEN + VLAN_HLEN,
VAR_0 - 2 * ETH_ALEN); } else { pci_dma_write(d, rx_addr, buf, VAR_0); } if (s->CpCmd & CPlusRxChkSum)
{ } val = cpu_to_le32(crc32(0, buf, size_)); pci_dma_write(d, rx_addr+VAR_0, (uint8_t *)&val, 4); #define CP_RX_STATUS_FS (1<<29)
#define CP_RX_STATUS_LS (1<<28)
#define CP_RX_STATUS_MAR (1<<26)
#define CP_RX_STATUS_PAM (1<<25)
#define CP_RX_STATUS_BAR (1<<24)
#define CP_RX_STATUS_RUNT (1<<19)
#define CP_RX_STATUS_CRC (1<<18)
#define CP_RX_STATUS_IPF (1<<15)
#define CP_RX_STATUS_UDPF (1<<14)
#define CP_RX_STATUS_TCPF (1<<13)
rxdw0 &= ~CP_RX_OWN; rxdw0 |= CP_RX_STATUS_FS; rxdw0 |= CP_RX_STATUS_LS; 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; rxdw0 &= ~CP_RX_BUFFER_SIZE_MASK; rxdw0 |= (VAR_0+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; } else
{ ++s->currCPlusRxDesc; } DPRINTF("done C+ Rx mode ----------------\n"); } else
{ DPRINTF("in ring Rx mode ================\n"); int VAR_5 = MOD2(s->RxBufferSize + s->RxBufPtr - s->RxBufAddr, s->RxBufferSize); #define RX_ALIGN(x) (((x) + 3) & ~0x3)
if (VAR_5 != 0 && RX_ALIGN(VAR_0 + 8) >= VAR_5)
{ DPRINTF("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, VAR_5, VAR_0 + 8); s->IntrStatus |= RxOverflow; ++s->RxMissed; rtl8139_update_irq(s); return size_; } packet_header |= RxStatusOK; packet_header |= (((VAR_0+4) << 16) & 0xffff0000); uint32_t val = cpu_to_le32(packet_header); rtl8139_write_buffer(s, (uint8_t *)&val, 4); rtl8139_write_buffer(s, buf, VAR_0); val = cpu_to_le32(crc32(0, buf, VAR_0)); rtl8139_write_buffer(s, (uint8_t *)&val, 4); s->RxBufAddr = MOD2(RX_ALIGN(s->RxBufAddr), s->RxBufferSize); DPRINTF("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); } return size_; }