]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/net/imx_fec.c
qdev: set properties with device_class_set_props()
[thirdparty/qemu.git] / hw / net / imx_fec.c
CommitLineData
fcbd8018
JCD
1/*
2 * i.MX Fast Ethernet Controller emulation.
3 *
4 * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
5 *
6 * Based on Coldfire Fast Ethernet Controller emulation.
7 *
8 * Copyright (c) 2007 CodeSourcery.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
8ef94f0b 24#include "qemu/osdep.h"
64552b6b 25#include "hw/irq.h"
fcbd8018 26#include "hw/net/imx_fec.h"
a27bd6c7 27#include "hw/qdev-properties.h"
d6454270 28#include "migration/vmstate.h"
fcbd8018 29#include "sysemu/dma.h"
03dd024f 30#include "qemu/log.h"
0b8fa32f 31#include "qemu/module.h"
a699b410
JCD
32#include "net/checksum.h"
33#include "net/eth.h"
fcbd8018
JCD
34
35/* For crc32 */
36#include <zlib.h>
37
b72d8d25
JCD
38#ifndef DEBUG_IMX_FEC
39#define DEBUG_IMX_FEC 0
fcbd8018
JCD
40#endif
41
b72d8d25
JCD
42#define FEC_PRINTF(fmt, args...) \
43 do { \
44 if (DEBUG_IMX_FEC) { \
45 fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_FEC, \
46 __func__, ##args); \
47 } \
fcbd8018 48 } while (0)
b72d8d25
JCD
49
50#ifndef DEBUG_IMX_PHY
51#define DEBUG_IMX_PHY 0
fcbd8018
JCD
52#endif
53
b72d8d25
JCD
54#define PHY_PRINTF(fmt, args...) \
55 do { \
56 if (DEBUG_IMX_PHY) { \
57 fprintf(stderr, "[%s.phy]%s: " fmt , TYPE_IMX_FEC, \
58 __func__, ##args); \
59 } \
fcbd8018 60 } while (0)
fcbd8018 61
81f17e0d
PP
62#define IMX_MAX_DESC 1024
63
a699b410 64static const char *imx_default_reg_name(IMXFECState *s, uint32_t index)
db0de352
JCD
65{
66 static char tmp[20];
a699b410
JCD
67 sprintf(tmp, "index %d", index);
68 return tmp;
69}
70
71static const char *imx_fec_reg_name(IMXFECState *s, uint32_t index)
72{
73 switch (index) {
74 case ENET_FRBR:
75 return "FRBR";
76 case ENET_FRSR:
77 return "FRSR";
78 case ENET_MIIGSK_CFGR:
79 return "MIIGSK_CFGR";
80 case ENET_MIIGSK_ENR:
81 return "MIIGSK_ENR";
82 default:
83 return imx_default_reg_name(s, index);
84 }
85}
86
87static const char *imx_enet_reg_name(IMXFECState *s, uint32_t index)
88{
89 switch (index) {
90 case ENET_RSFL:
91 return "RSFL";
92 case ENET_RSEM:
93 return "RSEM";
94 case ENET_RAEM:
95 return "RAEM";
96 case ENET_RAFL:
97 return "RAFL";
98 case ENET_TSEM:
99 return "TSEM";
100 case ENET_TAEM:
101 return "TAEM";
102 case ENET_TAFL:
103 return "TAFL";
104 case ENET_TIPG:
105 return "TIPG";
106 case ENET_FTRL:
107 return "FTRL";
108 case ENET_TACC:
109 return "TACC";
110 case ENET_RACC:
111 return "RACC";
112 case ENET_ATCR:
113 return "ATCR";
114 case ENET_ATVR:
115 return "ATVR";
116 case ENET_ATOFF:
117 return "ATOFF";
118 case ENET_ATPER:
119 return "ATPER";
120 case ENET_ATCOR:
121 return "ATCOR";
122 case ENET_ATINC:
123 return "ATINC";
124 case ENET_ATSTMP:
125 return "ATSTMP";
126 case ENET_TGSR:
127 return "TGSR";
128 case ENET_TCSR0:
129 return "TCSR0";
130 case ENET_TCCR0:
131 return "TCCR0";
132 case ENET_TCSR1:
133 return "TCSR1";
134 case ENET_TCCR1:
135 return "TCCR1";
136 case ENET_TCSR2:
137 return "TCSR2";
138 case ENET_TCCR2:
139 return "TCCR2";
140 case ENET_TCSR3:
141 return "TCSR3";
142 case ENET_TCCR3:
143 return "TCCR3";
144 default:
145 return imx_default_reg_name(s, index);
146 }
147}
db0de352 148
a699b410
JCD
149static const char *imx_eth_reg_name(IMXFECState *s, uint32_t index)
150{
db0de352
JCD
151 switch (index) {
152 case ENET_EIR:
153 return "EIR";
154 case ENET_EIMR:
155 return "EIMR";
156 case ENET_RDAR:
157 return "RDAR";
158 case ENET_TDAR:
159 return "TDAR";
160 case ENET_ECR:
161 return "ECR";
162 case ENET_MMFR:
163 return "MMFR";
164 case ENET_MSCR:
165 return "MSCR";
166 case ENET_MIBC:
167 return "MIBC";
168 case ENET_RCR:
169 return "RCR";
170 case ENET_TCR:
171 return "TCR";
172 case ENET_PALR:
173 return "PALR";
174 case ENET_PAUR:
175 return "PAUR";
176 case ENET_OPD:
177 return "OPD";
178 case ENET_IAUR:
179 return "IAUR";
180 case ENET_IALR:
181 return "IALR";
182 case ENET_GAUR:
183 return "GAUR";
184 case ENET_GALR:
185 return "GALR";
186 case ENET_TFWR:
187 return "TFWR";
188 case ENET_RDSR:
189 return "RDSR";
190 case ENET_TDSR:
191 return "TDSR";
192 case ENET_MRBR:
193 return "MRBR";
db0de352 194 default:
a699b410
JCD
195 if (s->is_fec) {
196 return imx_fec_reg_name(s, index);
197 } else {
198 return imx_enet_reg_name(s, index);
199 }
db0de352
JCD
200 }
201}
202
f93f961c
AS
203/*
204 * Versions of this device with more than one TX descriptor save the
205 * 2nd and 3rd descriptors in a subsection, to maintain migration
206 * compatibility with previous versions of the device that only
207 * supported a single descriptor.
208 */
209static bool imx_eth_is_multi_tx_ring(void *opaque)
210{
211 IMXFECState *s = IMX_FEC(opaque);
212
213 return s->tx_ring_num > 1;
214}
215
216static const VMStateDescription vmstate_imx_eth_txdescs = {
217 .name = "imx.fec/txdescs",
218 .version_id = 1,
219 .minimum_version_id = 1,
220 .needed = imx_eth_is_multi_tx_ring,
221 .fields = (VMStateField[]) {
222 VMSTATE_UINT32(tx_descriptor[1], IMXFECState),
223 VMSTATE_UINT32(tx_descriptor[2], IMXFECState),
224 VMSTATE_END_OF_LIST()
225 }
226};
227
a699b410 228static const VMStateDescription vmstate_imx_eth = {
fcbd8018 229 .name = TYPE_IMX_FEC,
db0de352
JCD
230 .version_id = 2,
231 .minimum_version_id = 2,
fcbd8018 232 .fields = (VMStateField[]) {
db0de352 233 VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
fcbd8018 234 VMSTATE_UINT32(rx_descriptor, IMXFECState),
f93f961c 235 VMSTATE_UINT32(tx_descriptor[0], IMXFECState),
fcbd8018
JCD
236 VMSTATE_UINT32(phy_status, IMXFECState),
237 VMSTATE_UINT32(phy_control, IMXFECState),
238 VMSTATE_UINT32(phy_advertise, IMXFECState),
239 VMSTATE_UINT32(phy_int, IMXFECState),
240 VMSTATE_UINT32(phy_int_mask, IMXFECState),
241 VMSTATE_END_OF_LIST()
f93f961c
AS
242 },
243 .subsections = (const VMStateDescription * []) {
244 &vmstate_imx_eth_txdescs,
245 NULL
246 },
fcbd8018
JCD
247};
248
249#define PHY_INT_ENERGYON (1 << 7)
250#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
251#define PHY_INT_FAULT (1 << 5)
252#define PHY_INT_DOWN (1 << 4)
253#define PHY_INT_AUTONEG_LP (1 << 3)
254#define PHY_INT_PARFAULT (1 << 2)
255#define PHY_INT_AUTONEG_PAGE (1 << 1)
256
a699b410 257static void imx_eth_update(IMXFECState *s);
fcbd8018
JCD
258
259/*
260 * The MII phy could raise a GPIO to the processor which in turn
261 * could be handled as an interrpt by the OS.
262 * For now we don't handle any GPIO/interrupt line, so the OS will
263 * have to poll for the PHY status.
264 */
265static void phy_update_irq(IMXFECState *s)
266{
a699b410 267 imx_eth_update(s);
fcbd8018
JCD
268}
269
270static void phy_update_link(IMXFECState *s)
271{
272 /* Autonegotiation status mirrors link status. */
273 if (qemu_get_queue(s->nic)->link_down) {
274 PHY_PRINTF("link is down\n");
275 s->phy_status &= ~0x0024;
276 s->phy_int |= PHY_INT_DOWN;
277 } else {
278 PHY_PRINTF("link is up\n");
279 s->phy_status |= 0x0024;
280 s->phy_int |= PHY_INT_ENERGYON;
281 s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
282 }
283 phy_update_irq(s);
284}
285
a699b410 286static void imx_eth_set_link(NetClientState *nc)
fcbd8018
JCD
287{
288 phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
289}
290
291static void phy_reset(IMXFECState *s)
292{
293 s->phy_status = 0x7809;
294 s->phy_control = 0x3000;
295 s->phy_advertise = 0x01e1;
296 s->phy_int_mask = 0;
297 s->phy_int = 0;
298 phy_update_link(s);
299}
300
301static uint32_t do_phy_read(IMXFECState *s, int reg)
302{
303 uint32_t val;
304
305 if (reg > 31) {
306 /* we only advertise one phy */
307 return 0;
308 }
309
310 switch (reg) {
311 case 0: /* Basic Control */
312 val = s->phy_control;
313 break;
314 case 1: /* Basic Status */
315 val = s->phy_status;
316 break;
317 case 2: /* ID1 */
318 val = 0x0007;
319 break;
320 case 3: /* ID2 */
321 val = 0xc0d1;
322 break;
323 case 4: /* Auto-neg advertisement */
324 val = s->phy_advertise;
325 break;
326 case 5: /* Auto-neg Link Partner Ability */
327 val = 0x0f71;
328 break;
329 case 6: /* Auto-neg Expansion */
330 val = 1;
331 break;
332 case 29: /* Interrupt source. */
333 val = s->phy_int;
334 s->phy_int = 0;
335 phy_update_irq(s);
336 break;
337 case 30: /* Interrupt mask */
338 val = s->phy_int_mask;
339 break;
340 case 17:
341 case 18:
342 case 27:
343 case 31:
b72d8d25 344 qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
fcbd8018
JCD
345 TYPE_IMX_FEC, __func__, reg);
346 val = 0;
347 break;
348 default:
b72d8d25 349 qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
fcbd8018
JCD
350 TYPE_IMX_FEC, __func__, reg);
351 val = 0;
352 break;
353 }
354
355 PHY_PRINTF("read 0x%04x @ %d\n", val, reg);
356
357 return val;
358}
359
360static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
361{
362 PHY_PRINTF("write 0x%04x @ %d\n", val, reg);
363
364 if (reg > 31) {
365 /* we only advertise one phy */
366 return;
367 }
368
369 switch (reg) {
370 case 0: /* Basic Control */
371 if (val & 0x8000) {
372 phy_reset(s);
373 } else {
374 s->phy_control = val & 0x7980;
375 /* Complete autonegotiation immediately. */
376 if (val & 0x1000) {
377 s->phy_status |= 0x0020;
378 }
379 }
380 break;
381 case 4: /* Auto-neg advertisement */
382 s->phy_advertise = (val & 0x2d7f) | 0x80;
383 break;
384 case 30: /* Interrupt mask */
385 s->phy_int_mask = val & 0xff;
386 phy_update_irq(s);
387 break;
388 case 17:
389 case 18:
390 case 27:
391 case 31:
b72d8d25 392 qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
fcbd8018
JCD
393 TYPE_IMX_FEC, __func__, reg);
394 break;
395 default:
b72d8d25 396 qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
fcbd8018
JCD
397 TYPE_IMX_FEC, __func__, reg);
398 break;
399 }
400}
401
402static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
403{
404 dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
405}
406
407static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
408{
409 dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
410}
411
a699b410
JCD
412static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr)
413{
414 dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
415}
416
417static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
fcbd8018 418{
a699b410
JCD
419 dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
420}
421
422static void imx_eth_update(IMXFECState *s)
423{
6461d7e2
GR
424 /*
425 * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER
426 * interrupts swapped. This worked with older versions of Linux (4.14
427 * and older) since Linux associated both interrupt lines with Ethernet
428 * MAC interrupts. Specifically,
429 * - Linux 4.15 and later have separate interrupt handlers for the MAC and
430 * timer interrupts. Those versions of Linux fail with versions of QEMU
431 * with swapped interrupt assignments.
432 * - In linux 4.14, both interrupt lines were registered with the Ethernet
433 * MAC interrupt handler. As a result, all versions of qemu happen to
434 * work, though that is accidental.
435 * - In Linux 4.9 and older, the timer interrupt was registered directly
436 * with the Ethernet MAC interrupt handler. The MAC interrupt was
437 * redirected to a GPIO interrupt to work around erratum ERR006687.
438 * This was implemented using the SOC's IOMUX block. In qemu, this GPIO
439 * interrupt never fired since IOMUX is currently not supported in qemu.
440 * Linux instead received MAC interrupts on the timer interrupt.
441 * As a result, qemu versions with the swapped interrupt assignment work,
442 * albeit accidentally, but qemu versions with the correct interrupt
443 * assignment fail.
444 *
445 * To ensure that all versions of Linux work, generate ENET_INT_MAC
446 * interrrupts on both interrupt lines. This should be changed if and when
447 * qemu supports IOMUX.
448 */
449 if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] &
450 (ENET_INT_MAC | ENET_INT_TS_TIMER)) {
a699b410
JCD
451 qemu_set_irq(s->irq[1], 1);
452 } else {
453 qemu_set_irq(s->irq[1], 0);
454 }
455
456 if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_MAC) {
457 qemu_set_irq(s->irq[0], 1);
db0de352 458 } else {
a699b410 459 qemu_set_irq(s->irq[0], 0);
fcbd8018 460 }
fcbd8018
JCD
461}
462
463static void imx_fec_do_tx(IMXFECState *s)
464{
81f17e0d 465 int frame_size = 0, descnt = 0;
7bac20dc 466 uint8_t *ptr = s->frame;
f93f961c 467 uint32_t addr = s->tx_descriptor[0];
fcbd8018 468
81f17e0d 469 while (descnt++ < IMX_MAX_DESC) {
fcbd8018
JCD
470 IMXFECBufDesc bd;
471 int len;
472
473 imx_fec_read_bd(&bd, addr);
474 FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n",
475 addr, bd.flags, bd.length, bd.data);
1bb3c371 476 if ((bd.flags & ENET_BD_R) == 0) {
fcbd8018 477 /* Run out of descriptors to transmit. */
a699b410 478 FEC_PRINTF("tx_bd ran out of descriptors to transmit\n");
fcbd8018
JCD
479 break;
480 }
481 len = bd.length;
1bb3c371
JCD
482 if (frame_size + len > ENET_MAX_FRAME_SIZE) {
483 len = ENET_MAX_FRAME_SIZE - frame_size;
db0de352 484 s->regs[ENET_EIR] |= ENET_INT_BABT;
fcbd8018
JCD
485 }
486 dma_memory_read(&address_space_memory, bd.data, ptr, len);
487 ptr += len;
488 frame_size += len;
1bb3c371 489 if (bd.flags & ENET_BD_L) {
fcbd8018 490 /* Last buffer in frame. */
7bac20dc
AS
491 qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
492 ptr = s->frame;
fcbd8018 493 frame_size = 0;
db0de352 494 s->regs[ENET_EIR] |= ENET_INT_TXF;
fcbd8018 495 }
db0de352 496 s->regs[ENET_EIR] |= ENET_INT_TXB;
1bb3c371 497 bd.flags &= ~ENET_BD_R;
fcbd8018
JCD
498 /* Write back the modified descriptor. */
499 imx_fec_write_bd(&bd, addr);
500 /* Advance to the next descriptor. */
1bb3c371 501 if ((bd.flags & ENET_BD_W) != 0) {
db0de352 502 addr = s->regs[ENET_TDSR];
fcbd8018 503 } else {
db0de352 504 addr += sizeof(bd);
fcbd8018
JCD
505 }
506 }
507
f93f961c 508 s->tx_descriptor[0] = addr;
fcbd8018 509
a699b410
JCD
510 imx_eth_update(s);
511}
512
f93f961c 513static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
a699b410 514{
81f17e0d 515 int frame_size = 0, descnt = 0;
f93f961c 516
7bac20dc 517 uint8_t *ptr = s->frame;
f93f961c
AS
518 uint32_t addr, int_txb, int_txf, tdsr;
519 size_t ring;
520
521 switch (index) {
522 case ENET_TDAR:
523 ring = 0;
524 int_txb = ENET_INT_TXB;
525 int_txf = ENET_INT_TXF;
526 tdsr = ENET_TDSR;
527 break;
528 case ENET_TDAR1:
529 ring = 1;
530 int_txb = ENET_INT_TXB1;
531 int_txf = ENET_INT_TXF1;
532 tdsr = ENET_TDSR1;
533 break;
534 case ENET_TDAR2:
535 ring = 2;
536 int_txb = ENET_INT_TXB2;
537 int_txf = ENET_INT_TXF2;
538 tdsr = ENET_TDSR2;
539 break;
540 default:
541 qemu_log_mask(LOG_GUEST_ERROR,
542 "%s: bogus value for index %x\n",
543 __func__, index);
544 abort();
545 break;
546 }
547
548 addr = s->tx_descriptor[ring];
a699b410 549
81f17e0d 550 while (descnt++ < IMX_MAX_DESC) {
a699b410
JCD
551 IMXENETBufDesc bd;
552 int len;
553
554 imx_enet_read_bd(&bd, addr);
555 FEC_PRINTF("tx_bd %x flags %04x len %d data %08x option %04x "
556 "status %04x\n", addr, bd.flags, bd.length, bd.data,
557 bd.option, bd.status);
558 if ((bd.flags & ENET_BD_R) == 0) {
559 /* Run out of descriptors to transmit. */
560 break;
561 }
562 len = bd.length;
563 if (frame_size + len > ENET_MAX_FRAME_SIZE) {
564 len = ENET_MAX_FRAME_SIZE - frame_size;
565 s->regs[ENET_EIR] |= ENET_INT_BABT;
566 }
567 dma_memory_read(&address_space_memory, bd.data, ptr, len);
568 ptr += len;
569 frame_size += len;
570 if (bd.flags & ENET_BD_L) {
571 if (bd.option & ENET_BD_PINS) {
7bac20dc 572 struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
a699b410 573 if (IP_HEADER_VERSION(ip_hd) == 4) {
7bac20dc 574 net_checksum_calculate(s->frame, frame_size);
a699b410
JCD
575 }
576 }
577 if (bd.option & ENET_BD_IINS) {
7bac20dc 578 struct ip_header *ip_hd = PKT_GET_IP_HDR(s->frame);
a699b410
JCD
579 /* We compute checksum only for IPv4 frames */
580 if (IP_HEADER_VERSION(ip_hd) == 4) {
581 uint16_t csum;
582 ip_hd->ip_sum = 0;
583 csum = net_raw_checksum((uint8_t *)ip_hd, sizeof(*ip_hd));
584 ip_hd->ip_sum = cpu_to_be16(csum);
585 }
586 }
587 /* Last buffer in frame. */
7bac20dc 588
52cfd584 589 qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
7bac20dc
AS
590 ptr = s->frame;
591
a699b410
JCD
592 frame_size = 0;
593 if (bd.option & ENET_BD_TX_INT) {
f93f961c 594 s->regs[ENET_EIR] |= int_txf;
a699b410 595 }
88e1b59e
AH
596 /* Indicate that we've updated the last buffer descriptor. */
597 bd.last_buffer = ENET_BD_BDU;
a699b410
JCD
598 }
599 if (bd.option & ENET_BD_TX_INT) {
f93f961c 600 s->regs[ENET_EIR] |= int_txb;
a699b410
JCD
601 }
602 bd.flags &= ~ENET_BD_R;
603 /* Write back the modified descriptor. */
604 imx_enet_write_bd(&bd, addr);
605 /* Advance to the next descriptor. */
606 if ((bd.flags & ENET_BD_W) != 0) {
f93f961c 607 addr = s->regs[tdsr];
a699b410
JCD
608 } else {
609 addr += sizeof(bd);
610 }
611 }
612
f93f961c 613 s->tx_descriptor[ring] = addr;
a699b410
JCD
614
615 imx_eth_update(s);
616}
617
f93f961c 618static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
a699b410
JCD
619{
620 if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
f93f961c 621 imx_enet_do_tx(s, index);
a699b410
JCD
622 } else {
623 imx_fec_do_tx(s);
624 }
fcbd8018
JCD
625}
626
b2b012af 627static void imx_eth_enable_rx(IMXFECState *s, bool flush)
fcbd8018
JCD
628{
629 IMXFECBufDesc bd;
fcbd8018
JCD
630
631 imx_fec_read_bd(&bd, s->rx_descriptor);
632
1b58d58f 633 s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0;
fcbd8018 634
1b58d58f 635 if (!s->regs[ENET_RDAR]) {
fcbd8018 636 FEC_PRINTF("RX buffer full\n");
b2b012af 637 } else if (flush) {
fcbd8018
JCD
638 qemu_flush_queued_packets(qemu_get_queue(s->nic));
639 }
fcbd8018
JCD
640}
641
a699b410 642static void imx_eth_reset(DeviceState *d)
fcbd8018
JCD
643{
644 IMXFECState *s = IMX_FEC(d);
645
a699b410 646 /* Reset the Device */
db0de352
JCD
647 memset(s->regs, 0, sizeof(s->regs));
648 s->regs[ENET_ECR] = 0xf0000000;
649 s->regs[ENET_MIBC] = 0xc0000000;
650 s->regs[ENET_RCR] = 0x05ee0001;
651 s->regs[ENET_OPD] = 0x00010000;
652
653 s->regs[ENET_PALR] = (s->conf.macaddr.a[0] << 24)
654 | (s->conf.macaddr.a[1] << 16)
655 | (s->conf.macaddr.a[2] << 8)
656 | s->conf.macaddr.a[3];
657 s->regs[ENET_PAUR] = (s->conf.macaddr.a[4] << 24)
658 | (s->conf.macaddr.a[5] << 16)
659 | 0x8808;
660
a699b410
JCD
661 if (s->is_fec) {
662 s->regs[ENET_FRBR] = 0x00000600;
663 s->regs[ENET_FRSR] = 0x00000500;
664 s->regs[ENET_MIIGSK_ENR] = 0x00000006;
665 } else {
666 s->regs[ENET_RAEM] = 0x00000004;
667 s->regs[ENET_RAFL] = 0x00000004;
668 s->regs[ENET_TAEM] = 0x00000004;
669 s->regs[ENET_TAFL] = 0x00000008;
670 s->regs[ENET_TIPG] = 0x0000000c;
671 s->regs[ENET_FTRL] = 0x000007ff;
672 s->regs[ENET_ATPER] = 0x3b9aca00;
673 }
db0de352
JCD
674
675 s->rx_descriptor = 0;
f93f961c 676 memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
fcbd8018
JCD
677
678 /* We also reset the PHY */
679 phy_reset(s);
680}
681
a699b410
JCD
682static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
683{
684 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
685 PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4);
686 return 0;
687}
688
689static uint32_t imx_fec_read(IMXFECState *s, uint32_t index)
690{
691 switch (index) {
692 case ENET_FRBR:
693 case ENET_FRSR:
694 case ENET_MIIGSK_CFGR:
695 case ENET_MIIGSK_ENR:
696 return s->regs[index];
697 default:
698 return imx_default_read(s, index);
699 }
700}
701
702static uint32_t imx_enet_read(IMXFECState *s, uint32_t index)
703{
704 switch (index) {
705 case ENET_RSFL:
706 case ENET_RSEM:
707 case ENET_RAEM:
708 case ENET_RAFL:
709 case ENET_TSEM:
710 case ENET_TAEM:
711 case ENET_TAFL:
712 case ENET_TIPG:
713 case ENET_FTRL:
714 case ENET_TACC:
715 case ENET_RACC:
716 case ENET_ATCR:
717 case ENET_ATVR:
718 case ENET_ATOFF:
719 case ENET_ATPER:
720 case ENET_ATCOR:
721 case ENET_ATINC:
722 case ENET_ATSTMP:
723 case ENET_TGSR:
724 case ENET_TCSR0:
725 case ENET_TCCR0:
726 case ENET_TCSR1:
727 case ENET_TCCR1:
728 case ENET_TCSR2:
729 case ENET_TCCR2:
730 case ENET_TCSR3:
731 case ENET_TCCR3:
732 return s->regs[index];
733 default:
734 return imx_default_read(s, index);
735 }
736}
737
738static uint64_t imx_eth_read(void *opaque, hwaddr offset, unsigned size)
fcbd8018 739{
db0de352 740 uint32_t value = 0;
fcbd8018 741 IMXFECState *s = IMX_FEC(opaque);
a699b410 742 uint32_t index = offset >> 2;
db0de352
JCD
743
744 switch (index) {
745 case ENET_EIR:
746 case ENET_EIMR:
747 case ENET_RDAR:
748 case ENET_TDAR:
749 case ENET_ECR:
750 case ENET_MMFR:
751 case ENET_MSCR:
752 case ENET_MIBC:
753 case ENET_RCR:
754 case ENET_TCR:
755 case ENET_PALR:
756 case ENET_PAUR:
757 case ENET_OPD:
758 case ENET_IAUR:
759 case ENET_IALR:
760 case ENET_GAUR:
761 case ENET_GALR:
762 case ENET_TFWR:
763 case ENET_RDSR:
764 case ENET_TDSR:
765 case ENET_MRBR:
db0de352
JCD
766 value = s->regs[index];
767 break;
fcbd8018 768 default:
a699b410
JCD
769 if (s->is_fec) {
770 value = imx_fec_read(s, index);
771 } else {
772 value = imx_enet_read(s, index);
773 }
db0de352 774 break;
fcbd8018 775 }
db0de352 776
a699b410 777 FEC_PRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
db0de352
JCD
778 value);
779
780 return value;
fcbd8018
JCD
781}
782
a699b410
JCD
783static void imx_default_write(IMXFECState *s, uint32_t index, uint32_t value)
784{
785 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
786 PRIx32 "\n", TYPE_IMX_FEC, __func__, index * 4);
787 return;
788}
789
790static void imx_fec_write(IMXFECState *s, uint32_t index, uint32_t value)
791{
792 switch (index) {
793 case ENET_FRBR:
794 /* FRBR is read only */
795 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Register FRBR is read only\n",
796 TYPE_IMX_FEC, __func__);
797 break;
798 case ENET_FRSR:
799 s->regs[index] = (value & 0x000003fc) | 0x00000400;
800 break;
801 case ENET_MIIGSK_CFGR:
802 s->regs[index] = value & 0x00000053;
803 break;
804 case ENET_MIIGSK_ENR:
805 s->regs[index] = (value & 0x00000002) ? 0x00000006 : 0;
806 break;
807 default:
808 imx_default_write(s, index, value);
809 break;
810 }
811}
812
813static void imx_enet_write(IMXFECState *s, uint32_t index, uint32_t value)
814{
815 switch (index) {
816 case ENET_RSFL:
817 case ENET_RSEM:
818 case ENET_RAEM:
819 case ENET_RAFL:
820 case ENET_TSEM:
821 case ENET_TAEM:
822 case ENET_TAFL:
823 s->regs[index] = value & 0x000001ff;
824 break;
825 case ENET_TIPG:
826 s->regs[index] = value & 0x0000001f;
827 break;
828 case ENET_FTRL:
829 s->regs[index] = value & 0x00003fff;
830 break;
831 case ENET_TACC:
832 s->regs[index] = value & 0x00000019;
833 break;
834 case ENET_RACC:
835 s->regs[index] = value & 0x000000C7;
836 break;
837 case ENET_ATCR:
838 s->regs[index] = value & 0x00002a9d;
839 break;
840 case ENET_ATVR:
841 case ENET_ATOFF:
842 case ENET_ATPER:
843 s->regs[index] = value;
844 break;
845 case ENET_ATSTMP:
846 /* ATSTMP is read only */
847 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Register ATSTMP is read only\n",
848 TYPE_IMX_FEC, __func__);
849 break;
850 case ENET_ATCOR:
851 s->regs[index] = value & 0x7fffffff;
852 break;
853 case ENET_ATINC:
854 s->regs[index] = value & 0x00007f7f;
855 break;
856 case ENET_TGSR:
857 /* implement clear timer flag */
858 value = value & 0x0000000f;
859 break;
860 case ENET_TCSR0:
861 case ENET_TCSR1:
862 case ENET_TCSR2:
863 case ENET_TCSR3:
864 value = value & 0x000000fd;
865 break;
866 case ENET_TCCR0:
867 case ENET_TCCR1:
868 case ENET_TCCR2:
869 case ENET_TCCR3:
870 s->regs[index] = value;
871 break;
872 default:
873 imx_default_write(s, index, value);
874 break;
875 }
876}
877
878static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
879 unsigned size)
fcbd8018
JCD
880{
881 IMXFECState *s = IMX_FEC(opaque);
f93f961c 882 const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s);
a699b410 883 uint32_t index = offset >> 2;
fcbd8018 884
a699b410
JCD
885 FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
886 (uint32_t)value);
fcbd8018 887
db0de352
JCD
888 switch (index) {
889 case ENET_EIR:
890 s->regs[index] &= ~value;
fcbd8018 891 break;
db0de352
JCD
892 case ENET_EIMR:
893 s->regs[index] = value;
fcbd8018 894 break;
db0de352
JCD
895 case ENET_RDAR:
896 if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
897 if (!s->regs[index]) {
b2b012af 898 imx_eth_enable_rx(s, true);
db0de352
JCD
899 }
900 } else {
901 s->regs[index] = 0;
fcbd8018
JCD
902 }
903 break;
7c45c1d3
PMD
904 case ENET_TDAR1:
905 case ENET_TDAR2:
f93f961c
AS
906 if (unlikely(single_tx_ring)) {
907 qemu_log_mask(LOG_GUEST_ERROR,
908 "[%s]%s: trying to access TDAR2 or TDAR1\n",
909 TYPE_IMX_FEC, __func__);
910 return;
911 }
174c556c
PMD
912 /* fall through */
913 case ENET_TDAR:
db0de352
JCD
914 if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
915 s->regs[index] = ENET_TDAR_TDAR;
f93f961c 916 imx_eth_do_tx(s, index);
fcbd8018 917 }
db0de352 918 s->regs[index] = 0;
fcbd8018 919 break;
db0de352 920 case ENET_ECR:
1bb3c371 921 if (value & ENET_ECR_RESET) {
a699b410 922 return imx_eth_reset(DEVICE(s));
fcbd8018 923 }
db0de352
JCD
924 s->regs[index] = value;
925 if ((s->regs[index] & ENET_ECR_ETHEREN) == 0) {
926 s->regs[ENET_RDAR] = 0;
927 s->rx_descriptor = s->regs[ENET_RDSR];
f93f961c
AS
928 s->regs[ENET_TDAR] = 0;
929 s->regs[ENET_TDAR1] = 0;
930 s->regs[ENET_TDAR2] = 0;
931 s->tx_descriptor[0] = s->regs[ENET_TDSR];
932 s->tx_descriptor[1] = s->regs[ENET_TDSR1];
933 s->tx_descriptor[2] = s->regs[ENET_TDSR2];
fcbd8018
JCD
934 }
935 break;
db0de352
JCD
936 case ENET_MMFR:
937 s->regs[index] = value;
4816dc16 938 if (extract32(value, 29, 1)) {
db0de352
JCD
939 /* This is a read operation */
940 s->regs[ENET_MMFR] = deposit32(s->regs[ENET_MMFR], 0, 16,
941 do_phy_read(s,
942 extract32(value,
943 18, 10)));
4816dc16 944 } else {
db0de352 945 /* This a write operation */
b413643a 946 do_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16));
fcbd8018
JCD
947 }
948 /* raise the interrupt as the PHY operation is done */
db0de352 949 s->regs[ENET_EIR] |= ENET_INT_MII;
fcbd8018 950 break;
db0de352
JCD
951 case ENET_MSCR:
952 s->regs[index] = value & 0xfe;
fcbd8018 953 break;
db0de352 954 case ENET_MIBC:
fcbd8018 955 /* TODO: Implement MIB. */
db0de352 956 s->regs[index] = (value & 0x80000000) ? 0xc0000000 : 0;
fcbd8018 957 break;
db0de352
JCD
958 case ENET_RCR:
959 s->regs[index] = value & 0x07ff003f;
fcbd8018
JCD
960 /* TODO: Implement LOOP mode. */
961 break;
db0de352 962 case ENET_TCR:
fcbd8018 963 /* We transmit immediately, so raise GRA immediately. */
db0de352 964 s->regs[index] = value;
fcbd8018 965 if (value & 1) {
db0de352 966 s->regs[ENET_EIR] |= ENET_INT_GRA;
fcbd8018
JCD
967 }
968 break;
db0de352
JCD
969 case ENET_PALR:
970 s->regs[index] = value;
fcbd8018
JCD
971 s->conf.macaddr.a[0] = value >> 24;
972 s->conf.macaddr.a[1] = value >> 16;
973 s->conf.macaddr.a[2] = value >> 8;
974 s->conf.macaddr.a[3] = value;
975 break;
db0de352
JCD
976 case ENET_PAUR:
977 s->regs[index] = (value | 0x0000ffff) & 0xffff8808;
fcbd8018
JCD
978 s->conf.macaddr.a[4] = value >> 24;
979 s->conf.macaddr.a[5] = value >> 16;
980 break;
db0de352
JCD
981 case ENET_OPD:
982 s->regs[index] = (value & 0x0000ffff) | 0x00010000;
fcbd8018 983 break;
db0de352
JCD
984 case ENET_IAUR:
985 case ENET_IALR:
986 case ENET_GAUR:
987 case ENET_GALR:
fcbd8018
JCD
988 /* TODO: implement MAC hash filtering. */
989 break;
db0de352 990 case ENET_TFWR:
a699b410
JCD
991 if (s->is_fec) {
992 s->regs[index] = value & 0x3;
993 } else {
994 s->regs[index] = value & 0x13f;
995 }
fcbd8018 996 break;
db0de352 997 case ENET_RDSR:
a699b410
JCD
998 if (s->is_fec) {
999 s->regs[index] = value & ~3;
1000 } else {
1001 s->regs[index] = value & ~7;
1002 }
db0de352 1003 s->rx_descriptor = s->regs[index];
fcbd8018 1004 break;
db0de352 1005 case ENET_TDSR:
a699b410
JCD
1006 if (s->is_fec) {
1007 s->regs[index] = value & ~3;
1008 } else {
1009 s->regs[index] = value & ~7;
1010 }
f93f961c
AS
1011 s->tx_descriptor[0] = s->regs[index];
1012 break;
1013 case ENET_TDSR1:
1014 if (unlikely(single_tx_ring)) {
1015 qemu_log_mask(LOG_GUEST_ERROR,
1016 "[%s]%s: trying to access TDSR1\n",
1017 TYPE_IMX_FEC, __func__);
1018 return;
1019 }
1020
1021 s->regs[index] = value & ~7;
1022 s->tx_descriptor[1] = s->regs[index];
1023 break;
1024 case ENET_TDSR2:
1025 if (unlikely(single_tx_ring)) {
1026 qemu_log_mask(LOG_GUEST_ERROR,
1027 "[%s]%s: trying to access TDSR2\n",
1028 TYPE_IMX_FEC, __func__);
1029 return;
1030 }
1031
1032 s->regs[index] = value & ~7;
1033 s->tx_descriptor[2] = s->regs[index];
fcbd8018 1034 break;
db0de352 1035 case ENET_MRBR:
a699b410 1036 s->regs[index] = value & 0x00003ff0;
fcbd8018
JCD
1037 break;
1038 default:
a699b410
JCD
1039 if (s->is_fec) {
1040 imx_fec_write(s, index, value);
1041 } else {
1042 imx_enet_write(s, index, value);
1043 }
1044 return;
fcbd8018
JCD
1045 }
1046
a699b410 1047 imx_eth_update(s);
fcbd8018
JCD
1048}
1049
a699b410 1050static int imx_eth_can_receive(NetClientState *nc)
fcbd8018
JCD
1051{
1052 IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
1053
a699b410
JCD
1054 FEC_PRINTF("\n");
1055
b2b012af 1056 return !!s->regs[ENET_RDAR];
fcbd8018
JCD
1057}
1058
1059static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
1060 size_t len)
1061{
1062 IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
1063 IMXFECBufDesc bd;
1064 uint32_t flags = 0;
1065 uint32_t addr;
1066 uint32_t crc;
1067 uint32_t buf_addr;
1068 uint8_t *crc_ptr;
1069 unsigned int buf_len;
1070 size_t size = len;
1071
1072 FEC_PRINTF("len %d\n", (int)size);
1073
db0de352 1074 if (!s->regs[ENET_RDAR]) {
b72d8d25 1075 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
fcbd8018
JCD
1076 TYPE_IMX_FEC, __func__);
1077 return 0;
1078 }
1079
1080 /* 4 bytes for the CRC. */
1081 size += 4;
1082 crc = cpu_to_be32(crc32(~0, buf, size));
1083 crc_ptr = (uint8_t *) &crc;
1084
a699b410 1085 /* Huge frames are truncated. */
1bb3c371
JCD
1086 if (size > ENET_MAX_FRAME_SIZE) {
1087 size = ENET_MAX_FRAME_SIZE;
1088 flags |= ENET_BD_TR | ENET_BD_LG;
fcbd8018
JCD
1089 }
1090
1091 /* Frames larger than the user limit just set error flags. */
db0de352 1092 if (size > (s->regs[ENET_RCR] >> 16)) {
1bb3c371 1093 flags |= ENET_BD_LG;
fcbd8018
JCD
1094 }
1095
1096 addr = s->rx_descriptor;
1097 while (size > 0) {
1098 imx_fec_read_bd(&bd, addr);
1bb3c371 1099 if ((bd.flags & ENET_BD_E) == 0) {
fcbd8018
JCD
1100 /* No descriptors available. Bail out. */
1101 /*
1102 * FIXME: This is wrong. We should probably either
1103 * save the remainder for when more RX buffers are
1104 * available, or flag an error.
1105 */
b72d8d25 1106 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Lost end of frame\n",
fcbd8018
JCD
1107 TYPE_IMX_FEC, __func__);
1108 break;
1109 }
db0de352 1110 buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
fcbd8018
JCD
1111 bd.length = buf_len;
1112 size -= buf_len;
b72d8d25
JCD
1113
1114 FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
1115
fcbd8018
JCD
1116 /* The last 4 bytes are the CRC. */
1117 if (size < 4) {
1118 buf_len += size - 4;
1119 }
1120 buf_addr = bd.data;
1121 dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
1122 buf += buf_len;
1123 if (size < 4) {
1124 dma_memory_write(&address_space_memory, buf_addr + buf_len,
1125 crc_ptr, 4 - size);
1126 crc_ptr += 4 - size;
1127 }
1bb3c371 1128 bd.flags &= ~ENET_BD_E;
fcbd8018
JCD
1129 if (size == 0) {
1130 /* Last buffer in frame. */
1bb3c371 1131 bd.flags |= flags | ENET_BD_L;
fcbd8018 1132 FEC_PRINTF("rx frame flags %04x\n", bd.flags);
db0de352 1133 s->regs[ENET_EIR] |= ENET_INT_RXF;
fcbd8018 1134 } else {
db0de352 1135 s->regs[ENET_EIR] |= ENET_INT_RXB;
fcbd8018
JCD
1136 }
1137 imx_fec_write_bd(&bd, addr);
1138 /* Advance to the next descriptor. */
1bb3c371 1139 if ((bd.flags & ENET_BD_W) != 0) {
db0de352 1140 addr = s->regs[ENET_RDSR];
fcbd8018 1141 } else {
db0de352 1142 addr += sizeof(bd);
fcbd8018
JCD
1143 }
1144 }
1145 s->rx_descriptor = addr;
b2b012af 1146 imx_eth_enable_rx(s, false);
a699b410
JCD
1147 imx_eth_update(s);
1148 return len;
1149}
1150
1151static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
1152 size_t len)
1153{
1154 IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
1155 IMXENETBufDesc bd;
1156 uint32_t flags = 0;
1157 uint32_t addr;
1158 uint32_t crc;
1159 uint32_t buf_addr;
1160 uint8_t *crc_ptr;
1161 unsigned int buf_len;
1162 size_t size = len;
ebdd8cdd 1163 bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
a699b410
JCD
1164
1165 FEC_PRINTF("len %d\n", (int)size);
1166
1167 if (!s->regs[ENET_RDAR]) {
1168 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
1169 TYPE_IMX_FEC, __func__);
1170 return 0;
1171 }
1172
1173 /* 4 bytes for the CRC. */
1174 size += 4;
1175 crc = cpu_to_be32(crc32(~0, buf, size));
1176 crc_ptr = (uint8_t *) &crc;
1177
ebdd8cdd
AS
1178 if (shift16) {
1179 size += 2;
1180 }
1181
894d74cc 1182 /* Huge frames are truncated. */
ff9a7fee
AS
1183 if (size > s->regs[ENET_FTRL]) {
1184 size = s->regs[ENET_FTRL];
a699b410
JCD
1185 flags |= ENET_BD_TR | ENET_BD_LG;
1186 }
1187
1188 /* Frames larger than the user limit just set error flags. */
1189 if (size > (s->regs[ENET_RCR] >> 16)) {
1190 flags |= ENET_BD_LG;
1191 }
1192
1193 addr = s->rx_descriptor;
1194 while (size > 0) {
1195 imx_enet_read_bd(&bd, addr);
1196 if ((bd.flags & ENET_BD_E) == 0) {
1197 /* No descriptors available. Bail out. */
1198 /*
1199 * FIXME: This is wrong. We should probably either
1200 * save the remainder for when more RX buffers are
1201 * available, or flag an error.
1202 */
1203 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Lost end of frame\n",
1204 TYPE_IMX_FEC, __func__);
1205 break;
1206 }
4c5e7a6c 1207 buf_len = MIN(size, s->regs[ENET_MRBR]);
a699b410
JCD
1208 bd.length = buf_len;
1209 size -= buf_len;
1210
1211 FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
1212
1213 /* The last 4 bytes are the CRC. */
1214 if (size < 4) {
1215 buf_len += size - 4;
1216 }
1217 buf_addr = bd.data;
ebdd8cdd
AS
1218
1219 if (shift16) {
1220 /*
1221 * If SHIFT16 bit of ENETx_RACC register is set we need to
1222 * align the payload to 4-byte boundary.
1223 */
1224 const uint8_t zeros[2] = { 0 };
1225
1226 dma_memory_write(&address_space_memory, buf_addr,
1227 zeros, sizeof(zeros));
1228
1229 buf_addr += sizeof(zeros);
1230 buf_len -= sizeof(zeros);
1231
1232 /* We only do this once per Ethernet frame */
1233 shift16 = false;
1234 }
1235
a699b410
JCD
1236 dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
1237 buf += buf_len;
1238 if (size < 4) {
1239 dma_memory_write(&address_space_memory, buf_addr + buf_len,
1240 crc_ptr, 4 - size);
1241 crc_ptr += 4 - size;
1242 }
1243 bd.flags &= ~ENET_BD_E;
1244 if (size == 0) {
1245 /* Last buffer in frame. */
1246 bd.flags |= flags | ENET_BD_L;
1247 FEC_PRINTF("rx frame flags %04x\n", bd.flags);
88e1b59e
AH
1248 /* Indicate that we've updated the last buffer descriptor. */
1249 bd.last_buffer = ENET_BD_BDU;
a699b410
JCD
1250 if (bd.option & ENET_BD_RX_INT) {
1251 s->regs[ENET_EIR] |= ENET_INT_RXF;
1252 }
1253 } else {
1254 if (bd.option & ENET_BD_RX_INT) {
1255 s->regs[ENET_EIR] |= ENET_INT_RXB;
1256 }
1257 }
1258 imx_enet_write_bd(&bd, addr);
1259 /* Advance to the next descriptor. */
1260 if ((bd.flags & ENET_BD_W) != 0) {
1261 addr = s->regs[ENET_RDSR];
1262 } else {
1263 addr += sizeof(bd);
1264 }
1265 }
1266 s->rx_descriptor = addr;
b2b012af 1267 imx_eth_enable_rx(s, false);
a699b410 1268 imx_eth_update(s);
fcbd8018
JCD
1269 return len;
1270}
1271
a699b410
JCD
1272static ssize_t imx_eth_receive(NetClientState *nc, const uint8_t *buf,
1273 size_t len)
1274{
1275 IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
1276
1277 if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
1278 return imx_enet_receive(nc, buf, len);
1279 } else {
1280 return imx_fec_receive(nc, buf, len);
1281 }
1282}
1283
1284static const MemoryRegionOps imx_eth_ops = {
1285 .read = imx_eth_read,
1286 .write = imx_eth_write,
fcbd8018
JCD
1287 .valid.min_access_size = 4,
1288 .valid.max_access_size = 4,
a699b410 1289 .endianness = DEVICE_NATIVE_ENDIAN,
fcbd8018
JCD
1290};
1291
a699b410 1292static void imx_eth_cleanup(NetClientState *nc)
fcbd8018
JCD
1293{
1294 IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
1295
1296 s->nic = NULL;
1297}
1298
a699b410 1299static NetClientInfo imx_eth_net_info = {
f394b2e2 1300 .type = NET_CLIENT_DRIVER_NIC,
a699b410
JCD
1301 .size = sizeof(NICState),
1302 .can_receive = imx_eth_can_receive,
1303 .receive = imx_eth_receive,
1304 .cleanup = imx_eth_cleanup,
1305 .link_status_changed = imx_eth_set_link,
fcbd8018
JCD
1306};
1307
1308
a699b410 1309static void imx_eth_realize(DeviceState *dev, Error **errp)
fcbd8018
JCD
1310{
1311 IMXFECState *s = IMX_FEC(dev);
1312 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1313
a699b410 1314 memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
831858ad 1315 TYPE_IMX_FEC, FSL_IMX25_FEC_SIZE);
fcbd8018 1316 sysbus_init_mmio(sbd, &s->iomem);
a699b410
JCD
1317 sysbus_init_irq(sbd, &s->irq[0]);
1318 sysbus_init_irq(sbd, &s->irq[1]);
1319
fcbd8018
JCD
1320 qemu_macaddr_default_if_unset(&s->conf.macaddr);
1321
a699b410
JCD
1322 s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
1323 object_get_typename(OBJECT(dev)),
1324 DEVICE(dev)->id, s);
1325
fcbd8018
JCD
1326 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1327}
1328
a699b410 1329static Property imx_eth_properties[] = {
fcbd8018 1330 DEFINE_NIC_PROPERTIES(IMXFECState, conf),
f93f961c 1331 DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
fcbd8018
JCD
1332 DEFINE_PROP_END_OF_LIST(),
1333};
1334
a699b410 1335static void imx_eth_class_init(ObjectClass *klass, void *data)
fcbd8018
JCD
1336{
1337 DeviceClass *dc = DEVICE_CLASS(klass);
1338
a699b410
JCD
1339 dc->vmsd = &vmstate_imx_eth;
1340 dc->reset = imx_eth_reset;
4f67d30b 1341 device_class_set_props(dc, imx_eth_properties);
a699b410
JCD
1342 dc->realize = imx_eth_realize;
1343 dc->desc = "i.MX FEC/ENET Ethernet Controller";
1344}
1345
1346static void imx_fec_init(Object *obj)
1347{
1348 IMXFECState *s = IMX_FEC(obj);
1349
1350 s->is_fec = true;
1351}
1352
1353static void imx_enet_init(Object *obj)
1354{
1355 IMXFECState *s = IMX_FEC(obj);
1356
1357 s->is_fec = false;
fcbd8018
JCD
1358}
1359
1360static const TypeInfo imx_fec_info = {
a699b410
JCD
1361 .name = TYPE_IMX_FEC,
1362 .parent = TYPE_SYS_BUS_DEVICE,
fcbd8018 1363 .instance_size = sizeof(IMXFECState),
a699b410
JCD
1364 .instance_init = imx_fec_init,
1365 .class_init = imx_eth_class_init,
1366};
1367
1368static const TypeInfo imx_enet_info = {
1369 .name = TYPE_IMX_ENET,
1370 .parent = TYPE_IMX_FEC,
1371 .instance_init = imx_enet_init,
fcbd8018
JCD
1372};
1373
a699b410 1374static void imx_eth_register_types(void)
fcbd8018
JCD
1375{
1376 type_register_static(&imx_fec_info);
a699b410 1377 type_register_static(&imx_enet_info);
fcbd8018
JCD
1378}
1379
a699b410 1380type_init(imx_eth_register_types)