Commit c64882682db39f594bec1cec5a56e943f58220f2

Authored by edgar_igl
1 parent 9d926598

ETRAX-FS: Correct ethernet PHY diagnostics register reads.

* Correct ethernet PHY diagnostics register reads.
* Add friendly names for the speed/duplex fields.
* Report duplex mismatches between MAC and PHY.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5300 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 51 additions and 4 deletions
hw/etraxfs_eth.c
... ... @@ -30,6 +30,12 @@
30 30  
31 31 #define D(x)
32 32  
  33 +/* Advertisement control register. */
  34 +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
  35 +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
  36 +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
  37 +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
  38 +
33 39 /*
34 40 * The MDIO extensions in the TDK PHY model were reversed engineered from the
35 41 * linux driver (PHYID and Diagnostics reg).
... ... @@ -78,9 +84,12 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
78 84 int speed_100 = 0;
79 85  
80 86 /* Are we advertising 100 half or 100 duplex ? */
81   - speed_100 = !!(phy->regs[4] & 0x180);
  87 + speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
  88 + speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
  89 +
82 90 /* Are we advertising 10 duplex or 100 duplex ? */
83   - duplex = !!(phy->regs[4] & 0x180);
  91 + duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
  92 + duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
84 93 r = (speed_100 << 10) | (duplex << 11);
85 94 }
86 95 break;
... ... @@ -322,10 +331,40 @@ struct fs_eth
322 331  
323 332 /* MDIO bus. */
324 333 struct qemu_mdio mdio_bus;
  334 + unsigned int phyaddr;
  335 + int duplex_mismatch;
  336 +
325 337 /* PHY. */
326 338 struct qemu_phy phy;
327 339 };
328 340  
  341 +static void eth_validate_duplex(struct fs_eth *eth)
  342 +{
  343 + struct qemu_phy *phy;
  344 + unsigned int phy_duplex;
  345 + unsigned int mac_duplex;
  346 + int new_mm = 0;
  347 +
  348 + phy = eth->mdio_bus.devs[eth->phyaddr];
  349 + phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
  350 + mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
  351 +
  352 + if (mac_duplex != phy_duplex)
  353 + new_mm = 1;
  354 +
  355 + if (eth->regs[RW_GEN_CTRL] & 1) {
  356 + if (new_mm != eth->duplex_mismatch) {
  357 + if (new_mm)
  358 + printf("HW: WARNING "
  359 + "ETH duplex mismatch MAC=%d PHY=%d\n",
  360 + mac_duplex, phy_duplex);
  361 + else
  362 + printf("HW: ETH duplex ok.\n");
  363 + }
  364 + eth->duplex_mismatch = new_mm;
  365 + }
  366 +}
  367 +
329 368 static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr)
330 369 {
331 370 struct fs_eth *eth = opaque;
... ... @@ -418,11 +457,18 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
418 457 /* Attach an MDIO/PHY abstraction. */
419 458 if (value & 2)
420 459 eth->mdio_bus.mdio = value & 1;
421   - if (eth->mdio_bus.mdc != (value & 4))
  460 + if (eth->mdio_bus.mdc != (value & 4)) {
422 461 mdio_cycle(&eth->mdio_bus);
  462 + eth_validate_duplex(eth);
  463 + }
423 464 eth->mdio_bus.mdc = !!(value & 4);
424 465 break;
425 466  
  467 + case RW_REC_CTRL:
  468 + eth->regs[addr] = value;
  469 + eth_validate_duplex(eth);
  470 + break;
  471 +
426 472 default:
427 473 eth->regs[addr] = value;
428 474 D(printf ("%s %x %x\n",
... ... @@ -591,8 +637,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
591 637 eth->dma_in = dma + 1;
592 638  
593 639 /* Connect the phy. */
  640 + eth->phyaddr = 1;
594 641 tdk_init(&eth->phy);
595   - mdio_attach(&eth->mdio_bus, &eth->phy, 0x1);
  642 + mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
596 643  
597 644 eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
598 645 cpu_register_physical_memory (base, 0x5c, eth->ethregs);
... ...