process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)

{

    PCIDevice *d = PCI_DEVICE(s);

    uint32_t txd_lower = le32_to_cpu(dp->lower.data);

    uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);

    unsigned int split_size = txd_lower & 0xffff, bytes, sz;

    unsigned int msh = 0xfffff;

    uint64_t addr;

    struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;

    struct e1000_tx *tp = &s->tx;



    s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);

    if (dtype == E1000_TXD_CMD_DEXT) {    /* context descriptor */

        e1000x_read_tx_ctx_descr(xp, &tp->props);

        tp->tso_frames = 0;

        if (tp->props.tucso == 0) {    /* this is probably wrong */

            DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");

            tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6);

        }

        return;

    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {

        // data descriptor

        if (tp->size == 0) {

            tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;

        }

        tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;

    } else {

        // legacy descriptor

        tp->props.cptse = 0;

    }



    if (e1000x_vlan_enabled(s->mac_reg) &&

        e1000x_is_vlan_txd(txd_lower) &&

        (tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {

        tp->vlan_needed = 1;

        stw_be_p(tp->vlan_header,

                      le16_to_cpu(s->mac_reg[VET]));

        stw_be_p(tp->vlan_header + 2,

                      le16_to_cpu(dp->upper.fields.special));

    }



    addr = le64_to_cpu(dp->buffer_addr);

    if (tp->props.tse && tp->props.cptse) {

        msh = tp->props.hdr_len + tp->props.mss;

        do {

            bytes = split_size;

            if (tp->size + bytes > msh)

                bytes = msh - tp->size;



            bytes = MIN(sizeof(tp->data) - tp->size, bytes);

            pci_dma_read(d, addr, tp->data + tp->size, bytes);

            sz = tp->size + bytes;

            if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) {

                memmove(tp->header, tp->data, tp->props.hdr_len);

            }

            tp->size = sz;

            addr += bytes;

            if (sz == msh) {

                xmit_seg(s);

                memmove(tp->data, tp->header, tp->props.hdr_len);

                tp->size = tp->props.hdr_len;

            }

            split_size -= bytes;

        } while (bytes && split_size);

    } else if (!tp->props.tse && tp->props.cptse) {

        // context descriptor TSE is not set, while data descriptor TSE is set

        DBGOUT(TXERR, "TCP segmentation error\n");

    } else {

        split_size = MIN(sizeof(tp->data) - tp->size, split_size);

        pci_dma_read(d, addr, tp->data + tp->size, split_size);

        tp->size += split_size;

    }



    if (!(txd_lower & E1000_TXD_CMD_EOP))

        return;

    if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) {

        xmit_seg(s);

    }

    tp->tso_frames = 0;

    tp->props.sum_needed = 0;

    tp->vlan_needed = 0;

    tp->size = 0;

    tp->props.cptse = 0;

}

process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)

{

    PCIDevice *d = PCI_DEVICE(s);

    uint32_t txd_lower = le32_to_cpu(dp->lower.data);

    uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);

    unsigned int split_size = txd_lower & 0xffff, bytes, sz;

    unsigned int msh = 0xfffff;

    uint64_t addr;

    struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;

    struct e1000_tx *tp = &s->tx;



    s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);

    if (dtype == E1000_TXD_CMD_DEXT) {    

        e1000x_read_tx_ctx_descr(xp, &tp->props);

        tp->tso_frames = 0;

        if (tp->props.tucso == 0) {    

            DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");

            tp->props.tucso = tp->props.tucss + (tp->props.tcp ? 16 : 6);

        }

        return;

    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {

        

        if (tp->size == 0) {

            tp->props.sum_needed = le32_to_cpu(dp->upper.data) >> 8;

        }

        tp->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;

    } else {

        

        tp->props.cptse = 0;

    }



    if (e1000x_vlan_enabled(s->mac_reg) &&

        e1000x_is_vlan_txd(txd_lower) &&

        (tp->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {

        tp->vlan_needed = 1;

        stw_be_p(tp->vlan_header,

                      le16_to_cpu(s->mac_reg[VET]));

        stw_be_p(tp->vlan_header + 2,

                      le16_to_cpu(dp->upper.fields.special));

    }



    addr = le64_to_cpu(dp->buffer_addr);

    if (tp->props.tse && tp->props.cptse) {

        msh = tp->props.hdr_len + tp->props.mss;

        do {

            bytes = split_size;

            if (tp->size + bytes > msh)

                bytes = msh - tp->size;



            bytes = MIN(sizeof(tp->data) - tp->size, bytes);

            pci_dma_read(d, addr, tp->data + tp->size, bytes);

            sz = tp->size + bytes;

            if (sz >= tp->props.hdr_len && tp->size < tp->props.hdr_len) {

                memmove(tp->header, tp->data, tp->props.hdr_len);

            }

            tp->size = sz;

            addr += bytes;

            if (sz == msh) {

                xmit_seg(s);

                memmove(tp->data, tp->header, tp->props.hdr_len);

                tp->size = tp->props.hdr_len;

            }

            split_size -= bytes;

        } while (bytes && split_size);

    } else if (!tp->props.tse && tp->props.cptse) {

        

        DBGOUT(TXERR, "TCP segmentation error\n");

    } else {

        split_size = MIN(sizeof(tp->data) - tp->size, split_size);

        pci_dma_read(d, addr, tp->data + tp->size, split_size);

        tp->size += split_size;

    }



    if (!(txd_lower & E1000_TXD_CMD_EOP))

        return;

    if (!(tp->props.tse && tp->props.cptse && tp->size < tp->props.hdr_len)) {

        xmit_seg(s);

    }

    tp->tso_frames = 0;

    tp->props.sum_needed = 0;

    tp->vlan_needed = 0;

    tp->size = 0;

    tp->props.cptse = 0;

}

FUNC_0(E1000State *VAR_0, struct e1000_tx_desc *VAR_1)

{

    PCIDevice *d = PCI_DEVICE(VAR_0);

    uint32_t txd_lower = le32_to_cpu(VAR_1->lower.data);

    uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);

    unsigned int VAR_2 = txd_lower & 0xffff, VAR_3, VAR_4;

    unsigned int VAR_5 = 0xfffff;

    uint64_t addr;

    struct e1000_context_desc *VAR_6 = (struct e1000_context_desc *)VAR_1;

    struct e1000_tx *VAR_7 = &VAR_0->tx;



    VAR_0->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);

    if (dtype == E1000_TXD_CMD_DEXT) {    

        e1000x_read_tx_ctx_descr(VAR_6, &VAR_7->props);

        VAR_7->tso_frames = 0;

        if (VAR_7->props.tucso == 0) {    

            DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");

            VAR_7->props.tucso = VAR_7->props.tucss + (VAR_7->props.tcp ? 16 : 6);

        }

        return;

    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {

        

        if (VAR_7->size == 0) {

            VAR_7->props.sum_needed = le32_to_cpu(VAR_1->upper.data) >> 8;

        }

        VAR_7->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0;

    } else {

        

        VAR_7->props.cptse = 0;

    }



    if (e1000x_vlan_enabled(VAR_0->mac_reg) &&

        e1000x_is_vlan_txd(txd_lower) &&

        (VAR_7->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) {

        VAR_7->vlan_needed = 1;

        stw_be_p(VAR_7->vlan_header,

                      le16_to_cpu(VAR_0->mac_reg[VET]));

        stw_be_p(VAR_7->vlan_header + 2,

                      le16_to_cpu(VAR_1->upper.fields.special));

    }



    addr = le64_to_cpu(VAR_1->buffer_addr);

    if (VAR_7->props.tse && VAR_7->props.cptse) {

        VAR_5 = VAR_7->props.hdr_len + VAR_7->props.mss;

        do {

            VAR_3 = VAR_2;

            if (VAR_7->size + VAR_3 > VAR_5)

                VAR_3 = VAR_5 - VAR_7->size;



            VAR_3 = MIN(sizeof(VAR_7->data) - VAR_7->size, VAR_3);

            pci_dma_read(d, addr, VAR_7->data + VAR_7->size, VAR_3);

            VAR_4 = VAR_7->size + VAR_3;

            if (VAR_4 >= VAR_7->props.hdr_len && VAR_7->size < VAR_7->props.hdr_len) {

                memmove(VAR_7->header, VAR_7->data, VAR_7->props.hdr_len);

            }

            VAR_7->size = VAR_4;

            addr += VAR_3;

            if (VAR_4 == VAR_5) {

                xmit_seg(VAR_0);

                memmove(VAR_7->data, VAR_7->header, VAR_7->props.hdr_len);

                VAR_7->size = VAR_7->props.hdr_len;

            }

            VAR_2 -= VAR_3;

        } while (VAR_3 && VAR_2);

    } else if (!VAR_7->props.tse && VAR_7->props.cptse) {

        

        DBGOUT(TXERR, "TCP segmentation error\n");

    } else {

        VAR_2 = MIN(sizeof(VAR_7->data) - VAR_7->size, VAR_2);

        pci_dma_read(d, addr, VAR_7->data + VAR_7->size, VAR_2);

        VAR_7->size += VAR_2;

    }



    if (!(txd_lower & E1000_TXD_CMD_EOP))

        return;

    if (!(VAR_7->props.tse && VAR_7->props.cptse && VAR_7->size < VAR_7->props.hdr_len)) {

        xmit_seg(VAR_0);

    }

    VAR_7->tso_frames = 0;

    VAR_7->props.sum_needed = 0;

    VAR_7->vlan_needed = 0;

    VAR_7->size = 0;

    VAR_7->props.cptse = 0;

}

FUNC_0(E1000State *VAR_0, struct e1000_tx_desc *VAR_1)
{ PCIDevice *d = PCI_DEVICE(VAR_0); uint32_t txd_lower = le32_to_cpu(VAR_1->lower.data); uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); unsigned int VAR_2 = txd_lower & 0xffff, VAR_3, VAR_4; unsigned int VAR_5 = 0xfffff; uint64_t addr; struct e1000_context_desc *VAR_6 = (struct e1000_context_desc *)VAR_1; struct e1000_tx *VAR_7 = &VAR_0->tx; VAR_0->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE); if (dtype == E1000_TXD_CMD_DEXT) { e1000x_read_tx_ctx_descr(VAR_6, &VAR_7->props); VAR_7->tso_frames = 0; if (VAR_7->props.tucso == 0) { DBGOUT(TXSUM, "TCP/UDP: cso 0!\n"); VAR_7->props.tucso = VAR_7->props.tucss + (VAR_7->props.tcp ? 16 : 6); } return; } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { if (VAR_7->size == 0) { VAR_7->props.sum_needed = le32_to_cpu(VAR_1->upper.data) >> 8; } VAR_7->props.cptse = (txd_lower & E1000_TXD_CMD_TSE) ? 1 : 0; } else { VAR_7->props.cptse = 0; } if (e1000x_vlan_enabled(VAR_0->mac_reg) &&
e1000x_is_vlan_txd(txd_lower) &&
(VAR_7->props.cptse || txd_lower & E1000_TXD_CMD_EOP)) { VAR_7->vlan_needed = 1; stw_be_p(VAR_7->vlan_header,
le16_to_cpu(VAR_0->mac_reg[VET])); stw_be_p(VAR_7->vlan_header + 2,
le16_to_cpu(VAR_1->upper.fields.special)); } addr = le64_to_cpu(VAR_1->buffer_addr); if (VAR_7->props.tse && VAR_7->props.cptse) { VAR_5 = VAR_7->props.hdr_len + VAR_7->props.mss; do { VAR_3 = VAR_2; if (VAR_7->size + VAR_3 > VAR_5)
VAR_3 = VAR_5 - VAR_7->size; VAR_3 = MIN(sizeof(VAR_7->data) - VAR_7->size, VAR_3); pci_dma_read(d, addr, VAR_7->data + VAR_7->size, VAR_3); VAR_4 = VAR_7->size + VAR_3; if (VAR_4 >= VAR_7->props.hdr_len && VAR_7->size < VAR_7->props.hdr_len) { memmove(VAR_7->header, VAR_7->data, VAR_7->props.hdr_len); } VAR_7->size = VAR_4; addr += VAR_3; if (VAR_4 == VAR_5) { xmit_seg(VAR_0); memmove(VAR_7->data, VAR_7->header, VAR_7->props.hdr_len); VAR_7->size = VAR_7->props.hdr_len; } VAR_2 -= VAR_3; } while (VAR_3 && VAR_2); } else if (!VAR_7->props.tse && VAR_7->props.cptse) { DBGOUT(TXERR, "TCP segmentation error\n"); } else { VAR_2 = MIN(sizeof(VAR_7->data) - VAR_7->size, VAR_2); pci_dma_read(d, addr, VAR_7->data + VAR_7->size, VAR_2); VAR_7->size += VAR_2; } if (!(txd_lower & E1000_TXD_CMD_EOP))
return; if (!(VAR_7->props.tse && VAR_7->props.cptse && VAR_7->size < VAR_7->props.hdr_len)) { xmit_seg(VAR_0); } VAR_7->tso_frames = 0; VAR_7->props.sum_needed = 0; VAR_7->vlan_needed = 0; VAR_7->size = 0; VAR_7->props.cptse = 0; }