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 #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 union { 342 void *vdma_out; 343 struct etraxfs_dma_client *dma_out; 344 }; 345 union { 346 void *vdma_in; 347 struct etraxfs_dma_client *dma_in; 348 }; 349 350 /* MDIO bus. */ 351 struct qemu_mdio mdio_bus; 352 unsigned int phyaddr; 353 int duplex_mismatch; 354 355 /* PHY. */ 356 struct qemu_phy phy; 357 } ETRAXFSEthState; 358 359 static void eth_validate_duplex(ETRAXFSEthState *eth) 360 { 361 struct qemu_phy *phy; 362 unsigned int phy_duplex; 363 unsigned int mac_duplex; 364 int new_mm = 0; 365 366 phy = eth->mdio_bus.devs[eth->phyaddr]; 367 phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); 368 mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); 369 370 if (mac_duplex != phy_duplex) { 371 new_mm = 1; 372 } 373 374 if (eth->regs[RW_GEN_CTRL] & 1) { 375 if (new_mm != eth->duplex_mismatch) { 376 if (new_mm) { 377 printf("HW: WARNING ETH duplex mismatch MAC=%d PHY=%d\n", 378 mac_duplex, phy_duplex); 379 } else { 380 printf("HW: ETH duplex ok.\n"); 381 } 382 } 383 eth->duplex_mismatch = new_mm; 384 } 385 } 386 387 static uint64_t 388 eth_read(void *opaque, hwaddr addr, unsigned int size) 389 { 390 ETRAXFSEthState *eth = opaque; 391 uint32_t r = 0; 392 393 addr >>= 2; 394 395 switch (addr) { 396 case R_STAT: 397 r = eth->mdio_bus.mdio & 1; 398 break; 399 default: 400 r = eth->regs[addr]; 401 D(printf("%s %x\n", __func__, addr * 4)); 402 break; 403 } 404 return r; 405 } 406 407 static void eth_update_ma(ETRAXFSEthState *eth, int ma) 408 { 409 int reg; 410 int i = 0; 411 412 ma &= 1; 413 414 reg = RW_MA0_LO; 415 if (ma) { 416 reg = RW_MA1_LO; 417 } 418 419 eth->macaddr[ma][i++] = eth->regs[reg]; 420 eth->macaddr[ma][i++] = eth->regs[reg] >> 8; 421 eth->macaddr[ma][i++] = eth->regs[reg] >> 16; 422 eth->macaddr[ma][i++] = eth->regs[reg] >> 24; 423 eth->macaddr[ma][i++] = eth->regs[reg + 1]; 424 eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8; 425 426 D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma, 427 eth->macaddr[ma][0], eth->macaddr[ma][1], 428 eth->macaddr[ma][2], eth->macaddr[ma][3], 429 eth->macaddr[ma][4], eth->macaddr[ma][5])); 430 } 431 432 static void 433 eth_write(void *opaque, hwaddr addr, 434 uint64_t val64, unsigned int size) 435 { 436 ETRAXFSEthState *eth = opaque; 437 uint32_t value = val64; 438 439 addr >>= 2; 440 switch (addr) { 441 case RW_MA0_LO: 442 case RW_MA0_HI: 443 eth->regs[addr] = value; 444 eth_update_ma(eth, 0); 445 break; 446 case RW_MA1_LO: 447 case RW_MA1_HI: 448 eth->regs[addr] = value; 449 eth_update_ma(eth, 1); 450 break; 451 452 case RW_MGM_CTRL: 453 /* Attach an MDIO/PHY abstraction. */ 454 if (value & 2) { 455 eth->mdio_bus.mdio = value & 1; 456 } 457 if (eth->mdio_bus.mdc != (value & 4)) { 458 mdio_cycle(ð->mdio_bus); 459 eth_validate_duplex(eth); 460 } 461 eth->mdio_bus.mdc = !!(value & 4); 462 eth->regs[addr] = value; 463 break; 464 465 case RW_REC_CTRL: 466 eth->regs[addr] = value; 467 eth_validate_duplex(eth); 468 break; 469 470 default: 471 eth->regs[addr] = value; 472 D(printf("%s %x %x\n", __func__, addr, value)); 473 break; 474 } 475 } 476 477 /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom 478 filter dropping group addresses we have not joined. The filter has 64 479 bits (m). The has function is a simple nible xor of the group addr. */ 480 static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa) 481 { 482 unsigned int hsh; 483 int m_individual = eth->regs[RW_REC_CTRL] & 4; 484 int match; 485 486 /* First bit on the wire of a MAC address signals multicast or 487 physical address. */ 488 if (!m_individual && !(sa[0] & 1)) { 489 return 0; 490 } 491 492 /* Calculate the hash index for the GA registers. */ 493 hsh = 0; 494 hsh ^= (*sa) & 0x3f; 495 hsh ^= ((*sa) >> 6) & 0x03; 496 ++sa; 497 hsh ^= ((*sa) << 2) & 0x03c; 498 hsh ^= ((*sa) >> 4) & 0xf; 499 ++sa; 500 hsh ^= ((*sa) << 4) & 0x30; 501 hsh ^= ((*sa) >> 2) & 0x3f; 502 ++sa; 503 hsh ^= (*sa) & 0x3f; 504 hsh ^= ((*sa) >> 6) & 0x03; 505 ++sa; 506 hsh ^= ((*sa) << 2) & 0x03c; 507 hsh ^= ((*sa) >> 4) & 0xf; 508 ++sa; 509 hsh ^= ((*sa) << 4) & 0x30; 510 hsh ^= ((*sa) >> 2) & 0x3f; 511 512 hsh &= 63; 513 if (hsh > 31) { 514 match = eth->regs[RW_GA_HI] & (1 << (hsh - 32)); 515 } else { 516 match = eth->regs[RW_GA_LO] & (1 << hsh); 517 } 518 D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh, 519 eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match)); 520 return match; 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 ETRAXFSEthState *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 ETRAXFSEthState *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 ETRAXFSEthState *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 NetClientInfo net_etraxfs_info = { 580 .type = NET_CLIENT_OPTIONS_KIND_NIC, 581 .size = sizeof(NICState), 582 .receive = eth_receive, 583 .link_status_changed = eth_set_link, 584 }; 585 586 static int fs_eth_init(SysBusDevice *sbd) 587 { 588 DeviceState *dev = DEVICE(sbd); 589 ETRAXFSEthState *s = ETRAX_FS_ETH(dev); 590 591 if (!s->dma_out || !s->dma_in) { 592 hw_error("Unconnected ETRAX-FS Ethernet MAC.\n"); 593 } 594 595 s->dma_out->client.push = eth_tx_push; 596 s->dma_out->client.opaque = s; 597 s->dma_in->client.opaque = s; 598 s->dma_in->client.pull = NULL; 599 600 memory_region_init_io(&s->mmio, OBJECT(dev), ð_ops, s, 601 "etraxfs-eth", 0x5c); 602 sysbus_init_mmio(sbd, &s->mmio); 603 604 qemu_macaddr_default_if_unset(&s->conf.macaddr); 605 s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, 606 object_get_typename(OBJECT(s)), dev->id, s); 607 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); 608 609 610 tdk_init(&s->phy); 611 mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr); 612 return 0; 613 } 614 615 static Property etraxfs_eth_properties[] = { 616 DEFINE_PROP_UINT32("phyaddr", ETRAXFSEthState, phyaddr, 1), 617 DEFINE_PROP_PTR("dma_out", ETRAXFSEthState, vdma_out), 618 DEFINE_PROP_PTR("dma_in", ETRAXFSEthState, vdma_in), 619 DEFINE_NIC_PROPERTIES(ETRAXFSEthState, conf), 620 DEFINE_PROP_END_OF_LIST(), 621 }; 622 623 static void etraxfs_eth_class_init(ObjectClass *klass, void *data) 624 { 625 DeviceClass *dc = DEVICE_CLASS(klass); 626 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 627 628 k->init = fs_eth_init; 629 dc->props = etraxfs_eth_properties; 630 /* Reason: pointer properties "dma_out", "dma_in" */ 631 dc->cannot_instantiate_with_device_add_yet = true; 632 } 633 634 static const TypeInfo etraxfs_eth_info = { 635 .name = TYPE_ETRAX_FS_ETH, 636 .parent = TYPE_SYS_BUS_DEVICE, 637 .instance_size = sizeof(ETRAXFSEthState), 638 .class_init = etraxfs_eth_class_init, 639 }; 640 641 static void etraxfs_eth_register_types(void) 642 { 643 type_register_static(&etraxfs_eth_info); 644 } 645 646 type_init(etraxfs_eth_register_types) 647