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
This commit is contained in:
parent
9d92659858
commit
c64882682d
@ -30,6 +30,12 @@
|
||||
|
||||
#define D(x)
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
|
||||
/*
|
||||
* The MDIO extensions in the TDK PHY model were reversed engineered from the
|
||||
* linux driver (PHYID and Diagnostics reg).
|
||||
@ -78,9 +84,12 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
|
||||
int speed_100 = 0;
|
||||
|
||||
/* Are we advertising 100 half or 100 duplex ? */
|
||||
speed_100 = !!(phy->regs[4] & 0x180);
|
||||
speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
|
||||
speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
|
||||
|
||||
/* Are we advertising 10 duplex or 100 duplex ? */
|
||||
duplex = !!(phy->regs[4] & 0x180);
|
||||
duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
|
||||
duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
|
||||
r = (speed_100 << 10) | (duplex << 11);
|
||||
}
|
||||
break;
|
||||
@ -322,10 +331,40 @@ struct fs_eth
|
||||
|
||||
/* MDIO bus. */
|
||||
struct qemu_mdio mdio_bus;
|
||||
unsigned int phyaddr;
|
||||
int duplex_mismatch;
|
||||
|
||||
/* PHY. */
|
||||
struct qemu_phy phy;
|
||||
};
|
||||
|
||||
static void eth_validate_duplex(struct fs_eth *eth)
|
||||
{
|
||||
struct qemu_phy *phy;
|
||||
unsigned int phy_duplex;
|
||||
unsigned int mac_duplex;
|
||||
int new_mm = 0;
|
||||
|
||||
phy = eth->mdio_bus.devs[eth->phyaddr];
|
||||
phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
|
||||
mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
|
||||
|
||||
if (mac_duplex != phy_duplex)
|
||||
new_mm = 1;
|
||||
|
||||
if (eth->regs[RW_GEN_CTRL] & 1) {
|
||||
if (new_mm != eth->duplex_mismatch) {
|
||||
if (new_mm)
|
||||
printf("HW: WARNING "
|
||||
"ETH duplex mismatch MAC=%d PHY=%d\n",
|
||||
mac_duplex, phy_duplex);
|
||||
else
|
||||
printf("HW: ETH duplex ok.\n");
|
||||
}
|
||||
eth->duplex_mismatch = new_mm;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
struct fs_eth *eth = opaque;
|
||||
@ -418,11 +457,18 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
/* Attach an MDIO/PHY abstraction. */
|
||||
if (value & 2)
|
||||
eth->mdio_bus.mdio = value & 1;
|
||||
if (eth->mdio_bus.mdc != (value & 4))
|
||||
if (eth->mdio_bus.mdc != (value & 4)) {
|
||||
mdio_cycle(ð->mdio_bus);
|
||||
eth_validate_duplex(eth);
|
||||
}
|
||||
eth->mdio_bus.mdc = !!(value & 4);
|
||||
break;
|
||||
|
||||
case RW_REC_CTRL:
|
||||
eth->regs[addr] = value;
|
||||
eth_validate_duplex(eth);
|
||||
break;
|
||||
|
||||
default:
|
||||
eth->regs[addr] = value;
|
||||
D(printf ("%s %x %x\n",
|
||||
@ -591,8 +637,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
|
||||
eth->dma_in = dma + 1;
|
||||
|
||||
/* Connect the phy. */
|
||||
eth->phyaddr = 1;
|
||||
tdk_init(ð->phy);
|
||||
mdio_attach(ð->mdio_bus, ð->phy, 0x1);
|
||||
mdio_attach(ð->mdio_bus, ð->phy, eth->phyaddr);
|
||||
|
||||
eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
|
||||
cpu_register_physical_memory (base, 0x5c, eth->ethregs);
|
||||
|
Loading…
Reference in New Issue
Block a user