Revision bf6b87a8

b/hw/rtl8139.c
45 45
 *  2010-Feb-04  Frediano Ziglio:   Rewrote timer support using QEMU timer only
46 46
 *                                  when strictly needed (required for for
47 47
 *                                  Darwin)
48
 *  2011-Mar-22  Benjamin Poirier:  Implemented VLAN offloading
48 49
 */
49 50

  
50 51
/* For crc32 */
......
56 57
#include "net.h"
57 58
#include "loader.h"
58 59
#include "sysemu.h"
60
#include "iov.h"
59 61

  
60 62
/* debug RTL8139 card */
61 63
//#define DEBUG_RTL8139 1
......
1756 1758
    return ret;
1757 1759
}
1758 1760

  
1759
static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size, int do_interrupt)
1761
static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
1762
    int do_interrupt, const uint8_t *dot1q_buf)
1760 1763
{
1764
    struct iovec *iov = NULL;
1765

  
1761 1766
    if (!size)
1762 1767
    {
1763 1768
        DEBUG_PRINT(("RTL8139: +++ empty ethernet frame\n"));
1764 1769
        return;
1765 1770
    }
1766 1771

  
1772
    if (dot1q_buf && size >= ETHER_ADDR_LEN * 2) {
1773
        iov = (struct iovec[3]) {
1774
            { .iov_base = buf, .iov_len = ETHER_ADDR_LEN * 2 },
1775
            { .iov_base = (void *) dot1q_buf, .iov_len = VLAN_HLEN },
1776
            { .iov_base = buf + ETHER_ADDR_LEN * 2,
1777
                .iov_len = size - ETHER_ADDR_LEN * 2 },
1778
        };
1779
    }
1780

  
1767 1781
    if (TxLoopBack == (s->TxConfig & TxLoopBack))
1768 1782
    {
1783
        size_t buf2_size;
1784
        uint8_t *buf2;
1785

  
1786
        if (iov) {
1787
            buf2_size = iov_size(iov, 3);
1788
            buf2 = qemu_malloc(buf2_size);
1789
            iov_to_buf(iov, 3, buf2, 0, buf2_size);
1790
            buf = buf2;
1791
        }
1792

  
1769 1793
        DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n"));
1770 1794
        rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt);
1795

  
1796
        if (iov) {
1797
            qemu_free(buf2);
1798
        }
1771 1799
    }
1772 1800
    else
1773 1801
    {
1774
        qemu_send_packet(&s->nic->nc, buf, size);
1802
        if (iov) {
1803
            qemu_sendv_packet(&s->nic->nc, iov, 3);
1804
        } else {
1805
            qemu_send_packet(&s->nic->nc, buf, size);
1806
        }
1775 1807
    }
1776 1808
}
1777 1809

  
......
1805 1837
    s->TxStatus[descriptor] |= TxHostOwns;
1806 1838
    s->TxStatus[descriptor] |= TxStatOK;
1807 1839

  
1808
    rtl8139_transfer_frame(s, txbuffer, txsize, 0);
1840
    rtl8139_transfer_frame(s, txbuffer, txsize, 0, NULL);
1809 1841

  
1810 1842
    DEBUG_PRINT(("RTL8139: +++ transmitted %d bytes from descriptor %d\n", txsize, descriptor));
1811 1843

  
......
1932 1964

  
1933 1965
    cpu_physical_memory_read(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
1934 1966
    txdw0 = le32_to_cpu(val);
1935
    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
1936 1967
    cpu_physical_memory_read(cplus_tx_ring_desc+4,  (uint8_t *)&val, 4);
1937 1968
    txdw1 = le32_to_cpu(val);
1938 1969
    cpu_physical_memory_read(cplus_tx_ring_desc+8,  (uint8_t *)&val, 4);
......
1944 1975
           descriptor,
1945 1976
           txdw0, txdw1, txbufLO, txbufHI));
1946 1977

  
1947
    /* TODO: the following discard cast should clean clang analyzer output */
1948
    (void)txdw1;
1949

  
1950 1978
/* w0 ownership flag */
1951 1979
#define CP_TX_OWN (1<<31)
1952 1980
/* w0 end of ring flag */
......
1970 1998
/* w0 bits 0...15 : buffer size */
1971 1999
#define CP_TX_BUFFER_SIZE (1<<16)
1972 2000
#define CP_TX_BUFFER_SIZE_MASK (CP_TX_BUFFER_SIZE - 1)
1973
/* w1 tag available flag */
1974
#define CP_RX_TAGC (1<<17)
1975
/* w1 bits 0...15 : VLAN tag */
2001
/* w1 add tag flag */
2002
#define CP_TX_TAGC (1<<17)
2003
/* w1 bits 0...15 : VLAN tag (big endian) */
1976 2004
#define CP_TX_VLAN_TAG_MASK ((1<<16) - 1)
1977 2005
/* w2 low  32bit of Rx buffer ptr */
1978 2006
/* w3 high 32bit of Rx buffer ptr */
......
2072 2100
    /* update ring data */
2073 2101
    val = cpu_to_le32(txdw0);
2074 2102
    cpu_physical_memory_write(cplus_tx_ring_desc,    (uint8_t *)&val, 4);
2075
    /* TODO: implement VLAN tagging support, VLAN tag data is read to txdw1 */
2076
//    val = cpu_to_le32(txdw1);
2077
//    cpu_physical_memory_write(cplus_tx_ring_desc+4,  &val, 4);
2078 2103

  
2079 2104
    /* Now decide if descriptor being processed is holding the last segment of packet */
2080 2105
    if (txdw0 & CP_TX_LS)
2081 2106
    {
2107
        uint8_t dot1q_buffer_space[VLAN_HLEN];
2108
        uint16_t *dot1q_buffer;
2109

  
2082 2110
        DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : descriptor %d is last segment descriptor\n", descriptor));
2083 2111

  
2084 2112
        /* can transfer fully assembled packet */
......
2087 2115
        int      saved_size    = s->cplus_txbuffer_offset;
2088 2116
        int      saved_buffer_len = s->cplus_txbuffer_len;
2089 2117

  
2118
        /* create vlan tag */
2119
        if (txdw1 & CP_TX_TAGC) {
2120
            /* the vlan tag is in BE byte order in the descriptor
2121
             * BE + le_to_cpu() + ~swap()~ = cpu */
2122
            DEBUG_PRINT(("RTL8139: +++ C+ Tx mode : inserting vlan tag with "
2123
                    "tci: %u\n", bswap16(txdw1 & CP_TX_VLAN_TAG_MASK)));
2124

  
2125
            dot1q_buffer = (uint16_t *) dot1q_buffer_space;
2126
            dot1q_buffer[0] = cpu_to_be16(ETH_P_8021Q);
2127
            /* BE + le_to_cpu() + ~cpu_to_le()~ = BE */
2128
            dot1q_buffer[1] = cpu_to_le16(txdw1 & CP_TX_VLAN_TAG_MASK);
2129
        } else {
2130
            dot1q_buffer = NULL;
2131
        }
2132

  
2090 2133
        /* reset the card space to protect from recursive call */
2091 2134
        s->cplus_txbuffer = NULL;
2092 2135
        s->cplus_txbuffer_offset = 0;
......
2240 2283

  
2241 2284
                        int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
2242 2285
                        DEBUG_PRINT(("RTL8139: +++ C+ mode TSO transferring packet size %d\n", tso_send_size));
2243
                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size, 0);
2286
                        rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
2287
                            0, (uint8_t *) dot1q_buffer);
2244 2288

  
2245 2289
                        /* add transferred count to TCP sequence number */
2246 2290
                        p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
......
2313 2357

  
2314 2358
        DEBUG_PRINT(("RTL8139: +++ C+ mode transmitting %d bytes packet\n", saved_size));
2315 2359

  
2316
        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1);
2360
        rtl8139_transfer_frame(s, saved_buffer, saved_size, 1,
2361
            (uint8_t *) dot1q_buffer);
2317 2362

  
2318 2363
        /* restore card space if there was no recursion and reset offset */
2319 2364
        if (!s->cplus_txbuffer)

Also available in: Unified diff