Statistics
| Branch: | Revision:

root / hw / net / xilinx_axienet.c @ a8aec295

History | View | Annotate | Download (27.9 kB)

1 93f1e401 Edgar E. Iglesias
/*
2 93f1e401 Edgar E. Iglesias
 * QEMU model of Xilinx AXI-Ethernet.
3 93f1e401 Edgar E. Iglesias
 *
4 93f1e401 Edgar E. Iglesias
 * Copyright (c) 2011 Edgar E. Iglesias.
5 93f1e401 Edgar E. Iglesias
 *
6 93f1e401 Edgar E. Iglesias
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 93f1e401 Edgar E. Iglesias
 * of this software and associated documentation files (the "Software"), to deal
8 93f1e401 Edgar E. Iglesias
 * in the Software without restriction, including without limitation the rights
9 93f1e401 Edgar E. Iglesias
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 93f1e401 Edgar E. Iglesias
 * copies of the Software, and to permit persons to whom the Software is
11 93f1e401 Edgar E. Iglesias
 * furnished to do so, subject to the following conditions:
12 93f1e401 Edgar E. Iglesias
 *
13 93f1e401 Edgar E. Iglesias
 * The above copyright notice and this permission notice shall be included in
14 93f1e401 Edgar E. Iglesias
 * all copies or substantial portions of the Software.
15 93f1e401 Edgar E. Iglesias
 *
16 93f1e401 Edgar E. Iglesias
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 93f1e401 Edgar E. Iglesias
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 93f1e401 Edgar E. Iglesias
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 93f1e401 Edgar E. Iglesias
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 93f1e401 Edgar E. Iglesias
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 93f1e401 Edgar E. Iglesias
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 93f1e401 Edgar E. Iglesias
 * THE SOFTWARE.
23 93f1e401 Edgar E. Iglesias
 */
24 93f1e401 Edgar E. Iglesias
25 83c9f4ca Paolo Bonzini
#include "hw/sysbus.h"
26 1de7afc9 Paolo Bonzini
#include "qemu/log.h"
27 1422e32d Paolo Bonzini
#include "net/net.h"
28 93f1e401 Edgar E. Iglesias
#include "net/checksum.h"
29 b4a42f81 Paolo Bonzini
#include "qapi/qmp/qerror.h"
30 93f1e401 Edgar E. Iglesias
31 83c9f4ca Paolo Bonzini
#include "hw/stream.h"
32 93f1e401 Edgar E. Iglesias
33 93f1e401 Edgar E. Iglesias
#define DPHY(x)
34 93f1e401 Edgar E. Iglesias
35 f0e7a81c Peter Crosthwaite
#define TYPE_XILINX_AXI_ENET "xlnx.axi-ethernet"
36 55b3e0c2 Peter Crosthwaite
#define TYPE_XILINX_AXI_ENET_DATA_STREAM "xilinx-axienet-data-stream"
37 42bb9c91 Peter Crosthwaite
#define TYPE_XILINX_AXI_ENET_CONTROL_STREAM "xilinx-axienet-control-stream"
38 f0e7a81c Peter Crosthwaite
39 f0e7a81c Peter Crosthwaite
#define XILINX_AXI_ENET(obj) \
40 f0e7a81c Peter Crosthwaite
     OBJECT_CHECK(XilinxAXIEnet, (obj), TYPE_XILINX_AXI_ENET)
41 f0e7a81c Peter Crosthwaite
42 55b3e0c2 Peter Crosthwaite
#define XILINX_AXI_ENET_DATA_STREAM(obj) \
43 55b3e0c2 Peter Crosthwaite
     OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
44 55b3e0c2 Peter Crosthwaite
     TYPE_XILINX_AXI_ENET_DATA_STREAM)
45 55b3e0c2 Peter Crosthwaite
46 42bb9c91 Peter Crosthwaite
#define XILINX_AXI_ENET_CONTROL_STREAM(obj) \
47 42bb9c91 Peter Crosthwaite
     OBJECT_CHECK(XilinxAXIEnetStreamSlave, (obj),\
48 42bb9c91 Peter Crosthwaite
     TYPE_XILINX_AXI_ENET_CONTROL_STREAM)
49 42bb9c91 Peter Crosthwaite
50 93f1e401 Edgar E. Iglesias
/* Advertisement control register. */
51 93f1e401 Edgar E. Iglesias
#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
52 93f1e401 Edgar E. Iglesias
#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
53 93f1e401 Edgar E. Iglesias
#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
54 93f1e401 Edgar E. Iglesias
#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
55 93f1e401 Edgar E. Iglesias
56 42bb9c91 Peter Crosthwaite
#define CONTROL_PAYLOAD_WORDS 5
57 42bb9c91 Peter Crosthwaite
#define CONTROL_PAYLOAD_SIZE (CONTROL_PAYLOAD_WORDS * (sizeof(uint32_t)))
58 42bb9c91 Peter Crosthwaite
59 93f1e401 Edgar E. Iglesias
struct PHY {
60 93f1e401 Edgar E. Iglesias
    uint32_t regs[32];
61 93f1e401 Edgar E. Iglesias
62 93f1e401 Edgar E. Iglesias
    int link;
63 93f1e401 Edgar E. Iglesias
64 93f1e401 Edgar E. Iglesias
    unsigned int (*read)(struct PHY *phy, unsigned int req);
65 93f1e401 Edgar E. Iglesias
    void (*write)(struct PHY *phy, unsigned int req,
66 93f1e401 Edgar E. Iglesias
                  unsigned int data);
67 93f1e401 Edgar E. Iglesias
};
68 93f1e401 Edgar E. Iglesias
69 93f1e401 Edgar E. Iglesias
static unsigned int tdk_read(struct PHY *phy, unsigned int req)
70 93f1e401 Edgar E. Iglesias
{
71 93f1e401 Edgar E. Iglesias
    int regnum;
72 93f1e401 Edgar E. Iglesias
    unsigned r = 0;
73 93f1e401 Edgar E. Iglesias
74 93f1e401 Edgar E. Iglesias
    regnum = req & 0x1f;
75 93f1e401 Edgar E. Iglesias
76 93f1e401 Edgar E. Iglesias
    switch (regnum) {
77 93f1e401 Edgar E. Iglesias
        case 1:
78 93f1e401 Edgar E. Iglesias
            if (!phy->link) {
79 93f1e401 Edgar E. Iglesias
                break;
80 93f1e401 Edgar E. Iglesias
            }
81 93f1e401 Edgar E. Iglesias
            /* MR1.  */
82 93f1e401 Edgar E. Iglesias
            /* Speeds and modes.  */
83 93f1e401 Edgar E. Iglesias
            r |= (1 << 13) | (1 << 14);
84 93f1e401 Edgar E. Iglesias
            r |= (1 << 11) | (1 << 12);
85 93f1e401 Edgar E. Iglesias
            r |= (1 << 5); /* Autoneg complete.  */
86 93f1e401 Edgar E. Iglesias
            r |= (1 << 3); /* Autoneg able.  */
87 93f1e401 Edgar E. Iglesias
            r |= (1 << 2); /* link.  */
88 93f1e401 Edgar E. Iglesias
            r |= (1 << 1); /* link.  */
89 93f1e401 Edgar E. Iglesias
            break;
90 93f1e401 Edgar E. Iglesias
        case 5:
91 93f1e401 Edgar E. Iglesias
            /* Link partner ability.
92 93f1e401 Edgar E. Iglesias
               We are kind; always agree with whatever best mode
93 93f1e401 Edgar E. Iglesias
               the guest advertises.  */
94 93f1e401 Edgar E. Iglesias
            r = 1 << 14; /* Success.  */
95 93f1e401 Edgar E. Iglesias
            /* Copy advertised modes.  */
96 93f1e401 Edgar E. Iglesias
            r |= phy->regs[4] & (15 << 5);
97 93f1e401 Edgar E. Iglesias
            /* Autoneg support.  */
98 93f1e401 Edgar E. Iglesias
            r |= 1;
99 93f1e401 Edgar E. Iglesias
            break;
100 93f1e401 Edgar E. Iglesias
        case 17:
101 93f1e401 Edgar E. Iglesias
            /* Marvel PHY on many xilinx boards.  */
102 93f1e401 Edgar E. Iglesias
            r = 0x8000; /* 1000Mb  */
103 93f1e401 Edgar E. Iglesias
            break;
104 93f1e401 Edgar E. Iglesias
        case 18:
105 93f1e401 Edgar E. Iglesias
            {
106 93f1e401 Edgar E. Iglesias
                /* Diagnostics reg.  */
107 93f1e401 Edgar E. Iglesias
                int duplex = 0;
108 93f1e401 Edgar E. Iglesias
                int speed_100 = 0;
109 93f1e401 Edgar E. Iglesias
110 93f1e401 Edgar E. Iglesias
                if (!phy->link) {
111 93f1e401 Edgar E. Iglesias
                    break;
112 93f1e401 Edgar E. Iglesias
                }
113 93f1e401 Edgar E. Iglesias
114 93f1e401 Edgar E. Iglesias
                /* Are we advertising 100 half or 100 duplex ? */
115 93f1e401 Edgar E. Iglesias
                speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
116 93f1e401 Edgar E. Iglesias
                speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
117 93f1e401 Edgar E. Iglesias
118 93f1e401 Edgar E. Iglesias
                /* Are we advertising 10 duplex or 100 duplex ? */
119 93f1e401 Edgar E. Iglesias
                duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
120 93f1e401 Edgar E. Iglesias
                duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
121 93f1e401 Edgar E. Iglesias
                r = (speed_100 << 10) | (duplex << 11);
122 93f1e401 Edgar E. Iglesias
            }
123 93f1e401 Edgar E. Iglesias
            break;
124 93f1e401 Edgar E. Iglesias
125 93f1e401 Edgar E. Iglesias
        default:
126 93f1e401 Edgar E. Iglesias
            r = phy->regs[regnum];
127 93f1e401 Edgar E. Iglesias
            break;
128 93f1e401 Edgar E. Iglesias
    }
129 93f1e401 Edgar E. Iglesias
    DPHY(qemu_log("\n%s %x = reg[%d]\n", __func__, r, regnum));
130 93f1e401 Edgar E. Iglesias
    return r;
131 93f1e401 Edgar E. Iglesias
}
132 93f1e401 Edgar E. Iglesias
133 93f1e401 Edgar E. Iglesias
static void
134 93f1e401 Edgar E. Iglesias
tdk_write(struct PHY *phy, unsigned int req, unsigned int data)
135 93f1e401 Edgar E. Iglesias
{
136 93f1e401 Edgar E. Iglesias
    int regnum;
137 93f1e401 Edgar E. Iglesias
138 93f1e401 Edgar E. Iglesias
    regnum = req & 0x1f;
139 93f1e401 Edgar E. Iglesias
    DPHY(qemu_log("%s reg[%d] = %x\n", __func__, regnum, data));
140 93f1e401 Edgar E. Iglesias
    switch (regnum) {
141 93f1e401 Edgar E. Iglesias
        default:
142 93f1e401 Edgar E. Iglesias
            phy->regs[regnum] = data;
143 93f1e401 Edgar E. Iglesias
            break;
144 93f1e401 Edgar E. Iglesias
    }
145 93f1e401 Edgar E. Iglesias
}
146 93f1e401 Edgar E. Iglesias
147 93f1e401 Edgar E. Iglesias
static void
148 93f1e401 Edgar E. Iglesias
tdk_init(struct PHY *phy)
149 93f1e401 Edgar E. Iglesias
{
150 93f1e401 Edgar E. Iglesias
    phy->regs[0] = 0x3100;
151 93f1e401 Edgar E. Iglesias
    /* PHY Id.  */
152 93f1e401 Edgar E. Iglesias
    phy->regs[2] = 0x0300;
153 93f1e401 Edgar E. Iglesias
    phy->regs[3] = 0xe400;
154 93f1e401 Edgar E. Iglesias
    /* Autonegotiation advertisement reg.  */
155 93f1e401 Edgar E. Iglesias
    phy->regs[4] = 0x01E1;
156 93f1e401 Edgar E. Iglesias
    phy->link = 1;
157 93f1e401 Edgar E. Iglesias
158 93f1e401 Edgar E. Iglesias
    phy->read = tdk_read;
159 93f1e401 Edgar E. Iglesias
    phy->write = tdk_write;
160 93f1e401 Edgar E. Iglesias
}
161 93f1e401 Edgar E. Iglesias
162 93f1e401 Edgar E. Iglesias
struct MDIOBus {
163 93f1e401 Edgar E. Iglesias
    /* bus.  */
164 93f1e401 Edgar E. Iglesias
    int mdc;
165 93f1e401 Edgar E. Iglesias
    int mdio;
166 93f1e401 Edgar E. Iglesias
167 93f1e401 Edgar E. Iglesias
    /* decoder.  */
168 93f1e401 Edgar E. Iglesias
    enum {
169 93f1e401 Edgar E. Iglesias
        PREAMBLE,
170 93f1e401 Edgar E. Iglesias
        SOF,
171 93f1e401 Edgar E. Iglesias
        OPC,
172 93f1e401 Edgar E. Iglesias
        ADDR,
173 93f1e401 Edgar E. Iglesias
        REQ,
174 93f1e401 Edgar E. Iglesias
        TURNAROUND,
175 93f1e401 Edgar E. Iglesias
        DATA
176 93f1e401 Edgar E. Iglesias
    } state;
177 93f1e401 Edgar E. Iglesias
    unsigned int drive;
178 93f1e401 Edgar E. Iglesias
179 93f1e401 Edgar E. Iglesias
    unsigned int cnt;
180 93f1e401 Edgar E. Iglesias
    unsigned int addr;
181 93f1e401 Edgar E. Iglesias
    unsigned int opc;
182 93f1e401 Edgar E. Iglesias
    unsigned int req;
183 93f1e401 Edgar E. Iglesias
    unsigned int data;
184 93f1e401 Edgar E. Iglesias
185 93f1e401 Edgar E. Iglesias
    struct PHY *devs[32];
186 93f1e401 Edgar E. Iglesias
};
187 93f1e401 Edgar E. Iglesias
188 93f1e401 Edgar E. Iglesias
static void
189 93f1e401 Edgar E. Iglesias
mdio_attach(struct MDIOBus *bus, struct PHY *phy, unsigned int addr)
190 93f1e401 Edgar E. Iglesias
{
191 93f1e401 Edgar E. Iglesias
    bus->devs[addr & 0x1f] = phy;
192 93f1e401 Edgar E. Iglesias
}
193 93f1e401 Edgar E. Iglesias
194 93f1e401 Edgar E. Iglesias
#ifdef USE_THIS_DEAD_CODE
195 93f1e401 Edgar E. Iglesias
static void
196 93f1e401 Edgar E. Iglesias
mdio_detach(struct MDIOBus *bus, struct PHY *phy, unsigned int addr)
197 93f1e401 Edgar E. Iglesias
{
198 93f1e401 Edgar E. Iglesias
    bus->devs[addr & 0x1f] = NULL;
199 93f1e401 Edgar E. Iglesias
}
200 93f1e401 Edgar E. Iglesias
#endif
201 93f1e401 Edgar E. Iglesias
202 93f1e401 Edgar E. Iglesias
static uint16_t mdio_read_req(struct MDIOBus *bus, unsigned int addr,
203 93f1e401 Edgar E. Iglesias
                  unsigned int reg)
204 93f1e401 Edgar E. Iglesias
{
205 93f1e401 Edgar E. Iglesias
    struct PHY *phy;
206 93f1e401 Edgar E. Iglesias
    uint16_t data;
207 93f1e401 Edgar E. Iglesias
208 93f1e401 Edgar E. Iglesias
    phy = bus->devs[addr];
209 93f1e401 Edgar E. Iglesias
    if (phy && phy->read) {
210 93f1e401 Edgar E. Iglesias
        data = phy->read(phy, reg);
211 93f1e401 Edgar E. Iglesias
    } else {
212 93f1e401 Edgar E. Iglesias
        data = 0xffff;
213 93f1e401 Edgar E. Iglesias
    }
214 93f1e401 Edgar E. Iglesias
    DPHY(qemu_log("%s addr=%d reg=%d data=%x\n", __func__, addr, reg, data));
215 93f1e401 Edgar E. Iglesias
    return data;
216 93f1e401 Edgar E. Iglesias
}
217 93f1e401 Edgar E. Iglesias
218 93f1e401 Edgar E. Iglesias
static void mdio_write_req(struct MDIOBus *bus, unsigned int addr,
219 93f1e401 Edgar E. Iglesias
               unsigned int reg, uint16_t data)
220 93f1e401 Edgar E. Iglesias
{
221 93f1e401 Edgar E. Iglesias
    struct PHY *phy;
222 93f1e401 Edgar E. Iglesias
223 93f1e401 Edgar E. Iglesias
    DPHY(qemu_log("%s addr=%d reg=%d data=%x\n", __func__, addr, reg, data));
224 93f1e401 Edgar E. Iglesias
    phy = bus->devs[addr];
225 93f1e401 Edgar E. Iglesias
    if (phy && phy->write) {
226 93f1e401 Edgar E. Iglesias
        phy->write(phy, reg, data);
227 93f1e401 Edgar E. Iglesias
    }
228 93f1e401 Edgar E. Iglesias
}
229 93f1e401 Edgar E. Iglesias
230 93f1e401 Edgar E. Iglesias
#define DENET(x)
231 93f1e401 Edgar E. Iglesias
232 93f1e401 Edgar E. Iglesias
#define R_RAF      (0x000 / 4)
233 93f1e401 Edgar E. Iglesias
enum {
234 93f1e401 Edgar E. Iglesias
    RAF_MCAST_REJ = (1 << 1),
235 93f1e401 Edgar E. Iglesias
    RAF_BCAST_REJ = (1 << 2),
236 93f1e401 Edgar E. Iglesias
    RAF_EMCF_EN = (1 << 12),
237 93f1e401 Edgar E. Iglesias
    RAF_NEWFUNC_EN = (1 << 11)
238 93f1e401 Edgar E. Iglesias
};
239 93f1e401 Edgar E. Iglesias
240 93f1e401 Edgar E. Iglesias
#define R_IS       (0x00C / 4)
241 93f1e401 Edgar E. Iglesias
enum {
242 93f1e401 Edgar E. Iglesias
    IS_HARD_ACCESS_COMPLETE = 1,
243 93f1e401 Edgar E. Iglesias
    IS_AUTONEG = (1 << 1),
244 93f1e401 Edgar E. Iglesias
    IS_RX_COMPLETE = (1 << 2),
245 93f1e401 Edgar E. Iglesias
    IS_RX_REJECT = (1 << 3),
246 93f1e401 Edgar E. Iglesias
    IS_TX_COMPLETE = (1 << 5),
247 93f1e401 Edgar E. Iglesias
    IS_RX_DCM_LOCK = (1 << 6),
248 93f1e401 Edgar E. Iglesias
    IS_MGM_RDY = (1 << 7),
249 93f1e401 Edgar E. Iglesias
    IS_PHY_RST_DONE = (1 << 8),
250 93f1e401 Edgar E. Iglesias
};
251 93f1e401 Edgar E. Iglesias
252 93f1e401 Edgar E. Iglesias
#define R_IP       (0x010 / 4)
253 93f1e401 Edgar E. Iglesias
#define R_IE       (0x014 / 4)
254 93f1e401 Edgar E. Iglesias
#define R_UAWL     (0x020 / 4)
255 93f1e401 Edgar E. Iglesias
#define R_UAWU     (0x024 / 4)
256 93f1e401 Edgar E. Iglesias
#define R_PPST     (0x030 / 4)
257 93f1e401 Edgar E. Iglesias
enum {
258 93f1e401 Edgar E. Iglesias
    PPST_LINKSTATUS = (1 << 0),
259 93f1e401 Edgar E. Iglesias
    PPST_PHY_LINKSTATUS = (1 << 7),
260 93f1e401 Edgar E. Iglesias
};
261 93f1e401 Edgar E. Iglesias
262 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_BYTESL (0x200 / 4)
263 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_BYTESH (0x204 / 4)
264 93f1e401 Edgar E. Iglesias
#define R_STATS_TX_BYTESL (0x208 / 4)
265 93f1e401 Edgar E. Iglesias
#define R_STATS_TX_BYTESH (0x20C / 4)
266 93f1e401 Edgar E. Iglesias
#define R_STATS_RXL       (0x290 / 4)
267 93f1e401 Edgar E. Iglesias
#define R_STATS_RXH       (0x294 / 4)
268 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_BCASTL (0x2a0 / 4)
269 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_BCASTH (0x2a4 / 4)
270 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_MCASTL (0x2a8 / 4)
271 93f1e401 Edgar E. Iglesias
#define R_STATS_RX_MCASTH (0x2ac / 4)
272 93f1e401 Edgar E. Iglesias
273 93f1e401 Edgar E. Iglesias
#define R_RCW0     (0x400 / 4)
274 93f1e401 Edgar E. Iglesias
#define R_RCW1     (0x404 / 4)
275 93f1e401 Edgar E. Iglesias
enum {
276 93f1e401 Edgar E. Iglesias
    RCW1_VLAN = (1 << 27),
277 93f1e401 Edgar E. Iglesias
    RCW1_RX   = (1 << 28),
278 93f1e401 Edgar E. Iglesias
    RCW1_FCS  = (1 << 29),
279 93f1e401 Edgar E. Iglesias
    RCW1_JUM  = (1 << 30),
280 93f1e401 Edgar E. Iglesias
    RCW1_RST  = (1 << 31),
281 93f1e401 Edgar E. Iglesias
};
282 93f1e401 Edgar E. Iglesias
283 93f1e401 Edgar E. Iglesias
#define R_TC       (0x408 / 4)
284 93f1e401 Edgar E. Iglesias
enum {
285 93f1e401 Edgar E. Iglesias
    TC_VLAN = (1 << 27),
286 93f1e401 Edgar E. Iglesias
    TC_TX   = (1 << 28),
287 93f1e401 Edgar E. Iglesias
    TC_FCS  = (1 << 29),
288 93f1e401 Edgar E. Iglesias
    TC_JUM  = (1 << 30),
289 93f1e401 Edgar E. Iglesias
    TC_RST  = (1 << 31),
290 93f1e401 Edgar E. Iglesias
};
291 93f1e401 Edgar E. Iglesias
292 93f1e401 Edgar E. Iglesias
#define R_EMMC     (0x410 / 4)
293 93f1e401 Edgar E. Iglesias
enum {
294 93f1e401 Edgar E. Iglesias
    EMMC_LINKSPEED_10MB = (0 << 30),
295 93f1e401 Edgar E. Iglesias
    EMMC_LINKSPEED_100MB = (1 << 30),
296 93f1e401 Edgar E. Iglesias
    EMMC_LINKSPEED_1000MB = (2 << 30),
297 93f1e401 Edgar E. Iglesias
};
298 93f1e401 Edgar E. Iglesias
299 93f1e401 Edgar E. Iglesias
#define R_PHYC     (0x414 / 4)
300 93f1e401 Edgar E. Iglesias
301 93f1e401 Edgar E. Iglesias
#define R_MC       (0x500 / 4)
302 93f1e401 Edgar E. Iglesias
#define MC_EN      (1 << 6)
303 93f1e401 Edgar E. Iglesias
304 93f1e401 Edgar E. Iglesias
#define R_MCR      (0x504 / 4)
305 93f1e401 Edgar E. Iglesias
#define R_MWD      (0x508 / 4)
306 93f1e401 Edgar E. Iglesias
#define R_MRD      (0x50c / 4)
307 93f1e401 Edgar E. Iglesias
#define R_MIS      (0x600 / 4)
308 93f1e401 Edgar E. Iglesias
#define R_MIP      (0x620 / 4)
309 93f1e401 Edgar E. Iglesias
#define R_MIE      (0x640 / 4)
310 93f1e401 Edgar E. Iglesias
#define R_MIC      (0x640 / 4)
311 93f1e401 Edgar E. Iglesias
312 93f1e401 Edgar E. Iglesias
#define R_UAW0     (0x700 / 4)
313 93f1e401 Edgar E. Iglesias
#define R_UAW1     (0x704 / 4)
314 93f1e401 Edgar E. Iglesias
#define R_FMI      (0x708 / 4)
315 93f1e401 Edgar E. Iglesias
#define R_AF0      (0x710 / 4)
316 93f1e401 Edgar E. Iglesias
#define R_AF1      (0x714 / 4)
317 93f1e401 Edgar E. Iglesias
#define R_MAX      (0x34 / 4)
318 93f1e401 Edgar E. Iglesias
319 93f1e401 Edgar E. Iglesias
/* Indirect registers.  */
320 93f1e401 Edgar E. Iglesias
struct TEMAC  {
321 93f1e401 Edgar E. Iglesias
    struct MDIOBus mdio_bus;
322 93f1e401 Edgar E. Iglesias
    struct PHY phy;
323 93f1e401 Edgar E. Iglesias
324 93f1e401 Edgar E. Iglesias
    void *parent;
325 93f1e401 Edgar E. Iglesias
};
326 93f1e401 Edgar E. Iglesias
327 55b3e0c2 Peter Crosthwaite
typedef struct XilinxAXIEnetStreamSlave XilinxAXIEnetStreamSlave;
328 545129e5 Peter Crosthwaite
typedef struct XilinxAXIEnet XilinxAXIEnet;
329 545129e5 Peter Crosthwaite
330 55b3e0c2 Peter Crosthwaite
struct XilinxAXIEnetStreamSlave {
331 55b3e0c2 Peter Crosthwaite
    Object parent;
332 55b3e0c2 Peter Crosthwaite
333 55b3e0c2 Peter Crosthwaite
    struct XilinxAXIEnet *enet;
334 55b3e0c2 Peter Crosthwaite
} ;
335 55b3e0c2 Peter Crosthwaite
336 93f1e401 Edgar E. Iglesias
struct XilinxAXIEnet {
337 93f1e401 Edgar E. Iglesias
    SysBusDevice busdev;
338 0dc31f3b Avi Kivity
    MemoryRegion iomem;
339 93f1e401 Edgar E. Iglesias
    qemu_irq irq;
340 42bb9c91 Peter Crosthwaite
    StreamSlave *tx_data_dev;
341 42bb9c91 Peter Crosthwaite
    StreamSlave *tx_control_dev;
342 55b3e0c2 Peter Crosthwaite
    XilinxAXIEnetStreamSlave rx_data_dev;
343 42bb9c91 Peter Crosthwaite
    XilinxAXIEnetStreamSlave rx_control_dev;
344 93f1e401 Edgar E. Iglesias
    NICState *nic;
345 93f1e401 Edgar E. Iglesias
    NICConf conf;
346 93f1e401 Edgar E. Iglesias
347 93f1e401 Edgar E. Iglesias
348 93f1e401 Edgar E. Iglesias
    uint32_t c_rxmem;
349 93f1e401 Edgar E. Iglesias
    uint32_t c_txmem;
350 93f1e401 Edgar E. Iglesias
    uint32_t c_phyaddr;
351 93f1e401 Edgar E. Iglesias
352 93f1e401 Edgar E. Iglesias
    struct TEMAC TEMAC;
353 93f1e401 Edgar E. Iglesias
354 93f1e401 Edgar E. Iglesias
    /* MII regs.  */
355 93f1e401 Edgar E. Iglesias
    union {
356 93f1e401 Edgar E. Iglesias
        uint32_t regs[4];
357 93f1e401 Edgar E. Iglesias
        struct {
358 93f1e401 Edgar E. Iglesias
            uint32_t mc;
359 93f1e401 Edgar E. Iglesias
            uint32_t mcr;
360 93f1e401 Edgar E. Iglesias
            uint32_t mwd;
361 93f1e401 Edgar E. Iglesias
            uint32_t mrd;
362 93f1e401 Edgar E. Iglesias
        };
363 93f1e401 Edgar E. Iglesias
    } mii;
364 93f1e401 Edgar E. Iglesias
365 93f1e401 Edgar E. Iglesias
    struct {
366 93f1e401 Edgar E. Iglesias
        uint64_t rx_bytes;
367 93f1e401 Edgar E. Iglesias
        uint64_t tx_bytes;
368 93f1e401 Edgar E. Iglesias
369 93f1e401 Edgar E. Iglesias
        uint64_t rx;
370 93f1e401 Edgar E. Iglesias
        uint64_t rx_bcast;
371 93f1e401 Edgar E. Iglesias
        uint64_t rx_mcast;
372 93f1e401 Edgar E. Iglesias
    } stats;
373 93f1e401 Edgar E. Iglesias
374 93f1e401 Edgar E. Iglesias
    /* Receive configuration words.  */
375 93f1e401 Edgar E. Iglesias
    uint32_t rcw[2];
376 93f1e401 Edgar E. Iglesias
    /* Transmit config.  */
377 93f1e401 Edgar E. Iglesias
    uint32_t tc;
378 93f1e401 Edgar E. Iglesias
    uint32_t emmc;
379 93f1e401 Edgar E. Iglesias
    uint32_t phyc;
380 93f1e401 Edgar E. Iglesias
381 93f1e401 Edgar E. Iglesias
    /* Unicast Address Word.  */
382 93f1e401 Edgar E. Iglesias
    uint32_t uaw[2];
383 93f1e401 Edgar E. Iglesias
    /* Unicast address filter used with extended mcast.  */
384 93f1e401 Edgar E. Iglesias
    uint32_t ext_uaw[2];
385 93f1e401 Edgar E. Iglesias
    uint32_t fmi;
386 93f1e401 Edgar E. Iglesias
387 93f1e401 Edgar E. Iglesias
    uint32_t regs[R_MAX];
388 93f1e401 Edgar E. Iglesias
389 93f1e401 Edgar E. Iglesias
    /* Multicast filter addrs.  */
390 93f1e401 Edgar E. Iglesias
    uint32_t maddr[4][2];
391 93f1e401 Edgar E. Iglesias
    /* 32K x 1 lookup filter.  */
392 93f1e401 Edgar E. Iglesias
    uint32_t ext_mtable[1024];
393 93f1e401 Edgar E. Iglesias
394 42bb9c91 Peter Crosthwaite
    uint32_t hdr[CONTROL_PAYLOAD_WORDS];
395 93f1e401 Edgar E. Iglesias
396 93f1e401 Edgar E. Iglesias
    uint8_t *rxmem;
397 3630ae95 Peter Crosthwaite
    uint32_t rxsize;
398 3630ae95 Peter Crosthwaite
    uint32_t rxpos;
399 42bb9c91 Peter Crosthwaite
400 42bb9c91 Peter Crosthwaite
    uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
401 42bb9c91 Peter Crosthwaite
    uint32_t rxappsize;
402 93f1e401 Edgar E. Iglesias
};
403 93f1e401 Edgar E. Iglesias
404 545129e5 Peter Crosthwaite
static void axienet_rx_reset(XilinxAXIEnet *s)
405 93f1e401 Edgar E. Iglesias
{
406 93f1e401 Edgar E. Iglesias
    s->rcw[1] = RCW1_JUM | RCW1_FCS | RCW1_RX | RCW1_VLAN;
407 93f1e401 Edgar E. Iglesias
}
408 93f1e401 Edgar E. Iglesias
409 545129e5 Peter Crosthwaite
static void axienet_tx_reset(XilinxAXIEnet *s)
410 93f1e401 Edgar E. Iglesias
{
411 93f1e401 Edgar E. Iglesias
    s->tc = TC_JUM | TC_TX | TC_VLAN;
412 93f1e401 Edgar E. Iglesias
}
413 93f1e401 Edgar E. Iglesias
414 545129e5 Peter Crosthwaite
static inline int axienet_rx_resetting(XilinxAXIEnet *s)
415 93f1e401 Edgar E. Iglesias
{
416 93f1e401 Edgar E. Iglesias
    return s->rcw[1] & RCW1_RST;
417 93f1e401 Edgar E. Iglesias
}
418 93f1e401 Edgar E. Iglesias
419 545129e5 Peter Crosthwaite
static inline int axienet_rx_enabled(XilinxAXIEnet *s)
420 93f1e401 Edgar E. Iglesias
{
421 93f1e401 Edgar E. Iglesias
    return s->rcw[1] & RCW1_RX;
422 93f1e401 Edgar E. Iglesias
}
423 93f1e401 Edgar E. Iglesias
424 545129e5 Peter Crosthwaite
static inline int axienet_extmcf_enabled(XilinxAXIEnet *s)
425 93f1e401 Edgar E. Iglesias
{
426 93f1e401 Edgar E. Iglesias
    return !!(s->regs[R_RAF] & RAF_EMCF_EN);
427 93f1e401 Edgar E. Iglesias
}
428 93f1e401 Edgar E. Iglesias
429 545129e5 Peter Crosthwaite
static inline int axienet_newfunc_enabled(XilinxAXIEnet *s)
430 93f1e401 Edgar E. Iglesias
{
431 93f1e401 Edgar E. Iglesias
    return !!(s->regs[R_RAF] & RAF_NEWFUNC_EN);
432 93f1e401 Edgar E. Iglesias
}
433 93f1e401 Edgar E. Iglesias
434 9ee0ceb7 Peter Crosthwaite
static void xilinx_axienet_reset(DeviceState *d)
435 93f1e401 Edgar E. Iglesias
{
436 9ee0ceb7 Peter Crosthwaite
    XilinxAXIEnet *s = XILINX_AXI_ENET(d);
437 9ee0ceb7 Peter Crosthwaite
438 93f1e401 Edgar E. Iglesias
    axienet_rx_reset(s);
439 93f1e401 Edgar E. Iglesias
    axienet_tx_reset(s);
440 93f1e401 Edgar E. Iglesias
441 93f1e401 Edgar E. Iglesias
    s->regs[R_PPST] = PPST_LINKSTATUS | PPST_PHY_LINKSTATUS;
442 93f1e401 Edgar E. Iglesias
    s->regs[R_IS] = IS_AUTONEG | IS_RX_DCM_LOCK | IS_MGM_RDY | IS_PHY_RST_DONE;
443 93f1e401 Edgar E. Iglesias
444 93f1e401 Edgar E. Iglesias
    s->emmc = EMMC_LINKSPEED_100MB;
445 93f1e401 Edgar E. Iglesias
}
446 93f1e401 Edgar E. Iglesias
447 545129e5 Peter Crosthwaite
static void enet_update_irq(XilinxAXIEnet *s)
448 93f1e401 Edgar E. Iglesias
{
449 93f1e401 Edgar E. Iglesias
    s->regs[R_IP] = s->regs[R_IS] & s->regs[R_IE];
450 93f1e401 Edgar E. Iglesias
    qemu_set_irq(s->irq, !!s->regs[R_IP]);
451 93f1e401 Edgar E. Iglesias
}
452 93f1e401 Edgar E. Iglesias
453 a8170e5e Avi Kivity
static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size)
454 93f1e401 Edgar E. Iglesias
{
455 545129e5 Peter Crosthwaite
    XilinxAXIEnet *s = opaque;
456 93f1e401 Edgar E. Iglesias
    uint32_t r = 0;
457 93f1e401 Edgar E. Iglesias
    addr >>= 2;
458 93f1e401 Edgar E. Iglesias
459 93f1e401 Edgar E. Iglesias
    switch (addr) {
460 93f1e401 Edgar E. Iglesias
        case R_RCW0:
461 93f1e401 Edgar E. Iglesias
        case R_RCW1:
462 93f1e401 Edgar E. Iglesias
            r = s->rcw[addr & 1];
463 93f1e401 Edgar E. Iglesias
            break;
464 93f1e401 Edgar E. Iglesias
465 93f1e401 Edgar E. Iglesias
        case R_TC:
466 93f1e401 Edgar E. Iglesias
            r = s->tc;
467 93f1e401 Edgar E. Iglesias
            break;
468 93f1e401 Edgar E. Iglesias
469 93f1e401 Edgar E. Iglesias
        case R_EMMC:
470 93f1e401 Edgar E. Iglesias
            r = s->emmc;
471 93f1e401 Edgar E. Iglesias
            break;
472 93f1e401 Edgar E. Iglesias
473 93f1e401 Edgar E. Iglesias
        case R_PHYC:
474 93f1e401 Edgar E. Iglesias
            r = s->phyc;
475 93f1e401 Edgar E. Iglesias
            break;
476 93f1e401 Edgar E. Iglesias
477 93f1e401 Edgar E. Iglesias
        case R_MCR:
478 93f1e401 Edgar E. Iglesias
            r = s->mii.regs[addr & 3] | (1 << 7); /* Always ready.  */
479 93f1e401 Edgar E. Iglesias
            break;
480 93f1e401 Edgar E. Iglesias
481 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_BYTESL:
482 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_BYTESH:
483 93f1e401 Edgar E. Iglesias
            r = s->stats.rx_bytes >> (32 * (addr & 1));
484 93f1e401 Edgar E. Iglesias
            break;
485 93f1e401 Edgar E. Iglesias
486 93f1e401 Edgar E. Iglesias
        case R_STATS_TX_BYTESL:
487 93f1e401 Edgar E. Iglesias
        case R_STATS_TX_BYTESH:
488 93f1e401 Edgar E. Iglesias
            r = s->stats.tx_bytes >> (32 * (addr & 1));
489 93f1e401 Edgar E. Iglesias
            break;
490 93f1e401 Edgar E. Iglesias
491 93f1e401 Edgar E. Iglesias
        case R_STATS_RXL:
492 93f1e401 Edgar E. Iglesias
        case R_STATS_RXH:
493 93f1e401 Edgar E. Iglesias
            r = s->stats.rx >> (32 * (addr & 1));
494 93f1e401 Edgar E. Iglesias
            break;
495 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_BCASTL:
496 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_BCASTH:
497 93f1e401 Edgar E. Iglesias
            r = s->stats.rx_bcast >> (32 * (addr & 1));
498 93f1e401 Edgar E. Iglesias
            break;
499 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_MCASTL:
500 93f1e401 Edgar E. Iglesias
        case R_STATS_RX_MCASTH:
501 93f1e401 Edgar E. Iglesias
            r = s->stats.rx_mcast >> (32 * (addr & 1));
502 93f1e401 Edgar E. Iglesias
            break;
503 93f1e401 Edgar E. Iglesias
504 93f1e401 Edgar E. Iglesias
        case R_MC:
505 93f1e401 Edgar E. Iglesias
        case R_MWD:
506 93f1e401 Edgar E. Iglesias
        case R_MRD:
507 93f1e401 Edgar E. Iglesias
            r = s->mii.regs[addr & 3];
508 93f1e401 Edgar E. Iglesias
            break;
509 93f1e401 Edgar E. Iglesias
510 93f1e401 Edgar E. Iglesias
        case R_UAW0:
511 93f1e401 Edgar E. Iglesias
        case R_UAW1:
512 93f1e401 Edgar E. Iglesias
            r = s->uaw[addr & 1];
513 93f1e401 Edgar E. Iglesias
            break;
514 93f1e401 Edgar E. Iglesias
515 93f1e401 Edgar E. Iglesias
        case R_UAWU:
516 93f1e401 Edgar E. Iglesias
        case R_UAWL:
517 93f1e401 Edgar E. Iglesias
            r = s->ext_uaw[addr & 1];
518 93f1e401 Edgar E. Iglesias
            break;
519 93f1e401 Edgar E. Iglesias
520 93f1e401 Edgar E. Iglesias
        case R_FMI:
521 93f1e401 Edgar E. Iglesias
            r = s->fmi;
522 93f1e401 Edgar E. Iglesias
            break;
523 93f1e401 Edgar E. Iglesias
524 93f1e401 Edgar E. Iglesias
        case R_AF0:
525 93f1e401 Edgar E. Iglesias
        case R_AF1:
526 93f1e401 Edgar E. Iglesias
            r = s->maddr[s->fmi & 3][addr & 1];
527 93f1e401 Edgar E. Iglesias
            break;
528 93f1e401 Edgar E. Iglesias
529 93f1e401 Edgar E. Iglesias
        case 0x8000 ... 0x83ff:
530 93f1e401 Edgar E. Iglesias
            r = s->ext_mtable[addr - 0x8000];
531 93f1e401 Edgar E. Iglesias
            break;
532 93f1e401 Edgar E. Iglesias
533 93f1e401 Edgar E. Iglesias
        default:
534 93f1e401 Edgar E. Iglesias
            if (addr < ARRAY_SIZE(s->regs)) {
535 93f1e401 Edgar E. Iglesias
                r = s->regs[addr];
536 93f1e401 Edgar E. Iglesias
            }
537 93f1e401 Edgar E. Iglesias
            DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
538 93f1e401 Edgar E. Iglesias
                            __func__, addr * 4, r));
539 93f1e401 Edgar E. Iglesias
            break;
540 93f1e401 Edgar E. Iglesias
    }
541 93f1e401 Edgar E. Iglesias
    return r;
542 93f1e401 Edgar E. Iglesias
}
543 93f1e401 Edgar E. Iglesias
544 a8170e5e Avi Kivity
static void enet_write(void *opaque, hwaddr addr,
545 0dc31f3b Avi Kivity
                       uint64_t value, unsigned size)
546 93f1e401 Edgar E. Iglesias
{
547 545129e5 Peter Crosthwaite
    XilinxAXIEnet *s = opaque;
548 93f1e401 Edgar E. Iglesias
    struct TEMAC *t = &s->TEMAC;
549 93f1e401 Edgar E. Iglesias
550 93f1e401 Edgar E. Iglesias
    addr >>= 2;
551 93f1e401 Edgar E. Iglesias
    switch (addr) {
552 93f1e401 Edgar E. Iglesias
        case R_RCW0:
553 93f1e401 Edgar E. Iglesias
        case R_RCW1:
554 93f1e401 Edgar E. Iglesias
            s->rcw[addr & 1] = value;
555 93f1e401 Edgar E. Iglesias
            if ((addr & 1) && value & RCW1_RST) {
556 93f1e401 Edgar E. Iglesias
                axienet_rx_reset(s);
557 4dbb9ed3 Peter Crosthwaite
            } else {
558 4dbb9ed3 Peter Crosthwaite
                qemu_flush_queued_packets(qemu_get_queue(s->nic));
559 93f1e401 Edgar E. Iglesias
            }
560 93f1e401 Edgar E. Iglesias
            break;
561 93f1e401 Edgar E. Iglesias
562 93f1e401 Edgar E. Iglesias
        case R_TC:
563 93f1e401 Edgar E. Iglesias
            s->tc = value;
564 93f1e401 Edgar E. Iglesias
            if (value & TC_RST) {
565 93f1e401 Edgar E. Iglesias
                axienet_tx_reset(s);
566 93f1e401 Edgar E. Iglesias
            }
567 93f1e401 Edgar E. Iglesias
            break;
568 93f1e401 Edgar E. Iglesias
569 93f1e401 Edgar E. Iglesias
        case R_EMMC:
570 93f1e401 Edgar E. Iglesias
            s->emmc = value;
571 93f1e401 Edgar E. Iglesias
            break;
572 93f1e401 Edgar E. Iglesias
573 93f1e401 Edgar E. Iglesias
        case R_PHYC:
574 93f1e401 Edgar E. Iglesias
            s->phyc = value;
575 93f1e401 Edgar E. Iglesias
            break;
576 93f1e401 Edgar E. Iglesias
577 93f1e401 Edgar E. Iglesias
        case R_MC:
578 4e298e46 Stefan Weil
             value &= ((1 << 7) - 1);
579 93f1e401 Edgar E. Iglesias
580 93f1e401 Edgar E. Iglesias
             /* Enable the MII.  */
581 93f1e401 Edgar E. Iglesias
             if (value & MC_EN) {
582 93f1e401 Edgar E. Iglesias
                 unsigned int miiclkdiv = value & ((1 << 6) - 1);
583 93f1e401 Edgar E. Iglesias
                 if (!miiclkdiv) {
584 93f1e401 Edgar E. Iglesias
                     qemu_log("AXIENET: MDIO enabled but MDIOCLK is zero!\n");
585 93f1e401 Edgar E. Iglesias
                 }
586 93f1e401 Edgar E. Iglesias
             }
587 93f1e401 Edgar E. Iglesias
             s->mii.mc = value;
588 93f1e401 Edgar E. Iglesias
             break;
589 93f1e401 Edgar E. Iglesias
590 93f1e401 Edgar E. Iglesias
        case R_MCR: {
591 93f1e401 Edgar E. Iglesias
             unsigned int phyaddr = (value >> 24) & 0x1f;
592 93f1e401 Edgar E. Iglesias
             unsigned int regaddr = (value >> 16) & 0x1f;
593 93f1e401 Edgar E. Iglesias
             unsigned int op = (value >> 14) & 3;
594 93f1e401 Edgar E. Iglesias
             unsigned int initiate = (value >> 11) & 1;
595 93f1e401 Edgar E. Iglesias
596 93f1e401 Edgar E. Iglesias
             if (initiate) {
597 93f1e401 Edgar E. Iglesias
                 if (op == 1) {
598 93f1e401 Edgar E. Iglesias
                     mdio_write_req(&t->mdio_bus, phyaddr, regaddr, s->mii.mwd);
599 93f1e401 Edgar E. Iglesias
                 } else if (op == 2) {
600 93f1e401 Edgar E. Iglesias
                     s->mii.mrd = mdio_read_req(&t->mdio_bus, phyaddr, regaddr);
601 93f1e401 Edgar E. Iglesias
                 } else {
602 93f1e401 Edgar E. Iglesias
                     qemu_log("AXIENET: invalid MDIOBus OP=%d\n", op);
603 93f1e401 Edgar E. Iglesias
                 }
604 93f1e401 Edgar E. Iglesias
             }
605 93f1e401 Edgar E. Iglesias
             s->mii.mcr = value;
606 93f1e401 Edgar E. Iglesias
             break;
607 93f1e401 Edgar E. Iglesias
        }
608 93f1e401 Edgar E. Iglesias
609 93f1e401 Edgar E. Iglesias
        case R_MWD:
610 93f1e401 Edgar E. Iglesias
        case R_MRD:
611 93f1e401 Edgar E. Iglesias
             s->mii.regs[addr & 3] = value;
612 93f1e401 Edgar E. Iglesias
             break;
613 93f1e401 Edgar E. Iglesias
614 93f1e401 Edgar E. Iglesias
615 93f1e401 Edgar E. Iglesias
        case R_UAW0:
616 93f1e401 Edgar E. Iglesias
        case R_UAW1:
617 93f1e401 Edgar E. Iglesias
            s->uaw[addr & 1] = value;
618 93f1e401 Edgar E. Iglesias
            break;
619 93f1e401 Edgar E. Iglesias
620 93f1e401 Edgar E. Iglesias
        case R_UAWL:
621 93f1e401 Edgar E. Iglesias
        case R_UAWU:
622 93f1e401 Edgar E. Iglesias
            s->ext_uaw[addr & 1] = value;
623 93f1e401 Edgar E. Iglesias
            break;
624 93f1e401 Edgar E. Iglesias
625 93f1e401 Edgar E. Iglesias
        case R_FMI:
626 93f1e401 Edgar E. Iglesias
            s->fmi = value;
627 93f1e401 Edgar E. Iglesias
            break;
628 93f1e401 Edgar E. Iglesias
629 93f1e401 Edgar E. Iglesias
        case R_AF0:
630 93f1e401 Edgar E. Iglesias
        case R_AF1:
631 93f1e401 Edgar E. Iglesias
            s->maddr[s->fmi & 3][addr & 1] = value;
632 93f1e401 Edgar E. Iglesias
            break;
633 93f1e401 Edgar E. Iglesias
634 d4d230da Peter Crosthwaite
        case R_IS:
635 d4d230da Peter Crosthwaite
            s->regs[addr] &= ~value;
636 d4d230da Peter Crosthwaite
            break;
637 d4d230da Peter Crosthwaite
638 93f1e401 Edgar E. Iglesias
        case 0x8000 ... 0x83ff:
639 93f1e401 Edgar E. Iglesias
            s->ext_mtable[addr - 0x8000] = value;
640 93f1e401 Edgar E. Iglesias
            break;
641 93f1e401 Edgar E. Iglesias
642 93f1e401 Edgar E. Iglesias
        default:
643 93f1e401 Edgar E. Iglesias
            DENET(qemu_log("%s addr=" TARGET_FMT_plx " v=%x\n",
644 0dc31f3b Avi Kivity
                           __func__, addr * 4, (unsigned)value));
645 93f1e401 Edgar E. Iglesias
            if (addr < ARRAY_SIZE(s->regs)) {
646 93f1e401 Edgar E. Iglesias
                s->regs[addr] = value;
647 93f1e401 Edgar E. Iglesias
            }
648 93f1e401 Edgar E. Iglesias
            break;
649 93f1e401 Edgar E. Iglesias
    }
650 93f1e401 Edgar E. Iglesias
    enet_update_irq(s);
651 93f1e401 Edgar E. Iglesias
}
652 93f1e401 Edgar E. Iglesias
653 0dc31f3b Avi Kivity
static const MemoryRegionOps enet_ops = {
654 0dc31f3b Avi Kivity
    .read = enet_read,
655 0dc31f3b Avi Kivity
    .write = enet_write,
656 0dc31f3b Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
657 93f1e401 Edgar E. Iglesias
};
658 93f1e401 Edgar E. Iglesias
659 4e68f7a0 Stefan Hajnoczi
static int eth_can_rx(NetClientState *nc)
660 93f1e401 Edgar E. Iglesias
{
661 545129e5 Peter Crosthwaite
    XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
662 93f1e401 Edgar E. Iglesias
663 93f1e401 Edgar E. Iglesias
    /* RX enabled?  */
664 3630ae95 Peter Crosthwaite
    return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
665 93f1e401 Edgar E. Iglesias
}
666 93f1e401 Edgar E. Iglesias
667 93f1e401 Edgar E. Iglesias
static int enet_match_addr(const uint8_t *buf, uint32_t f0, uint32_t f1)
668 93f1e401 Edgar E. Iglesias
{
669 93f1e401 Edgar E. Iglesias
    int match = 1;
670 93f1e401 Edgar E. Iglesias
671 93f1e401 Edgar E. Iglesias
    if (memcmp(buf, &f0, 4)) {
672 93f1e401 Edgar E. Iglesias
        match = 0;
673 93f1e401 Edgar E. Iglesias
    }
674 93f1e401 Edgar E. Iglesias
675 93f1e401 Edgar E. Iglesias
    if (buf[4] != (f1 & 0xff) || buf[5] != ((f1 >> 8) & 0xff)) {
676 93f1e401 Edgar E. Iglesias
        match = 0;
677 93f1e401 Edgar E. Iglesias
    }
678 93f1e401 Edgar E. Iglesias
679 93f1e401 Edgar E. Iglesias
    return match;
680 93f1e401 Edgar E. Iglesias
}
681 93f1e401 Edgar E. Iglesias
682 3630ae95 Peter Crosthwaite
static void axienet_eth_rx_notify(void *opaque)
683 3630ae95 Peter Crosthwaite
{
684 3630ae95 Peter Crosthwaite
    XilinxAXIEnet *s = XILINX_AXI_ENET(opaque);
685 3630ae95 Peter Crosthwaite
686 42bb9c91 Peter Crosthwaite
    while (s->rxappsize && stream_can_push(s->tx_control_dev,
687 42bb9c91 Peter Crosthwaite
                                           axienet_eth_rx_notify, s)) {
688 42bb9c91 Peter Crosthwaite
        size_t ret = stream_push(s->tx_control_dev,
689 42bb9c91 Peter Crosthwaite
                                 (void *)s->rxapp + CONTROL_PAYLOAD_SIZE
690 42bb9c91 Peter Crosthwaite
                                 - s->rxappsize, s->rxappsize);
691 42bb9c91 Peter Crosthwaite
        s->rxappsize -= ret;
692 42bb9c91 Peter Crosthwaite
    }
693 42bb9c91 Peter Crosthwaite
694 42bb9c91 Peter Crosthwaite
    while (s->rxsize && stream_can_push(s->tx_data_dev,
695 42bb9c91 Peter Crosthwaite
                                        axienet_eth_rx_notify, s)) {
696 42bb9c91 Peter Crosthwaite
        size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos,
697 42bb9c91 Peter Crosthwaite
                                 s->rxsize);
698 3630ae95 Peter Crosthwaite
        s->rxsize -= ret;
699 3630ae95 Peter Crosthwaite
        s->rxpos += ret;
700 3630ae95 Peter Crosthwaite
        if (!s->rxsize) {
701 3630ae95 Peter Crosthwaite
            s->regs[R_IS] |= IS_RX_COMPLETE;
702 3630ae95 Peter Crosthwaite
        }
703 3630ae95 Peter Crosthwaite
    }
704 3630ae95 Peter Crosthwaite
    enet_update_irq(s);
705 3630ae95 Peter Crosthwaite
}
706 3630ae95 Peter Crosthwaite
707 4e68f7a0 Stefan Hajnoczi
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
708 93f1e401 Edgar E. Iglesias
{
709 545129e5 Peter Crosthwaite
    XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
710 93f1e401 Edgar E. Iglesias
    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
711 93f1e401 Edgar E. Iglesias
                                              0xff, 0xff, 0xff};
712 93f1e401 Edgar E. Iglesias
    static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
713 42bb9c91 Peter Crosthwaite
    uint32_t app[CONTROL_PAYLOAD_WORDS] = {0};
714 93f1e401 Edgar E. Iglesias
    int promisc = s->fmi & (1 << 31);
715 93f1e401 Edgar E. Iglesias
    int unicast, broadcast, multicast, ip_multicast = 0;
716 93f1e401 Edgar E. Iglesias
    uint32_t csum32;
717 93f1e401 Edgar E. Iglesias
    uint16_t csum16;
718 93f1e401 Edgar E. Iglesias
    int i;
719 93f1e401 Edgar E. Iglesias
720 93f1e401 Edgar E. Iglesias
    DENET(qemu_log("%s: %zd bytes\n", __func__, size));
721 93f1e401 Edgar E. Iglesias
722 93f1e401 Edgar E. Iglesias
    unicast = ~buf[0] & 0x1;
723 93f1e401 Edgar E. Iglesias
    broadcast = memcmp(buf, sa_bcast, 6) == 0;
724 93f1e401 Edgar E. Iglesias
    multicast = !unicast && !broadcast;
725 93f1e401 Edgar E. Iglesias
    if (multicast && (memcmp(sa_ipmcast, buf, sizeof sa_ipmcast) == 0)) {
726 93f1e401 Edgar E. Iglesias
        ip_multicast = 1;
727 93f1e401 Edgar E. Iglesias
    }
728 93f1e401 Edgar E. Iglesias
729 93f1e401 Edgar E. Iglesias
    /* Jumbo or vlan sizes ?  */
730 93f1e401 Edgar E. Iglesias
    if (!(s->rcw[1] & RCW1_JUM)) {
731 93f1e401 Edgar E. Iglesias
        if (size > 1518 && size <= 1522 && !(s->rcw[1] & RCW1_VLAN)) {
732 93f1e401 Edgar E. Iglesias
            return size;
733 93f1e401 Edgar E. Iglesias
        }
734 93f1e401 Edgar E. Iglesias
    }
735 93f1e401 Edgar E. Iglesias
736 93f1e401 Edgar E. Iglesias
    /* Basic Address filters.  If you want to use the extended filters
737 93f1e401 Edgar E. Iglesias
       you'll generally have to place the ethernet mac into promiscuous mode
738 93f1e401 Edgar E. Iglesias
       to avoid the basic filtering from dropping most frames.  */
739 93f1e401 Edgar E. Iglesias
    if (!promisc) {
740 93f1e401 Edgar E. Iglesias
        if (unicast) {
741 93f1e401 Edgar E. Iglesias
            if (!enet_match_addr(buf, s->uaw[0], s->uaw[1])) {
742 93f1e401 Edgar E. Iglesias
                return size;
743 93f1e401 Edgar E. Iglesias
            }
744 93f1e401 Edgar E. Iglesias
        } else {
745 93f1e401 Edgar E. Iglesias
            if (broadcast) {
746 93f1e401 Edgar E. Iglesias
                /* Broadcast.  */
747 93f1e401 Edgar E. Iglesias
                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
748 93f1e401 Edgar E. Iglesias
                    return size;
749 93f1e401 Edgar E. Iglesias
                }
750 93f1e401 Edgar E. Iglesias
            } else {
751 93f1e401 Edgar E. Iglesias
                int drop = 1;
752 93f1e401 Edgar E. Iglesias
753 93f1e401 Edgar E. Iglesias
                /* Multicast.  */
754 93f1e401 Edgar E. Iglesias
                if (s->regs[R_RAF] & RAF_MCAST_REJ) {
755 93f1e401 Edgar E. Iglesias
                    return size;
756 93f1e401 Edgar E. Iglesias
                }
757 93f1e401 Edgar E. Iglesias
758 93f1e401 Edgar E. Iglesias
                for (i = 0; i < 4; i++) {
759 93f1e401 Edgar E. Iglesias
                    if (enet_match_addr(buf, s->maddr[i][0], s->maddr[i][1])) {
760 93f1e401 Edgar E. Iglesias
                        drop = 0;
761 93f1e401 Edgar E. Iglesias
                        break;
762 93f1e401 Edgar E. Iglesias
                    }
763 93f1e401 Edgar E. Iglesias
                }
764 93f1e401 Edgar E. Iglesias
765 93f1e401 Edgar E. Iglesias
                if (drop) {
766 93f1e401 Edgar E. Iglesias
                    return size;
767 93f1e401 Edgar E. Iglesias
                }
768 93f1e401 Edgar E. Iglesias
            }
769 93f1e401 Edgar E. Iglesias
        }
770 93f1e401 Edgar E. Iglesias
    }
771 93f1e401 Edgar E. Iglesias
772 93f1e401 Edgar E. Iglesias
    /* Extended mcast filtering enabled?  */
773 93f1e401 Edgar E. Iglesias
    if (axienet_newfunc_enabled(s) && axienet_extmcf_enabled(s)) {
774 93f1e401 Edgar E. Iglesias
        if (unicast) {
775 93f1e401 Edgar E. Iglesias
            if (!enet_match_addr(buf, s->ext_uaw[0], s->ext_uaw[1])) {
776 93f1e401 Edgar E. Iglesias
                return size;
777 93f1e401 Edgar E. Iglesias
            }
778 93f1e401 Edgar E. Iglesias
        } else {
779 93f1e401 Edgar E. Iglesias
            if (broadcast) {
780 93f1e401 Edgar E. Iglesias
                /* Broadcast. ???  */
781 93f1e401 Edgar E. Iglesias
                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
782 93f1e401 Edgar E. Iglesias
                    return size;
783 93f1e401 Edgar E. Iglesias
                }
784 93f1e401 Edgar E. Iglesias
            } else {
785 93f1e401 Edgar E. Iglesias
                int idx, bit;
786 93f1e401 Edgar E. Iglesias
787 93f1e401 Edgar E. Iglesias
                /* Multicast.  */
788 93f1e401 Edgar E. Iglesias
                if (!memcmp(buf, sa_ipmcast, 3)) {
789 93f1e401 Edgar E. Iglesias
                    return size;
790 93f1e401 Edgar E. Iglesias
                }
791 93f1e401 Edgar E. Iglesias
792 93f1e401 Edgar E. Iglesias
                idx  = (buf[4] & 0x7f) << 8;
793 93f1e401 Edgar E. Iglesias
                idx |= buf[5];
794 93f1e401 Edgar E. Iglesias
795 93f1e401 Edgar E. Iglesias
                bit = 1 << (idx & 0x1f);
796 93f1e401 Edgar E. Iglesias
                idx >>= 5;
797 93f1e401 Edgar E. Iglesias
798 93f1e401 Edgar E. Iglesias
                if (!(s->ext_mtable[idx] & bit)) {
799 93f1e401 Edgar E. Iglesias
                    return size;
800 93f1e401 Edgar E. Iglesias
                }
801 93f1e401 Edgar E. Iglesias
            }
802 93f1e401 Edgar E. Iglesias
        }
803 93f1e401 Edgar E. Iglesias
    }
804 93f1e401 Edgar E. Iglesias
805 93f1e401 Edgar E. Iglesias
    if (size < 12) {
806 93f1e401 Edgar E. Iglesias
        s->regs[R_IS] |= IS_RX_REJECT;
807 93f1e401 Edgar E. Iglesias
        enet_update_irq(s);
808 93f1e401 Edgar E. Iglesias
        return -1;
809 93f1e401 Edgar E. Iglesias
    }
810 93f1e401 Edgar E. Iglesias
811 93f1e401 Edgar E. Iglesias
    if (size > (s->c_rxmem - 4)) {
812 93f1e401 Edgar E. Iglesias
        size = s->c_rxmem - 4;
813 93f1e401 Edgar E. Iglesias
    }
814 93f1e401 Edgar E. Iglesias
815 93f1e401 Edgar E. Iglesias
    memcpy(s->rxmem, buf, size);
816 93f1e401 Edgar E. Iglesias
    memset(s->rxmem + size, 0, 4); /* Clear the FCS.  */
817 93f1e401 Edgar E. Iglesias
818 93f1e401 Edgar E. Iglesias
    if (s->rcw[1] & RCW1_FCS) {
819 93f1e401 Edgar E. Iglesias
        size += 4; /* fcs is inband.  */
820 93f1e401 Edgar E. Iglesias
    }
821 93f1e401 Edgar E. Iglesias
822 93f1e401 Edgar E. Iglesias
    app[0] = 5 << 28;
823 93f1e401 Edgar E. Iglesias
    csum32 = net_checksum_add(size - 14, (uint8_t *)s->rxmem + 14);
824 93f1e401 Edgar E. Iglesias
    /* Fold it once.  */
825 93f1e401 Edgar E. Iglesias
    csum32 = (csum32 & 0xffff) + (csum32 >> 16);
826 93f1e401 Edgar E. Iglesias
    /* And twice to get rid of possible carries.  */
827 93f1e401 Edgar E. Iglesias
    csum16 = (csum32 & 0xffff) + (csum32 >> 16);
828 93f1e401 Edgar E. Iglesias
    app[3] = csum16;
829 93f1e401 Edgar E. Iglesias
    app[4] = size & 0xffff;
830 93f1e401 Edgar E. Iglesias
831 93f1e401 Edgar E. Iglesias
    s->stats.rx_bytes += size;
832 93f1e401 Edgar E. Iglesias
    s->stats.rx++;
833 93f1e401 Edgar E. Iglesias
    if (multicast) {
834 93f1e401 Edgar E. Iglesias
        s->stats.rx_mcast++;
835 93f1e401 Edgar E. Iglesias
        app[2] |= 1 | (ip_multicast << 1);
836 93f1e401 Edgar E. Iglesias
    } else if (broadcast) {
837 93f1e401 Edgar E. Iglesias
        s->stats.rx_bcast++;
838 93f1e401 Edgar E. Iglesias
        app[2] |= 1 << 3;
839 93f1e401 Edgar E. Iglesias
    }
840 93f1e401 Edgar E. Iglesias
841 93f1e401 Edgar E. Iglesias
    /* Good frame.  */
842 93f1e401 Edgar E. Iglesias
    app[2] |= 1 << 6;
843 93f1e401 Edgar E. Iglesias
844 3630ae95 Peter Crosthwaite
    s->rxsize = size;
845 3630ae95 Peter Crosthwaite
    s->rxpos = 0;
846 42bb9c91 Peter Crosthwaite
    for (i = 0; i < ARRAY_SIZE(app); ++i) {
847 42bb9c91 Peter Crosthwaite
        app[i] = cpu_to_le32(app[i]);
848 42bb9c91 Peter Crosthwaite
    }
849 42bb9c91 Peter Crosthwaite
    s->rxappsize = CONTROL_PAYLOAD_SIZE;
850 42bb9c91 Peter Crosthwaite
    memcpy(s->rxapp, app, s->rxappsize);
851 3630ae95 Peter Crosthwaite
    axienet_eth_rx_notify(s);
852 93f1e401 Edgar E. Iglesias
853 93f1e401 Edgar E. Iglesias
    enet_update_irq(s);
854 93f1e401 Edgar E. Iglesias
    return size;
855 93f1e401 Edgar E. Iglesias
}
856 93f1e401 Edgar E. Iglesias
857 4e68f7a0 Stefan Hajnoczi
static void eth_cleanup(NetClientState *nc)
858 93f1e401 Edgar E. Iglesias
{
859 93f1e401 Edgar E. Iglesias
    /* FIXME.  */
860 545129e5 Peter Crosthwaite
    XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
861 7267c094 Anthony Liguori
    g_free(s->rxmem);
862 7267c094 Anthony Liguori
    g_free(s);
863 93f1e401 Edgar E. Iglesias
}
864 93f1e401 Edgar E. Iglesias
865 35e60bfd Peter Crosthwaite
static size_t
866 42bb9c91 Peter Crosthwaite
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
867 42bb9c91 Peter Crosthwaite
{
868 42bb9c91 Peter Crosthwaite
    int i;
869 42bb9c91 Peter Crosthwaite
    XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj);
870 42bb9c91 Peter Crosthwaite
    XilinxAXIEnet *s = cs->enet;
871 42bb9c91 Peter Crosthwaite
872 42bb9c91 Peter Crosthwaite
    if (len != CONTROL_PAYLOAD_SIZE) {
873 42bb9c91 Peter Crosthwaite
        hw_error("AXI Enet requires %d byte control stream payload\n",
874 42bb9c91 Peter Crosthwaite
                 (int)CONTROL_PAYLOAD_SIZE);
875 42bb9c91 Peter Crosthwaite
    }
876 42bb9c91 Peter Crosthwaite
877 42bb9c91 Peter Crosthwaite
    memcpy(s->hdr, buf, len);
878 42bb9c91 Peter Crosthwaite
879 42bb9c91 Peter Crosthwaite
    for (i = 0; i < ARRAY_SIZE(s->hdr); ++i) {
880 42bb9c91 Peter Crosthwaite
        s->hdr[i] = le32_to_cpu(s->hdr[i]);
881 42bb9c91 Peter Crosthwaite
    }
882 42bb9c91 Peter Crosthwaite
    return len;
883 42bb9c91 Peter Crosthwaite
}
884 42bb9c91 Peter Crosthwaite
885 42bb9c91 Peter Crosthwaite
static size_t
886 42bb9c91 Peter Crosthwaite
xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
887 93f1e401 Edgar E. Iglesias
{
888 55b3e0c2 Peter Crosthwaite
    XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
889 55b3e0c2 Peter Crosthwaite
    XilinxAXIEnet *s = ds->enet;
890 93f1e401 Edgar E. Iglesias
891 93f1e401 Edgar E. Iglesias
    /* TX enable ?  */
892 93f1e401 Edgar E. Iglesias
    if (!(s->tc & TC_TX)) {
893 35e60bfd Peter Crosthwaite
        return size;
894 93f1e401 Edgar E. Iglesias
    }
895 93f1e401 Edgar E. Iglesias
896 93f1e401 Edgar E. Iglesias
    /* Jumbo or vlan sizes ?  */
897 93f1e401 Edgar E. Iglesias
    if (!(s->tc & TC_JUM)) {
898 93f1e401 Edgar E. Iglesias
        if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) {
899 35e60bfd Peter Crosthwaite
            return size;
900 93f1e401 Edgar E. Iglesias
        }
901 93f1e401 Edgar E. Iglesias
    }
902 93f1e401 Edgar E. Iglesias
903 42bb9c91 Peter Crosthwaite
    if (s->hdr[0] & 1) {
904 42bb9c91 Peter Crosthwaite
        unsigned int start_off = s->hdr[1] >> 16;
905 42bb9c91 Peter Crosthwaite
        unsigned int write_off = s->hdr[1] & 0xffff;
906 93f1e401 Edgar E. Iglesias
        uint32_t tmp_csum;
907 93f1e401 Edgar E. Iglesias
        uint16_t csum;
908 93f1e401 Edgar E. Iglesias
909 93f1e401 Edgar E. Iglesias
        tmp_csum = net_checksum_add(size - start_off,
910 93f1e401 Edgar E. Iglesias
                                    (uint8_t *)buf + start_off);
911 93f1e401 Edgar E. Iglesias
        /* Accumulate the seed.  */
912 42bb9c91 Peter Crosthwaite
        tmp_csum += s->hdr[2] & 0xffff;
913 93f1e401 Edgar E. Iglesias
914 93f1e401 Edgar E. Iglesias
        /* Fold the 32bit partial checksum.  */
915 93f1e401 Edgar E. Iglesias
        csum = net_checksum_finish(tmp_csum);
916 93f1e401 Edgar E. Iglesias
917 93f1e401 Edgar E. Iglesias
        /* Writeback.  */
918 93f1e401 Edgar E. Iglesias
        buf[write_off] = csum >> 8;
919 93f1e401 Edgar E. Iglesias
        buf[write_off + 1] = csum & 0xff;
920 93f1e401 Edgar E. Iglesias
    }
921 93f1e401 Edgar E. Iglesias
922 b356f76d Jason Wang
    qemu_send_packet(qemu_get_queue(s->nic), buf, size);
923 93f1e401 Edgar E. Iglesias
924 93f1e401 Edgar E. Iglesias
    s->stats.tx_bytes += size;
925 93f1e401 Edgar E. Iglesias
    s->regs[R_IS] |= IS_TX_COMPLETE;
926 93f1e401 Edgar E. Iglesias
    enet_update_irq(s);
927 35e60bfd Peter Crosthwaite
928 35e60bfd Peter Crosthwaite
    return size;
929 93f1e401 Edgar E. Iglesias
}
930 93f1e401 Edgar E. Iglesias
931 93f1e401 Edgar E. Iglesias
static NetClientInfo net_xilinx_enet_info = {
932 2be64a68 Laszlo Ersek
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
933 93f1e401 Edgar E. Iglesias
    .size = sizeof(NICState),
934 93f1e401 Edgar E. Iglesias
    .can_receive = eth_can_rx,
935 93f1e401 Edgar E. Iglesias
    .receive = eth_rx,
936 93f1e401 Edgar E. Iglesias
    .cleanup = eth_cleanup,
937 93f1e401 Edgar E. Iglesias
};
938 93f1e401 Edgar E. Iglesias
939 b2d9dfe9 Peter Crosthwaite
static void xilinx_enet_realize(DeviceState *dev, Error **errp)
940 93f1e401 Edgar E. Iglesias
{
941 f0e7a81c Peter Crosthwaite
    XilinxAXIEnet *s = XILINX_AXI_ENET(dev);
942 55b3e0c2 Peter Crosthwaite
    XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(&s->rx_data_dev);
943 42bb9c91 Peter Crosthwaite
    XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(
944 42bb9c91 Peter Crosthwaite
                                                            &s->rx_control_dev);
945 55b3e0c2 Peter Crosthwaite
    Error *local_errp = NULL;
946 55b3e0c2 Peter Crosthwaite
947 55b3e0c2 Peter Crosthwaite
    object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
948 55b3e0c2 Peter Crosthwaite
                             (Object **) &ds->enet, &local_errp);
949 42bb9c91 Peter Crosthwaite
    object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
950 42bb9c91 Peter Crosthwaite
                             (Object **) &cs->enet, &local_errp);
951 55b3e0c2 Peter Crosthwaite
    if (local_errp) {
952 55b3e0c2 Peter Crosthwaite
        goto xilinx_enet_realize_fail;
953 55b3e0c2 Peter Crosthwaite
    }
954 55b3e0c2 Peter Crosthwaite
    object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_errp);
955 42bb9c91 Peter Crosthwaite
    object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_errp);
956 55b3e0c2 Peter Crosthwaite
    if (local_errp) {
957 55b3e0c2 Peter Crosthwaite
        goto xilinx_enet_realize_fail;
958 55b3e0c2 Peter Crosthwaite
    }
959 93f1e401 Edgar E. Iglesias
960 93f1e401 Edgar E. Iglesias
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
961 93f1e401 Edgar E. Iglesias
    s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
962 b2d9dfe9 Peter Crosthwaite
                          object_get_typename(OBJECT(dev)), dev->id, s);
963 b356f76d Jason Wang
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
964 93f1e401 Edgar E. Iglesias
965 93f1e401 Edgar E. Iglesias
    tdk_init(&s->TEMAC.phy);
966 93f1e401 Edgar E. Iglesias
    mdio_attach(&s->TEMAC.mdio_bus, &s->TEMAC.phy, s->c_phyaddr);
967 93f1e401 Edgar E. Iglesias
968 93f1e401 Edgar E. Iglesias
    s->TEMAC.parent = s;
969 93f1e401 Edgar E. Iglesias
970 7267c094 Anthony Liguori
    s->rxmem = g_malloc(s->c_rxmem);
971 55b3e0c2 Peter Crosthwaite
    return;
972 55b3e0c2 Peter Crosthwaite
973 55b3e0c2 Peter Crosthwaite
xilinx_enet_realize_fail:
974 55b3e0c2 Peter Crosthwaite
    if (!*errp) {
975 55b3e0c2 Peter Crosthwaite
        *errp = local_errp;
976 55b3e0c2 Peter Crosthwaite
    }
977 93f1e401 Edgar E. Iglesias
}
978 93f1e401 Edgar E. Iglesias
979 b2d9dfe9 Peter Crosthwaite
static void xilinx_enet_init(Object *obj)
980 669b4983 Peter A. G. Crosthwaite
{
981 f0e7a81c Peter Crosthwaite
    XilinxAXIEnet *s = XILINX_AXI_ENET(obj);
982 b2d9dfe9 Peter Crosthwaite
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
983 b15aaca4 Peter Crosthwaite
    Error *errp = NULL;
984 669b4983 Peter A. G. Crosthwaite
985 669b4983 Peter A. G. Crosthwaite
    object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE,
986 42bb9c91 Peter Crosthwaite
                             (Object **) &s->tx_data_dev, &errp);
987 42bb9c91 Peter Crosthwaite
    assert_no_error(errp);
988 42bb9c91 Peter Crosthwaite
    object_property_add_link(obj, "axistream-control-connected",
989 42bb9c91 Peter Crosthwaite
                             TYPE_STREAM_SLAVE,
990 42bb9c91 Peter Crosthwaite
                             (Object **) &s->tx_control_dev, &errp);
991 b15aaca4 Peter Crosthwaite
    assert_no_error(errp);
992 b2d9dfe9 Peter Crosthwaite
993 55b3e0c2 Peter Crosthwaite
    object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM);
994 42bb9c91 Peter Crosthwaite
    object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_ENET_CONTROL_STREAM);
995 55b3e0c2 Peter Crosthwaite
    object_property_add_child(OBJECT(s), "axistream-connected-target",
996 55b3e0c2 Peter Crosthwaite
                              (Object *)&s->rx_data_dev, &errp);
997 55b3e0c2 Peter Crosthwaite
    assert_no_error(errp);
998 42bb9c91 Peter Crosthwaite
    object_property_add_child(OBJECT(s), "axistream-control-connected-target",
999 42bb9c91 Peter Crosthwaite
                              (Object *)&s->rx_control_dev, &errp);
1000 42bb9c91 Peter Crosthwaite
    assert_no_error(errp);
1001 55b3e0c2 Peter Crosthwaite
1002 b2d9dfe9 Peter Crosthwaite
    sysbus_init_irq(sbd, &s->irq);
1003 b2d9dfe9 Peter Crosthwaite
1004 b2d9dfe9 Peter Crosthwaite
    memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000);
1005 b2d9dfe9 Peter Crosthwaite
    sysbus_init_mmio(sbd, &s->iomem);
1006 669b4983 Peter A. G. Crosthwaite
}
1007 669b4983 Peter A. G. Crosthwaite
1008 999e12bb Anthony Liguori
static Property xilinx_enet_properties[] = {
1009 545129e5 Peter Crosthwaite
    DEFINE_PROP_UINT32("phyaddr", XilinxAXIEnet, c_phyaddr, 7),
1010 545129e5 Peter Crosthwaite
    DEFINE_PROP_UINT32("rxmem", XilinxAXIEnet, c_rxmem, 0x1000),
1011 545129e5 Peter Crosthwaite
    DEFINE_PROP_UINT32("txmem", XilinxAXIEnet, c_txmem, 0x1000),
1012 545129e5 Peter Crosthwaite
    DEFINE_NIC_PROPERTIES(XilinxAXIEnet, conf),
1013 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1014 999e12bb Anthony Liguori
};
1015 999e12bb Anthony Liguori
1016 999e12bb Anthony Liguori
static void xilinx_enet_class_init(ObjectClass *klass, void *data)
1017 999e12bb Anthony Liguori
{
1018 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1019 999e12bb Anthony Liguori
1020 b2d9dfe9 Peter Crosthwaite
    dc->realize = xilinx_enet_realize;
1021 39bffca2 Anthony Liguori
    dc->props = xilinx_enet_properties;
1022 9ee0ceb7 Peter Crosthwaite
    dc->reset = xilinx_axienet_reset;
1023 55b3e0c2 Peter Crosthwaite
}
1024 55b3e0c2 Peter Crosthwaite
1025 55b3e0c2 Peter Crosthwaite
static void xilinx_enet_stream_class_init(ObjectClass *klass, void *data)
1026 55b3e0c2 Peter Crosthwaite
{
1027 55b3e0c2 Peter Crosthwaite
    StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
1028 55b3e0c2 Peter Crosthwaite
1029 55b3e0c2 Peter Crosthwaite
    ssc->push = data;
1030 999e12bb Anthony Liguori
}
1031 999e12bb Anthony Liguori
1032 8c43a6f0 Andreas Färber
static const TypeInfo xilinx_enet_info = {
1033 f0e7a81c Peter Crosthwaite
    .name          = TYPE_XILINX_AXI_ENET,
1034 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
1035 545129e5 Peter Crosthwaite
    .instance_size = sizeof(XilinxAXIEnet),
1036 39bffca2 Anthony Liguori
    .class_init    = xilinx_enet_class_init,
1037 b2d9dfe9 Peter Crosthwaite
    .instance_init = xilinx_enet_init,
1038 55b3e0c2 Peter Crosthwaite
};
1039 55b3e0c2 Peter Crosthwaite
1040 55b3e0c2 Peter Crosthwaite
static const TypeInfo xilinx_enet_data_stream_info = {
1041 55b3e0c2 Peter Crosthwaite
    .name          = TYPE_XILINX_AXI_ENET_DATA_STREAM,
1042 55b3e0c2 Peter Crosthwaite
    .parent        = TYPE_OBJECT,
1043 55b3e0c2 Peter Crosthwaite
    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
1044 55b3e0c2 Peter Crosthwaite
    .class_init    = xilinx_enet_stream_class_init,
1045 55b3e0c2 Peter Crosthwaite
    .class_data    = xilinx_axienet_data_stream_push,
1046 669b4983 Peter A. G. Crosthwaite
    .interfaces = (InterfaceInfo[]) {
1047 669b4983 Peter A. G. Crosthwaite
            { TYPE_STREAM_SLAVE },
1048 669b4983 Peter A. G. Crosthwaite
            { }
1049 669b4983 Peter A. G. Crosthwaite
    }
1050 93f1e401 Edgar E. Iglesias
};
1051 83f7d43a Andreas Färber
1052 42bb9c91 Peter Crosthwaite
static const TypeInfo xilinx_enet_control_stream_info = {
1053 42bb9c91 Peter Crosthwaite
    .name          = TYPE_XILINX_AXI_ENET_CONTROL_STREAM,
1054 42bb9c91 Peter Crosthwaite
    .parent        = TYPE_OBJECT,
1055 42bb9c91 Peter Crosthwaite
    .instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
1056 42bb9c91 Peter Crosthwaite
    .class_init    = xilinx_enet_stream_class_init,
1057 42bb9c91 Peter Crosthwaite
    .class_data    = xilinx_axienet_control_stream_push,
1058 42bb9c91 Peter Crosthwaite
    .interfaces = (InterfaceInfo[]) {
1059 42bb9c91 Peter Crosthwaite
            { TYPE_STREAM_SLAVE },
1060 42bb9c91 Peter Crosthwaite
            { }
1061 42bb9c91 Peter Crosthwaite
    }
1062 42bb9c91 Peter Crosthwaite
};
1063 42bb9c91 Peter Crosthwaite
1064 83f7d43a Andreas Färber
static void xilinx_enet_register_types(void)
1065 93f1e401 Edgar E. Iglesias
{
1066 39bffca2 Anthony Liguori
    type_register_static(&xilinx_enet_info);
1067 55b3e0c2 Peter Crosthwaite
    type_register_static(&xilinx_enet_data_stream_info);
1068 42bb9c91 Peter Crosthwaite
    type_register_static(&xilinx_enet_control_stream_info);
1069 93f1e401 Edgar E. Iglesias
}
1070 93f1e401 Edgar E. Iglesias
1071 83f7d43a Andreas Färber
type_init(xilinx_enet_register_types)