Statistics
| Branch: | Revision:

root / hw / e1000.c @ dfb021bc

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