Skip to contentSkip to conversation

e1000: CTRL.RST emulation

PATCH In review Michael S. Tsirkin 3 participants 6 messages Sep 27, 2011

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 e1000: CTRL.RST emulation

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Fix suggested by Andy Gospodarek <[email protected]>

---
 hw/e1000.c |   97 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 51 insertions(+), 46 deletions(-)
hw/e1000.c +51 -46
index 6a3a941..81328f4 100644
@@ -151,6 +151,40 @@ static const char phy_regcap[0x20] = {
     [PHY_ID2] = PHY_R,		[M88E1000_PHY_SPEC_STATUS] = PHY_R
 };
 
+static const uint16_t e1000_eeprom_template[64] = {
+    0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
+    0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
+    0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
+    0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
+    0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
+    0x0100, 0x4000, 0x121c, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
+    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
+};
+
+static const uint16_t phy_reg_init[] = {
+    [PHY_CTRL] = 0x1140,			[PHY_STATUS] = 0x796d, // link initially up
+    [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,
+    [PHY_LP_ABILITY] = 0x1e0,			[PHY_1000T_STATUS] = 0x3c00,
+    [M88E1000_PHY_SPEC_STATUS] = 0xac00,
+};
+
+static const uint32_t mac_reg_init[] = {
+    [PBA] =     0x00100030,
+    [LEDCTL] =  0x602,
+    [CTRL] =    E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
+                E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
+    [STATUS] =  0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
+                E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
+                E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
+                E1000_STATUS_LU,
+    [MANC] =    E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
+                E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
+                E1000_MANC_RMCP_EN,
+};
+
 static void
 set_interrupt_cause(E1000State *s, int index, uint32_t val)
 {
@@ -192,9 +226,26 @@ rxbufsize(uint32_t v)
     return 2048;
 }
 
+static void e1000_reset(void *opaque)
+{
+    E1000State *d = opaque;
+
+    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);
+    memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
+    d->rxbuf_min_shift = 1;
+    memset(&d->tx, 0, sizeof d->tx);
+}
+
 static void
 set_ctrl(E1000State *s, int index, uint32_t val)
 {
+    if (val & E1000_CTRL_RST) {
+        e1000_reset(s);
+        qemu_set_irq(s->dev.irq[0], 0);
+    }
+
     /* RST is self clearing */
     s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
 }
@@ -1047,40 +1098,6 @@ static const VMStateDescription vmstate_e1000 = {
     }
 };
 
-static const uint16_t e1000_eeprom_template[64] = {
-    0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
-    0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
-    0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
-    0x6cc9, 0x3150, 0x0722, 0x040b,      0x0984, 0x0000,      0xc000, 0x0706,
-    0x1008, 0x0000, 0x0f04, 0x7fff,      0x4d01, 0xffff,      0xffff, 0xffff,
-    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
-    0x0100, 0x4000, 0x121c, 0xffff,      0xffff, 0xffff,      0xffff, 0xffff,
-    0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
-};
-
-static const uint16_t phy_reg_init[] = {
-    [PHY_CTRL] = 0x1140,			[PHY_STATUS] = 0x796d, // link initially up
-    [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,
-    [PHY_LP_ABILITY] = 0x1e0,			[PHY_1000T_STATUS] = 0x3c00,
-    [M88E1000_PHY_SPEC_STATUS] = 0xac00,
-};
-
-static const uint32_t mac_reg_init[] = {
-    [PBA] =     0x00100030,
-    [LEDCTL] =  0x602,
-    [CTRL] =    E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
-                E1000_CTRL_SPD_1000 | E1000_CTRL_SLU,
-    [STATUS] =  0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE |
-                E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK |
-                E1000_STATUS_SPEED_1000 | E1000_STATUS_FD |
-                E1000_STATUS_LU,
-    [MANC] =    E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN |
-                E1000_MANC_ARP_EN | E1000_MANC_0298_EN |
-                E1000_MANC_RMCP_EN,
-};
-
 /* PCI interface */
 
 static void
@@ -1120,18 +1137,6 @@ pci_e1000_uninit(PCIDevice *dev)
     return 0;
 }
 
-static void e1000_reset(void *opaque)
-{
-    E1000State *d = opaque;
-
-    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);
-    memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
-    d->rxbuf_min_shift = 1;
-    memset(&d->tx, 0, sizeof d->tx);
-}
-
 static NetClientInfo net_e1000_info = {
     .type = NET_CLIENT_TYPE_NIC,
     .size = sizeof(NICState),
Signature · 1 line
1.7.5.53.gc233e
#1 lore raw
Quoted 5 lines · Michael S. Tsirkin

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Fix suggested by Andy Gospodarek <[email protected]>

Doesn't this have the same effect as this patch:
http://patchwork.ozlabs.org/patch/108673/

except that it's harder to read because it's moved a lot of code around in the file?

(I think you have an extra qemu_set_irq() call in there, actually. But it was hard to find. Also your code has the bug that was in earlier revisions of Anthony's patch where after doing the reset you fall through and allow other bits in the ctrl register to be set.)

-- PMM

#2 lore raw
Quoted 9 lines · Peter Maydell
Quoted 5 lines · Michael S. Tsirkin

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Fix suggested by Andy Gospodarek <[email protected]>

Doesn't this have the same effect as this patch:
http://patchwork.ozlabs.org/patch/108673/

Right except mine clears the interrupts as well. I missed that patch - what happened to it in the end?

Quoted 4 lines

except that it's harder to read because it's moved a lot of code around in the file?

(I think you have an extra qemu_set_irq() call in there,

The device spec says we should reset the interrupts. So it seems necessary.

Quoted 1 line

actually. But it was hard to find.

I probably should split the patch out
1. code movement
2. code change

Forward declarations just to work around random placement of functions in file seem wrong - why not order the functions sensibly instead?

Quoted 6 lines

Also your code has the
bug that was in earlier revisions of Anthony's patch where after doing the reset you fall through and allow other bits in the ctrl register to be set.)

-- PMM

True.

Signature · 1 line
MST
#3 lore raw
Quoted 6 lines · Michael S. Tsirkin
Quoted 5 lines · Peter Maydell
Quoted 4 lines · Michael S. Tsirkin

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

Fix suggested by Andy Gospodarek <[email protected]>

Doesn't this have the same effect as this patch:
http://patchwork.ozlabs.org/patch/108673/

Right except mine clears the interrupts as well.

I agree that's required, but why doesn't it belong in e1000_reset() ? Surely a qdev reset ought also to clear the output irq signals...
[Disclaimer: this is fishing for somebody to explain to me what the semantics of qdev reset actually are :-)]

Quoted 1 line

I missed that patch - what happened to it in the end?

I think it just got lost in the shuffle (Anthony L never did come back and actually produce a compiler that gave a warning on it, so I think that was just a misremembering on his part.)

-- PMM

#4 lore raw
Quoted 9 lines · Peter Maydell
Quoted 8 lines · Michael S. Tsirkin
Quoted 7 lines · Peter Maydell
Quoted 5 lines · Michael S. Tsirkin

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Fix suggested by Andy Gospodarek <[email protected]>

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

Doesn't this have the same effect as this patch:
http://patchwork.ozlabs.org/patch/108673/

Right except mine clears the interrupts as well.

I agree that's required, but why doesn't it belong in e1000_reset() ?

I think not, because pci core resets interrupts for us.

Quoted 4 lines

Surely a qdev reset ought also to clear
the output irq signals...
[Disclaimer: this is fishing for somebody to explain to me what the semantics of qdev reset actually are :-)]

AFAIK what happens is that the qdev is only involved until we get to the pci root. From then on pci_bus_reset calls pci_device_reset to reset the device.

Quoted 8 lines
Quoted 1 line

I missed that patch - what happened to it in the end?

I think it just got lost in the shuffle (Anthony L never did come back and actually produce a compiler that gave a warning on it, so I think that was just a misremembering on his part.)

-- PMM

Yes, that just looks strange. So I intend to just stick this patch in my tree, unless someone NACKs. Then it'll get merged in due course.

Signature · 1 line
MST
#5 lore raw
In reply to Peter Maydell
Quoted 10 lines · Peter Maydell
Quoted 5 lines · Michael S. Tsirkin

e1000 spec says CTRL.RST write should have the same effect as bus reset, except that is preserves PCI Config. Reset device registers and interrupts.

Fix suggested by Andy Gospodarek<[email protected]>

Doesn't this have the same effect as this patch:
http://patchwork.ozlabs.org/patch/108673/

Quoted 8 lines

except that it's harder to read because it's moved a lot of code around in the file?

(I think you have an extra qemu_set_irq() call in there, actually. But it was hard to find. Also your code has the bug that was in earlier revisions of Anthony's patch where after doing the reset you fall through and allow other bits in the ctrl register to be set.)

I didn't see your note which said not to rend the patch unless I produce a compiler that issues a warning. Since Anthony P. was going to resubmit, I never looked into it further.

I honestly don't care at this point which patch gets merged.

Regards,

Anthony Liguori

Quoted 2 lines

-- PMM