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