* [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register
@ 2012-03-22 10:01 Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 2/7] e1000: conditionally raise irq at the end of MDI cycle Jason Wang
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:01 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
This would be used be following patches.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000_hw.h | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/hw/e1000_hw.h b/hw/e1000_hw.h
index 9e29af8..c9cb79e 100644
--- a/hw/e1000_hw.h
+++ b/hw/e1000_hw.h
@@ -349,6 +349,18 @@
#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */
#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */
+/* PHY Control Register */
+#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */
+#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
+#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
+#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */
+#define MII_CR_POWER_DOWN 0x0800 /* Power down */
+#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
+#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */
+#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
+#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
+
/* PHY Status Register */
#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */
#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/7] e1000: conditionally raise irq at the end of MDI cycle
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
@ 2012-03-22 10:01 ` Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 3/7] e1000: PHY loopback mode support Jason Wang
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:01 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
According to the spec:
"When set to 1b by software, it causes an Interrupt to be
asserted to indicate the end of an MDI cycle."
We need check the Interrupt Enable bit and raise irq only when it is
set.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 7babc0b..dd6a97d 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -234,7 +234,10 @@ set_mdic(E1000State *s, int index, uint32_t val)
s->phy_reg[addr] = data;
}
s->mac_reg[MDIC] = val | E1000_MDIC_READY;
- set_ics(s, 0, E1000_ICR_MDAC);
+
+ if (val & E1000_MDIC_INT_EN) {
+ set_ics(s, 0, E1000_ICR_MDAC);
+ }
}
static uint32_t
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 3/7] e1000: PHY loopback mode support
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 2/7] e1000: conditionally raise irq at the end of MDI cycle Jason Wang
@ 2012-03-22 10:01 ` Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 4/7] e1000: introduce helpers to manipulate link status Jason Wang
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:01 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
The missing of loopback mode prevent the running of self diagnosis
program in guest. This patch adds this support.
After this patch, loopback test of ethtool were passed in guest.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index dd6a97d..bc26a0c 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -352,6 +352,16 @@ fcs_len(E1000State *s)
}
static void
+e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
+{
+ if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
+ s->nic->nc.info->receive(&s->nic->nc, buf, size);
+ } else {
+ qemu_send_packet(&s->nic->nc, buf, size);
+ }
+}
+
+static void
xmit_seg(E1000State *s)
{
uint16_t len, *sp;
@@ -400,9 +410,9 @@ xmit_seg(E1000State *s)
memmove(tp->vlan, tp->data, 4);
memmove(tp->data, tp->data + 4, 8);
memcpy(tp->data + 8, tp->vlan_header, 4);
- qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4);
+ e1000_send_packet(s, tp->vlan, tp->size + 4);
} else
- qemu_send_packet(&s->nic->nc, tp->data, tp->size);
+ e1000_send_packet(s, tp->data, tp->size);
s->mac_reg[TPT]++;
s->mac_reg[GPTC]++;
n = s->mac_reg[TOTL];
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 4/7] e1000: introduce helpers to manipulate link status
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 2/7] e1000: conditionally raise irq at the end of MDI cycle Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 3/7] e1000: PHY loopback mode support Jason Wang
@ 2012-03-22 10:02 ` Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 5/7] e1000: introduce bit for debugging PHY emulation Jason Wang
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:02 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
This patch introduces helpers to change link status bit for phy/mac
register. This would help to reduce code duplication and would be used
by following patches.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 23 +++++++++++++++++------
1 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index bc26a0c..fc30361 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -142,6 +142,20 @@ enum {
defreg(VET),
};
+static void
+e1000_link_down(E1000State *s)
+{
+ s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+}
+
+static void
+e1000_link_up(E1000State *s)
+{
+ s->mac_reg[STATUS] |= E1000_STATUS_LU;
+ s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+}
+
enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
static const char phy_regcap[0x20] = {
[PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
@@ -635,11 +649,9 @@ e1000_set_link_status(VLANClientState *nc)
uint32_t old_status = s->mac_reg[STATUS];
if (nc->link_down) {
- s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ e1000_link_down(s);
} else {
- s->mac_reg[STATUS] |= E1000_STATUS_LU;
- s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
+ e1000_link_up(s);
}
if (s->mac_reg[STATUS] != old_status)
@@ -1148,8 +1160,7 @@ static void e1000_reset(void *opaque)
memset(&d->tx, 0, sizeof d->tx);
if (d->nic->nc.link_down) {
- d->mac_reg[STATUS] &= ~E1000_STATUS_LU;
- d->phy_reg[PHY_STATUS] &= ~MII_SR_LINK_STATUS;
+ e1000_link_down(d);
}
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 5/7] e1000: introduce bit for debugging PHY emulation
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
` (2 preceding siblings ...)
2012-03-22 10:02 ` [Qemu-devel] [PATCH 4/7] e1000: introduce helpers to manipulate link status Jason Wang
@ 2012-03-22 10:02 ` Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 6/7] e1000: link auto-negotiation emulation Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 7/7] e1000: set E1000_ICR_INT_ASSERTED only for 8257x Jason Wang
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:02 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index fc30361..4eb95be 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -42,7 +42,7 @@ enum {
DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
DEBUG_UNKNOWN, DEBUG_TXSUM, DEBUG_TXERR, DEBUG_RXERR,
- DEBUG_RXFILTER, DEBUG_NOTYET,
+ DEBUG_RXFILTER, DEBUG_PHY, DEBUG_NOTYET,
};
#define DBGBIT(x) (1<<DEBUG_##x)
static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 6/7] e1000: link auto-negotiation emulation
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
` (3 preceding siblings ...)
2012-03-22 10:02 ` [Qemu-devel] [PATCH 5/7] e1000: introduce bit for debugging PHY emulation Jason Wang
@ 2012-03-22 10:02 ` Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 7/7] e1000: set E1000_ICR_INT_ASSERTED only for 8257x Jason Wang
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:02 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
Indeed, there's nothing else except for the time spent on the
negotiation needs to be emulated. This is needed for resuming windows
guest from hibernation, as without a proper delay, qemu would send the
packet too early ( guest even does not have a proper intr handler),
which could lead windows guest hang.
This patch first introduces an array of function pointers to make it
possible to emulate per-register write behavior. Then traps the
PHY_CTRL register write and when guest want to restart the link auto
negotiation, we would down the link and mark the auto negotiation in
progress in PHY_STATUS register. After time, a timer with 500 ms (
which is the minimum timeout of auto-negotation specified in 802.3
spec). The link would be up when timer expired.
Test with resuming windows guest plus flood ping and linux ethtool
linkstatus test.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 4eb95be..921f0cc 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -125,6 +125,8 @@ typedef struct E1000State_st {
uint16_t reading;
uint32_t old_eecd;
} eecd_state;
+
+ QEMUTimer *autoneg_timer;
} E1000State;
#define defreg(x) x = (E1000_##x>>2)
@@ -156,6 +158,34 @@ e1000_link_up(E1000State *s)
s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
}
+static void
+set_phy_ctrl(E1000State *s, int index, uint16_t val)
+{
+ if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
+ s->nic->nc.link_down = true;
+ e1000_link_down(s);
+ s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Start link auto negotiation\n");
+ qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ }
+}
+
+static void
+e1000_autoneg_timer(void *opaque)
+{
+ E1000State *s = opaque;
+ s->nic->nc.link_down = false;
+ e1000_link_up(s);
+ s->phy_reg[PHY_STATUS] |= MII_SR_AUTONEG_COMPLETE;
+ DBGOUT(PHY, "Auto negotiation is completed\n");
+}
+
+static void (*phyreg_writeops[])(E1000State *, int, uint16_t) = {
+ [PHY_CTRL] = set_phy_ctrl,
+};
+
+enum { NPHYWRITEOPS = ARRAY_SIZE(phyreg_writeops) };
+
enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
static const char phy_regcap[0x20] = {
[PHY_STATUS] = PHY_R, [M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
@@ -244,8 +274,12 @@ set_mdic(E1000State *s, int index, uint32_t val)
if (!(phy_regcap[addr] & PHY_W)) {
DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
val |= E1000_MDIC_ERROR;
- } else
+ } else {
+ if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
+ phyreg_writeops[addr](s, index, data);
+ }
s->phy_reg[addr] = data;
+ }
}
s->mac_reg[MDIC] = val | E1000_MDIC_READY;
@@ -926,6 +960,7 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
[MTA ... MTA+127] = &mac_writereg,
[VFTA ... VFTA+127] = &mac_writereg,
};
+
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) };
static void
@@ -1087,7 +1122,8 @@ static const uint16_t e1000_eeprom_template[64] = {
};
static const uint16_t phy_reg_init[] = {
- [PHY_CTRL] = 0x1140, [PHY_STATUS] = 0x796d, // link initially up
+ [PHY_CTRL] = 0x1140,
+ [PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
[PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
[PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
[M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
@@ -1142,6 +1178,8 @@ pci_e1000_uninit(PCIDevice *dev)
{
E1000State *d = DO_UPCAST(E1000State, dev, dev);
+ qemu_del_timer(d->autoneg_timer);
+ qemu_free_timer(d->autoneg_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
qemu_del_vlan_client(&d->nic->nc);
@@ -1152,6 +1190,7 @@ static void e1000_reset(void *opaque)
{
E1000State *d = opaque;
+ qemu_del_timer(d->autoneg_timer);
memset(d->phy_reg, 0, sizeof d->phy_reg);
memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
memset(d->mac_reg, 0, sizeof d->mac_reg);
@@ -1212,6 +1251,8 @@ static int pci_e1000_init(PCIDevice *pci_dev)
add_boot_device_path(d->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
+ d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d);
+
return 0;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 7/7] e1000: set E1000_ICR_INT_ASSERTED only for 8257x
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
` (4 preceding siblings ...)
2012-03-22 10:02 ` [Qemu-devel] [PATCH 6/7] e1000: link auto-negotiation emulation Jason Wang
@ 2012-03-22 10:02 ` Jason Wang
5 siblings, 0 replies; 7+ messages in thread
From: Jason Wang @ 2012-03-22 10:02 UTC (permalink / raw)
To: qemu-devel, aliguori, stefanha, mst
E1000_ICR_INT_ASSERTED were introduced only for 8257x, so we need to
check the E1000_DEVID before setting this bit in ICS.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/e1000.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/hw/e1000.c b/hw/e1000.c
index 921f0cc..5584cc6 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -199,8 +199,10 @@ static const char phy_regcap[0x20] = {
static void
set_interrupt_cause(E1000State *s, int index, uint32_t val)
{
- if (val)
+ if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
+ /* Only for 8257x */
val |= E1000_ICR_INT_ASSERTED;
+ }
s->mac_reg[ICR] = val;
s->mac_reg[ICS] = val;
qemu_set_irq(s->dev.irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-03-22 10:07 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-22 10:01 [Qemu-devel] [PATCH 1/7] e1000: introduce bits of PHY control register Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 2/7] e1000: conditionally raise irq at the end of MDI cycle Jason Wang
2012-03-22 10:01 ` [Qemu-devel] [PATCH 3/7] e1000: PHY loopback mode support Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 4/7] e1000: introduce helpers to manipulate link status Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 5/7] e1000: introduce bit for debugging PHY emulation Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 6/7] e1000: link auto-negotiation emulation Jason Wang
2012-03-22 10:02 ` [Qemu-devel] [PATCH 7/7] e1000: set E1000_ICR_INT_ASSERTED only for 8257x Jason Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).