Revision c6488268

b/hw/etraxfs_eth.c
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 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 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 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 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);

Also available in: Unified diff