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