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 <stdio.h> 26 #include "hw/sysbus.h" 27 #include "net/net.h" 28 #include "hw/cris/etraxfs.h" 29 30 #define D(x) 31 32 /* Advertisement control register. */ 33 #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ 34 #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ 35 #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ 36 #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ 37 38 /* 39 * The MDIO extensions in the TDK PHY model were reversed engineered from the 40 * linux driver (PHYID and Diagnostics reg). 41 * TODO: Add friendly names for the register nums. 42 */ 43 struct qemu_phy 44 { 45 uint32_t regs[32]; 46 47 int link; 48 49 unsigned int (*read)(struct qemu_phy *phy, unsigned int req); 50 void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data); 51 }; 52 53 static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) 54 { 55 int regnum; 56 unsigned r = 0; 57 58 regnum = req & 0x1f; 59 60 switch (regnum) { 61 case 1: 62 if (!phy->link) { 63 break; 64 } 65 /* MR1. */ 66 /* Speeds and modes. */ 67 r |= (1 << 13) | (1 << 14); 68 r |= (1 << 11) | (1 << 12); 69 r |= (1 << 5); /* Autoneg complete. */ 70 r |= (1 << 3); /* Autoneg able. */ 71 r |= (1 << 2); /* link. */ 72 break; 73 case 5: 74 /* Link partner ability. 75 We are kind; always agree with whatever best mode 76 the guest advertises. */ 77 r = 1 << 14; /* Success. */ 78 /* Copy advertised modes. */ 79 r |= phy->regs[4] & (15 << 5); 80 /* Autoneg support. */ 81 r |= 1; 82 break; 83 case 18: 84 { 85 /* Diagnostics reg. */ 86 int duplex = 0; 87 int speed_100 = 0; 88 89 if (!phy->link) { 90 break; 91 } 92 93 /* Are we advertising 100 half or 100 duplex ? */ 94 speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); 95 speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); 96 97 /* Are we advertising 10 duplex or 100 duplex ? */ 98 duplex = !!(phy->regs[4] & ADVERTISE_100FULL); 99 duplex |= !!(phy->regs[4] & ADVERTISE_10FULL); 100 r = (speed_100 << 10) | (duplex << 11); 101 } 102 break; 103 104 default: 105 r = phy->regs[regnum]; 106 break; 107 } 108 D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum)); 109 return r; 110 } 111 112 static void 113 tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data) 114 { 115 int regnum; 116 117 regnum = req & 0x1f; 118 D(printf("%s reg[%d] = %x\n", __func__, regnum, data)); 119 switch (regnum) { 120 default: 121 phy->regs[regnum] = data; 122 break; 123 } 124 } 125 126 static void 127 tdk_init(struct qemu_phy *phy) 128 { 129 phy->regs[0] = 0x3100; 130 /* PHY Id. */ 131 phy->regs[2] = 0x0300; 132 phy->regs[3] = 0xe400; 133 /* Autonegotiation advertisement reg. */ 134 phy->regs[4] = 0x01E1; 135 phy->link = 1; 136 137 phy->read = tdk_read; 138 phy->write = tdk_write; 139 } 140 141 struct qemu_mdio 142 { 143 /* bus. */ 144 int mdc; 145 int mdio; 146 147 /* decoder. */ 148 enum { 149 PREAMBLE, 150 SOF, 151 OPC, 152 ADDR, 153 REQ, 154 TURNAROUND, 155 DATA 156 } state; 157 unsigned int drive; 158 159 unsigned int cnt; 160 unsigned int addr; 161 unsigned int opc; 162 unsigned int req; 163 unsigned int data; 164 165 struct qemu_phy *devs[32]; 166 }; 167 168 static void 169 mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) 170 { 171 bus->devs[addr & 0x1f] = phy; 172 } 173 174 #ifdef USE_THIS_DEAD_CODE 175 static void 176 mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) 177 { 178 bus->devs[addr & 0x1f] = NULL; 179 } 180 #endif 181 182 static void mdio_read_req(struct qemu_mdio *bus) 183 { 184 struct qemu_phy *phy; 185 186 phy = bus->devs[bus->addr]; 187 if (phy && phy->read) { 188 bus->data = phy->read(phy, bus->req); 189 } else { 190 bus->data = 0xffff; 191 } 192 } 193 194 static void mdio_write_req(struct qemu_mdio *bus) 195 { 196 struct qemu_phy *phy; 197 198 phy = bus->devs[bus->addr]; 199 if (phy && phy->write) { 200 phy->write(phy, bus->req, bus->data); 201 } 202 } 203 204 static void mdio_cycle(struct qemu_mdio *bus) 205 { 206 bus->cnt++; 207 208 D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n", 209 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 struct fs_eth 326 { 327 SysBusDevice busdev; 328 MemoryRegion mmio; 329 NICState *nic; 330 NICConf conf; 331 332 /* Two addrs in the filter. */ 333 uint8_t macaddr[2][6]; 334 uint32_t regs[FS_ETH_MAX_REGS]; 335 336 union { 337 void *vdma_out; 338 struct etraxfs_dma_client *dma_out; 339 }; 340 union { 341 void *vdma_in; 342 struct etraxfs_dma_client *dma_in; 343 }; 344 345 /* MDIO bus. */ 346 struct qemu_mdio mdio_bus; 347 unsigned int phyaddr; 348 int duplex_mismatch; 349 350 /* PHY. */ 351 struct qemu_phy phy; 352 }; 353 354 static void eth_validate_duplex(struct fs_eth *eth) 355 { 356 struct qemu_phy *phy; 357 unsigned int phy_duplex; 358 unsigned int mac_duplex; 359 int new_mm = 0; 360 361 phy = eth->mdio_bus.devs[eth->phyaddr]; 362 phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); 363 mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); 364 365 if (mac_duplex != phy_duplex) { 366 new_mm = 1; 367 } 368 369 if (eth->regs[RW_GEN_CTRL] & 1) { 370 if (new_mm != eth->duplex_mismatch) { 371 if (new_mm) { 372 printf("HW: WARNING ETH duplex mismatch MAC=%d PHY=%d\n", 373 mac_duplex, phy_duplex); 374 } else { 375 printf("HW: ETH duplex ok.\n"); 376 } 377 } 378 eth->duplex_mismatch = new_mm; 379 } 380 } 381 382 static uint64_t 383 eth_read(void *opaque, hwaddr addr, unsigned int size) 384 { 385 struct fs_eth *eth = opaque; 386 uint32_t r = 0; 387 388 addr >>= 2; 389 390 switch (addr) { 391 case R_STAT: 392 r = eth->mdio_bus.mdio & 1; 393 break; 394 default: 395 r = eth->regs[addr]; 396 D(printf("%s %x\n", __func__, addr * 4)); 397 break; 398 } 399 return r; 400 } 401 402 static void eth_update_ma(struct fs_eth *eth, int ma) 403 { 404 int reg; 405 int i = 0; 406 407 ma &= 1; 408 409 reg = RW_MA0_LO; 410 if (ma) { 411 reg = RW_MA1_LO; 412 } 413 414 eth->macaddr[ma][i++] = eth->regs[reg]; 415 eth->macaddr[ma][i++] = eth->regs[reg] >> 8; 416 eth->macaddr[ma][i++] = eth->regs[reg] >> 16; 417 eth->macaddr[ma][i++] = eth->regs[reg] >> 24; 418 eth->macaddr[ma][i++] = eth->regs[reg + 1]; 419 eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8; 420 421 D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma, 422 eth->macaddr[ma][0], eth->macaddr[ma][1], 423 eth->macaddr[ma][2], eth->macaddr[ma][3], 424 eth->macaddr[ma][4], eth->macaddr[ma][5])); 425 } 426 427 static void 428 eth_write(void *opaque, hwaddr addr, 429 uint64_t val64, unsigned int size) 430 { 431 struct fs_eth *eth = opaque; 432 uint32_t value = val64; 433 434 addr >>= 2; 435 switch (addr) { 436 case RW_MA0_LO: 437 case RW_MA0_HI: 438 eth->regs[addr] = value; 439 eth_update_ma(eth, 0); 440 break; 441 case RW_MA1_LO: 442 case RW_MA1_HI: 443 eth->regs[addr] = value; 444 eth_update_ma(eth, 1); 445 break; 446 447 case RW_MGM_CTRL: 448 /* Attach an MDIO/PHY abstraction. */ 449 if (value & 2) { 450 eth->mdio_bus.mdio = value & 1; 451 } 452 if (eth->mdio_bus.mdc != (value & 4)) { 453 mdio_cycle(ð->mdio_bus); 454 eth_validate_duplex(eth); 455 } 456 eth->mdio_bus.mdc = !!(value & 4); 457 eth->regs[addr] = value; 458 break; 459 460 case RW_REC_CTRL: 461 eth->regs[addr] = value; 462 eth_validate_duplex(eth); 463 break; 464 465 default: 466 eth->regs[addr] = value; 467 D(printf("%s %x %x\n", __func__, addr, value)); 468 break; 469 } 470 } 471 472 /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom 473 filter dropping group addresses we have not joined. The filter has 64 474 bits (m). The has function is a simple nible xor of the group addr. */ 475 static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa) 476 { 477 unsigned int hsh; 478 int m_individual = eth->regs[RW_REC_CTRL] & 4; 479 int match; 480 481 /* First bit on the wire of a MAC address signals multicast or 482 physical address. */ 483 if (!m_individual && !(sa[0] & 1)) { 484 return 0; 485 } 486 487 /* Calculate the hash index for the GA registers. */ 488 hsh = 0; 489 hsh ^= (*sa) & 0x3f; 490 hsh ^= ((*sa) >> 6) & 0x03; 491 ++sa; 492 hsh ^= ((*sa) << 2) & 0x03c; 493 hsh ^= ((*sa) >> 4) & 0xf; 494 ++sa; 495 hsh ^= ((*sa) << 4) & 0x30; 496 hsh ^= ((*sa) >> 2) & 0x3f; 497 ++sa; 498 hsh ^= (*sa) & 0x3f; 499 hsh ^= ((*sa) >> 6) & 0x03; 500 ++sa; 501 hsh ^= ((*sa) << 2) & 0x03c; 502 hsh ^= ((*sa) >> 4) & 0xf; 503 ++sa; 504 hsh ^= ((*sa) << 4) & 0x30; 505 hsh ^= ((*sa) >> 2) & 0x3f; 506 507 hsh &= 63; 508 if (hsh > 31) { 509 match = eth->regs[RW_GA_HI] & (1 << (hsh - 32)); 510 } else { 511 match = eth->regs[RW_GA_LO] & (1 << hsh); 512 } 513 D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh, 514 eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match)); 515 return match; 516 } 517 518 static int eth_can_receive(NetClientState *nc) 519 { 520 return 1; 521 } 522 523 static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) 524 { 525 unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 526 struct fs_eth *eth = qemu_get_nic_opaque(nc); 527 int use_ma0 = eth->regs[RW_REC_CTRL] & 1; 528 int use_ma1 = eth->regs[RW_REC_CTRL] & 2; 529 int r_bcast = eth->regs[RW_REC_CTRL] & 8; 530 531 if (size < 12) { 532 return -1; 533 } 534 535 D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n", 536 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 537 use_ma0, use_ma1, r_bcast)); 538 539 /* Does the frame get through the address filters? */ 540 if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6)) 541 && (!use_ma1 || memcmp(buf, eth->macaddr[1], 6)) 542 && (!r_bcast || memcmp(buf, sa_bcast, 6)) 543 && !eth_match_groupaddr(eth, buf)) { 544 return size; 545 } 546 547 /* FIXME: Find another way to pass on the fake csum. */ 548 etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1); 549 550 return size; 551 } 552 553 static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop) 554 { 555 struct fs_eth *eth = opaque; 556 557 D(printf("%s buf=%p len=%d\n", __func__, buf, len)); 558 qemu_send_packet(qemu_get_queue(eth->nic), buf, len); 559 return len; 560 } 561 562 static void eth_set_link(NetClientState *nc) 563 { 564 struct fs_eth *eth = qemu_get_nic_opaque(nc); 565 D(printf("%s %d\n", __func__, nc->link_down)); 566 eth->phy.link = !nc->link_down; 567 } 568 569 static const MemoryRegionOps eth_ops = { 570 .read = eth_read, 571 .write = eth_write, 572 .endianness = DEVICE_LITTLE_ENDIAN, 573 .valid = { 574 .min_access_size = 4, 575 .max_access_size = 4 576 } 577 }; 578 579 static void eth_cleanup(NetClientState *nc) 580 { 581 struct fs_eth *eth = qemu_get_nic_opaque(nc); 582 583 /* Disconnect the client. */ 584 eth->dma_out->client.push = NULL; 585 eth->dma_out->client.opaque = NULL; 586 eth->dma_in->client.opaque = NULL; 587 eth->dma_in->client.pull = NULL; 588 g_free(eth); 589 } 590 591 static NetClientInfo net_etraxfs_info = { 592 .type = NET_CLIENT_OPTIONS_KIND_NIC, 593 .size = sizeof(NICState), 594 .can_receive = eth_can_receive, 595 .receive = eth_receive, 596 .cleanup = eth_cleanup, 597 .link_status_changed = eth_set_link, 598 }; 599 600 static int fs_eth_init(SysBusDevice *dev) 601 { 602 struct fs_eth *s = FROM_SYSBUS(typeof(*s), dev); 603 604 if (!s->dma_out || !s->dma_in) { 605 hw_error("Unconnected ETRAX-FS Ethernet MAC.\n"); 606 } 607 608 s->dma_out->client.push = eth_tx_push; 609 s->dma_out->client.opaque = s; 610 s->dma_in->client.opaque = s; 611 s->dma_in->client.pull = NULL; 612 613 memory_region_init_io(&s->mmio, NULL, ð_ops, s, "etraxfs-eth", 0x5c); 614 sysbus_init_mmio(dev, &s->mmio); 615 616 qemu_macaddr_default_if_unset(&s->conf.macaddr); 617 s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, 618 object_get_typename(OBJECT(s)), dev->qdev.id, s); 619 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); 620 621 622 tdk_init(&s->phy); 623 mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr); 624 return 0; 625 } 626 627 static Property etraxfs_eth_properties[] = { 628 DEFINE_PROP_UINT32("phyaddr", struct fs_eth, phyaddr, 1), 629 DEFINE_PROP_PTR("dma_out", struct fs_eth, vdma_out), 630 DEFINE_PROP_PTR("dma_in", struct fs_eth, vdma_in), 631 DEFINE_NIC_PROPERTIES(struct fs_eth, conf), 632 DEFINE_PROP_END_OF_LIST(), 633 }; 634 635 static void etraxfs_eth_class_init(ObjectClass *klass, void *data) 636 { 637 DeviceClass *dc = DEVICE_CLASS(klass); 638 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 639 640 k->init = fs_eth_init; 641 dc->props = etraxfs_eth_properties; 642 } 643 644 static const TypeInfo etraxfs_eth_info = { 645 .name = "etraxfs-eth", 646 .parent = TYPE_SYS_BUS_DEVICE, 647 .instance_size = sizeof(struct fs_eth), 648 .class_init = etraxfs_eth_class_init, 649 }; 650 651 static void etraxfs_eth_register_types(void) 652 { 653 type_register_static(&etraxfs_eth_info); 654 } 655 656 type_init(etraxfs_eth_register_types) 657