1 /* 2 * QEMU ETRAX Ethernet Controller. 3 * 4 * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB. 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 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "hw/sysbus.h" 28 #include "net/net.h" 29 #include "hw/cris/etraxfs.h" 30 #include "qemu/error-report.h" 31 #include "qemu/module.h" 32 #include "trace.h" 33 34 #define D(x) 35 36 /* Advertisement control register. */ 37 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ 38 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ 39 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ 40 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ 41 42 /* 43 * The MDIO extensions in the TDK PHY model were reversed engineered from the 44 * linux driver (PHYID and Diagnostics reg). 45 * TODO: Add friendly names for the register nums. 46 */ 47 struct qemu_phy 48 { 49 uint32_t regs[32]; 50 51 int link; 52 53 unsigned int (*read)(struct qemu_phy *phy, unsigned int req); 54 void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data); 55 }; 56 57 static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) 58 { 59 int regnum; 60 unsigned r = 0; 61 62 regnum = req & 0x1f; 63 64 switch (regnum) { 65 case 1: 66 if (!phy->link) { 67 break; 68 } 69 /* MR1. */ 70 /* Speeds and modes. */ 71 r |= (1 << 13) | (1 << 14); 72 r |= (1 << 11) | (1 << 12); 73 r |= (1 << 5); /* Autoneg complete. */ 74 r |= (1 << 3); /* Autoneg able. */ 75 r |= (1 << 2); /* 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 18: 88 { 89 /* Diagnostics reg. */ 90 int duplex = 0; 91 int speed_100 = 0; 92 93 if (!phy->link) { 94 break; 95 } 96 97 /* Are we advertising 100 half or 100 duplex ? */ 98 speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); 99 speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); 100 101 /* Are we advertising 10 duplex or 100 duplex ? */ 102 duplex = !!(phy->regs[4] & ADVERTISE_100FULL); 103 duplex |= !!(phy->regs[4] & ADVERTISE_10FULL); 104 r = (speed_100 << 10) | (duplex << 11); 105 } 106 break; 107 108 default: 109 r = phy->regs[regnum]; 110 break; 111 } 112 trace_mdio_phy_read(regnum, r); 113 return r; 114 } 115 116 static void 117 tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data) 118 { 119 int regnum; 120 121 regnum = req & 0x1f; 122 trace_mdio_phy_write(regnum, data); 123 switch (regnum) { 124 default: 125 phy->regs[regnum] = data; 126 break; 127 } 128 } 129 130 static void 131 tdk_reset(struct qemu_phy *phy) 132 { 133 phy->regs[0] = 0x3100; 134 /* PHY Id. */ 135 phy->regs[2] = 0x0300; 136 phy->regs[3] = 0xe400; 137 /* Autonegotiation advertisement reg. */ 138 phy->regs[4] = 0x01E1; 139 phy->link = 1; 140 } 141 142 struct qemu_mdio 143 { 144 /* bus. */ 145 int mdc; 146 int mdio; 147 148 /* decoder. */ 149 enum { 150 PREAMBLE, 151 SOF, 152 OPC, 153 ADDR, 154 REQ, 155 TURNAROUND, 156 DATA 157 } state; 158 unsigned int drive; 159 160 unsigned int cnt; 161 unsigned int addr; 162 unsigned int opc; 163 unsigned int req; 164 unsigned int data; 165 166 struct qemu_phy *devs[32]; 167 }; 168 169 static void 170 mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) 171 { 172 bus->devs[addr & 0x1f] = phy; 173 } 174 175 #ifdef USE_THIS_DEAD_CODE 176 static void 177 mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) 178 { 179 bus->devs[addr & 0x1f] = NULL; 180 } 181 #endif 182 183 static void mdio_read_req(struct qemu_mdio *bus) 184 { 185 struct qemu_phy *phy; 186 187 phy = bus->devs[bus->addr]; 188 if (phy && phy->read) { 189 bus->data = phy->read(phy, bus->req); 190 } else { 191 bus->data = 0xffff; 192 } 193 } 194 195 static void mdio_write_req(struct qemu_mdio *bus) 196 { 197 struct qemu_phy *phy; 198 199 phy = bus->devs[bus->addr]; 200 if (phy && phy->write) { 201 phy->write(phy, bus->req, bus->data); 202 } 203 } 204 205 static void mdio_cycle(struct qemu_mdio *bus) 206 { 207 bus->cnt++; 208 209 trace_mdio_bitbang(bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive); 210 #if 0 211 if (bus->mdc) { 212 printf("%d", bus->mdio); 213 } 214 #endif 215 switch (bus->state) { 216 case PREAMBLE: 217 if (bus->mdc) { 218 if (bus->cnt >= (32 * 2) && !bus->mdio) { 219 bus->cnt = 0; 220 bus->state = SOF; 221 bus->data = 0; 222 } 223 } 224 break; 225 case SOF: 226 if (bus->mdc) { 227 if (bus->mdio != 1) { 228 printf("WARNING: no SOF\n"); 229 } 230 if (bus->cnt == 1*2) { 231 bus->cnt = 0; 232 bus->opc = 0; 233 bus->state = OPC; 234 } 235 } 236 break; 237 case OPC: 238 if (bus->mdc) { 239 bus->opc <<= 1; 240 bus->opc |= bus->mdio & 1; 241 if (bus->cnt == 2*2) { 242 bus->cnt = 0; 243 bus->addr = 0; 244 bus->state = ADDR; 245 } 246 } 247 break; 248 case ADDR: 249 if (bus->mdc) { 250 bus->addr <<= 1; 251 bus->addr |= bus->mdio & 1; 252 253 if (bus->cnt == 5*2) { 254 bus->cnt = 0; 255 bus->req = 0; 256 bus->state = REQ; 257 } 258 } 259 break; 260 case REQ: 261 if (bus->mdc) { 262 bus->req <<= 1; 263 bus->req |= bus->mdio & 1; 264 if (bus->cnt == 5*2) { 265 bus->cnt = 0; 266 bus->state = TURNAROUND; 267 } 268 } 269 break; 270 case TURNAROUND: 271 if (bus->mdc && bus->cnt == 2*2) { 272 bus->mdio = 0; 273 bus->cnt = 0; 274 275 if (bus->opc == 2) { 276 bus->drive = 1; 277 mdio_read_req(bus); 278 bus->mdio = bus->data & 1; 279 } 280 bus->state = DATA; 281 } 282 break; 283 case DATA: 284 if (!bus->mdc) { 285 if (bus->drive) { 286 bus->mdio = !!(bus->data & (1 << 15)); 287 bus->data <<= 1; 288 } 289 } else { 290 if (!bus->drive) { 291 bus->data <<= 1; 292 bus->data |= bus->mdio; 293 } 294 if (bus->cnt == 16 * 2) { 295 bus->cnt = 0; 296 bus->state = PREAMBLE; 297 if (!bus->drive) { 298 mdio_write_req(bus); 299 } 300 bus->drive = 0; 301 } 302 } 303 break; 304 default: 305 break; 306 } 307 } 308 309 /* ETRAX-FS Ethernet MAC block starts here. */ 310 311 #define RW_MA0_LO 0x00 312 #define RW_MA0_HI 0x01 313 #define RW_MA1_LO 0x02 314 #define RW_MA1_HI 0x03 315 #define RW_GA_LO 0x04 316 #define RW_GA_HI 0x05 317 #define RW_GEN_CTRL 0x06 318 #define RW_REC_CTRL 0x07 319 #define RW_TR_CTRL 0x08 320 #define RW_CLR_ERR 0x09 321 #define RW_MGM_CTRL 0x0a 322 #define R_STAT 0x0b 323 #define FS_ETH_MAX_REGS 0x17 324 325 #define TYPE_ETRAX_FS_ETH "etraxfs-eth" 326 #define ETRAX_FS_ETH(obj) \ 327 OBJECT_CHECK(ETRAXFSEthState, (obj), TYPE_ETRAX_FS_ETH) 328 329 typedef struct ETRAXFSEthState 330 { 331 SysBusDevice parent_obj; 332 333 MemoryRegion mmio; 334 NICState *nic; 335 NICConf conf; 336 337 /* Two addrs in the filter. */ 338 uint8_t macaddr[2][6]; 339 uint32_t regs[FS_ETH_MAX_REGS]; 340 341 struct etraxfs_dma_client *dma_out; 342 struct etraxfs_dma_client *dma_in; 343 344 /* MDIO bus. */ 345 struct qemu_mdio mdio_bus; 346 unsigned int phyaddr; 347 int duplex_mismatch; 348 349 /* PHY. */ 350 struct qemu_phy phy; 351 } ETRAXFSEthState; 352 353 static void eth_validate_duplex(ETRAXFSEthState *eth) 354 { 355 struct qemu_phy *phy; 356 unsigned int phy_duplex; 357 unsigned int mac_duplex; 358 int new_mm = 0; 359 360 phy = eth->mdio_bus.devs[eth->phyaddr]; 361 phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); 362 mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); 363 364 if (mac_duplex != phy_duplex) { 365 new_mm = 1; 366 } 367 368 if (eth->regs[RW_GEN_CTRL] & 1) { 369 if (new_mm != eth->duplex_mismatch) { 370 if (new_mm) { 371 printf("HW: WARNING ETH duplex mismatch MAC=%d PHY=%d\n", 372 mac_duplex, phy_duplex); 373 } else { 374 printf("HW: ETH duplex ok.\n"); 375 } 376 } 377 eth->duplex_mismatch = new_mm; 378 } 379 } 380 381 static uint64_t 382 eth_read(void *opaque, hwaddr addr, unsigned int size) 383 { 384 ETRAXFSEthState *eth = opaque; 385 uint32_t r = 0; 386 387 addr >>= 2; 388 389 switch (addr) { 390 case R_STAT: 391 r = eth->mdio_bus.mdio & 1; 392 break; 393 default: 394 r = eth->regs[addr]; 395 D(printf("%s %x\n", __func__, addr * 4)); 396 break; 397 } 398 return r; 399 } 400 401 static void eth_update_ma(ETRAXFSEthState *eth, int ma) 402 { 403 int reg; 404 int i = 0; 405 406 ma &= 1; 407 408 reg = RW_MA0_LO; 409 if (ma) { 410 reg = RW_MA1_LO; 411 } 412 413 eth->macaddr[ma][i++] = eth->regs[reg]; 414 eth->macaddr[ma][i++] = eth->regs[reg] >> 8; 415 eth->macaddr[ma][i++] = eth->regs[reg] >> 16; 416 eth->macaddr[ma][i++] = eth->regs[reg] >> 24; 417 eth->macaddr[ma][i++] = eth->regs[reg + 1]; 418 eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8; 419 420 D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma, 421 eth->macaddr[ma][0], eth->macaddr[ma][1], 422 eth->macaddr[ma][2], eth->macaddr[ma][3], 423 eth->macaddr[ma][4], eth->macaddr[ma][5])); 424 } 425 426 static void 427 eth_write(void *opaque, hwaddr addr, 428 uint64_t val64, unsigned int size) 429 { 430 ETRAXFSEthState *eth = opaque; 431 uint32_t value = val64; 432 433 addr >>= 2; 434 switch (addr) { 435 case RW_MA0_LO: 436 case RW_MA0_HI: 437 eth->regs[addr] = value; 438 eth_update_ma(eth, 0); 439 break; 440 case RW_MA1_LO: 441 case RW_MA1_HI: 442 eth->regs[addr] = value; 443 eth_update_ma(eth, 1); 444 break; 445 446 case RW_MGM_CTRL: 447 /* Attach an MDIO/PHY abstraction. */ 448 if (value & 2) { 449 eth->mdio_bus.mdio = value & 1; 450 } 451 if (eth->mdio_bus.mdc != (value & 4)) { 452 mdio_cycle(ð->mdio_bus); 453 eth_validate_duplex(eth); 454 } 455 eth->mdio_bus.mdc = !!(value & 4); 456 eth->regs[addr] = value; 457 break; 458 459 case RW_REC_CTRL: 460 eth->regs[addr] = value; 461 eth_validate_duplex(eth); 462 break; 463 464 default: 465 eth->regs[addr] = value; 466 D(printf("%s %x %x\n", __func__, addr, value)); 467 break; 468 } 469 } 470 471 /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom 472 filter dropping group addresses we have not joined. The filter has 64 473 bits (m). The has function is a simple nible xor of the group addr. */ 474 static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa) 475 { 476 unsigned int hsh; 477 int m_individual = eth->regs[RW_REC_CTRL] & 4; 478 int match; 479 480 /* First bit on the wire of a MAC address signals multicast or 481 physical address. */ 482 if (!m_individual && !(sa[0] & 1)) { 483 return 0; 484 } 485 486 /* Calculate the hash index for the GA registers. */ 487 hsh = 0; 488 hsh ^= (*sa) & 0x3f; 489 hsh ^= ((*sa) >> 6) & 0x03; 490 ++sa; 491 hsh ^= ((*sa) << 2) & 0x03c; 492 hsh ^= ((*sa) >> 4) & 0xf; 493 ++sa; 494 hsh ^= ((*sa) << 4) & 0x30; 495 hsh ^= ((*sa) >> 2) & 0x3f; 496 ++sa; 497 hsh ^= (*sa) & 0x3f; 498 hsh ^= ((*sa) >> 6) & 0x03; 499 ++sa; 500 hsh ^= ((*sa) << 2) & 0x03c; 501 hsh ^= ((*sa) >> 4) & 0xf; 502 ++sa; 503 hsh ^= ((*sa) << 4) & 0x30; 504 hsh ^= ((*sa) >> 2) & 0x3f; 505 506 hsh &= 63; 507 if (hsh > 31) { 508 match = eth->regs[RW_GA_HI] & (1 << (hsh - 32)); 509 } else { 510 match = eth->regs[RW_GA_LO] & (1 << hsh); 511 } 512 D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh, 513 eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match)); 514 return match; 515 } 516 517 static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) 518 { 519 unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 520 ETRAXFSEthState *eth = qemu_get_nic_opaque(nc); 521 int use_ma0 = eth->regs[RW_REC_CTRL] & 1; 522 int use_ma1 = eth->regs[RW_REC_CTRL] & 2; 523 int r_bcast = eth->regs[RW_REC_CTRL] & 8; 524 525 if (size < 12) { 526 return -1; 527 } 528 529 D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n", 530 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 531 use_ma0, use_ma1, r_bcast)); 532 533 /* Does the frame get through the address filters? */ 534 if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6)) 535 && (!use_ma1 || memcmp(buf, eth->macaddr[1], 6)) 536 && (!r_bcast || memcmp(buf, sa_bcast, 6)) 537 && !eth_match_groupaddr(eth, buf)) { 538 return size; 539 } 540 541 /* FIXME: Find another way to pass on the fake csum. */ 542 etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1); 543 544 return size; 545 } 546 547 static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop) 548 { 549 ETRAXFSEthState *eth = opaque; 550 551 D(printf("%s buf=%p len=%d\n", __func__, buf, len)); 552 qemu_send_packet(qemu_get_queue(eth->nic), buf, len); 553 return len; 554 } 555 556 static void eth_set_link(NetClientState *nc) 557 { 558 ETRAXFSEthState *eth = qemu_get_nic_opaque(nc); 559 D(printf("%s %d\n", __func__, nc->link_down)); 560 eth->phy.link = !nc->link_down; 561 } 562 563 static const MemoryRegionOps eth_ops = { 564 .read = eth_read, 565 .write = eth_write, 566 .endianness = DEVICE_LITTLE_ENDIAN, 567 .valid = { 568 .min_access_size = 4, 569 .max_access_size = 4 570 } 571 }; 572 573 static NetClientInfo net_etraxfs_info = { 574 .type = NET_CLIENT_DRIVER_NIC, 575 .size = sizeof(NICState), 576 .receive = eth_receive, 577 .link_status_changed = eth_set_link, 578 }; 579 580 static void etraxfs_eth_reset(DeviceState *dev) 581 { 582 ETRAXFSEthState *s = ETRAX_FS_ETH(dev); 583 584 memset(s->regs, 0, sizeof(s->regs)); 585 memset(s->macaddr, 0, sizeof(s->macaddr)); 586 s->duplex_mismatch = 0; 587 588 s->mdio_bus.mdc = 0; 589 s->mdio_bus.mdio = 0; 590 s->mdio_bus.state = 0; 591 s->mdio_bus.drive = 0; 592 s->mdio_bus.cnt = 0; 593 s->mdio_bus.addr = 0; 594 s->mdio_bus.opc = 0; 595 s->mdio_bus.req = 0; 596 s->mdio_bus.data = 0; 597 598 tdk_reset(&s->phy); 599 } 600 601 static void etraxfs_eth_realize(DeviceState *dev, Error **errp) 602 { 603 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 604 ETRAXFSEthState *s = ETRAX_FS_ETH(dev); 605 606 if (!s->dma_out || !s->dma_in) { 607 error_setg(errp, "Unconnected ETRAX-FS Ethernet MAC"); 608 return; 609 } 610 611 s->dma_out->client.push = eth_tx_push; 612 s->dma_out->client.opaque = s; 613 s->dma_in->client.opaque = s; 614 s->dma_in->client.pull = NULL; 615 616 memory_region_init_io(&s->mmio, OBJECT(dev), ð_ops, s, 617 "etraxfs-eth", 0x5c); 618 sysbus_init_mmio(sbd, &s->mmio); 619 620 qemu_macaddr_default_if_unset(&s->conf.macaddr); 621 s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, 622 object_get_typename(OBJECT(s)), dev->id, s); 623 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); 624 625 s->phy.read = tdk_read; 626 s->phy.write = tdk_write; 627 mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr); 628 } 629 630 static Property etraxfs_eth_properties[] = { 631 DEFINE_PROP_UINT32("phyaddr", ETRAXFSEthState, phyaddr, 1), 632 DEFINE_NIC_PROPERTIES(ETRAXFSEthState, conf), 633 DEFINE_PROP_END_OF_LIST(), 634 }; 635 636 static void etraxfs_eth_class_init(ObjectClass *klass, void *data) 637 { 638 DeviceClass *dc = DEVICE_CLASS(klass); 639 640 dc->realize = etraxfs_eth_realize; 641 dc->reset = etraxfs_eth_reset; 642 dc->props = etraxfs_eth_properties; 643 /* Reason: dma_out, dma_in are not user settable */ 644 dc->user_creatable = false; 645 } 646 647 648 /* Instantiate an ETRAXFS Ethernet MAC. */ 649 DeviceState * 650 etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, 651 struct etraxfs_dma_client *dma_out, 652 struct etraxfs_dma_client *dma_in) 653 { 654 DeviceState *dev; 655 qemu_check_nic_model(nd, "fseth"); 656 657 dev = qdev_create(NULL, "etraxfs-eth"); 658 qdev_set_nic_properties(dev, nd); 659 qdev_prop_set_uint32(dev, "phyaddr", phyaddr); 660 661 /* 662 * TODO: QOM design, define a QOM interface for "I am an etraxfs 663 * DMA client" (which replaces the current 'struct 664 * etraxfs_dma_client' ad-hoc interface), implement it on the 665 * ethernet device, and then have QOM link properties on the DMA 666 * controller device so that you can pass the interface 667 * implementations to it. 668 */ 669 ETRAX_FS_ETH(dev)->dma_out = dma_out; 670 ETRAX_FS_ETH(dev)->dma_in = dma_in; 671 qdev_init_nofail(dev); 672 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); 673 674 return dev; 675 } 676 677 static const TypeInfo etraxfs_eth_info = { 678 .name = TYPE_ETRAX_FS_ETH, 679 .parent = TYPE_SYS_BUS_DEVICE, 680 .instance_size = sizeof(ETRAXFSEthState), 681 .class_init = etraxfs_eth_class_init, 682 }; 683 684 static void etraxfs_eth_register_types(void) 685 { 686 type_register_static(&etraxfs_eth_info); 687 } 688 689 type_init(etraxfs_eth_register_types) 690