diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index f7bdd1465bf8d082cd85bcb1a64d5a31a2d51c5b..c20524bd8cced1d6ac638fb902cb35bf4c81eb7d 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -304,10 +304,11 @@ void axisdev88_init (ram_addr_t ram_size, int vga_ram_size, /* Add the two ethernet blocks. */ nd_table[0].model = nd_table[0].model ? nd_table[0].model : "fseth"; - eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000); + eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000, 1); if (nb_nics > 1) { nd_table[1].model = nd_table[1].model ? nd_table[1].model : "fseth"; - eth[1] = etraxfs_eth_init(&nd_table[1], env, pic->irq + 26, 0x30036000); + eth[1] = etraxfs_eth_init(&nd_table[1], env, + pic->irq + 26, 0x30036000, 2); } /* The DMA Connector block is missing, hardwire things for now. */ diff --git a/hw/etraxfs.c b/hw/etraxfs.c index 01b5a6e6fe486d4f954f118ddad8aa14c3df08d8..01569bc1b995194af7399e8cb8c96f41a15b7768 100644 --- a/hw/etraxfs.c +++ b/hw/etraxfs.c @@ -95,10 +95,11 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size, /* Add the two ethernet blocks. */ nd_table[0].model = nd_table[0].model ? nd_table[0].model : "fseth"; - eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000); + eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000, 1); if (nb_nics > 1) { nd_table[1].model = nd_table[1].model ? nd_table[1].model : "fseth"; - eth[1] = etraxfs_eth_init(&nd_table[1], env, pic->irq + 26, 0x30036000); + eth[1] = etraxfs_eth_init(&nd_table[1], env, + pic->irq + 26, 0x30036000, 2); } /* The DMA Connector block is missing, hardwire things for now. */ diff --git a/hw/etraxfs.h b/hw/etraxfs.h index 0c9fdbb608e687e69d15c1bcb07f213981aee407..17dca29a446a25ba5062c7c9816de971c7ba3b78 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -37,6 +37,6 @@ struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base); void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi, target_phys_addr_t base); void *etraxfs_eth_init(NICInfo *nd, CPUState *env, - qemu_irq *irq, target_phys_addr_t base); + qemu_irq *irq, target_phys_addr_t base, int phyaddr); void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr, target_phys_addr_t base); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 239e0d872c40e937fe9151d2ce1793f58e24433d..4ae97b11eb35feccd8d8939c15267494f706561b 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -45,6 +45,8 @@ struct qemu_phy { uint32_t regs[32]; + int link; + unsigned int (*read)(struct qemu_phy *phy, unsigned int req); void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data); @@ -59,13 +61,15 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) switch (regnum) { case 1: + if (!phy->link) + break; /* MR1. */ /* Speeds and modes. */ r |= (1 << 13) | (1 << 14); r |= (1 << 11) | (1 << 12); r |= (1 << 5); /* Autoneg complete. */ r |= (1 << 3); /* Autoneg able. */ - r |= (1 << 2); /* Link. */ + r |= (1 << 2); /* link. */ break; case 5: /* Link partner ability. @@ -83,6 +87,9 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) int duplex = 0; int speed_100 = 0; + if (!phy->link) + break; + /* Are we advertising 100 half or 100 duplex ? */ speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); @@ -125,6 +132,7 @@ tdk_init(struct qemu_phy *phy) phy->regs[3] = 0xe400; /* Autonegotiation advertisement reg. */ phy->regs[4] = 0x01E1; + phy->link = 1; phy->read = tdk_read; phy->write = tdk_write; @@ -530,6 +538,13 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len) return len; } +static void eth_set_link(VLANClientState *vc) +{ + struct fs_eth *eth = vc->opaque; + D(printf("%s %d\n", __func__, vc->link_down)); + eth->phy.link = !vc->link_down; +} + static CPUReadMemoryFunc *eth_read[] = { NULL, NULL, ð_readl, @@ -541,7 +556,7 @@ static CPUWriteMemoryFunc *eth_write[] = { }; void *etraxfs_eth_init(NICInfo *nd, CPUState *env, - qemu_irq *irq, target_phys_addr_t base) + qemu_irq *irq, target_phys_addr_t base, int phyaddr) { struct etraxfs_dma_client *dma = NULL; struct fs_eth *eth = NULL; @@ -565,7 +580,7 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, eth->dma_in = dma + 1; /* Connect the phy. */ - eth->phyaddr = 1; + eth->phyaddr = phyaddr & 0x1f; tdk_init(ð->phy); mdio_attach(ð->mdio_bus, ð->phy, eth->phyaddr); @@ -574,6 +589,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, eth_receive, eth_can_receive, eth); + eth->vc->opaque = eth; + eth->vc->link_status_changed = eth_set_link; return dma; err: