xref: /qemu/hw/net/allwinner_emac.c (revision 37677d7d)
1 /*
2  * Emulation of Allwinner EMAC Fast Ethernet controller and
3  * Realtek RTL8201CP PHY
4  *
5  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
6  *
7  * This model is based on reverse-engineering of Linux kernel driver.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  */
19 
20 #include "qemu/osdep.h"
21 #include "hw/sysbus.h"
22 #include "net/net.h"
23 #include "qemu/fifo8.h"
24 #include "hw/net/allwinner_emac.h"
25 #include "qemu/log.h"
26 #include "qemu/module.h"
27 #include <zlib.h>
28 
29 static uint8_t padding[60];
30 
31 static void mii_set_link(RTL8201CPState *mii, bool link_ok)
32 {
33     if (link_ok) {
34         mii->bmsr |= MII_BMSR_LINK_ST | MII_BMSR_AN_COMP;
35         mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 |
36                        MII_ANAR_CSMACD;
37     } else {
38         mii->bmsr &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
39         mii->anlpar = MII_ANAR_TX;
40     }
41 }
42 
43 static void mii_reset(RTL8201CPState *mii, bool link_ok)
44 {
45     mii->bmcr = MII_BMCR_FD | MII_BMCR_AUTOEN | MII_BMCR_SPEED;
46     mii->bmsr = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD |
47                 MII_BMSR_10T_HD | MII_BMSR_MFPS | MII_BMSR_AUTONEG;
48     mii->anar = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD | MII_ANAR_10 |
49                 MII_ANAR_CSMACD;
50     mii->anlpar = MII_ANAR_TX;
51 
52     mii_set_link(mii, link_ok);
53 }
54 
55 static uint16_t RTL8201CP_mdio_read(AwEmacState *s, uint8_t addr, uint8_t reg)
56 {
57     RTL8201CPState *mii = &s->mii;
58     uint16_t ret = 0xffff;
59 
60     if (addr == s->phy_addr) {
61         switch (reg) {
62         case MII_BMCR:
63             return mii->bmcr;
64         case MII_BMSR:
65             return mii->bmsr;
66         case MII_PHYID1:
67             return RTL8201CP_PHYID1;
68         case MII_PHYID2:
69             return RTL8201CP_PHYID2;
70         case MII_ANAR:
71             return mii->anar;
72         case MII_ANLPAR:
73             return mii->anlpar;
74         case MII_ANER:
75         case MII_NSR:
76         case MII_LBREMR:
77         case MII_REC:
78         case MII_SNRDR:
79         case MII_TEST:
80             qemu_log_mask(LOG_UNIMP,
81                           "allwinner_emac: read from unimpl. mii reg 0x%x\n",
82                           reg);
83             return 0;
84         default:
85             qemu_log_mask(LOG_GUEST_ERROR,
86                           "allwinner_emac: read from invalid mii reg 0x%x\n",
87                           reg);
88             return 0;
89         }
90     }
91     return ret;
92 }
93 
94 static void RTL8201CP_mdio_write(AwEmacState *s, uint8_t addr, uint8_t reg,
95                                  uint16_t value)
96 {
97     RTL8201CPState *mii = &s->mii;
98     NetClientState *nc;
99 
100     if (addr == s->phy_addr) {
101         switch (reg) {
102         case MII_BMCR:
103             if (value & MII_BMCR_RESET) {
104                 nc = qemu_get_queue(s->nic);
105                 mii_reset(mii, !nc->link_down);
106             } else {
107                 mii->bmcr = value;
108             }
109             break;
110         case MII_ANAR:
111             mii->anar = value;
112             break;
113         case MII_BMSR:
114         case MII_PHYID1:
115         case MII_PHYID2:
116         case MII_ANLPAR:
117         case MII_ANER:
118             qemu_log_mask(LOG_GUEST_ERROR,
119                           "allwinner_emac: write to read-only mii reg 0x%x\n",
120                           reg);
121             break;
122         case MII_NSR:
123         case MII_LBREMR:
124         case MII_REC:
125         case MII_SNRDR:
126         case MII_TEST:
127             qemu_log_mask(LOG_UNIMP,
128                           "allwinner_emac: write to unimpl. mii reg 0x%x\n",
129                           reg);
130             break;
131         default:
132             qemu_log_mask(LOG_GUEST_ERROR,
133                           "allwinner_emac: write to invalid mii reg 0x%x\n",
134                           reg);
135         }
136     }
137 }
138 
139 static void aw_emac_update_irq(AwEmacState *s)
140 {
141     qemu_set_irq(s->irq, (s->int_sta & s->int_ctl) != 0);
142 }
143 
144 static void aw_emac_tx_reset(AwEmacState *s, int chan)
145 {
146     fifo8_reset(&s->tx_fifo[chan]);
147     s->tx_length[chan] = 0;
148 }
149 
150 static void aw_emac_rx_reset(AwEmacState *s)
151 {
152     fifo8_reset(&s->rx_fifo);
153     s->rx_num_packets = 0;
154     s->rx_packet_size = 0;
155     s->rx_packet_pos = 0;
156 }
157 
158 static void fifo8_push_word(Fifo8 *fifo, uint32_t val)
159 {
160     fifo8_push(fifo, val);
161     fifo8_push(fifo, val >> 8);
162     fifo8_push(fifo, val >> 16);
163     fifo8_push(fifo, val >> 24);
164 }
165 
166 static uint32_t fifo8_pop_word(Fifo8 *fifo)
167 {
168     uint32_t ret;
169 
170     ret = fifo8_pop(fifo);
171     ret |= fifo8_pop(fifo) << 8;
172     ret |= fifo8_pop(fifo) << 16;
173     ret |= fifo8_pop(fifo) << 24;
174 
175     return ret;
176 }
177 
178 static int aw_emac_can_receive(NetClientState *nc)
179 {
180     AwEmacState *s = qemu_get_nic_opaque(nc);
181 
182     /*
183      * To avoid packet drops, allow reception only when there is space
184      * for a full frame: 1522 + 8 (rx headers) + 2 (padding).
185      */
186     return (s->ctl & EMAC_CTL_RX_EN) && (fifo8_num_free(&s->rx_fifo) >= 1532);
187 }
188 
189 static ssize_t aw_emac_receive(NetClientState *nc, const uint8_t *buf,
190                                size_t size)
191 {
192     AwEmacState *s = qemu_get_nic_opaque(nc);
193     Fifo8 *fifo = &s->rx_fifo;
194     size_t padded_size, total_size;
195     uint32_t crc;
196 
197     padded_size = size > 60 ? size : 60;
198     total_size = QEMU_ALIGN_UP(RX_HDR_SIZE + padded_size + CRC_SIZE, 4);
199 
200     if (!(s->ctl & EMAC_CTL_RX_EN) || (fifo8_num_free(fifo) < total_size)) {
201         return -1;
202     }
203 
204     fifo8_push_word(fifo, EMAC_UNDOCUMENTED_MAGIC);
205     fifo8_push_word(fifo, EMAC_RX_HEADER(padded_size + CRC_SIZE,
206                                          EMAC_RX_IO_DATA_STATUS_OK));
207     fifo8_push_all(fifo, buf, size);
208     crc = crc32(~0, buf, size);
209 
210     if (padded_size != size) {
211         fifo8_push_all(fifo, padding, padded_size - size);
212         crc = crc32(crc, padding, padded_size - size);
213     }
214 
215     fifo8_push_word(fifo, crc);
216     fifo8_push_all(fifo, padding, QEMU_ALIGN_UP(padded_size, 4) - padded_size);
217     s->rx_num_packets++;
218 
219     s->int_sta |= EMAC_INT_RX;
220     aw_emac_update_irq(s);
221 
222     return size;
223 }
224 
225 static void aw_emac_reset(DeviceState *dev)
226 {
227     AwEmacState *s = AW_EMAC(dev);
228     NetClientState *nc = qemu_get_queue(s->nic);
229 
230     s->ctl = 0;
231     s->tx_mode = 0;
232     s->int_ctl = 0;
233     s->int_sta = 0;
234     s->tx_channel = 0;
235     s->phy_target = 0;
236 
237     aw_emac_tx_reset(s, 0);
238     aw_emac_tx_reset(s, 1);
239     aw_emac_rx_reset(s);
240 
241     mii_reset(&s->mii, !nc->link_down);
242 }
243 
244 static uint64_t aw_emac_read(void *opaque, hwaddr offset, unsigned size)
245 {
246     AwEmacState *s = opaque;
247     Fifo8 *fifo = &s->rx_fifo;
248     NetClientState *nc;
249     uint64_t ret;
250 
251     switch (offset) {
252     case EMAC_CTL_REG:
253         return s->ctl;
254     case EMAC_TX_MODE_REG:
255         return s->tx_mode;
256     case EMAC_TX_INS_REG:
257         return s->tx_channel;
258     case EMAC_RX_CTL_REG:
259         return s->rx_ctl;
260     case EMAC_RX_IO_DATA_REG:
261         if (!s->rx_num_packets) {
262             qemu_log_mask(LOG_GUEST_ERROR,
263                           "Read IO data register when no packet available");
264             return 0;
265         }
266 
267         ret = fifo8_pop_word(fifo);
268 
269         switch (s->rx_packet_pos) {
270         case 0:     /* Word is magic header */
271             s->rx_packet_pos += 4;
272             break;
273         case 4:     /* Word is rx info header */
274             s->rx_packet_pos += 4;
275             s->rx_packet_size = QEMU_ALIGN_UP(extract32(ret, 0, 16), 4);
276             break;
277         default:    /* Word is packet data */
278             s->rx_packet_pos += 4;
279             s->rx_packet_size -= 4;
280 
281             if (!s->rx_packet_size) {
282                 s->rx_packet_pos = 0;
283                 s->rx_num_packets--;
284                 nc = qemu_get_queue(s->nic);
285                 if (aw_emac_can_receive(nc)) {
286                     qemu_flush_queued_packets(nc);
287                 }
288             }
289         }
290         return ret;
291     case EMAC_RX_FBC_REG:
292         return s->rx_num_packets;
293     case EMAC_INT_CTL_REG:
294         return s->int_ctl;
295     case EMAC_INT_STA_REG:
296         return s->int_sta;
297     case EMAC_MAC_MRDD_REG:
298         return RTL8201CP_mdio_read(s,
299                                    extract32(s->phy_target, PHY_ADDR_SHIFT, 8),
300                                    extract32(s->phy_target, PHY_REG_SHIFT, 8));
301     default:
302         qemu_log_mask(LOG_UNIMP,
303                       "allwinner_emac: read access to unknown register 0x"
304                       TARGET_FMT_plx "\n", offset);
305         ret = 0;
306     }
307 
308     return ret;
309 }
310 
311 static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value,
312                           unsigned size)
313 {
314     AwEmacState *s = opaque;
315     Fifo8 *fifo;
316     NetClientState *nc = qemu_get_queue(s->nic);
317     int chan;
318 
319     switch (offset) {
320     case EMAC_CTL_REG:
321         if (value & EMAC_CTL_RESET) {
322             aw_emac_reset(DEVICE(s));
323             value &= ~EMAC_CTL_RESET;
324         }
325         s->ctl = value;
326         if (aw_emac_can_receive(nc)) {
327             qemu_flush_queued_packets(nc);
328         }
329         break;
330     case EMAC_TX_MODE_REG:
331         s->tx_mode = value;
332         break;
333     case EMAC_TX_CTL0_REG:
334     case EMAC_TX_CTL1_REG:
335         chan = (offset == EMAC_TX_CTL0_REG ? 0 : 1);
336         if ((value & 1) && (s->ctl & EMAC_CTL_TX_EN)) {
337             uint32_t len, ret;
338             const uint8_t *data;
339 
340             fifo = &s->tx_fifo[chan];
341             len = s->tx_length[chan];
342 
343             if (len > fifo8_num_used(fifo)) {
344                 len = fifo8_num_used(fifo);
345                 qemu_log_mask(LOG_GUEST_ERROR,
346                               "allwinner_emac: TX length > fifo data length\n");
347             }
348             if (len > 0) {
349                 data = fifo8_pop_buf(fifo, len, &ret);
350                 qemu_send_packet(nc, data, ret);
351                 aw_emac_tx_reset(s, chan);
352                 /* Raise TX interrupt */
353                 s->int_sta |= EMAC_INT_TX_CHAN(chan);
354                 aw_emac_update_irq(s);
355             }
356         }
357         break;
358     case EMAC_TX_INS_REG:
359         s->tx_channel = value < NUM_TX_FIFOS ? value : 0;
360         break;
361     case EMAC_TX_PL0_REG:
362     case EMAC_TX_PL1_REG:
363         chan = (offset == EMAC_TX_PL0_REG ? 0 : 1);
364         if (value > TX_FIFO_SIZE) {
365             qemu_log_mask(LOG_GUEST_ERROR,
366                           "allwinner_emac: invalid TX frame length %d\n",
367                           (int)value);
368             value = TX_FIFO_SIZE;
369         }
370         s->tx_length[chan] = value;
371         break;
372     case EMAC_TX_IO_DATA_REG:
373         fifo = &s->tx_fifo[s->tx_channel];
374         if (fifo8_num_free(fifo) < 4) {
375             qemu_log_mask(LOG_GUEST_ERROR,
376                           "allwinner_emac: TX data overruns fifo\n");
377             break;
378         }
379         fifo8_push_word(fifo, value);
380         break;
381     case EMAC_RX_CTL_REG:
382         s->rx_ctl = value;
383         break;
384     case EMAC_RX_FBC_REG:
385         if (value == 0) {
386             aw_emac_rx_reset(s);
387         }
388         break;
389     case EMAC_INT_CTL_REG:
390         s->int_ctl = value;
391         aw_emac_update_irq(s);
392         break;
393     case EMAC_INT_STA_REG:
394         s->int_sta &= ~value;
395         aw_emac_update_irq(s);
396         break;
397     case EMAC_MAC_MADR_REG:
398         s->phy_target = value;
399         break;
400     case EMAC_MAC_MWTD_REG:
401         RTL8201CP_mdio_write(s, extract32(s->phy_target, PHY_ADDR_SHIFT, 8),
402                              extract32(s->phy_target, PHY_REG_SHIFT, 8), value);
403         break;
404     default:
405         qemu_log_mask(LOG_UNIMP,
406                       "allwinner_emac: write access to unknown register 0x"
407                       TARGET_FMT_plx "\n", offset);
408     }
409 }
410 
411 static void aw_emac_set_link(NetClientState *nc)
412 {
413     AwEmacState *s = qemu_get_nic_opaque(nc);
414 
415     mii_set_link(&s->mii, !nc->link_down);
416 }
417 
418 static const MemoryRegionOps aw_emac_mem_ops = {
419     .read = aw_emac_read,
420     .write = aw_emac_write,
421     .endianness = DEVICE_NATIVE_ENDIAN,
422     .valid = {
423         .min_access_size = 4,
424         .max_access_size = 4,
425     },
426 };
427 
428 static NetClientInfo net_aw_emac_info = {
429     .type = NET_CLIENT_DRIVER_NIC,
430     .size = sizeof(NICState),
431     .can_receive = aw_emac_can_receive,
432     .receive = aw_emac_receive,
433     .link_status_changed = aw_emac_set_link,
434 };
435 
436 static void aw_emac_init(Object *obj)
437 {
438     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
439     AwEmacState *s = AW_EMAC(obj);
440 
441     memory_region_init_io(&s->iomem, OBJECT(s), &aw_emac_mem_ops, s,
442                           "aw_emac", 0x1000);
443     sysbus_init_mmio(sbd, &s->iomem);
444     sysbus_init_irq(sbd, &s->irq);
445 }
446 
447 static void aw_emac_realize(DeviceState *dev, Error **errp)
448 {
449     AwEmacState *s = AW_EMAC(dev);
450 
451     qemu_macaddr_default_if_unset(&s->conf.macaddr);
452     s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf,
453                           object_get_typename(OBJECT(dev)), dev->id, s);
454     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
455 
456     fifo8_create(&s->rx_fifo, RX_FIFO_SIZE);
457     fifo8_create(&s->tx_fifo[0], TX_FIFO_SIZE);
458     fifo8_create(&s->tx_fifo[1], TX_FIFO_SIZE);
459 }
460 
461 static Property aw_emac_properties[] = {
462     DEFINE_NIC_PROPERTIES(AwEmacState, conf),
463     DEFINE_PROP_UINT8("phy-addr", AwEmacState, phy_addr, 0),
464     DEFINE_PROP_END_OF_LIST(),
465 };
466 
467 static const VMStateDescription vmstate_mii = {
468     .name = "rtl8201cp",
469     .version_id = 1,
470     .minimum_version_id = 1,
471     .fields = (VMStateField[]) {
472         VMSTATE_UINT16(bmcr, RTL8201CPState),
473         VMSTATE_UINT16(bmsr, RTL8201CPState),
474         VMSTATE_UINT16(anar, RTL8201CPState),
475         VMSTATE_UINT16(anlpar, RTL8201CPState),
476         VMSTATE_END_OF_LIST()
477     }
478 };
479 
480 static int aw_emac_post_load(void *opaque, int version_id)
481 {
482     AwEmacState *s = opaque;
483 
484     aw_emac_set_link(qemu_get_queue(s->nic));
485 
486     return 0;
487 }
488 
489 static const VMStateDescription vmstate_aw_emac = {
490     .name = "allwinner_emac",
491     .version_id = 1,
492     .minimum_version_id = 1,
493     .post_load = aw_emac_post_load,
494     .fields = (VMStateField[]) {
495         VMSTATE_STRUCT(mii, AwEmacState, 1, vmstate_mii, RTL8201CPState),
496         VMSTATE_UINT32(ctl, AwEmacState),
497         VMSTATE_UINT32(tx_mode, AwEmacState),
498         VMSTATE_UINT32(rx_ctl, AwEmacState),
499         VMSTATE_UINT32(int_ctl, AwEmacState),
500         VMSTATE_UINT32(int_sta, AwEmacState),
501         VMSTATE_UINT32(phy_target, AwEmacState),
502         VMSTATE_FIFO8(rx_fifo, AwEmacState),
503         VMSTATE_UINT32(rx_num_packets, AwEmacState),
504         VMSTATE_UINT32(rx_packet_size, AwEmacState),
505         VMSTATE_UINT32(rx_packet_pos, AwEmacState),
506         VMSTATE_STRUCT_ARRAY(tx_fifo, AwEmacState, NUM_TX_FIFOS, 1,
507                              vmstate_fifo8, Fifo8),
508         VMSTATE_UINT32_ARRAY(tx_length, AwEmacState, NUM_TX_FIFOS),
509         VMSTATE_UINT32(tx_channel, AwEmacState),
510         VMSTATE_END_OF_LIST()
511     }
512 };
513 
514 static void aw_emac_class_init(ObjectClass *klass, void *data)
515 {
516     DeviceClass *dc = DEVICE_CLASS(klass);
517 
518     dc->realize = aw_emac_realize;
519     dc->props = aw_emac_properties;
520     dc->reset = aw_emac_reset;
521     dc->vmsd = &vmstate_aw_emac;
522 }
523 
524 static const TypeInfo aw_emac_info = {
525     .name           = TYPE_AW_EMAC,
526     .parent         = TYPE_SYS_BUS_DEVICE,
527     .instance_size  = sizeof(AwEmacState),
528     .instance_init   = aw_emac_init,
529     .class_init     = aw_emac_class_init,
530 };
531 
532 static void aw_emac_register_types(void)
533 {
534     type_register_static(&aw_emac_info);
535 }
536 
537 type_init(aw_emac_register_types)
538