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