qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2] e1000: initial link negotiation on mac osx


From: Alexander Graf
Subject: Re: [Qemu-devel] [PATCH v2] e1000: initial link negotiation on mac osx
Date: Fri, 8 Nov 2013 00:12:52 +0100


Am 07.11.2013 um 21:28 schrieb "Gabriel L. Somlo" <address@hidden>:

> Some guest operating systems' drivers (particularly Mac OS X)
> expect the link state to be pre-initialized by an earlier
> component such as a proprietary BIOS. This patch injects
> additional LSC events upon PHY reset, allowing the OS X driver
> to successfully complete initial link negotiation. This is a
> follow-up to commit 372254c6e5c078fb13b236bb648d2b9b2b0c70f1,
> which works around the OS X driver's failure to properly set
> up the MAC address.
> 
> Signed-off-by: Gabriel Somlo <address@hidden>
> ---
> 
> On Thu, Nov 07, 2013 at 08:28:47PM +0100, Paolo Bonzini wrote:
>> Is there any way to work around this in the guest?  Such as using a
>> UEFI driver for e1000 or something like that.
> 
> Currently OS X boots on top of SeaBIOS and Chameleon, neither of which
> know anything about the e1000 hardware. On real hardware, the XNU e1000
> driver expects the proprietary BIOS to set things up "just right", and
> doesn't have to bother jumping through all the hoops to properly
> initialize the hardware from scratch (after all, the XNU driver
> developers only have to care about a limited range of carefully
> controlled hardware).
> 
> In the VM/guest scenario, QEMU is the only piece that has any knowledge
> of the e1000 hardware, so having it prep things for the guest would be
> the path of least resistance. Using a completely different alternative
> to SeaBIOS (one that would/could assume e1000 is present and would know
> enough about it to configure it just right) sounds a lot less feasible.

I'm not sure I agree. We can easily modify SeaBIOS to just loop through all PCI 
devices, look for an e1000 and initialize it far enough for XNU, no?

After all, it sounds like that's closer to the way a real Mac works.

Alex

> 
> Oh, and it gets worse :) My v1 patch does enough cheating to get OS X
> to link up successfully on a e1000-equipped *Q35* VM. If Q35 is not
> specified, then another bit of trickery is needed (i.e. inject another
> LSC when the driver initially unmasks LSC in the IMS register...
> 
> Anyhow, this second version seems to work both with Q35 and without,
> on my vanilla SnowLeopard image.
> 
> Any more thoughts and ideas much appreciated!
> 
> Thanks,
>  Gabriel
> 
> hw/net/e1000.c | 20 +++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/net/e1000.c b/hw/net/e1000.c
> index ae63591..fe0f34e 100644
> --- a/hw/net/e1000.c
> +++ b/hw/net/e1000.c
> @@ -186,6 +186,9 @@ e1000_link_up(E1000State *s)
>     s->phy_reg[PHY_STATUS] |= MII_SR_LINK_STATUS;
> }
> 
> +/* Forward decl. for use in set_phy_ctrl() (OS X link nego. workaround) */
> +static void set_ics(E1000State *s, int index, uint32_t val);
> +
> static void
> set_phy_ctrl(E1000State *s, int index, uint16_t val)
> {
> @@ -197,6 +200,15 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val)
>     if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
>         return;
>     }
> +    /*
> +     * The Mac OS X driver expects a pre-initialized network card; injecting
> +     * an extra LSC event here allows initial link negotiation to succeed in
> +     * the absence of the Apple EFI BIOS.
> +     */
> +    if ((val & MII_CR_RESET)) {
> +        set_ics(s, 0, E1000_ICR_LSC);
> +        return;
> +    }
>     if ((val & MII_CR_AUTO_NEG_EN) && (val & MII_CR_RESTART_AUTO_NEG)) {
>         e1000_link_down(s);
>         s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
> @@ -1159,8 +1171,14 @@ set_imc(E1000State *s, int index, uint32_t val)
> static void
> set_ims(E1000State *s, int index, uint32_t val)
> {
> +    uint32_t ics_val = 0;
> +
> +    /* When Mac OS X initially unmasks LSC, it expects to see it set in ICS 
> */
> +    if (s->mac_reg[IMS] == 0 && (val & E1000_IMS_LSC))
> +        ics_val |= E1000_ICR_LSC;
> +
>     s->mac_reg[IMS] |= val;
> -    set_ics(s, 0, 0);
> +    set_ics(s, 0, ics_val);
> }
> 
> #define getreg(x)    [x] = mac_readreg
> -- 
> 1.8.1.4
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]