Statistics
| Branch: | Revision:

root / hw / e1000.c @ 72cf2d4f

History | View | Annotate | Download (36 kB)

1 7c23b892 balrog
/*
2 7c23b892 balrog
 * QEMU e1000 emulation
3 7c23b892 balrog
 *
4 7c23b892 balrog
 * Nir Peleg, Tutis Systems Ltd. for Qumranet Inc.
5 7c23b892 balrog
 * Copyright (c) 2008 Qumranet
6 7c23b892 balrog
 * Based on work done by:
7 7c23b892 balrog
 * Copyright (c) 2007 Dan Aloni
8 7c23b892 balrog
 * Copyright (c) 2004 Antony T Curtis
9 7c23b892 balrog
 *
10 7c23b892 balrog
 * This library is free software; you can redistribute it and/or
11 7c23b892 balrog
 * modify it under the terms of the GNU Lesser General Public
12 7c23b892 balrog
 * License as published by the Free Software Foundation; either
13 7c23b892 balrog
 * version 2 of the License, or (at your option) any later version.
14 7c23b892 balrog
 *
15 7c23b892 balrog
 * This library is distributed in the hope that it will be useful,
16 7c23b892 balrog
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 7c23b892 balrog
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 7c23b892 balrog
 * Lesser General Public License for more details.
19 7c23b892 balrog
 *
20 7c23b892 balrog
 * You should have received a copy of the GNU Lesser General Public
21 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 7c23b892 balrog
 */
23 7c23b892 balrog
24 7c23b892 balrog
25 7c23b892 balrog
#include "hw.h"
26 7c23b892 balrog
#include "pci.h"
27 7c23b892 balrog
#include "net.h"
28 7c23b892 balrog
29 7c23b892 balrog
#include "e1000_hw.h"
30 7c23b892 balrog
31 7c23b892 balrog
#define DEBUG
32 7c23b892 balrog
33 7c23b892 balrog
#ifdef DEBUG
34 7c23b892 balrog
enum {
35 7c23b892 balrog
    DEBUG_GENERAL,        DEBUG_IO,        DEBUG_MMIO,        DEBUG_INTERRUPT,
36 7c23b892 balrog
    DEBUG_RX,                DEBUG_TX,        DEBUG_MDIC,        DEBUG_EEPROM,
37 7c23b892 balrog
    DEBUG_UNKNOWN,        DEBUG_TXSUM,        DEBUG_TXERR,        DEBUG_RXERR,
38 7c23b892 balrog
    DEBUG_RXFILTER,        DEBUG_NOTYET,
39 7c23b892 balrog
};
40 7c23b892 balrog
#define DBGBIT(x)        (1<<DEBUG_##x)
41 7c23b892 balrog
static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
42 7c23b892 balrog
43 6c7f4b47 Blue Swirl
#define        DBGOUT(what, fmt, ...) do { \
44 7c23b892 balrog
    if (debugflags & DBGBIT(what)) \
45 6c7f4b47 Blue Swirl
        fprintf(stderr, "e1000: " fmt, ## __VA_ARGS__); \
46 7c23b892 balrog
    } while (0)
47 7c23b892 balrog
#else
48 6c7f4b47 Blue Swirl
#define        DBGOUT(what, fmt, ...) do {} while (0)
49 7c23b892 balrog
#endif
50 7c23b892 balrog
51 7c23b892 balrog
#define IOPORT_SIZE       0x40
52 e94bbefe aurel32
#define PNPMMIO_SIZE      0x20000
53 7c23b892 balrog
54 7c23b892 balrog
/*
55 7c23b892 balrog
 * HW models:
56 7c23b892 balrog
 *  E1000_DEV_ID_82540EM works with Windows and Linux
57 7c23b892 balrog
 *  E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
58 7c23b892 balrog
 *        appears to perform better than 82540EM, but breaks with Linux 2.6.18
59 7c23b892 balrog
 *  E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
60 7c23b892 balrog
 *  Others never tested
61 7c23b892 balrog
 */
62 7c23b892 balrog
enum { E1000_DEVID = E1000_DEV_ID_82540EM };
63 7c23b892 balrog
64 7c23b892 balrog
/*
65 7c23b892 balrog
 * May need to specify additional MAC-to-PHY entries --
66 7c23b892 balrog
 * Intel's Windows driver refuses to initialize unless they match
67 7c23b892 balrog
 */
68 7c23b892 balrog
enum {
69 7c23b892 balrog
    PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ?                0xcc2 :
70 7c23b892 balrog
                   E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ?        0xc30 :
71 7c23b892 balrog
                   /* default to E1000_DEV_ID_82540EM */        0xc20
72 7c23b892 balrog
};
73 7c23b892 balrog
74 7c23b892 balrog
typedef struct E1000State_st {
75 7c23b892 balrog
    PCIDevice dev;
76 7c23b892 balrog
    VLANClientState *vc;
77 7c23b892 balrog
    int mmio_index;
78 7c23b892 balrog
79 7c23b892 balrog
    uint32_t mac_reg[0x8000];
80 7c23b892 balrog
    uint16_t phy_reg[0x20];
81 7c23b892 balrog
    uint16_t eeprom_data[64];
82 7c23b892 balrog
83 7c23b892 balrog
    uint32_t rxbuf_size;
84 7c23b892 balrog
    uint32_t rxbuf_min_shift;
85 7c23b892 balrog
    int check_rxov;
86 7c23b892 balrog
    struct e1000_tx {
87 7c23b892 balrog
        unsigned char header[256];
88 8f2e8d1f aliguori
        unsigned char vlan_header[4];
89 8f2e8d1f aliguori
        unsigned char vlan[4];
90 7c23b892 balrog
        unsigned char data[0x10000];
91 7c23b892 balrog
        uint16_t size;
92 7c23b892 balrog
        unsigned char sum_needed;
93 8f2e8d1f aliguori
        unsigned char vlan_needed;
94 7c23b892 balrog
        uint8_t ipcss;
95 7c23b892 balrog
        uint8_t ipcso;
96 7c23b892 balrog
        uint16_t ipcse;
97 7c23b892 balrog
        uint8_t tucss;
98 7c23b892 balrog
        uint8_t tucso;
99 7c23b892 balrog
        uint16_t tucse;
100 7c23b892 balrog
        uint8_t hdr_len;
101 7c23b892 balrog
        uint16_t mss;
102 7c23b892 balrog
        uint32_t paylen;
103 7c23b892 balrog
        uint16_t tso_frames;
104 7c23b892 balrog
        char tse;
105 b6c4f71f blueswir1
        int8_t ip;
106 b6c4f71f blueswir1
        int8_t tcp;
107 1b0009db balrog
        char cptse;     // current packet tse bit
108 7c23b892 balrog
    } tx;
109 7c23b892 balrog
110 7c23b892 balrog
    struct {
111 7c23b892 balrog
        uint32_t val_in;        // shifted in from guest driver
112 7c23b892 balrog
        uint16_t bitnum_in;
113 7c23b892 balrog
        uint16_t bitnum_out;
114 7c23b892 balrog
        uint16_t reading;
115 7c23b892 balrog
        uint32_t old_eecd;
116 7c23b892 balrog
    } eecd_state;
117 7c23b892 balrog
} E1000State;
118 7c23b892 balrog
119 7c23b892 balrog
#define        defreg(x)        x = (E1000_##x>>2)
120 7c23b892 balrog
enum {
121 7c23b892 balrog
    defreg(CTRL),        defreg(EECD),        defreg(EERD),        defreg(GPRC),
122 7c23b892 balrog
    defreg(GPTC),        defreg(ICR),        defreg(ICS),        defreg(IMC),
123 7c23b892 balrog
    defreg(IMS),        defreg(LEDCTL),        defreg(MANC),        defreg(MDIC),
124 7c23b892 balrog
    defreg(MPC),        defreg(PBA),        defreg(RCTL),        defreg(RDBAH),
125 7c23b892 balrog
    defreg(RDBAL),        defreg(RDH),        defreg(RDLEN),        defreg(RDT),
126 7c23b892 balrog
    defreg(STATUS),        defreg(SWSM),        defreg(TCTL),        defreg(TDBAH),
127 7c23b892 balrog
    defreg(TDBAL),        defreg(TDH),        defreg(TDLEN),        defreg(TDT),
128 7c23b892 balrog
    defreg(TORH),        defreg(TORL),        defreg(TOTH),        defreg(TOTL),
129 7c23b892 balrog
    defreg(TPR),        defreg(TPT),        defreg(TXDCTL),        defreg(WUFC),
130 8f2e8d1f aliguori
    defreg(RA),                defreg(MTA),        defreg(CRCERRS),defreg(VFTA),
131 8f2e8d1f aliguori
    defreg(VET),
132 7c23b892 balrog
};
133 7c23b892 balrog
134 7c23b892 balrog
enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
135 88b4e9db blueswir1
static const char phy_regcap[0x20] = {
136 7c23b892 balrog
    [PHY_STATUS] = PHY_R,        [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
137 7c23b892 balrog
    [PHY_ID1] = PHY_R,                [M88E1000_PHY_SPEC_CTRL] = PHY_RW,
138 7c23b892 balrog
    [PHY_CTRL] = PHY_RW,        [PHY_1000T_CTRL] = PHY_RW,
139 7c23b892 balrog
    [PHY_LP_ABILITY] = PHY_R,        [PHY_1000T_STATUS] = PHY_R,
140 7c23b892 balrog
    [PHY_AUTONEG_ADV] = PHY_RW,        [M88E1000_RX_ERR_CNTR] = PHY_R,
141 700f6e2c aurel32
    [PHY_ID2] = PHY_R,                [M88E1000_PHY_SPEC_STATUS] = PHY_R
142 7c23b892 balrog
};
143 7c23b892 balrog
144 7c23b892 balrog
static void
145 7c23b892 balrog
ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr,
146 7c23b892 balrog
           uint32_t size, int type)
147 7c23b892 balrog
{
148 7c23b892 balrog
    DBGOUT(IO, "e1000_ioport_map addr=0x%04x size=0x%08x\n", addr, size);
149 7c23b892 balrog
}
150 7c23b892 balrog
151 7c23b892 balrog
static void
152 7c23b892 balrog
set_interrupt_cause(E1000State *s, int index, uint32_t val)
153 7c23b892 balrog
{
154 7c23b892 balrog
    if (val)
155 7c23b892 balrog
        val |= E1000_ICR_INT_ASSERTED;
156 7c23b892 balrog
    s->mac_reg[ICR] = val;
157 b1332393 Bill Paul
    s->mac_reg[ICS] = val;
158 bc26e55a Blue Swirl
    qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
159 7c23b892 balrog
}
160 7c23b892 balrog
161 7c23b892 balrog
static void
162 7c23b892 balrog
set_ics(E1000State *s, int index, uint32_t val)
163 7c23b892 balrog
{
164 7c23b892 balrog
    DBGOUT(INTERRUPT, "set_ics %x, ICR %x, IMR %x\n", val, s->mac_reg[ICR],
165 7c23b892 balrog
        s->mac_reg[IMS]);
166 7c23b892 balrog
    set_interrupt_cause(s, 0, val | s->mac_reg[ICR]);
167 7c23b892 balrog
}
168 7c23b892 balrog
169 7c23b892 balrog
static int
170 7c23b892 balrog
rxbufsize(uint32_t v)
171 7c23b892 balrog
{
172 7c23b892 balrog
    v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 |
173 7c23b892 balrog
         E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 |
174 7c23b892 balrog
         E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256;
175 7c23b892 balrog
    switch (v) {
176 7c23b892 balrog
    case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384:
177 7c23b892 balrog
        return 16384;
178 7c23b892 balrog
    case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192:
179 7c23b892 balrog
        return 8192;
180 7c23b892 balrog
    case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096:
181 7c23b892 balrog
        return 4096;
182 7c23b892 balrog
    case E1000_RCTL_SZ_1024:
183 7c23b892 balrog
        return 1024;
184 7c23b892 balrog
    case E1000_RCTL_SZ_512:
185 7c23b892 balrog
        return 512;
186 7c23b892 balrog
    case E1000_RCTL_SZ_256:
187 7c23b892 balrog
        return 256;
188 7c23b892 balrog
    }
189 7c23b892 balrog
    return 2048;
190 7c23b892 balrog
}
191 7c23b892 balrog
192 7c23b892 balrog
static void
193 cab3c825 Kevin Wolf
set_ctrl(E1000State *s, int index, uint32_t val)
194 cab3c825 Kevin Wolf
{
195 cab3c825 Kevin Wolf
    /* RST is self clearing */
196 cab3c825 Kevin Wolf
    s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
197 cab3c825 Kevin Wolf
}
198 cab3c825 Kevin Wolf
199 cab3c825 Kevin Wolf
static void
200 7c23b892 balrog
set_rx_control(E1000State *s, int index, uint32_t val)
201 7c23b892 balrog
{
202 7c23b892 balrog
    s->mac_reg[RCTL] = val;
203 7c23b892 balrog
    s->rxbuf_size = rxbufsize(val);
204 7c23b892 balrog
    s->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1;
205 7c23b892 balrog
    DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] = 0x%x\n", s->mac_reg[RDT],
206 7c23b892 balrog
           s->mac_reg[RCTL]);
207 7c23b892 balrog
}
208 7c23b892 balrog
209 7c23b892 balrog
static void
210 7c23b892 balrog
set_mdic(E1000State *s, int index, uint32_t val)
211 7c23b892 balrog
{
212 7c23b892 balrog
    uint32_t data = val & E1000_MDIC_DATA_MASK;
213 7c23b892 balrog
    uint32_t addr = ((val & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
214 7c23b892 balrog
215 7c23b892 balrog
    if ((val & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) // phy #
216 7c23b892 balrog
        val = s->mac_reg[MDIC] | E1000_MDIC_ERROR;
217 7c23b892 balrog
    else if (val & E1000_MDIC_OP_READ) {
218 7c23b892 balrog
        DBGOUT(MDIC, "MDIC read reg 0x%x\n", addr);
219 7c23b892 balrog
        if (!(phy_regcap[addr] & PHY_R)) {
220 7c23b892 balrog
            DBGOUT(MDIC, "MDIC read reg %x unhandled\n", addr);
221 7c23b892 balrog
            val |= E1000_MDIC_ERROR;
222 7c23b892 balrog
        } else
223 7c23b892 balrog
            val = (val ^ data) | s->phy_reg[addr];
224 7c23b892 balrog
    } else if (val & E1000_MDIC_OP_WRITE) {
225 7c23b892 balrog
        DBGOUT(MDIC, "MDIC write reg 0x%x, value 0x%x\n", addr, data);
226 7c23b892 balrog
        if (!(phy_regcap[addr] & PHY_W)) {
227 7c23b892 balrog
            DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
228 7c23b892 balrog
            val |= E1000_MDIC_ERROR;
229 7c23b892 balrog
        } else
230 7c23b892 balrog
            s->phy_reg[addr] = data;
231 7c23b892 balrog
    }
232 7c23b892 balrog
    s->mac_reg[MDIC] = val | E1000_MDIC_READY;
233 7c23b892 balrog
    set_ics(s, 0, E1000_ICR_MDAC);
234 7c23b892 balrog
}
235 7c23b892 balrog
236 7c23b892 balrog
static uint32_t
237 7c23b892 balrog
get_eecd(E1000State *s, int index)
238 7c23b892 balrog
{
239 7c23b892 balrog
    uint32_t ret = E1000_EECD_PRES|E1000_EECD_GNT | s->eecd_state.old_eecd;
240 7c23b892 balrog
241 7c23b892 balrog
    DBGOUT(EEPROM, "reading eeprom bit %d (reading %d)\n",
242 7c23b892 balrog
           s->eecd_state.bitnum_out, s->eecd_state.reading);
243 7c23b892 balrog
    if (!s->eecd_state.reading ||
244 7c23b892 balrog
        ((s->eeprom_data[(s->eecd_state.bitnum_out >> 4) & 0x3f] >>
245 7c23b892 balrog
          ((s->eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1)
246 7c23b892 balrog
        ret |= E1000_EECD_DO;
247 7c23b892 balrog
    return ret;
248 7c23b892 balrog
}
249 7c23b892 balrog
250 7c23b892 balrog
static void
251 7c23b892 balrog
set_eecd(E1000State *s, int index, uint32_t val)
252 7c23b892 balrog
{
253 7c23b892 balrog
    uint32_t oldval = s->eecd_state.old_eecd;
254 7c23b892 balrog
255 7c23b892 balrog
    s->eecd_state.old_eecd = val & (E1000_EECD_SK | E1000_EECD_CS |
256 7c23b892 balrog
            E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ);
257 7c23b892 balrog
    if (!(E1000_EECD_SK & (val ^ oldval)))        // no clock edge
258 7c23b892 balrog
        return;
259 7c23b892 balrog
    if (!(E1000_EECD_SK & val)) {                // falling edge
260 7c23b892 balrog
        s->eecd_state.bitnum_out++;
261 7c23b892 balrog
        return;
262 7c23b892 balrog
    }
263 7c23b892 balrog
    if (!(val & E1000_EECD_CS)) {                // rising, no CS (EEPROM reset)
264 7c23b892 balrog
        memset(&s->eecd_state, 0, sizeof s->eecd_state);
265 356c7ff4 Naphtali Sprei
        /*
266 356c7ff4 Naphtali Sprei
         * restore old_eecd's E1000_EECD_SK (known to be on)
267 356c7ff4 Naphtali Sprei
         * to avoid false detection of a clock edge
268 356c7ff4 Naphtali Sprei
         */
269 356c7ff4 Naphtali Sprei
        s->eecd_state.old_eecd = E1000_EECD_SK;
270 7c23b892 balrog
        return;
271 7c23b892 balrog
    }
272 7c23b892 balrog
    s->eecd_state.val_in <<= 1;
273 7c23b892 balrog
    if (val & E1000_EECD_DI)
274 7c23b892 balrog
        s->eecd_state.val_in |= 1;
275 7c23b892 balrog
    if (++s->eecd_state.bitnum_in == 9 && !s->eecd_state.reading) {
276 7c23b892 balrog
        s->eecd_state.bitnum_out = ((s->eecd_state.val_in & 0x3f)<<4)-1;
277 7c23b892 balrog
        s->eecd_state.reading = (((s->eecd_state.val_in >> 6) & 7) ==
278 7c23b892 balrog
            EEPROM_READ_OPCODE_MICROWIRE);
279 7c23b892 balrog
    }
280 7c23b892 balrog
    DBGOUT(EEPROM, "eeprom bitnum in %d out %d, reading %d\n",
281 7c23b892 balrog
           s->eecd_state.bitnum_in, s->eecd_state.bitnum_out,
282 7c23b892 balrog
           s->eecd_state.reading);
283 7c23b892 balrog
}
284 7c23b892 balrog
285 7c23b892 balrog
static uint32_t
286 7c23b892 balrog
flash_eerd_read(E1000State *s, int x)
287 7c23b892 balrog
{
288 7c23b892 balrog
    unsigned int index, r = s->mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START;
289 7c23b892 balrog
290 b1332393 Bill Paul
    if ((s->mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0)
291 b1332393 Bill Paul
        return (s->mac_reg[EERD]);
292 b1332393 Bill Paul
293 7c23b892 balrog
    if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG)
294 b1332393 Bill Paul
        return (E1000_EEPROM_RW_REG_DONE | r);
295 b1332393 Bill Paul
296 b1332393 Bill Paul
    return ((s->eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) |
297 b1332393 Bill Paul
           E1000_EEPROM_RW_REG_DONE | r);
298 7c23b892 balrog
}
299 7c23b892 balrog
300 7c23b892 balrog
static void
301 7c23b892 balrog
putsum(uint8_t *data, uint32_t n, uint32_t sloc, uint32_t css, uint32_t cse)
302 7c23b892 balrog
{
303 c6a6a5e3 aliguori
    uint32_t sum;
304 c6a6a5e3 aliguori
305 7c23b892 balrog
    if (cse && cse < n)
306 7c23b892 balrog
        n = cse + 1;
307 c6a6a5e3 aliguori
    if (sloc < n-1) {
308 c6a6a5e3 aliguori
        sum = net_checksum_add(n-css, data+css);
309 7c23b892 balrog
        cpu_to_be16wu((uint16_t *)(data + sloc),
310 c6a6a5e3 aliguori
                      net_checksum_finish(sum));
311 c6a6a5e3 aliguori
    }
312 7c23b892 balrog
}
313 7c23b892 balrog
314 8f2e8d1f aliguori
static inline int
315 8f2e8d1f aliguori
vlan_enabled(E1000State *s)
316 8f2e8d1f aliguori
{
317 8f2e8d1f aliguori
    return ((s->mac_reg[CTRL] & E1000_CTRL_VME) != 0);
318 8f2e8d1f aliguori
}
319 8f2e8d1f aliguori
320 8f2e8d1f aliguori
static inline int
321 8f2e8d1f aliguori
vlan_rx_filter_enabled(E1000State *s)
322 8f2e8d1f aliguori
{
323 8f2e8d1f aliguori
    return ((s->mac_reg[RCTL] & E1000_RCTL_VFE) != 0);
324 8f2e8d1f aliguori
}
325 8f2e8d1f aliguori
326 8f2e8d1f aliguori
static inline int
327 8f2e8d1f aliguori
is_vlan_packet(E1000State *s, const uint8_t *buf)
328 8f2e8d1f aliguori
{
329 8f2e8d1f aliguori
    return (be16_to_cpup((uint16_t *)(buf + 12)) ==
330 8f2e8d1f aliguori
                le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
331 8f2e8d1f aliguori
}
332 8f2e8d1f aliguori
333 8f2e8d1f aliguori
static inline int
334 8f2e8d1f aliguori
is_vlan_txd(uint32_t txd_lower)
335 8f2e8d1f aliguori
{
336 8f2e8d1f aliguori
    return ((txd_lower & E1000_TXD_CMD_VLE) != 0);
337 8f2e8d1f aliguori
}
338 8f2e8d1f aliguori
339 7c23b892 balrog
static void
340 7c23b892 balrog
xmit_seg(E1000State *s)
341 7c23b892 balrog
{
342 7c23b892 balrog
    uint16_t len, *sp;
343 7c23b892 balrog
    unsigned int frames = s->tx.tso_frames, css, sofar, n;
344 7c23b892 balrog
    struct e1000_tx *tp = &s->tx;
345 7c23b892 balrog
346 1b0009db balrog
    if (tp->tse && tp->cptse) {
347 7c23b892 balrog
        css = tp->ipcss;
348 7c23b892 balrog
        DBGOUT(TXSUM, "frames %d size %d ipcss %d\n",
349 7c23b892 balrog
               frames, tp->size, css);
350 7c23b892 balrog
        if (tp->ip) {                // IPv4
351 7c23b892 balrog
            cpu_to_be16wu((uint16_t *)(tp->data+css+2),
352 7c23b892 balrog
                          tp->size - css);
353 7c23b892 balrog
            cpu_to_be16wu((uint16_t *)(tp->data+css+4),
354 7c23b892 balrog
                          be16_to_cpup((uint16_t *)(tp->data+css+4))+frames);
355 7c23b892 balrog
        } else                        // IPv6
356 7c23b892 balrog
            cpu_to_be16wu((uint16_t *)(tp->data+css+4),
357 7c23b892 balrog
                          tp->size - css);
358 7c23b892 balrog
        css = tp->tucss;
359 7c23b892 balrog
        len = tp->size - css;
360 7c23b892 balrog
        DBGOUT(TXSUM, "tcp %d tucss %d len %d\n", tp->tcp, css, len);
361 7c23b892 balrog
        if (tp->tcp) {
362 7c23b892 balrog
            sofar = frames * tp->mss;
363 7c23b892 balrog
            cpu_to_be32wu((uint32_t *)(tp->data+css+4),        // seq
364 88738c09 aurel32
                be32_to_cpupu((uint32_t *)(tp->data+css+4))+sofar);
365 7c23b892 balrog
            if (tp->paylen - sofar > tp->mss)
366 7c23b892 balrog
                tp->data[css + 13] &= ~9;                // PSH, FIN
367 7c23b892 balrog
        } else        // UDP
368 7c23b892 balrog
            cpu_to_be16wu((uint16_t *)(tp->data+css+4), len);
369 7c23b892 balrog
        if (tp->sum_needed & E1000_TXD_POPTS_TXSM) {
370 7c23b892 balrog
            // add pseudo-header length before checksum calculation
371 7c23b892 balrog
            sp = (uint16_t *)(tp->data + tp->tucso);
372 7c23b892 balrog
            cpu_to_be16wu(sp, be16_to_cpup(sp) + len);
373 7c23b892 balrog
        }
374 7c23b892 balrog
        tp->tso_frames++;
375 7c23b892 balrog
    }
376 7c23b892 balrog
377 7c23b892 balrog
    if (tp->sum_needed & E1000_TXD_POPTS_TXSM)
378 7c23b892 balrog
        putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse);
379 7c23b892 balrog
    if (tp->sum_needed & E1000_TXD_POPTS_IXSM)
380 7c23b892 balrog
        putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse);
381 8f2e8d1f aliguori
    if (tp->vlan_needed) {
382 8f2e8d1f aliguori
        memmove(tp->vlan, tp->data, 12);
383 8f2e8d1f aliguori
        memcpy(tp->data + 8, tp->vlan_header, 4);
384 8f2e8d1f aliguori
        qemu_send_packet(s->vc, tp->vlan, tp->size + 4);
385 8f2e8d1f aliguori
    } else
386 8f2e8d1f aliguori
        qemu_send_packet(s->vc, tp->data, tp->size);
387 7c23b892 balrog
    s->mac_reg[TPT]++;
388 7c23b892 balrog
    s->mac_reg[GPTC]++;
389 7c23b892 balrog
    n = s->mac_reg[TOTL];
390 7c23b892 balrog
    if ((s->mac_reg[TOTL] += s->tx.size) < n)
391 7c23b892 balrog
        s->mac_reg[TOTH]++;
392 7c23b892 balrog
}
393 7c23b892 balrog
394 7c23b892 balrog
static void
395 7c23b892 balrog
process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
396 7c23b892 balrog
{
397 7c23b892 balrog
    uint32_t txd_lower = le32_to_cpu(dp->lower.data);
398 7c23b892 balrog
    uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D);
399 7c23b892 balrog
    unsigned int split_size = txd_lower & 0xffff, bytes, sz, op;
400 7c23b892 balrog
    unsigned int msh = 0xfffff, hdr = 0;
401 7c23b892 balrog
    uint64_t addr;
402 7c23b892 balrog
    struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
403 7c23b892 balrog
    struct e1000_tx *tp = &s->tx;
404 7c23b892 balrog
405 7c23b892 balrog
    if (dtype == E1000_TXD_CMD_DEXT) {        // context descriptor
406 7c23b892 balrog
        op = le32_to_cpu(xp->cmd_and_length);
407 7c23b892 balrog
        tp->ipcss = xp->lower_setup.ip_fields.ipcss;
408 7c23b892 balrog
        tp->ipcso = xp->lower_setup.ip_fields.ipcso;
409 7c23b892 balrog
        tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse);
410 7c23b892 balrog
        tp->tucss = xp->upper_setup.tcp_fields.tucss;
411 7c23b892 balrog
        tp->tucso = xp->upper_setup.tcp_fields.tucso;
412 7c23b892 balrog
        tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse);
413 7c23b892 balrog
        tp->paylen = op & 0xfffff;
414 7c23b892 balrog
        tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len;
415 7c23b892 balrog
        tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss);
416 7c23b892 balrog
        tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0;
417 7c23b892 balrog
        tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0;
418 7c23b892 balrog
        tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0;
419 7c23b892 balrog
        tp->tso_frames = 0;
420 7c23b892 balrog
        if (tp->tucso == 0) {        // this is probably wrong
421 7c23b892 balrog
            DBGOUT(TXSUM, "TCP/UDP: cso 0!\n");
422 7c23b892 balrog
            tp->tucso = tp->tucss + (tp->tcp ? 16 : 6);
423 7c23b892 balrog
        }
424 7c23b892 balrog
        return;
425 1b0009db balrog
    } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) {
426 1b0009db balrog
        // data descriptor
427 7c23b892 balrog
        tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8;
428 1b0009db balrog
        tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0;
429 1b0009db balrog
    } else
430 1b0009db balrog
        // legacy descriptor
431 1b0009db balrog
        tp->cptse = 0;
432 7c23b892 balrog
433 8f2e8d1f aliguori
    if (vlan_enabled(s) && is_vlan_txd(txd_lower) &&
434 8f2e8d1f aliguori
        (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) {
435 8f2e8d1f aliguori
        tp->vlan_needed = 1;
436 8f2e8d1f aliguori
        cpu_to_be16wu((uint16_t *)(tp->vlan_header),
437 8f2e8d1f aliguori
                      le16_to_cpup((uint16_t *)(s->mac_reg + VET)));
438 8f2e8d1f aliguori
        cpu_to_be16wu((uint16_t *)(tp->vlan_header + 2),
439 8f2e8d1f aliguori
                      le16_to_cpu(dp->upper.fields.special));
440 8f2e8d1f aliguori
    }
441 8f2e8d1f aliguori
        
442 7c23b892 balrog
    addr = le64_to_cpu(dp->buffer_addr);
443 1b0009db balrog
    if (tp->tse && tp->cptse) {
444 7c23b892 balrog
        hdr = tp->hdr_len;
445 7c23b892 balrog
        msh = hdr + tp->mss;
446 1b0009db balrog
        do {
447 1b0009db balrog
            bytes = split_size;
448 1b0009db balrog
            if (tp->size + bytes > msh)
449 1b0009db balrog
                bytes = msh - tp->size;
450 1b0009db balrog
            cpu_physical_memory_read(addr, tp->data + tp->size, bytes);
451 1b0009db balrog
            if ((sz = tp->size + bytes) >= hdr && tp->size < hdr)
452 1b0009db balrog
                memmove(tp->header, tp->data, hdr);
453 1b0009db balrog
            tp->size = sz;
454 1b0009db balrog
            addr += bytes;
455 1b0009db balrog
            if (sz == msh) {
456 1b0009db balrog
                xmit_seg(s);
457 1b0009db balrog
                memmove(tp->data, tp->header, hdr);
458 1b0009db balrog
                tp->size = hdr;
459 1b0009db balrog
            }
460 1b0009db balrog
        } while (split_size -= bytes);
461 1b0009db balrog
    } else if (!tp->tse && tp->cptse) {
462 1b0009db balrog
        // context descriptor TSE is not set, while data descriptor TSE is set
463 1b0009db balrog
        DBGOUT(TXERR, "TCP segmentaion Error\n");
464 1b0009db balrog
    } else {
465 1b0009db balrog
        cpu_physical_memory_read(addr, tp->data + tp->size, split_size);
466 1b0009db balrog
        tp->size += split_size;
467 7c23b892 balrog
    }
468 7c23b892 balrog
469 7c23b892 balrog
    if (!(txd_lower & E1000_TXD_CMD_EOP))
470 7c23b892 balrog
        return;
471 1b0009db balrog
    if (!(tp->tse && tp->cptse && tp->size < hdr))
472 7c23b892 balrog
        xmit_seg(s);
473 7c23b892 balrog
    tp->tso_frames = 0;
474 7c23b892 balrog
    tp->sum_needed = 0;
475 8f2e8d1f aliguori
    tp->vlan_needed = 0;
476 7c23b892 balrog
    tp->size = 0;
477 1b0009db balrog
    tp->cptse = 0;
478 7c23b892 balrog
}
479 7c23b892 balrog
480 7c23b892 balrog
static uint32_t
481 7c23b892 balrog
txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp)
482 7c23b892 balrog
{
483 7c23b892 balrog
    uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data);
484 7c23b892 balrog
485 7c23b892 balrog
    if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS)))
486 7c23b892 balrog
        return 0;
487 7c23b892 balrog
    txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) &
488 7c23b892 balrog
                ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU);
489 7c23b892 balrog
    dp->upper.data = cpu_to_le32(txd_upper);
490 7c23b892 balrog
    cpu_physical_memory_write(base + ((char *)&dp->upper - (char *)dp),
491 7c23b892 balrog
                              (void *)&dp->upper, sizeof(dp->upper));
492 7c23b892 balrog
    return E1000_ICR_TXDW;
493 7c23b892 balrog
}
494 7c23b892 balrog
495 7c23b892 balrog
static void
496 7c23b892 balrog
start_xmit(E1000State *s)
497 7c23b892 balrog
{
498 7c23b892 balrog
    target_phys_addr_t base;
499 7c23b892 balrog
    struct e1000_tx_desc desc;
500 7c23b892 balrog
    uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE;
501 7c23b892 balrog
502 7c23b892 balrog
    if (!(s->mac_reg[TCTL] & E1000_TCTL_EN)) {
503 7c23b892 balrog
        DBGOUT(TX, "tx disabled\n");
504 7c23b892 balrog
        return;
505 7c23b892 balrog
    }
506 7c23b892 balrog
507 7c23b892 balrog
    while (s->mac_reg[TDH] != s->mac_reg[TDT]) {
508 7c23b892 balrog
        base = ((uint64_t)s->mac_reg[TDBAH] << 32) + s->mac_reg[TDBAL] +
509 7c23b892 balrog
               sizeof(struct e1000_tx_desc) * s->mac_reg[TDH];
510 7c23b892 balrog
        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
511 7c23b892 balrog
512 7c23b892 balrog
        DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH],
513 6106075b ths
               (void *)(intptr_t)desc.buffer_addr, desc.lower.data,
514 7c23b892 balrog
               desc.upper.data);
515 7c23b892 balrog
516 7c23b892 balrog
        process_tx_desc(s, &desc);
517 7c23b892 balrog
        cause |= txdesc_writeback(base, &desc);
518 7c23b892 balrog
519 7c23b892 balrog
        if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN])
520 7c23b892 balrog
            s->mac_reg[TDH] = 0;
521 7c23b892 balrog
        /*
522 7c23b892 balrog
         * the following could happen only if guest sw assigns
523 7c23b892 balrog
         * bogus values to TDT/TDLEN.
524 7c23b892 balrog
         * there's nothing too intelligent we could do about this.
525 7c23b892 balrog
         */
526 7c23b892 balrog
        if (s->mac_reg[TDH] == tdh_start) {
527 7c23b892 balrog
            DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
528 7c23b892 balrog
                   tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
529 7c23b892 balrog
            break;
530 7c23b892 balrog
        }
531 7c23b892 balrog
    }
532 7c23b892 balrog
    set_ics(s, 0, cause);
533 7c23b892 balrog
}
534 7c23b892 balrog
535 7c23b892 balrog
static int
536 7c23b892 balrog
receive_filter(E1000State *s, const uint8_t *buf, int size)
537 7c23b892 balrog
{
538 7c23b892 balrog
    static uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
539 7c23b892 balrog
    static int mta_shift[] = {4, 3, 2, 0};
540 7c23b892 balrog
    uint32_t f, rctl = s->mac_reg[RCTL], ra[2], *rp;
541 7c23b892 balrog
542 8f2e8d1f aliguori
    if (is_vlan_packet(s, buf) && vlan_rx_filter_enabled(s)) {
543 8f2e8d1f aliguori
        uint16_t vid = be16_to_cpup((uint16_t *)(buf + 14));
544 8f2e8d1f aliguori
        uint32_t vfta = le32_to_cpup((uint32_t *)(s->mac_reg + VFTA) +
545 8f2e8d1f aliguori
                                     ((vid >> 5) & 0x7f));
546 8f2e8d1f aliguori
        if ((vfta & (1 << (vid & 0x1f))) == 0)
547 8f2e8d1f aliguori
            return 0;
548 8f2e8d1f aliguori
    }
549 8f2e8d1f aliguori
550 7c23b892 balrog
    if (rctl & E1000_RCTL_UPE)                        // promiscuous
551 7c23b892 balrog
        return 1;
552 7c23b892 balrog
553 7c23b892 balrog
    if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE))        // promiscuous mcast
554 7c23b892 balrog
        return 1;
555 7c23b892 balrog
556 7c23b892 balrog
    if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast))
557 7c23b892 balrog
        return 1;
558 7c23b892 balrog
559 7c23b892 balrog
    for (rp = s->mac_reg + RA; rp < s->mac_reg + RA + 32; rp += 2) {
560 7c23b892 balrog
        if (!(rp[1] & E1000_RAH_AV))
561 7c23b892 balrog
            continue;
562 7c23b892 balrog
        ra[0] = cpu_to_le32(rp[0]);
563 7c23b892 balrog
        ra[1] = cpu_to_le32(rp[1]);
564 7c23b892 balrog
        if (!memcmp(buf, (uint8_t *)ra, 6)) {
565 7c23b892 balrog
            DBGOUT(RXFILTER,
566 7c23b892 balrog
                   "unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x\n",
567 7c23b892 balrog
                   (int)(rp - s->mac_reg - RA)/2,
568 7c23b892 balrog
                   buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
569 7c23b892 balrog
            return 1;
570 7c23b892 balrog
        }
571 7c23b892 balrog
    }
572 7c23b892 balrog
    DBGOUT(RXFILTER, "unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x\n",
573 7c23b892 balrog
           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
574 7c23b892 balrog
575 7c23b892 balrog
    f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3];
576 7c23b892 balrog
    f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff;
577 7c23b892 balrog
    if (s->mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f)))
578 7c23b892 balrog
        return 1;
579 7c23b892 balrog
    DBGOUT(RXFILTER,
580 7c23b892 balrog
           "dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x\n",
581 7c23b892 balrog
           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
582 7c23b892 balrog
           (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5,
583 7c23b892 balrog
           s->mac_reg[MTA + (f >> 5)]);
584 7c23b892 balrog
585 7c23b892 balrog
    return 0;
586 7c23b892 balrog
}
587 7c23b892 balrog
588 99ed7e30 aliguori
static void
589 99ed7e30 aliguori
e1000_set_link_status(VLANClientState *vc)
590 99ed7e30 aliguori
{
591 99ed7e30 aliguori
    E1000State *s = vc->opaque;
592 99ed7e30 aliguori
    uint32_t old_status = s->mac_reg[STATUS];
593 99ed7e30 aliguori
594 99ed7e30 aliguori
    if (vc->link_down)
595 99ed7e30 aliguori
        s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
596 99ed7e30 aliguori
    else
597 99ed7e30 aliguori
        s->mac_reg[STATUS] |= E1000_STATUS_LU;
598 99ed7e30 aliguori
599 99ed7e30 aliguori
    if (s->mac_reg[STATUS] != old_status)
600 99ed7e30 aliguori
        set_ics(s, 0, E1000_ICR_LSC);
601 99ed7e30 aliguori
}
602 99ed7e30 aliguori
603 7c23b892 balrog
static int
604 e3f5ec2b Mark McLoughlin
e1000_can_receive(VLANClientState *vc)
605 7c23b892 balrog
{
606 e3f5ec2b Mark McLoughlin
    E1000State *s = vc->opaque;
607 7c23b892 balrog
608 4105de67 aliguori
    return (s->mac_reg[RCTL] & E1000_RCTL_EN);
609 7c23b892 balrog
}
610 7c23b892 balrog
611 4f1c942b Mark McLoughlin
static ssize_t
612 e3f5ec2b Mark McLoughlin
e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
613 7c23b892 balrog
{
614 e3f5ec2b Mark McLoughlin
    E1000State *s = vc->opaque;
615 7c23b892 balrog
    struct e1000_rx_desc desc;
616 7c23b892 balrog
    target_phys_addr_t base;
617 7c23b892 balrog
    unsigned int n, rdt;
618 7c23b892 balrog
    uint32_t rdh_start;
619 8f2e8d1f aliguori
    uint16_t vlan_special = 0;
620 8f2e8d1f aliguori
    uint8_t vlan_status = 0, vlan_offset = 0;
621 7c23b892 balrog
622 7c23b892 balrog
    if (!(s->mac_reg[RCTL] & E1000_RCTL_EN))
623 4f1c942b Mark McLoughlin
        return -1;
624 7c23b892 balrog
625 7c23b892 balrog
    if (size > s->rxbuf_size) {
626 cda9046b Mark McLoughlin
        DBGOUT(RX, "packet too large for buffers (%lu > %d)\n",
627 cda9046b Mark McLoughlin
               (unsigned long)size, s->rxbuf_size);
628 4f1c942b Mark McLoughlin
        return -1;
629 7c23b892 balrog
    }
630 7c23b892 balrog
631 7c23b892 balrog
    if (!receive_filter(s, buf, size))
632 4f1c942b Mark McLoughlin
        return size;
633 7c23b892 balrog
634 8f2e8d1f aliguori
    if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
635 8f2e8d1f aliguori
        vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
636 8f2e8d1f aliguori
        memmove((void *)(buf + 4), buf, 12);
637 8f2e8d1f aliguori
        vlan_status = E1000_RXD_STAT_VP;
638 8f2e8d1f aliguori
        vlan_offset = 4;
639 8f2e8d1f aliguori
        size -= 4;
640 8f2e8d1f aliguori
    }
641 8f2e8d1f aliguori
642 7c23b892 balrog
    rdh_start = s->mac_reg[RDH];
643 7c23b892 balrog
    size += 4; // for the header
644 7c23b892 balrog
    do {
645 7c23b892 balrog
        if (s->mac_reg[RDH] == s->mac_reg[RDT] && s->check_rxov) {
646 7c23b892 balrog
            set_ics(s, 0, E1000_ICS_RXO);
647 4f1c942b Mark McLoughlin
            return -1;
648 7c23b892 balrog
        }
649 7c23b892 balrog
        base = ((uint64_t)s->mac_reg[RDBAH] << 32) + s->mac_reg[RDBAL] +
650 7c23b892 balrog
               sizeof(desc) * s->mac_reg[RDH];
651 7c23b892 balrog
        cpu_physical_memory_read(base, (void *)&desc, sizeof(desc));
652 8f2e8d1f aliguori
        desc.special = vlan_special;
653 8f2e8d1f aliguori
        desc.status |= (vlan_status | E1000_RXD_STAT_DD);
654 7c23b892 balrog
        if (desc.buffer_addr) {
655 7c23b892 balrog
            cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr),
656 8f2e8d1f aliguori
                                      (void *)(buf + vlan_offset), size);
657 7c23b892 balrog
            desc.length = cpu_to_le16(size);
658 7c23b892 balrog
            desc.status |= E1000_RXD_STAT_EOP|E1000_RXD_STAT_IXSM;
659 7c23b892 balrog
        } else // as per intel docs; skip descriptors with null buf addr
660 7c23b892 balrog
            DBGOUT(RX, "Null RX descriptor!!\n");
661 7c23b892 balrog
        cpu_physical_memory_write(base, (void *)&desc, sizeof(desc));
662 7c23b892 balrog
663 7c23b892 balrog
        if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
664 7c23b892 balrog
            s->mac_reg[RDH] = 0;
665 7c23b892 balrog
        s->check_rxov = 1;
666 7c23b892 balrog
        /* see comment in start_xmit; same here */
667 7c23b892 balrog
        if (s->mac_reg[RDH] == rdh_start) {
668 7c23b892 balrog
            DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
669 7c23b892 balrog
                   rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
670 7c23b892 balrog
            set_ics(s, 0, E1000_ICS_RXO);
671 4f1c942b Mark McLoughlin
            return -1;
672 7c23b892 balrog
        }
673 7c23b892 balrog
    } while (desc.buffer_addr == 0);
674 7c23b892 balrog
675 7c23b892 balrog
    s->mac_reg[GPRC]++;
676 7c23b892 balrog
    s->mac_reg[TPR]++;
677 7c23b892 balrog
    n = s->mac_reg[TORL];
678 7c23b892 balrog
    if ((s->mac_reg[TORL] += size) < n)
679 7c23b892 balrog
        s->mac_reg[TORH]++;
680 7c23b892 balrog
681 7c23b892 balrog
    n = E1000_ICS_RXT0;
682 7c23b892 balrog
    if ((rdt = s->mac_reg[RDT]) < s->mac_reg[RDH])
683 7c23b892 balrog
        rdt += s->mac_reg[RDLEN] / sizeof(desc);
684 bf16cc8f aliguori
    if (((rdt - s->mac_reg[RDH]) * sizeof(desc)) <= s->mac_reg[RDLEN] >>
685 bf16cc8f aliguori
        s->rxbuf_min_shift)
686 7c23b892 balrog
        n |= E1000_ICS_RXDMT0;
687 7c23b892 balrog
688 7c23b892 balrog
    set_ics(s, 0, n);
689 4f1c942b Mark McLoughlin
690 4f1c942b Mark McLoughlin
    return size;
691 7c23b892 balrog
}
692 7c23b892 balrog
693 7c23b892 balrog
static uint32_t
694 7c23b892 balrog
mac_readreg(E1000State *s, int index)
695 7c23b892 balrog
{
696 7c23b892 balrog
    return s->mac_reg[index];
697 7c23b892 balrog
}
698 7c23b892 balrog
699 7c23b892 balrog
static uint32_t
700 7c23b892 balrog
mac_icr_read(E1000State *s, int index)
701 7c23b892 balrog
{
702 7c23b892 balrog
    uint32_t ret = s->mac_reg[ICR];
703 7c23b892 balrog
704 7c23b892 balrog
    DBGOUT(INTERRUPT, "ICR read: %x\n", ret);
705 7c23b892 balrog
    set_interrupt_cause(s, 0, 0);
706 7c23b892 balrog
    return ret;
707 7c23b892 balrog
}
708 7c23b892 balrog
709 7c23b892 balrog
static uint32_t
710 7c23b892 balrog
mac_read_clr4(E1000State *s, int index)
711 7c23b892 balrog
{
712 7c23b892 balrog
    uint32_t ret = s->mac_reg[index];
713 7c23b892 balrog
714 7c23b892 balrog
    s->mac_reg[index] = 0;
715 7c23b892 balrog
    return ret;
716 7c23b892 balrog
}
717 7c23b892 balrog
718 7c23b892 balrog
static uint32_t
719 7c23b892 balrog
mac_read_clr8(E1000State *s, int index)
720 7c23b892 balrog
{
721 7c23b892 balrog
    uint32_t ret = s->mac_reg[index];
722 7c23b892 balrog
723 7c23b892 balrog
    s->mac_reg[index] = 0;
724 7c23b892 balrog
    s->mac_reg[index-1] = 0;
725 7c23b892 balrog
    return ret;
726 7c23b892 balrog
}
727 7c23b892 balrog
728 7c23b892 balrog
static void
729 7c23b892 balrog
mac_writereg(E1000State *s, int index, uint32_t val)
730 7c23b892 balrog
{
731 7c23b892 balrog
    s->mac_reg[index] = val;
732 7c23b892 balrog
}
733 7c23b892 balrog
734 7c23b892 balrog
static void
735 7c23b892 balrog
set_rdt(E1000State *s, int index, uint32_t val)
736 7c23b892 balrog
{
737 7c23b892 balrog
    s->check_rxov = 0;
738 7c23b892 balrog
    s->mac_reg[index] = val & 0xffff;
739 7c23b892 balrog
}
740 7c23b892 balrog
741 7c23b892 balrog
static void
742 7c23b892 balrog
set_16bit(E1000State *s, int index, uint32_t val)
743 7c23b892 balrog
{
744 7c23b892 balrog
    s->mac_reg[index] = val & 0xffff;
745 7c23b892 balrog
}
746 7c23b892 balrog
747 7c23b892 balrog
static void
748 7c23b892 balrog
set_dlen(E1000State *s, int index, uint32_t val)
749 7c23b892 balrog
{
750 7c23b892 balrog
    s->mac_reg[index] = val & 0xfff80;
751 7c23b892 balrog
}
752 7c23b892 balrog
753 7c23b892 balrog
static void
754 7c23b892 balrog
set_tctl(E1000State *s, int index, uint32_t val)
755 7c23b892 balrog
{
756 7c23b892 balrog
    s->mac_reg[index] = val;
757 7c23b892 balrog
    s->mac_reg[TDT] &= 0xffff;
758 7c23b892 balrog
    start_xmit(s);
759 7c23b892 balrog
}
760 7c23b892 balrog
761 7c23b892 balrog
static void
762 7c23b892 balrog
set_icr(E1000State *s, int index, uint32_t val)
763 7c23b892 balrog
{
764 7c23b892 balrog
    DBGOUT(INTERRUPT, "set_icr %x\n", val);
765 7c23b892 balrog
    set_interrupt_cause(s, 0, s->mac_reg[ICR] & ~val);
766 7c23b892 balrog
}
767 7c23b892 balrog
768 7c23b892 balrog
static void
769 7c23b892 balrog
set_imc(E1000State *s, int index, uint32_t val)
770 7c23b892 balrog
{
771 7c23b892 balrog
    s->mac_reg[IMS] &= ~val;
772 7c23b892 balrog
    set_ics(s, 0, 0);
773 7c23b892 balrog
}
774 7c23b892 balrog
775 7c23b892 balrog
static void
776 7c23b892 balrog
set_ims(E1000State *s, int index, uint32_t val)
777 7c23b892 balrog
{
778 7c23b892 balrog
    s->mac_reg[IMS] |= val;
779 7c23b892 balrog
    set_ics(s, 0, 0);
780 7c23b892 balrog
}
781 7c23b892 balrog
782 7c23b892 balrog
#define getreg(x)        [x] = mac_readreg
783 7c23b892 balrog
static uint32_t (*macreg_readops[])(E1000State *, int) = {
784 7c23b892 balrog
    getreg(PBA),        getreg(RCTL),        getreg(TDH),        getreg(TXDCTL),
785 7c23b892 balrog
    getreg(WUFC),        getreg(TDT),        getreg(CTRL),        getreg(LEDCTL),
786 7c23b892 balrog
    getreg(MANC),        getreg(MDIC),        getreg(SWSM),        getreg(STATUS),
787 7c23b892 balrog
    getreg(TORL),        getreg(TOTL),        getreg(IMS),        getreg(TCTL),
788 b1332393 Bill Paul
    getreg(RDH),        getreg(RDT),        getreg(VET),        getreg(ICS),
789 7c23b892 balrog
790 7c23b892 balrog
    [TOTH] = mac_read_clr8,        [TORH] = mac_read_clr8,        [GPRC] = mac_read_clr4,
791 7c23b892 balrog
    [GPTC] = mac_read_clr4,        [TPR] = mac_read_clr4,        [TPT] = mac_read_clr4,
792 7c23b892 balrog
    [ICR] = mac_icr_read,        [EECD] = get_eecd,        [EERD] = flash_eerd_read,
793 7c23b892 balrog
    [CRCERRS ... MPC] = &mac_readreg,
794 7c23b892 balrog
    [RA ... RA+31] = &mac_readreg,
795 7c23b892 balrog
    [MTA ... MTA+127] = &mac_readreg,
796 8f2e8d1f aliguori
    [VFTA ... VFTA+127] = &mac_readreg,
797 7c23b892 balrog
};
798 b1503cda malc
enum { NREADOPS = ARRAY_SIZE(macreg_readops) };
799 7c23b892 balrog
800 7c23b892 balrog
#define putreg(x)        [x] = mac_writereg
801 7c23b892 balrog
static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
802 7c23b892 balrog
    putreg(PBA),        putreg(EERD),        putreg(SWSM),        putreg(WUFC),
803 7c23b892 balrog
    putreg(TDBAL),        putreg(TDBAH),        putreg(TXDCTL),        putreg(RDBAH),
804 cab3c825 Kevin Wolf
    putreg(RDBAL),        putreg(LEDCTL), putreg(VET),
805 7c23b892 balrog
    [TDLEN] = set_dlen,        [RDLEN] = set_dlen,        [TCTL] = set_tctl,
806 7c23b892 balrog
    [TDT] = set_tctl,        [MDIC] = set_mdic,        [ICS] = set_ics,
807 7c23b892 balrog
    [TDH] = set_16bit,        [RDH] = set_16bit,        [RDT] = set_rdt,
808 7c23b892 balrog
    [IMC] = set_imc,        [IMS] = set_ims,        [ICR] = set_icr,
809 cab3c825 Kevin Wolf
    [EECD] = set_eecd,        [RCTL] = set_rx_control, [CTRL] = set_ctrl,
810 7c23b892 balrog
    [RA ... RA+31] = &mac_writereg,
811 7c23b892 balrog
    [MTA ... MTA+127] = &mac_writereg,
812 8f2e8d1f aliguori
    [VFTA ... VFTA+127] = &mac_writereg,
813 7c23b892 balrog
};
814 b1503cda malc
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
815 7c23b892 balrog
816 7c23b892 balrog
static void
817 7c23b892 balrog
e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
818 7c23b892 balrog
{
819 7c23b892 balrog
    E1000State *s = opaque;
820 8da3ff18 pbrook
    unsigned int index = (addr & 0x1ffff) >> 2;
821 7c23b892 balrog
822 6b59fc74 aurel32
#ifdef TARGET_WORDS_BIGENDIAN
823 6b59fc74 aurel32
    val = bswap32(val);
824 6b59fc74 aurel32
#endif
825 7c23b892 balrog
    if (index < NWRITEOPS && macreg_writeops[index])
826 6b59fc74 aurel32
        macreg_writeops[index](s, index, val);
827 7c23b892 balrog
    else if (index < NREADOPS && macreg_readops[index])
828 7c23b892 balrog
        DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
829 7c23b892 balrog
    else
830 7c23b892 balrog
        DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
831 7c23b892 balrog
               index<<2, val);
832 7c23b892 balrog
}
833 7c23b892 balrog
834 7c23b892 balrog
static void
835 7c23b892 balrog
e1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
836 7c23b892 balrog
{
837 7c23b892 balrog
    // emulate hw without byte enables: no RMW
838 7c23b892 balrog
    e1000_mmio_writel(opaque, addr & ~3,
839 6b59fc74 aurel32
                      (val & 0xffff) << (8*(addr & 3)));
840 7c23b892 balrog
}
841 7c23b892 balrog
842 7c23b892 balrog
static void
843 7c23b892 balrog
e1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
844 7c23b892 balrog
{
845 7c23b892 balrog
    // emulate hw without byte enables: no RMW
846 7c23b892 balrog
    e1000_mmio_writel(opaque, addr & ~3,
847 6b59fc74 aurel32
                      (val & 0xff) << (8*(addr & 3)));
848 7c23b892 balrog
}
849 7c23b892 balrog
850 7c23b892 balrog
static uint32_t
851 7c23b892 balrog
e1000_mmio_readl(void *opaque, target_phys_addr_t addr)
852 7c23b892 balrog
{
853 7c23b892 balrog
    E1000State *s = opaque;
854 8da3ff18 pbrook
    unsigned int index = (addr & 0x1ffff) >> 2;
855 7c23b892 balrog
856 7c23b892 balrog
    if (index < NREADOPS && macreg_readops[index])
857 6b59fc74 aurel32
    {
858 6b59fc74 aurel32
        uint32_t val = macreg_readops[index](s, index);
859 6b59fc74 aurel32
#ifdef TARGET_WORDS_BIGENDIAN
860 6b59fc74 aurel32
        val = bswap32(val);
861 6b59fc74 aurel32
#endif
862 6b59fc74 aurel32
        return val;
863 6b59fc74 aurel32
    }
864 7c23b892 balrog
    DBGOUT(UNKNOWN, "MMIO unknown read addr=0x%08x\n", index<<2);
865 7c23b892 balrog
    return 0;
866 7c23b892 balrog
}
867 7c23b892 balrog
868 7c23b892 balrog
static uint32_t
869 7c23b892 balrog
e1000_mmio_readb(void *opaque, target_phys_addr_t addr)
870 7c23b892 balrog
{
871 6b59fc74 aurel32
    return ((e1000_mmio_readl(opaque, addr & ~3)) >>
872 7c23b892 balrog
            (8 * (addr & 3))) & 0xff;
873 7c23b892 balrog
}
874 7c23b892 balrog
875 7c23b892 balrog
static uint32_t
876 7c23b892 balrog
e1000_mmio_readw(void *opaque, target_phys_addr_t addr)
877 7c23b892 balrog
{
878 6b59fc74 aurel32
    return ((e1000_mmio_readl(opaque, addr & ~3)) >>
879 6b59fc74 aurel32
            (8 * (addr & 3))) & 0xffff;
880 7c23b892 balrog
}
881 7c23b892 balrog
882 88b4e9db blueswir1
static const int mac_regtosave[] = {
883 7c23b892 balrog
    CTRL,        EECD,        EERD,        GPRC,        GPTC,        ICR,        ICS,        IMC,        IMS,
884 7c23b892 balrog
    LEDCTL,        MANC,        MDIC,        MPC,        PBA,        RCTL,        RDBAH,        RDBAL,        RDH,
885 7c23b892 balrog
    RDLEN,        RDT,        STATUS,        SWSM,        TCTL,        TDBAH,        TDBAL,        TDH,        TDLEN,
886 7c23b892 balrog
    TDT,        TORH,        TORL,        TOTH,        TOTL,        TPR,        TPT,        TXDCTL,        WUFC,
887 8f2e8d1f aliguori
    VET,
888 7c23b892 balrog
};
889 b1503cda malc
enum { MAC_NSAVE = ARRAY_SIZE(mac_regtosave) };
890 7c23b892 balrog
891 88b4e9db blueswir1
static const struct {
892 7c23b892 balrog
    int size;
893 7c23b892 balrog
    int array0;
894 8f2e8d1f aliguori
} mac_regarraystosave[] = { {32, RA}, {128, MTA}, {128, VFTA} };
895 b1503cda malc
enum { MAC_NARRAYS = ARRAY_SIZE(mac_regarraystosave) };
896 7c23b892 balrog
897 7c23b892 balrog
static void
898 7c23b892 balrog
nic_save(QEMUFile *f, void *opaque)
899 7c23b892 balrog
{
900 7d9e52bd Juan Quintela
    E1000State *s = opaque;
901 7c23b892 balrog
    int i, j;
902 7c23b892 balrog
903 7c23b892 balrog
    pci_device_save(&s->dev, f);
904 8da3ff18 pbrook
    qemu_put_be32(f, 0);
905 7c23b892 balrog
    qemu_put_be32s(f, &s->rxbuf_size);
906 7c23b892 balrog
    qemu_put_be32s(f, &s->rxbuf_min_shift);
907 7c23b892 balrog
    qemu_put_be32s(f, &s->eecd_state.val_in);
908 7c23b892 balrog
    qemu_put_be16s(f, &s->eecd_state.bitnum_in);
909 7c23b892 balrog
    qemu_put_be16s(f, &s->eecd_state.bitnum_out);
910 7c23b892 balrog
    qemu_put_be16s(f, &s->eecd_state.reading);
911 7c23b892 balrog
    qemu_put_be32s(f, &s->eecd_state.old_eecd);
912 7c23b892 balrog
    qemu_put_8s(f, &s->tx.ipcss);
913 7c23b892 balrog
    qemu_put_8s(f, &s->tx.ipcso);
914 7c23b892 balrog
    qemu_put_be16s(f, &s->tx.ipcse);
915 7c23b892 balrog
    qemu_put_8s(f, &s->tx.tucss);
916 7c23b892 balrog
    qemu_put_8s(f, &s->tx.tucso);
917 7c23b892 balrog
    qemu_put_be16s(f, &s->tx.tucse);
918 7c23b892 balrog
    qemu_put_be32s(f, &s->tx.paylen);
919 7c23b892 balrog
    qemu_put_8s(f, &s->tx.hdr_len);
920 7c23b892 balrog
    qemu_put_be16s(f, &s->tx.mss);
921 7c23b892 balrog
    qemu_put_be16s(f, &s->tx.size);
922 7c23b892 balrog
    qemu_put_be16s(f, &s->tx.tso_frames);
923 7c23b892 balrog
    qemu_put_8s(f, &s->tx.sum_needed);
924 b6c4f71f blueswir1
    qemu_put_s8s(f, &s->tx.ip);
925 b6c4f71f blueswir1
    qemu_put_s8s(f, &s->tx.tcp);
926 7c23b892 balrog
    qemu_put_buffer(f, s->tx.header, sizeof s->tx.header);
927 7c23b892 balrog
    qemu_put_buffer(f, s->tx.data, sizeof s->tx.data);
928 7c23b892 balrog
    for (i = 0; i < 64; i++)
929 7c23b892 balrog
        qemu_put_be16s(f, s->eeprom_data + i);
930 7c23b892 balrog
    for (i = 0; i < 0x20; i++)
931 7c23b892 balrog
        qemu_put_be16s(f, s->phy_reg + i);
932 7c23b892 balrog
    for (i = 0; i < MAC_NSAVE; i++)
933 7c23b892 balrog
        qemu_put_be32s(f, s->mac_reg + mac_regtosave[i]);
934 7c23b892 balrog
    for (i = 0; i < MAC_NARRAYS; i++)
935 7c23b892 balrog
        for (j = 0; j < mac_regarraystosave[i].size; j++)
936 7c23b892 balrog
            qemu_put_be32s(f,
937 7c23b892 balrog
                           s->mac_reg + mac_regarraystosave[i].array0 + j);
938 7c23b892 balrog
}
939 7c23b892 balrog
940 7c23b892 balrog
static int
941 7c23b892 balrog
nic_load(QEMUFile *f, void *opaque, int version_id)
942 7c23b892 balrog
{
943 7d9e52bd Juan Quintela
    E1000State *s = opaque;
944 7c23b892 balrog
    int i, j, ret;
945 7c23b892 balrog
946 7c23b892 balrog
    if ((ret = pci_device_load(&s->dev, f)) < 0)
947 7c23b892 balrog
        return ret;
948 18fdb1c5 ths
    if (version_id == 1)
949 b6c4f71f blueswir1
        qemu_get_sbe32s(f, &i); /* once some unused instance id */
950 8da3ff18 pbrook
    qemu_get_be32(f); /* Ignored.  Was mmio_base.  */
951 7c23b892 balrog
    qemu_get_be32s(f, &s->rxbuf_size);
952 7c23b892 balrog
    qemu_get_be32s(f, &s->rxbuf_min_shift);
953 7c23b892 balrog
    qemu_get_be32s(f, &s->eecd_state.val_in);
954 7c23b892 balrog
    qemu_get_be16s(f, &s->eecd_state.bitnum_in);
955 7c23b892 balrog
    qemu_get_be16s(f, &s->eecd_state.bitnum_out);
956 7c23b892 balrog
    qemu_get_be16s(f, &s->eecd_state.reading);
957 7c23b892 balrog
    qemu_get_be32s(f, &s->eecd_state.old_eecd);
958 7c23b892 balrog
    qemu_get_8s(f, &s->tx.ipcss);
959 7c23b892 balrog
    qemu_get_8s(f, &s->tx.ipcso);
960 7c23b892 balrog
    qemu_get_be16s(f, &s->tx.ipcse);
961 7c23b892 balrog
    qemu_get_8s(f, &s->tx.tucss);
962 7c23b892 balrog
    qemu_get_8s(f, &s->tx.tucso);
963 7c23b892 balrog
    qemu_get_be16s(f, &s->tx.tucse);
964 7c23b892 balrog
    qemu_get_be32s(f, &s->tx.paylen);
965 7c23b892 balrog
    qemu_get_8s(f, &s->tx.hdr_len);
966 7c23b892 balrog
    qemu_get_be16s(f, &s->tx.mss);
967 7c23b892 balrog
    qemu_get_be16s(f, &s->tx.size);
968 7c23b892 balrog
    qemu_get_be16s(f, &s->tx.tso_frames);
969 7c23b892 balrog
    qemu_get_8s(f, &s->tx.sum_needed);
970 b6c4f71f blueswir1
    qemu_get_s8s(f, &s->tx.ip);
971 b6c4f71f blueswir1
    qemu_get_s8s(f, &s->tx.tcp);
972 7c23b892 balrog
    qemu_get_buffer(f, s->tx.header, sizeof s->tx.header);
973 7c23b892 balrog
    qemu_get_buffer(f, s->tx.data, sizeof s->tx.data);
974 7c23b892 balrog
    for (i = 0; i < 64; i++)
975 7c23b892 balrog
        qemu_get_be16s(f, s->eeprom_data + i);
976 7c23b892 balrog
    for (i = 0; i < 0x20; i++)
977 7c23b892 balrog
        qemu_get_be16s(f, s->phy_reg + i);
978 7c23b892 balrog
    for (i = 0; i < MAC_NSAVE; i++)
979 7c23b892 balrog
        qemu_get_be32s(f, s->mac_reg + mac_regtosave[i]);
980 7c23b892 balrog
    for (i = 0; i < MAC_NARRAYS; i++)
981 7c23b892 balrog
        for (j = 0; j < mac_regarraystosave[i].size; j++)
982 7c23b892 balrog
            qemu_get_be32s(f,
983 7c23b892 balrog
                           s->mac_reg + mac_regarraystosave[i].array0 + j);
984 7c23b892 balrog
    return 0;
985 7c23b892 balrog
}
986 7c23b892 balrog
987 88b4e9db blueswir1
static const uint16_t e1000_eeprom_template[64] = {
988 7c23b892 balrog
    0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
989 7c23b892 balrog
    0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
990 7c23b892 balrog
    0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
991 7c23b892 balrog
    0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
992 7c23b892 balrog
    0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
993 7c23b892 balrog
    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
994 7c23b892 balrog
    0x0100, 0x4000, 0x121c, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
995 7c23b892 balrog
    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
996 7c23b892 balrog
};
997 7c23b892 balrog
998 88b4e9db blueswir1
static const uint16_t phy_reg_init[] = {
999 7c23b892 balrog
    [PHY_CTRL] = 0x1140,                        [PHY_STATUS] = 0x796d, // link initially up
1000 7c23b892 balrog
    [PHY_ID1] = 0x141,                                [PHY_ID2] = PHY_ID2_INIT,
1001 7c23b892 balrog
    [PHY_1000T_CTRL] = 0x0e00,                        [M88E1000_PHY_SPEC_CTRL] = 0x360,
1002 7c23b892 balrog
    [M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60,        [PHY_AUTONEG_ADV] = 0xde1,
1003 7c23b892 balrog
    [PHY_LP_ABILITY] = 0x1e0,                        [PHY_1000T_STATUS] = 0x3c00,
1004 700f6e2c aurel32
    [M88E1000_PHY_SPEC_STATUS] = 0xac00,
1005 7c23b892 balrog
};
1006 7c23b892 balrog
1007 88b4e9db blueswir1
static const uint32_t mac_reg_init[] = {
1008 7c23b892 balrog
    [PBA] =     0x00100030,
1009 7c23b892 balrog
    [LEDCTL] =  0x602,
1010 7c23b892 balrog
    [CTRL] =    E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
1011 7c23b892 balrog
                E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
1012 7c23b892 balrog
    [STATUS] =  0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
1013 7c23b892 balrog
                E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
1014 7c23b892 balrog
                E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
1015 7c23b892 balrog
                E1000_STATUS_LU,
1016 7c23b892 balrog
    [MANC] =    E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
1017 7c23b892 balrog
                E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
1018 7c23b892 balrog
                E1000_MANC_RMCP_EN,
1019 7c23b892 balrog
};
1020 7c23b892 balrog
1021 7c23b892 balrog
/* PCI interface */
1022 7c23b892 balrog
1023 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const e1000_mmio_write[] = {
1024 7c23b892 balrog
    e1000_mmio_writeb,        e1000_mmio_writew,        e1000_mmio_writel
1025 7c23b892 balrog
};
1026 7c23b892 balrog
1027 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const e1000_mmio_read[] = {
1028 7c23b892 balrog
    e1000_mmio_readb,        e1000_mmio_readw,        e1000_mmio_readl
1029 7c23b892 balrog
};
1030 7c23b892 balrog
1031 7c23b892 balrog
static void
1032 7c23b892 balrog
e1000_mmio_map(PCIDevice *pci_dev, int region_num,
1033 7c23b892 balrog
                uint32_t addr, uint32_t size, int type)
1034 7c23b892 balrog
{
1035 7d9e52bd Juan Quintela
    E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
1036 f65ed4c1 aliguori
    int i;
1037 f65ed4c1 aliguori
    const uint32_t excluded_regs[] = {
1038 f65ed4c1 aliguori
        E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS,
1039 f65ed4c1 aliguori
        E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE
1040 f65ed4c1 aliguori
    };
1041 f65ed4c1 aliguori
1042 7c23b892 balrog
1043 7c23b892 balrog
    DBGOUT(MMIO, "e1000_mmio_map addr=0x%08x 0x%08x\n", addr, size);
1044 7c23b892 balrog
1045 7c23b892 balrog
    cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index);
1046 f65ed4c1 aliguori
    qemu_register_coalesced_mmio(addr, excluded_regs[0]);
1047 f65ed4c1 aliguori
1048 f65ed4c1 aliguori
    for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++)
1049 f65ed4c1 aliguori
        qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4,
1050 f65ed4c1 aliguori
                                     excluded_regs[i + 1] -
1051 f65ed4c1 aliguori
                                     excluded_regs[i] - 4);
1052 7c23b892 balrog
}
1053 7c23b892 balrog
1054 b946a153 aliguori
static void
1055 b946a153 aliguori
e1000_cleanup(VLANClientState *vc)
1056 b946a153 aliguori
{
1057 b946a153 aliguori
    E1000State *d = vc->opaque;
1058 b946a153 aliguori
1059 b946a153 aliguori
    unregister_savevm("e1000", d);
1060 b946a153 aliguori
}
1061 b946a153 aliguori
1062 4b09be85 aliguori
static int
1063 4b09be85 aliguori
pci_e1000_uninit(PCIDevice *dev)
1064 4b09be85 aliguori
{
1065 7d9e52bd Juan Quintela
    E1000State *d = DO_UPCAST(E1000State, dev, dev);
1066 4b09be85 aliguori
1067 4b09be85 aliguori
    cpu_unregister_io_memory(d->mmio_index);
1068 4b09be85 aliguori
1069 4b09be85 aliguori
    return 0;
1070 4b09be85 aliguori
}
1071 4b09be85 aliguori
1072 32c86e95 Blue Swirl
static void e1000_reset(void *opaque)
1073 32c86e95 Blue Swirl
{
1074 32c86e95 Blue Swirl
    E1000State *d = opaque;
1075 32c86e95 Blue Swirl
1076 32c86e95 Blue Swirl
    memset(d->phy_reg, 0, sizeof d->phy_reg);
1077 32c86e95 Blue Swirl
    memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
1078 32c86e95 Blue Swirl
    memset(d->mac_reg, 0, sizeof d->mac_reg);
1079 32c86e95 Blue Swirl
    memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
1080 32c86e95 Blue Swirl
    d->rxbuf_min_shift = 1;
1081 32c86e95 Blue Swirl
    memset(&d->tx, 0, sizeof d->tx);
1082 32c86e95 Blue Swirl
}
1083 32c86e95 Blue Swirl
1084 81a322d4 Gerd Hoffmann
static int pci_e1000_init(PCIDevice *pci_dev)
1085 7c23b892 balrog
{
1086 7d9e52bd Juan Quintela
    E1000State *d = DO_UPCAST(E1000State, dev, pci_dev);
1087 7c23b892 balrog
    uint8_t *pci_conf;
1088 7c23b892 balrog
    uint16_t checksum = 0;
1089 7ccfb2eb blueswir1
    static const char info_str[] = "e1000";
1090 7c23b892 balrog
    int i;
1091 9d07d757 Paul Brook
    uint8_t macaddr[6];
1092 aff427a1 Chris Wright
1093 7c23b892 balrog
    pci_conf = d->dev.config;
1094 7c23b892 balrog
1095 deb54399 aliguori
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
1096 deb54399 aliguori
    pci_config_set_device_id(pci_conf, E1000_DEVID);
1097 7c23b892 balrog
    *(uint16_t *)(pci_conf+0x04) = cpu_to_le16(0x0407);
1098 7c23b892 balrog
    *(uint16_t *)(pci_conf+0x06) = cpu_to_le16(0x0010);
1099 7c23b892 balrog
    pci_conf[0x08] = 0x03;
1100 173a543b blueswir1
    pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
1101 7c23b892 balrog
    pci_conf[0x0c] = 0x10;
1102 7c23b892 balrog
1103 7c23b892 balrog
    pci_conf[0x3d] = 1; // interrupt pin 0
1104 7c23b892 balrog
1105 1eed09cb Avi Kivity
    d->mmio_index = cpu_register_io_memory(e1000_mmio_read,
1106 7c23b892 balrog
            e1000_mmio_write, d);
1107 7c23b892 balrog
1108 28c2c264 Avi Kivity
    pci_register_bar((PCIDevice *)d, 0, PNPMMIO_SIZE,
1109 7c23b892 balrog
                           PCI_ADDRESS_SPACE_MEM, e1000_mmio_map);
1110 7c23b892 balrog
1111 28c2c264 Avi Kivity
    pci_register_bar((PCIDevice *)d, 1, IOPORT_SIZE,
1112 7c23b892 balrog
                           PCI_ADDRESS_SPACE_IO, ioport_map);
1113 7c23b892 balrog
1114 7c23b892 balrog
    memmove(d->eeprom_data, e1000_eeprom_template,
1115 7c23b892 balrog
        sizeof e1000_eeprom_template);
1116 9d07d757 Paul Brook
    qdev_get_macaddr(&d->dev.qdev, macaddr);
1117 7c23b892 balrog
    for (i = 0; i < 3; i++)
1118 9d07d757 Paul Brook
        d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
1119 7c23b892 balrog
    for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
1120 7c23b892 balrog
        checksum += d->eeprom_data[i];
1121 7c23b892 balrog
    checksum = (uint16_t) EEPROM_SUM - checksum;
1122 7c23b892 balrog
    d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum;
1123 7c23b892 balrog
1124 9d07d757 Paul Brook
    d->vc = qdev_get_vlan_client(&d->dev.qdev,
1125 463af534 Mark McLoughlin
                                 e1000_can_receive, e1000_receive,
1126 463af534 Mark McLoughlin
                                 NULL, e1000_cleanup, d);
1127 99ed7e30 aliguori
    d->vc->link_status_changed = e1000_set_link_status;
1128 7c23b892 balrog
1129 9d07d757 Paul Brook
    qemu_format_nic_info_str(d->vc, macaddr);
1130 7c23b892 balrog
1131 18fdb1c5 ths
    register_savevm(info_str, -1, 2, nic_save, nic_load, d);
1132 4b09be85 aliguori
    d->dev.unregister = pci_e1000_uninit;
1133 a08d4367 Jan Kiszka
    qemu_register_reset(e1000_reset, d);
1134 32c86e95 Blue Swirl
    e1000_reset(d);
1135 81a322d4 Gerd Hoffmann
    return 0;
1136 9d07d757 Paul Brook
}
1137 72da4208 aliguori
1138 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo e1000_info = {
1139 0aab0d3a Gerd Hoffmann
    .qdev.name = "e1000",
1140 0aab0d3a Gerd Hoffmann
    .qdev.size = sizeof(E1000State),
1141 0aab0d3a Gerd Hoffmann
    .init      = pci_e1000_init,
1142 0aab0d3a Gerd Hoffmann
};
1143 0aab0d3a Gerd Hoffmann
1144 9d07d757 Paul Brook
static void e1000_register_devices(void)
1145 9d07d757 Paul Brook
{
1146 0aab0d3a Gerd Hoffmann
    pci_qdev_register(&e1000_info);
1147 7c23b892 balrog
}
1148 9d07d757 Paul Brook
1149 9d07d757 Paul Brook
device_init(e1000_register_devices)