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,6 +30,12 @@
30 30
31 #define D(x) 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 * The MDIO extensions in the TDK PHY model were reversed engineered from the 40 * The MDIO extensions in the TDK PHY model were reversed engineered from the
35 * linux driver (PHYID and Diagnostics reg). 41 * linux driver (PHYID and Diagnostics reg).
@@ -78,9 +84,12 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) @@ -78,9 +84,12 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
78 int speed_100 = 0; 84 int speed_100 = 0;
79 85
80 /* Are we advertising 100 half or 100 duplex ? */ 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 /* Are we advertising 10 duplex or 100 duplex ? */ 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 r = (speed_100 << 10) | (duplex << 11); 93 r = (speed_100 << 10) | (duplex << 11);
85 } 94 }
86 break; 95 break;
@@ -322,10 +331,40 @@ struct fs_eth @@ -322,10 +331,40 @@ struct fs_eth
322 331
323 /* MDIO bus. */ 332 /* MDIO bus. */
324 struct qemu_mdio mdio_bus; 333 struct qemu_mdio mdio_bus;
  334 + unsigned int phyaddr;
  335 + int duplex_mismatch;
  336 +
325 /* PHY. */ 337 /* PHY. */
326 struct qemu_phy phy; 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 static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr) 368 static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr)
330 { 369 {
331 struct fs_eth *eth = opaque; 370 struct fs_eth *eth = opaque;
@@ -418,11 +457,18 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) @@ -418,11 +457,18 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
418 /* Attach an MDIO/PHY abstraction. */ 457 /* Attach an MDIO/PHY abstraction. */
419 if (value & 2) 458 if (value & 2)
420 eth->mdio_bus.mdio = value & 1; 459 eth->mdio_bus.mdio = value & 1;
421 - if (eth->mdio_bus.mdc != (value & 4)) 460 + if (eth->mdio_bus.mdc != (value & 4)) {
422 mdio_cycle(&eth->mdio_bus); 461 mdio_cycle(&eth->mdio_bus);
  462 + eth_validate_duplex(eth);
  463 + }
423 eth->mdio_bus.mdc = !!(value & 4); 464 eth->mdio_bus.mdc = !!(value & 4);
424 break; 465 break;
425 466
  467 + case RW_REC_CTRL:
  468 + eth->regs[addr] = value;
  469 + eth_validate_duplex(eth);
  470 + break;
  471 +
426 default: 472 default:
427 eth->regs[addr] = value; 473 eth->regs[addr] = value;
428 D(printf ("%s %x %x\n", 474 D(printf ("%s %x %x\n",
@@ -591,8 +637,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, @@ -591,8 +637,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
591 eth->dma_in = dma + 1; 637 eth->dma_in = dma + 1;
592 638
593 /* Connect the phy. */ 639 /* Connect the phy. */
  640 + eth->phyaddr = 1;
594 tdk_init(&eth->phy); 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 eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth); 644 eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
598 cpu_register_physical_memory (base, 0x5c, eth->ethregs); 645 cpu_register_physical_memory (base, 0x5c, eth->ethregs);