Patchwork e1000 patch for osx

login
register
mail settings
Submitter jacek burghardt
Date Oct. 31, 2013, 12:21 a.m.
Message ID <CAHyyzzTKL_yic2aTV7vo-5aKaqzHEocu2as1nd6ytbQvL9c9HQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/287367/
State New
Headers show

Comments

jacek burghardt - Oct. 31, 2013, 12:21 a.m.
I am in process of recompiling qemu right now
I came up with this patch is this correct
     }
@@ -409,6 +417,8 @@
 {
     /* RST is self clearing */
     s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
+    if (val & E1000_CTRL_RST)
+       set_ics(s, 0, E1000_ICR_LSC);
 }

 static void
@@ -446,7 +456,15 @@
             if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
                 phyreg_writeops[addr](s, index, data);
             }
-            s->phy_reg[addr] = data;
+            switch (addr) {
+           case PHY_CTRL:
+               s->phy_reg[addr] = data & 0x7eff;
+               if (s->phy_reg[addr] != data)
+                       set_ics(s, 0, E1000_ICR_LSC);
+               break;
+           default:
+               s->phy_reg[addr] = data;
+           }
         }
     }
     s->mac_reg[MDIC] = val | E1000_MDIC_READY;
@@ -1163,8 +1181,13 @@
 static void
 set_ims(E1000State *s, int index, uint32_t val)
 {
+    uint32_t old_val = s->mac_reg[IMS];
     s->mac_reg[IMS] |= val;
-    set_ics(s, 0, 0);
+    if ((val & E1000_ICR_LSC) && old_val == 0) {
+      set_ics(s, 0, E1000_ICR_LSC); /* inject Link Status for
uncooperative Darwin driver */
+    } else {
+      set_ics(s, 0, 0);
+    }
 }

 #define getreg(x)      [x] = mac_readreg
@@ -1192,7 +1215,7 @@
 static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
     putreg(PBA),       putreg(EERD),   putreg(SWSM),   putreg(WUFC),
     putreg(TDBAL),     putreg(TDBAH),  putreg(TXDCTL), putreg(RDBAH),
-    putreg(RDBAL),     putreg(LEDCTL), putreg(VET),
+    putreg(RDBAL),     putreg(LEDCTL), putreg(VET),    putreg(MANC),
     [TDLEN] = set_dlen,        [RDLEN] = set_dlen,     [TCTL] = set_tctl,
     [TDT] = set_tctl,  [MDIC] = set_mdic,      [ICS] = set_ics,
     [TDH] = set_16bit, [RDH] = set_16bit,      [RDT] = set_rdt,



On Wed, Oct 30, 2013 at 6:00 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:

> Il 31/10/2013 00:54, jacek burghardt ha scritto:
> > I wonder if anyone can post reworked patch to latest  qemu
>
> That's what I did 5 hours ago, though what I did was actually to look at
> the bits affected by the patch and reimplement them based on the e1000
> hardware spec.  Can you test the second patch I posted and see if it
> works for you?
>
> Paolo
>
jacek burghardt - Oct. 31, 2013, 12:24 a.m.
i got this error
hw/net/e1000.c: In function 'set_phy_ctrl':
hw/net/e1000.c:209:10: warning: implicit declaration of function 'set_ics'
[-Wimplicit-function-declaration]
          set_ics(s, 0, E1000_ICR_LSC);
          ^
hw/net/e1000.c:209:10: warning: nested extern declaration of 'set_ics'
[-Wnested-externs]
hw/net/e1000.c: At top level:
hw/net/e1000.c:351:1: warning: conflicting types for 'set_ics' [enabled by
default]
 set_ics(E1000State *s, int index, uint32_t val)
 ^
hw/net/e1000.c:351:1: error: static declaration of 'set_ics' follows
non-static declaration
hw/net/e1000.c:209:10: note: previous implicit declaration of 'set_ics' was
here
          set_ics(s, 0, E1000_ICR_LSC);
          ^
/data/dev/xen/xen-git/src/xen-build/tools/qemu-xen-dir/rules.mak:25: recipe
for target 'hw/net/e1000.o' failed



On Wed, Oct 30, 2013 at 6:21 PM, jacek burghardt
<jaceksburghardt@gmail.com>wrote:

> I am in process of recompiling qemu right now
> I came up with this patch is this correct
> diff -Naur qemu/hw/net/e1000.c qemu-a/hw/net/e1000.c
> --- qemu/hw/net/e1000.c 2013-10-27 15:36:05.496526538 -0600
> +++ qemu-a/hw/net/e1000.c       2013-10-30 18:09:03.101711694 -0600
> @@ -203,6 +203,12 @@
>          DBGOUT(PHY, "Start link auto negotiation\n");
>          timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
> + 500);
>      }
> +
> +     if (val & 0x8000) {
> +         val &= 0x7fff;
> +         set_ics(s, 0, E1000_ICR_LSC);
> +     }
> +     s->phy_reg[PHY_CTRL] = val;
>  }
>
>  static void
> @@ -390,6 +396,8 @@
>      d->rxbuf_min_shift = 1;
>      memset(&d->tx, 0, sizeof d->tx);
>
> +    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
> (macaddr[1] << 8) | macaddr[0];
> +    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
>      if (qemu_get_queue(d->nic)->link_down) {
>          e1000_link_down(d);
>      }
> @@ -409,6 +417,8 @@
>  {
>      /* RST is self clearing */
>      s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
> +    if (val & E1000_CTRL_RST)
> +       set_ics(s, 0, E1000_ICR_LSC);
>  }
>
>  static void
> @@ -446,7 +456,15 @@
>              if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
>                  phyreg_writeops[addr](s, index, data);
>              }
> -            s->phy_reg[addr] = data;
> +            switch (addr) {
> +           case PHY_CTRL:
> +               s->phy_reg[addr] = data & 0x7eff;
> +               if (s->phy_reg[addr] != data)
> +                       set_ics(s, 0, E1000_ICR_LSC);
> +               break;
> +           default:
> +               s->phy_reg[addr] = data;
> +           }
>          }
>      }
>      s->mac_reg[MDIC] = val | E1000_MDIC_READY;
> @@ -1163,8 +1181,13 @@
>  static void
>  set_ims(E1000State *s, int index, uint32_t val)
>  {
> +    uint32_t old_val = s->mac_reg[IMS];
>      s->mac_reg[IMS] |= val;
> -    set_ics(s, 0, 0);
> +    if ((val & E1000_ICR_LSC) && old_val == 0) {
> +      set_ics(s, 0, E1000_ICR_LSC); /* inject Link Status for
> uncooperative Darwin driver */
> +    } else {
> +      set_ics(s, 0, 0);
> +    }
>  }
>
>  #define getreg(x)      [x] = mac_readreg
> @@ -1192,7 +1215,7 @@
>  static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
>      putreg(PBA),       putreg(EERD),   putreg(SWSM),   putreg(WUFC),
>      putreg(TDBAL),     putreg(TDBAH),  putreg(TXDCTL), putreg(RDBAH),
> -    putreg(RDBAL),     putreg(LEDCTL), putreg(VET),
> +    putreg(RDBAL),     putreg(LEDCTL), putreg(VET),    putreg(MANC),
>      [TDLEN] = set_dlen,        [RDLEN] = set_dlen,     [TCTL] = set_tctl,
>      [TDT] = set_tctl,  [MDIC] = set_mdic,      [ICS] = set_ics,
>      [TDH] = set_16bit, [RDH] = set_16bit,      [RDT] = set_rdt,
>
>
>
> On Wed, Oct 30, 2013 at 6:00 PM, Paolo Bonzini <pbonzini@redhat.com>wrote:
>
>> Il 31/10/2013 00:54, jacek burghardt ha scritto:
>> > I wonder if anyone can post reworked patch to latest  qemu
>>
>> That's what I did 5 hours ago, though what I did was actually to look at
>> the bits affected by the patch and reimplement them based on the e1000
>> hardware spec.  Can you test the second patch I posted and see if it
>> works for you?
>>
>> Paolo
>>
>
>
Paolo Bonzini - Oct. 31, 2013, 12:27 a.m.
Il 31/10/2013 01:21, jacek burghardt ha scritto:
> I am in process of recompiling qemu right now 
> I came up with this patch is this correct
> diff -Naur qemu/hw/net/e1000.c qemu-a/hw/net/e1000.c
> --- qemu/hw/net/e1000.c 2013-10-27 15:36:05.496526538 -0600
> +++ qemu-a/hw/net/e1000.c       2013-10-30 18:09:03.101711694 -0600
> @@ -203,6 +203,12 @@
>          DBGOUT(PHY, "Start link auto negotiation\n");
>          timer_mod(s->autoneg_timer,
> qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
>      }
> +
> +     if (val & 0x8000) {
> +         val &= 0x7fff;
> +         set_ics(s, 0, E1000_ICR_LSC);
> +     }
> +     s->phy_reg[PHY_CTRL] = val;
>  }
> 
>  static void
> @@ -390,6 +396,8 @@
>      d->rxbuf_min_shift = 1;
>      memset(&d->tx, 0, sizeof d->tx);
> 
> +    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
> (macaddr[1] << 8) | macaddr[0];
> +    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
>      if (qemu_get_queue(d->nic)->link_down) {
>          e1000_link_down(d);
>      }
> @@ -409,6 +417,8 @@
>  {
>      /* RST is self clearing */
>      s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
> +    if (val & E1000_CTRL_RST)
> +       set_ics(s, 0, E1000_ICR_LSC);

Are these two lines necessary?

>  }
> 
>  static void
> @@ -446,7 +456,15 @@
>              if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
>                  phyreg_writeops[addr](s, index, data);
>              }
> -            s->phy_reg[addr] = data;
> +            switch (addr) {
> +           case PHY_CTRL:
> +               s->phy_reg[addr] = data & 0x7eff;

Does it work if you put 0x7fff here?

Paolo
jacek burghardt - Oct. 31, 2013, 12:31 a.m.
I will try that the original patch:
--- qemu-kvm-0.12.5/hw/e1000.c.vanilla 2011-02-19 12:28:38.000000000 +0000

+++ qemu-kvm-0.12.5/hw/e1000.c	2011-02-21 14:11:33.000000000 +0000
@@ -199,6 +202,8 @@
 {
     /* RST is self clearing */
     s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
+    if (val & E1000_CTRL_RST)
+	set_ics(s, 0, E1000_ICR_LSC);
 }

 static void
@@ -231,8 +236,18 @@
         if (!(phy_regcap[addr] & PHY_W)) {
             DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
             val |= E1000_MDIC_ERROR;
-        } else
-            s->phy_reg[addr] = data;
+        } else {
+	    /* some (reset) bits are self clearing, so better clear them */
+	    switch (addr) {
+	    case PHY_CTRL:
+		s->phy_reg[addr] = data & 0x7eff;
+		if (s->phy_reg[addr] != data)
+			set_ics(s, 0, E1000_ICR_LSC);
+		break;
+	    default:
+		s->phy_reg[addr] = data;
+	    }
+	}
     }
     s->mac_reg[MDIC] = val | E1000_MDIC_READY;
 DBGOUT(MDIC, "mac_reg[MDIC] = %x\n", s->mac_reg[MDIC]);
@@ -802,8 +807,13 @@
 static void
 set_ims(E1000State *s, int index, uint32_t val)
 {
+    uint32_t old_val = s->mac_reg[IMS];
     s->mac_reg[IMS] |= val;
-    set_ics(s, 0, 0);
+    if ((val & E1000_ICR_LSC) && old_val == 0) {
+      set_ics(s, 0, E1000_ICR_LSC); /* inject Link Status for
uncooperative Darwin driver */
+    } else {
+      set_ics(s, 0, 0);
+    }
 }

 #define getreg(x)	[x] = mac_readreg
@@ -810,7 +825,7 @@
 static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
     putreg(PBA),	putreg(EERD),	putreg(SWSM),	putreg(WUFC),
     putreg(TDBAL),	putreg(TDBAH),	putreg(TXDCTL),	putreg(RDBAH),
-    putreg(RDBAL),	putreg(LEDCTL), putreg(VET),
+    putreg(RDBAL),	putreg(LEDCTL), putreg(VET),	putreg(MANC),
     [TDLEN] = set_dlen,	[RDLEN] = set_dlen,	[TCTL] = set_tctl,
     [TDT] = set_tctl,	[MDIC] = set_mdic,	[ICS] = set_ics,
     [TDH] = set_16bit,	[RDH] = set_16bit,	[RDT] = set_rdt,
@@ -1059,6 +1059,7 @@
 static void e1000_reset(void *opaque)
 {
     E1000State *d = opaque;
+    uint8_t *macaddr = d->eeprom_data;

     memset(d->phy_reg, 0, sizeof d->phy_reg);
     memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
@@ -1066,6 +1067,9 @@
     memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
     d->rxbuf_min_shift = 1;
     memset(&d->tx, 0, sizeof d->tx);
+
+    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
(macaddr[1] << 8) | macaddr[0];
+    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
 }

 static NetClientInfo net_e1000_info = {



On Wed, Oct 30, 2013 at 6:27 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:

> Il 31/10/2013 01:21, jacek burghardt ha scritto:
> > I am in process of recompiling qemu right now
> > I came up with this patch is this correct
> > diff -Naur qemu/hw/net/e1000.c qemu-a/hw/net/e1000.c
> > --- qemu/hw/net/e1000.c 2013-10-27 15:36:05.496526538 -0600
> > +++ qemu-a/hw/net/e1000.c       2013-10-30 18:09:03.101711694 -0600
> > @@ -203,6 +203,12 @@
> >          DBGOUT(PHY, "Start link auto negotiation\n");
> >          timer_mod(s->autoneg_timer,
> > qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
> >      }
> > +
> > +     if (val & 0x8000) {
> > +         val &= 0x7fff;
> > +         set_ics(s, 0, E1000_ICR_LSC);
> > +     }
> > +     s->phy_reg[PHY_CTRL] = val;
> >  }
> >
> >  static void
> > @@ -390,6 +396,8 @@
> >      d->rxbuf_min_shift = 1;
> >      memset(&d->tx, 0, sizeof d->tx);
> >
> > +    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
> > (macaddr[1] << 8) | macaddr[0];
> > +    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
> >      if (qemu_get_queue(d->nic)->link_down) {
> >          e1000_link_down(d);
> >      }
> > @@ -409,6 +417,8 @@
> >  {
> >      /* RST is self clearing */
> >      s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
> > +    if (val & E1000_CTRL_RST)
> > +       set_ics(s, 0, E1000_ICR_LSC);
>
> Are these two lines necessary?
>
> >  }
> >
> >  static void
> > @@ -446,7 +456,15 @@
> >              if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
> >                  phyreg_writeops[addr](s, index, data);
> >              }
> > -            s->phy_reg[addr] = data;
> > +            switch (addr) {
> > +           case PHY_CTRL:
> > +               s->phy_reg[addr] = data & 0x7eff;
>
> Does it work if you put 0x7fff here?
>
> Paolo
>
>
jacek burghardt - Oct. 31, 2013, 12:51 a.m.
I got this error
hw/net/e1000.c: In function 'set_phy_ctrl':
hw/net/e1000.c:209:10: warning: implicit declaration of function 'set_ics'
[-Wimplicit-function-declaration]
          set_ics(s, 0, E1000_ICR_LSC);
          ^
hw/net/e1000.c:209:10: warning: nested extern declaration of 'set_ics'
[-Wnested-externs]
hw/net/e1000.c: At top level:
hw/net/e1000.c:351:1: warning: conflicting types for 'set_ics' [enabled by
default]
 set_ics(E1000State *s, int index, uint32_t val)
 ^
hw/net/e1000.c:351:1: error: static declaration of 'set_ics' follows
non-static declaration
hw/net/e1000.c:209:10: note: previous implicit declaration of 'set_ics' was
here
          set_ics(s, 0, E1000_ICR_LSC);



On Wed, Oct 30, 2013 at 6:31 PM, jacek burghardt
<jaceksburghardt@gmail.com>wrote:

> I will try that the original patch:
> --- qemu-kvm-0.12.5/hw/e1000.c.vanilla 2011-02-19 12:28:38.000000000 +0000
>
> +++ qemu-kvm-0.12.5/hw/e1000.c	2011-02-21 14:11:33.000000000 +0000
> @@ -199,6 +202,8 @@
>  {
>      /* RST is self clearing */
>      s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
> +    if (val & E1000_CTRL_RST)
> +	set_ics(s, 0, E1000_ICR_LSC);
>  }
>
>  static void
> @@ -231,8 +236,18 @@
>          if (!(phy_regcap[addr] & PHY_W)) {
>              DBGOUT(MDIC, "MDIC write reg %x unhandled\n", addr);
>              val |= E1000_MDIC_ERROR;
> -        } else
> -            s->phy_reg[addr] = data;
> +        } else {
> +	    /* some (reset) bits are self clearing, so better clear them */
> +	    switch (addr) {
> +	    case PHY_CTRL:
> +		s->phy_reg[addr] = data & 0x7eff;
> +		if (s->phy_reg[addr] != data)
> +			set_ics(s, 0, E1000_ICR_LSC);
> +		break;
> +	    default:
> +		s->phy_reg[addr] = data;
> +	    }
> +	}
>      }
>      s->mac_reg[MDIC] = val | E1000_MDIC_READY;
>  DBGOUT(MDIC, "mac_reg[MDIC] = %x\n", s->mac_reg[MDIC]);
> @@ -802,8 +807,13 @@
>  static void
>  set_ims(E1000State *s, int index, uint32_t val)
>  {
> +    uint32_t old_val = s->mac_reg[IMS];
>      s->mac_reg[IMS] |= val;
> -    set_ics(s, 0, 0);
> +    if ((val & E1000_ICR_LSC) && old_val == 0) {
> +      set_ics(s, 0, E1000_ICR_LSC); /* inject Link Status for uncooperative Darwin driver */
> +    } else {
> +      set_ics(s, 0, 0);
> +    }
>  }
>
>  #define getreg(x)	[x] = mac_readreg
> @@ -810,7 +825,7 @@
>  static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
>      putreg(PBA),	putreg(EERD),	putreg(SWSM),	putreg(WUFC),
>      putreg(TDBAL),	putreg(TDBAH),	putreg(TXDCTL),	putreg(RDBAH),
> -    putreg(RDBAL),	putreg(LEDCTL), putreg(VET),
> +    putreg(RDBAL),	putreg(LEDCTL), putreg(VET),	putreg(MANC),
>      [TDLEN] = set_dlen,	[RDLEN] = set_dlen,	[TCTL] = set_tctl,
>      [TDT] = set_tctl,	[MDIC] = set_mdic,	[ICS] = set_ics,
>      [TDH] = set_16bit,	[RDH] = set_16bit,	[RDT] = set_rdt,
> @@ -1059,6 +1059,7 @@
>  static void e1000_reset(void *opaque)
>  {
>      E1000State *d = opaque;
> +    uint8_t *macaddr = d->eeprom_data;
>
>      memset(d->phy_reg, 0, sizeof d->phy_reg);
>      memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
> @@ -1066,6 +1067,9 @@
>      memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
>      d->rxbuf_min_shift = 1;
>      memset(&d->tx, 0, sizeof d->tx);
> +
> +    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) | (macaddr[1] << 8) | macaddr[0];
> +    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
>  }
>
>  static NetClientInfo net_e1000_info = {
>
>
>
> On Wed, Oct 30, 2013 at 6:27 PM, Paolo Bonzini <pbonzini@redhat.com>wrote:
>
>> Il 31/10/2013 01:21, jacek burghardt ha scritto:
>> > I am in process of recompiling qemu right now
>> > I came up with this patch is this correct
>> > diff -Naur qemu/hw/net/e1000.c qemu-a/hw/net/e1000.c
>> > --- qemu/hw/net/e1000.c 2013-10-27 15:36:05.496526538 -0600
>> > +++ qemu-a/hw/net/e1000.c       2013-10-30 18:09:03.101711694 -0600
>> > @@ -203,6 +203,12 @@
>> >          DBGOUT(PHY, "Start link auto negotiation\n");
>> >          timer_mod(s->autoneg_timer,
>> > qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
>> >      }
>> > +
>> > +     if (val & 0x8000) {
>> > +         val &= 0x7fff;
>> > +         set_ics(s, 0, E1000_ICR_LSC);
>> > +     }
>> > +     s->phy_reg[PHY_CTRL] = val;
>> >  }
>> >
>> >  static void
>> > @@ -390,6 +396,8 @@
>> >      d->rxbuf_min_shift = 1;
>> >      memset(&d->tx, 0, sizeof d->tx);
>> >
>> > +    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
>> > (macaddr[1] << 8) | macaddr[0];
>> > +    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
>> >      if (qemu_get_queue(d->nic)->link_down) {
>> >          e1000_link_down(d);
>> >      }
>> > @@ -409,6 +417,8 @@
>> >  {
>> >      /* RST is self clearing */
>> >      s->mac_reg[CTRL] = val & ~E1000_CTRL_RST;
>> > +    if (val & E1000_CTRL_RST)
>> > +       set_ics(s, 0, E1000_ICR_LSC);
>>
>> Are these two lines necessary?
>>
>> >  }
>> >
>> >  static void
>> > @@ -446,7 +456,15 @@
>> >              if (addr < NPHYWRITEOPS && phyreg_writeops[addr]) {
>> >                  phyreg_writeops[addr](s, index, data);
>> >              }
>> > -            s->phy_reg[addr] = data;
>> > +            switch (addr) {
>> > +           case PHY_CTRL:
>> > +               s->phy_reg[addr] = data & 0x7eff;
>>
>> Does it work if you put 0x7fff here?
>>
>> Paolo
>>
>>
>

Patch

diff -Naur qemu/hw/net/e1000.c qemu-a/hw/net/e1000.c
--- qemu/hw/net/e1000.c 2013-10-27 15:36:05.496526538 -0600
+++ qemu-a/hw/net/e1000.c       2013-10-30 18:09:03.101711694 -0600
@@ -203,6 +203,12 @@ 
         DBGOUT(PHY, "Start link auto negotiation\n");
         timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)
+ 500);
     }
+
+     if (val & 0x8000) {
+         val &= 0x7fff;
+         set_ics(s, 0, E1000_ICR_LSC);
+     }
+     s->phy_reg[PHY_CTRL] = val;
 }

 static void
@@ -390,6 +396,8 @@ 
     d->rxbuf_min_shift = 1;
     memset(&d->tx, 0, sizeof d->tx);

+    d->mac_reg[RA+0] = (macaddr[3] << 24) | (macaddr[2] << 16) |
(macaddr[1] << 8) | macaddr[0];
+    d->mac_reg[RA+1] = E1000_RAH_AV | (macaddr[5] << 8) | macaddr[4];
     if (qemu_get_queue(d->nic)->link_down) {
         e1000_link_down(d);