e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,

                             const E1000E_RxRing *rxr,

                             const E1000E_RSSInfo *rss_info)

{

    PCIDevice *d = core->owner;

    dma_addr_t base;

    uint8_t desc[E1000_MAX_RX_DESC_LEN];

    size_t desc_size;

    size_t desc_offset = 0;

    size_t iov_ofs = 0;



    struct iovec *iov = net_rx_pkt_get_iovec(pkt);

    size_t size = net_rx_pkt_get_total_len(pkt);

    size_t total_size = size + e1000x_fcs_len(core->mac);

    const E1000E_RingInfo *rxi;

    size_t ps_hdr_len = 0;

    bool do_ps = e1000e_do_ps(core, pkt, &ps_hdr_len);



    rxi = rxr->i;



    do {

        hwaddr ba[MAX_PS_BUFFERS];

        e1000e_ba_state bastate = { { 0 } };

        bool is_last = false;

        bool is_first = true;



        desc_size = total_size - desc_offset;



        if (desc_size > core->rx_desc_buf_size) {

            desc_size = core->rx_desc_buf_size;

        }



        base = e1000e_ring_head_descr(core, rxi);



        pci_dma_read(d, base, &desc, core->rx_desc_len);



        trace_e1000e_rx_descr(rxi->idx, base, core->rx_desc_len);



        e1000e_read_rx_descr(core, desc, &ba);



        if (ba[0]) {

            if (desc_offset < size) {

                static const uint32_t fcs_pad;

                size_t iov_copy;

                size_t copy_size = size - desc_offset;

                if (copy_size > core->rx_desc_buf_size) {

                    copy_size = core->rx_desc_buf_size;

                }



                /* For PS mode copy the packet header first */

                if (do_ps) {

                    if (is_first) {

                        size_t ps_hdr_copied = 0;

                        do {

                            iov_copy = MIN(ps_hdr_len - ps_hdr_copied,

                                           iov->iov_len - iov_ofs);



                            e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,

                                                      iov->iov_base, iov_copy);



                            copy_size -= iov_copy;

                            ps_hdr_copied += iov_copy;



                            iov_ofs += iov_copy;

                            if (iov_ofs == iov->iov_len) {

                                iov++;

                                iov_ofs = 0;

                            }

                        } while (ps_hdr_copied < ps_hdr_len);



                        is_first = false;

                    } else {

                        /* Leave buffer 0 of each descriptor except first */

                        /* empty as per spec 7.1.5.1                      */

                        e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,

                                                       NULL, 0);

                    }

                }



                /* Copy packet payload */

                while (copy_size) {

                    iov_copy = MIN(copy_size, iov->iov_len - iov_ofs);



                    e1000e_write_to_rx_buffers(core, &ba, &bastate,

                                            iov->iov_base + iov_ofs, iov_copy);



                    copy_size -= iov_copy;

                    iov_ofs += iov_copy;

                    if (iov_ofs == iov->iov_len) {

                        iov++;

                        iov_ofs = 0;

                    }

                }



                if (desc_offset + desc_size >= total_size) {

                    /* Simulate FCS checksum presence in the last descriptor */

                    e1000e_write_to_rx_buffers(core, &ba, &bastate,

                          (const char *) &fcs_pad, e1000x_fcs_len(core->mac));

                }

            }

            desc_offset += desc_size;

            if (desc_offset >= total_size) {

                is_last = true;

            }

        } else { /* as per intel docs; skip descriptors with null buf addr */

            trace_e1000e_rx_null_descriptor();

        }



        e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,

                           rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);

        pci_dma_write(d, base, &desc, core->rx_desc_len);



        e1000e_ring_advance(core, rxi,

                            core->rx_desc_len / E1000_MIN_RX_DESC_LEN);



    } while (desc_offset < total_size);



    e1000e_update_rx_stats(core, size, total_size);

}

e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,

                             const E1000E_RxRing *rxr,

                             const E1000E_RSSInfo *rss_info)

{

    PCIDevice *d = core->owner;

    dma_addr_t base;

    uint8_t desc[E1000_MAX_RX_DESC_LEN];

    size_t desc_size;

    size_t desc_offset = 0;

    size_t iov_ofs = 0;



    struct iovec *iov = net_rx_pkt_get_iovec(pkt);

    size_t size = net_rx_pkt_get_total_len(pkt);

    size_t total_size = size + e1000x_fcs_len(core->mac);

    const E1000E_RingInfo *rxi;

    size_t ps_hdr_len = 0;

    bool do_ps = e1000e_do_ps(core, pkt, &ps_hdr_len);



    rxi = rxr->i;



    do {

        hwaddr ba[MAX_PS_BUFFERS];

        e1000e_ba_state bastate = { { 0 } };

        bool is_last = false;

        bool is_first = true;



        desc_size = total_size - desc_offset;



        if (desc_size > core->rx_desc_buf_size) {

            desc_size = core->rx_desc_buf_size;

        }



        base = e1000e_ring_head_descr(core, rxi);



        pci_dma_read(d, base, &desc, core->rx_desc_len);



        trace_e1000e_rx_descr(rxi->idx, base, core->rx_desc_len);



        e1000e_read_rx_descr(core, desc, &ba);



        if (ba[0]) {

            if (desc_offset < size) {

                static const uint32_t fcs_pad;

                size_t iov_copy;

                size_t copy_size = size - desc_offset;

                if (copy_size > core->rx_desc_buf_size) {

                    copy_size = core->rx_desc_buf_size;

                }



                

                if (do_ps) {

                    if (is_first) {

                        size_t ps_hdr_copied = 0;

                        do {

                            iov_copy = MIN(ps_hdr_len - ps_hdr_copied,

                                           iov->iov_len - iov_ofs);



                            e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,

                                                      iov->iov_base, iov_copy);



                            copy_size -= iov_copy;

                            ps_hdr_copied += iov_copy;



                            iov_ofs += iov_copy;

                            if (iov_ofs == iov->iov_len) {

                                iov++;

                                iov_ofs = 0;

                            }

                        } while (ps_hdr_copied < ps_hdr_len);



                        is_first = false;

                    } else {

                        

                        

                        e1000e_write_hdr_to_rx_buffers(core, &ba, &bastate,

                                                       NULL, 0);

                    }

                }



                

                while (copy_size) {

                    iov_copy = MIN(copy_size, iov->iov_len - iov_ofs);



                    e1000e_write_to_rx_buffers(core, &ba, &bastate,

                                            iov->iov_base + iov_ofs, iov_copy);



                    copy_size -= iov_copy;

                    iov_ofs += iov_copy;

                    if (iov_ofs == iov->iov_len) {

                        iov++;

                        iov_ofs = 0;

                    }

                }



                if (desc_offset + desc_size >= total_size) {

                    

                    e1000e_write_to_rx_buffers(core, &ba, &bastate,

                          (const char *) &fcs_pad, e1000x_fcs_len(core->mac));

                }

            }

            desc_offset += desc_size;

            if (desc_offset >= total_size) {

                is_last = true;

            }

        } else { 

            trace_e1000e_rx_null_descriptor();

        }



        e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,

                           rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);

        pci_dma_write(d, base, &desc, core->rx_desc_len);



        e1000e_ring_advance(core, rxi,

                            core->rx_desc_len / E1000_MIN_RX_DESC_LEN);



    } while (desc_offset < total_size);



    e1000e_update_rx_stats(core, size, total_size);

}

FUNC_0(E1000ECore *VAR_0, struct NetRxPkt *VAR_1,

                             const E1000E_RxRing *VAR_2,

                             const E1000E_RSSInfo *VAR_3)

{

    PCIDevice *d = VAR_0->owner;

    dma_addr_t base;

    uint8_t desc[E1000_MAX_RX_DESC_LEN];

    size_t desc_size;

    size_t desc_offset = 0;

    size_t iov_ofs = 0;



    struct iovec *VAR_4 = net_rx_pkt_get_iovec(VAR_1);

    size_t size = net_rx_pkt_get_total_len(VAR_1);

    size_t total_size = size + e1000x_fcs_len(VAR_0->mac);

    const E1000E_RingInfo *VAR_5;

    size_t ps_hdr_len = 0;

    bool do_ps = e1000e_do_ps(VAR_0, VAR_1, &ps_hdr_len);



    VAR_5 = VAR_2->i;



    do {

        hwaddr ba[MAX_PS_BUFFERS];

        e1000e_ba_state bastate = { { 0 } };

        bool is_last = false;

        bool is_first = true;



        desc_size = total_size - desc_offset;



        if (desc_size > VAR_0->rx_desc_buf_size) {

            desc_size = VAR_0->rx_desc_buf_size;

        }



        base = e1000e_ring_head_descr(VAR_0, VAR_5);



        pci_dma_read(d, base, &desc, VAR_0->rx_desc_len);



        trace_e1000e_rx_descr(VAR_5->idx, base, VAR_0->rx_desc_len);



        e1000e_read_rx_descr(VAR_0, desc, &ba);



        if (ba[0]) {

            if (desc_offset < size) {

                static const uint32_t VAR_6;

                size_t iov_copy;

                size_t copy_size = size - desc_offset;

                if (copy_size > VAR_0->rx_desc_buf_size) {

                    copy_size = VAR_0->rx_desc_buf_size;

                }



                

                if (do_ps) {

                    if (is_first) {

                        size_t ps_hdr_copied = 0;

                        do {

                            iov_copy = MIN(ps_hdr_len - ps_hdr_copied,

                                           VAR_4->iov_len - iov_ofs);



                            e1000e_write_hdr_to_rx_buffers(VAR_0, &ba, &bastate,

                                                      VAR_4->iov_base, iov_copy);



                            copy_size -= iov_copy;

                            ps_hdr_copied += iov_copy;



                            iov_ofs += iov_copy;

                            if (iov_ofs == VAR_4->iov_len) {

                                VAR_4++;

                                iov_ofs = 0;

                            }

                        } while (ps_hdr_copied < ps_hdr_len);



                        is_first = false;

                    } else {

                        

                        

                        e1000e_write_hdr_to_rx_buffers(VAR_0, &ba, &bastate,

                                                       NULL, 0);

                    }

                }



                

                while (copy_size) {

                    iov_copy = MIN(copy_size, VAR_4->iov_len - iov_ofs);



                    e1000e_write_to_rx_buffers(VAR_0, &ba, &bastate,

                                            VAR_4->iov_base + iov_ofs, iov_copy);



                    copy_size -= iov_copy;

                    iov_ofs += iov_copy;

                    if (iov_ofs == VAR_4->iov_len) {

                        VAR_4++;

                        iov_ofs = 0;

                    }

                }



                if (desc_offset + desc_size >= total_size) {

                    

                    e1000e_write_to_rx_buffers(VAR_0, &ba, &bastate,

                          (const char *) &VAR_6, e1000x_fcs_len(VAR_0->mac));

                }

            }

            desc_offset += desc_size;

            if (desc_offset >= total_size) {

                is_last = true;

            }

        } else { 

            trace_e1000e_rx_null_descriptor();

        }



        e1000e_write_rx_descr(VAR_0, desc, is_last ? VAR_0->rx_pkt : NULL,

                           VAR_3, do_ps ? ps_hdr_len : 0, &bastate.written);

        pci_dma_write(d, base, &desc, VAR_0->rx_desc_len);



        e1000e_ring_advance(VAR_0, VAR_5,

                            VAR_0->rx_desc_len / E1000_MIN_RX_DESC_LEN);



    } while (desc_offset < total_size);



    e1000e_update_rx_stats(VAR_0, size, total_size);

}

FUNC_0(E1000ECore *VAR_0, struct NetRxPkt *VAR_1,
const E1000E_RxRing *VAR_2,
const E1000E_RSSInfo *VAR_3)
{ PCIDevice *d = VAR_0->owner; dma_addr_t base; uint8_t desc[E1000_MAX_RX_DESC_LEN]; size_t desc_size; size_t desc_offset = 0; size_t iov_ofs = 0; struct iovec *VAR_4 = net_rx_pkt_get_iovec(VAR_1); size_t size = net_rx_pkt_get_total_len(VAR_1); size_t total_size = size + e1000x_fcs_len(VAR_0->mac); const E1000E_RingInfo *VAR_5; size_t ps_hdr_len = 0; bool do_ps = e1000e_do_ps(VAR_0, VAR_1, &ps_hdr_len); VAR_5 = VAR_2->i; do { hwaddr ba[MAX_PS_BUFFERS]; e1000e_ba_state bastate = { { 0 } }; bool is_last = false; bool is_first = true; desc_size = total_size - desc_offset; if (desc_size > VAR_0->rx_desc_buf_size) { desc_size = VAR_0->rx_desc_buf_size; } base = e1000e_ring_head_descr(VAR_0, VAR_5); pci_dma_read(d, base, &desc, VAR_0->rx_desc_len); trace_e1000e_rx_descr(VAR_5->idx, base, VAR_0->rx_desc_len); e1000e_read_rx_descr(VAR_0, desc, &ba); if (ba[0]) { if (desc_offset < size) { static const uint32_t VAR_6; size_t iov_copy; size_t copy_size = size - desc_offset; if (copy_size > VAR_0->rx_desc_buf_size) { copy_size = VAR_0->rx_desc_buf_size; } if (do_ps) { if (is_first) { size_t ps_hdr_copied = 0; do { iov_copy = MIN(ps_hdr_len - ps_hdr_copied,
VAR_4->iov_len - iov_ofs); e1000e_write_hdr_to_rx_buffers(VAR_0, &ba, &bastate,
VAR_4->iov_base, iov_copy); copy_size -= iov_copy; ps_hdr_copied += iov_copy; iov_ofs += iov_copy; if (iov_ofs == VAR_4->iov_len) { VAR_4++; iov_ofs = 0; } } while (ps_hdr_copied < ps_hdr_len); is_first = false; } else { e1000e_write_hdr_to_rx_buffers(VAR_0, &ba, &bastate,
NULL, 0); } } while (copy_size) { iov_copy = MIN(copy_size, VAR_4->iov_len - iov_ofs); e1000e_write_to_rx_buffers(VAR_0, &ba, &bastate,
VAR_4->iov_base + iov_ofs, iov_copy); copy_size -= iov_copy; iov_ofs += iov_copy; if (iov_ofs == VAR_4->iov_len) { VAR_4++; iov_ofs = 0; } } if (desc_offset + desc_size >= total_size) { e1000e_write_to_rx_buffers(VAR_0, &ba, &bastate,
(const char *) &VAR_6, e1000x_fcs_len(VAR_0->mac)); } } desc_offset += desc_size; if (desc_offset >= total_size) { is_last = true; } } else { trace_e1000e_rx_null_descriptor(); } e1000e_write_rx_descr(VAR_0, desc, is_last ? VAR_0->rx_pkt : NULL,
VAR_3, do_ps ? ps_hdr_len : 0, &bastate.written); pci_dma_write(d, base, &desc, VAR_0->rx_desc_len); e1000e_ring_advance(VAR_0, VAR_5,
VAR_0->rx_desc_len / E1000_MIN_RX_DESC_LEN); } while (desc_offset < total_size); e1000e_update_rx_stats(VAR_0, size, total_size); }