From win-pv-devel-bounces@lists.xenproject.org Mon Dec 08 15:51:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 08 Dec 2014 15:51:07 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xy0aZ-0006Jx-V5; Mon, 08 Dec 2014 15:51:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xy0aY-0006Jp-KE
	for win-pv-devel@lists.xenproject.org; Mon, 08 Dec 2014 15:51:06 +0000
Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id
	92/49-26740-9E8C5845; Mon, 08 Dec 2014 15:51:05 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-31.messagelabs.com!1418053865!11714859!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 29578 invoked from network); 8 Dec 2014 15:51:05 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	8 Dec 2014 15:51:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,539,1413244800"; d="scan'208";a="27629100"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 1/2] Add registry setting for removable capability of PDOs
Thread-Index: AQHQCxBbbiDmM16F+UimTo3IMPSEMJx2GJXggA/OiEA=
Date: Mon, 8 Dec 2014 15:50:59 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025782D5C@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Paul Durrant <Paul.Durrant@citrix.com>, Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 1/2] Add registry setting for removable
 capability of PDOs
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Paul Durrant
> Sent: 28 November 2014 14:29
> To: Owen Smith; win-pv-devel@lists.xenproject.org
> Cc: Owen Smith
> Subject: Re: [win-pv-devel] [PATCH 1/2] Add registry setting for removable
> capability of PDOs
> 
> > -----Original Message-----
> > From: Owen Smith [mailto:owen.smith@citrix.com]
> > Sent: 28 November 2014 13:37
> > To: win-pv-devel@lists.xenproject.org
> > Cc: Paul Durrant; Owen Smith
> > Subject: [PATCH 1/2] Add registry setting for removable capability of PDOs
> >
> > Setting "Removable" to 0 under the key
> > HKLM/System/CurrentControlSet/services/XENBUS/Parameters/<PDO-
> > Name>
> > will disable the PDOs removable and surprise removable capability.
> >
> > Signed-off-by: Owen Smith <owen.smith@citrix.com>
> > ---
> >  src/xenbus/pdo.c | 47
> > +++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 45 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
> > index ad0d4de..9e84ccd 100644
> > --- a/src/xenbus/pdo.c
> > +++ b/src/xenbus/pdo.c
> > @@ -45,6 +45,7 @@
> >  #include "bus.h"
> >  #include "driver.h"
> >  #include "thread.h"
> > +#include "registry.h"
> >  #include "dbg_print.h"
> >  #include "assert.h"
> >
> > @@ -61,6 +62,7 @@ struct _XENBUS_PDO {
> >      PIRP                        DevicePowerIrp;
> >
> >      PXENBUS_FDO                 Fdo;
> > +    BOOLEAN                     Removable;
> >      BOOLEAN                     Missing;
> >      const CHAR                  *Reason;
> >
> > @@ -1119,12 +1121,12 @@ PdoQueryCapabilities(
> >      Capabilities->DeviceD2 = 0;
> >      Capabilities->LockSupported = 0;
> >      Capabilities->EjectSupported = 0;
> > -    Capabilities->Removable = 1;
> > +    Capabilities->Removable = !!Pdo->Removable;
> >      Capabilities->DockDevice = 0;
> >      Capabilities->UniqueID = 1;
> >      Capabilities->SilentInstall = 1;
> >      Capabilities->RawDeviceOK = 0;
> > -    Capabilities->SurpriseRemovalOK = 1;
> > +    Capabilities->SurpriseRemovalOK = !!Pdo->Removable;
> >      Capabilities->HardwareDisabled = 0;
> >      Capabilities->NoDisplayInUI = 0;
> >
> > @@ -2041,6 +2043,43 @@ PdoSuspend(
> >      UNREFERENCED_PARAMETER(Pdo);
> >  }
> >
> > +static FORCEINLINE VOID
> > +__PdoReadRegistryFlags(
> > +    IN  PXENBUS_PDO     Pdo
> > +    )
> > +{
> > +    HANDLE              ParametersKey;
> > +    HANDLE              Key;
> > +    ULONG               Value;
> > +    NTSTATUS            status;
> > +
> > +    ParametersKey = DriverGetParametersKey();
> > +    if (ParametersKey == NULL)
> > +        goto fail1;
> > +
> > +    status = RegistryOpenSubKey(ParametersKey,
> > +                                __PdoGetName(Pdo),
> > +                                KEY_READ,
> > +                                &Key);
> > +    if (!NT_SUCCESS(status))
> > +        goto fail2;
> > +
> > +    status = RegistryQueryDwordValue(Key,
> > +                                     "Removable",
> > +                                     &Value);
> > +    if (!NT_SUCCESS(status))
> > +        Value = 1;
> > +
> > +    Pdo->Removable = !!Value;
> > +
> > +    RegistryCloseKey(Key);
> > +    return;
> > +
> > +fail2:
> > +fail1:
> > +    Pdo->Removable = TRUE;
> > +}
> > +
> >  NTSTATUS
> >  PdoCreate(
> >      IN  PXENBUS_FDO     Fdo,
> > @@ -2092,6 +2131,7 @@ PdoCreate(
> >          goto fail4;
> >
> >      __PdoSetName(Pdo, Name);
> > +    __PdoReadRegistryFlags(Pdo);
> 
> I'm not reading this once at creation time is necessarily a good idea - I think it
> may cause problems with un-installation of the bus driver so it may be
> necessary to sample in the IRP handler so the flag can be dynamically
> adjusted. I'll re-work the patch myself.
> 

After offline discussion with Owen, I agree that reading once at creation time is ok so I'll post v3 which is the same as this code with some minor cosmetic tweaks.

  Paul

>   Paul
> 
> >
> >      status = PdoSetRevisions(Pdo);
> >      if (!NT_SUCCESS(status))
> > @@ -2132,6 +2172,8 @@ fail6:
> >  fail5:
> >      Error("fail5\n");
> >
> > +    Pdo->Removable = FALSE;
> > +
> >      ThreadAlert(Pdo->DevicePowerThread);
> >      ThreadJoin(Pdo->DevicePowerThread);
> >      Pdo->DevicePowerThread = NULL;
> > @@ -2195,6 +2237,7 @@ PdoDestroy(
> >      __PdoFree(Pdo->Revision);
> >      Pdo->Revision = NULL;
> >      Pdo->Count = 0;
> > +    Pdo->Removable = FALSE;
> >
> >      ThreadAlert(Pdo->DevicePowerThread);
> >      ThreadJoin(Pdo->DevicePowerThread);
> > --
> > 1.9.4.msysgit.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Mon Dec 08 15:51:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 08 Dec 2014 15:51:07 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xy0aZ-0006Jx-V5; Mon, 08 Dec 2014 15:51:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xy0aY-0006Jp-KE
	for win-pv-devel@lists.xenproject.org; Mon, 08 Dec 2014 15:51:06 +0000
Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id
	92/49-26740-9E8C5845; Mon, 08 Dec 2014 15:51:05 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-31.messagelabs.com!1418053865!11714859!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 29578 invoked from network); 8 Dec 2014 15:51:05 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	8 Dec 2014 15:51:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,539,1413244800"; d="scan'208";a="27629100"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 1/2] Add registry setting for removable capability of PDOs
Thread-Index: AQHQCxBbbiDmM16F+UimTo3IMPSEMJx2GJXggA/OiEA=
Date: Mon, 8 Dec 2014 15:50:59 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025782D5C@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Paul Durrant <Paul.Durrant@citrix.com>, Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 1/2] Add registry setting for removable
 capability of PDOs
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Paul Durrant
> Sent: 28 November 2014 14:29
> To: Owen Smith; win-pv-devel@lists.xenproject.org
> Cc: Owen Smith
> Subject: Re: [win-pv-devel] [PATCH 1/2] Add registry setting for removable
> capability of PDOs
> 
> > -----Original Message-----
> > From: Owen Smith [mailto:owen.smith@citrix.com]
> > Sent: 28 November 2014 13:37
> > To: win-pv-devel@lists.xenproject.org
> > Cc: Paul Durrant; Owen Smith
> > Subject: [PATCH 1/2] Add registry setting for removable capability of PDOs
> >
> > Setting "Removable" to 0 under the key
> > HKLM/System/CurrentControlSet/services/XENBUS/Parameters/<PDO-
> > Name>
> > will disable the PDOs removable and surprise removable capability.
> >
> > Signed-off-by: Owen Smith <owen.smith@citrix.com>
> > ---
> >  src/xenbus/pdo.c | 47
> > +++++++++++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 45 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
> > index ad0d4de..9e84ccd 100644
> > --- a/src/xenbus/pdo.c
> > +++ b/src/xenbus/pdo.c
> > @@ -45,6 +45,7 @@
> >  #include "bus.h"
> >  #include "driver.h"
> >  #include "thread.h"
> > +#include "registry.h"
> >  #include "dbg_print.h"
> >  #include "assert.h"
> >
> > @@ -61,6 +62,7 @@ struct _XENBUS_PDO {
> >      PIRP                        DevicePowerIrp;
> >
> >      PXENBUS_FDO                 Fdo;
> > +    BOOLEAN                     Removable;
> >      BOOLEAN                     Missing;
> >      const CHAR                  *Reason;
> >
> > @@ -1119,12 +1121,12 @@ PdoQueryCapabilities(
> >      Capabilities->DeviceD2 = 0;
> >      Capabilities->LockSupported = 0;
> >      Capabilities->EjectSupported = 0;
> > -    Capabilities->Removable = 1;
> > +    Capabilities->Removable = !!Pdo->Removable;
> >      Capabilities->DockDevice = 0;
> >      Capabilities->UniqueID = 1;
> >      Capabilities->SilentInstall = 1;
> >      Capabilities->RawDeviceOK = 0;
> > -    Capabilities->SurpriseRemovalOK = 1;
> > +    Capabilities->SurpriseRemovalOK = !!Pdo->Removable;
> >      Capabilities->HardwareDisabled = 0;
> >      Capabilities->NoDisplayInUI = 0;
> >
> > @@ -2041,6 +2043,43 @@ PdoSuspend(
> >      UNREFERENCED_PARAMETER(Pdo);
> >  }
> >
> > +static FORCEINLINE VOID
> > +__PdoReadRegistryFlags(
> > +    IN  PXENBUS_PDO     Pdo
> > +    )
> > +{
> > +    HANDLE              ParametersKey;
> > +    HANDLE              Key;
> > +    ULONG               Value;
> > +    NTSTATUS            status;
> > +
> > +    ParametersKey = DriverGetParametersKey();
> > +    if (ParametersKey == NULL)
> > +        goto fail1;
> > +
> > +    status = RegistryOpenSubKey(ParametersKey,
> > +                                __PdoGetName(Pdo),
> > +                                KEY_READ,
> > +                                &Key);
> > +    if (!NT_SUCCESS(status))
> > +        goto fail2;
> > +
> > +    status = RegistryQueryDwordValue(Key,
> > +                                     "Removable",
> > +                                     &Value);
> > +    if (!NT_SUCCESS(status))
> > +        Value = 1;
> > +
> > +    Pdo->Removable = !!Value;
> > +
> > +    RegistryCloseKey(Key);
> > +    return;
> > +
> > +fail2:
> > +fail1:
> > +    Pdo->Removable = TRUE;
> > +}
> > +
> >  NTSTATUS
> >  PdoCreate(
> >      IN  PXENBUS_FDO     Fdo,
> > @@ -2092,6 +2131,7 @@ PdoCreate(
> >          goto fail4;
> >
> >      __PdoSetName(Pdo, Name);
> > +    __PdoReadRegistryFlags(Pdo);
> 
> I'm not reading this once at creation time is necessarily a good idea - I think it
> may cause problems with un-installation of the bus driver so it may be
> necessary to sample in the IRP handler so the flag can be dynamically
> adjusted. I'll re-work the patch myself.
> 

After offline discussion with Owen, I agree that reading once at creation time is ok so I'll post v3 which is the same as this code with some minor cosmetic tweaks.

  Paul

>   Paul
> 
> >
> >      status = PdoSetRevisions(Pdo);
> >      if (!NT_SUCCESS(status))
> > @@ -2132,6 +2172,8 @@ fail6:
> >  fail5:
> >      Error("fail5\n");
> >
> > +    Pdo->Removable = FALSE;
> > +
> >      ThreadAlert(Pdo->DevicePowerThread);
> >      ThreadJoin(Pdo->DevicePowerThread);
> >      Pdo->DevicePowerThread = NULL;
> > @@ -2195,6 +2237,7 @@ PdoDestroy(
> >      __PdoFree(Pdo->Revision);
> >      Pdo->Revision = NULL;
> >      Pdo->Count = 0;
> > +    Pdo->Removable = FALSE;
> >
> >      ThreadAlert(Pdo->DevicePowerThread);
> >      ThreadJoin(Pdo->DevicePowerThread);
> > --
> > 1.9.4.msysgit.1
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Mon Dec 08 15:52:17 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 08 Dec 2014 15:52:17 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xy0bh-0006Q9-Dz; Mon, 08 Dec 2014 15:52:17 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xy0bg-0006Px-JV
	for win-pv-devel@lists.xenproject.org; Mon, 08 Dec 2014 15:52:16 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	C7/EB-19763-F29C5845; Mon, 08 Dec 2014 15:52:15 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-206.messagelabs.com!1418053932!12161876!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 2731 invoked from network); 8 Dec 2014 15:52:15 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	8 Dec 2014 15:52:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,539,1413244800"; d="scan'208";a="201450592"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Mon, 8 Dec 2014 10:52:09 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Xy0bY-000434-T2;
	Mon, 08 Dec 2014 15:52:08 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Mon, 8 Dec 2014 15:52:11 +0000
Message-ID: <1418053931-32740-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>,
	Owen Smith <owen.smith@citrix.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v3] Add registry setting for removable
	capability of PDOs
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

From: Owen Smith <owen.smith-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>

Setting "Removable" to 0 under the key
HKLM/System/CurrentControlSet/services/XENBUS/Parameters/<PDO-Name>
will disable the PDOs removable and surprise removable capability.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 msbuild.bat      | 10 +++++++++-
 src/xenbus/pdo.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/msbuild.bat b/msbuild.bat
index 1b1fbc8..f3f10ac 100644
--- a/msbuild.bat
+++ b/msbuild.bat
@@ -1,7 +1,15 @@
 call "%VS%\VC\vcvarsall.bat" x86
 @echo on
-msbuild.exe /m:1 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" %EXTRA% %FILE%
+
+cov-build --dir cov_dir msbuild.exe /m:1 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" %EXTRA% %FILE%
+
 if errorlevel 1 goto error
+
+cov-analyze --dir cov_dir -j auto --aggressiveness-level high --security --concurrency --preview --all --rule --enable-fnptr --strip-path c:\git\xenbus
+
+cov-commit-defects --dir cov_dir --host dagu-4.uk.xensource.com --port 8080 --user windows --password coverity --stream %PLATFORM%
+
+
 exit 0
 
 :error
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index ad0d4de..65f63e5 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -45,6 +45,7 @@
 #include "bus.h"
 #include "driver.h"
 #include "thread.h"
+#include "registry.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -64,6 +65,8 @@ struct _XENBUS_PDO {
     BOOLEAN                     Missing;
     const CHAR                  *Reason;
 
+    BOOLEAN                     Removable;
+
     PULONG                      Revision;
     ULONG                       Count;
 
@@ -254,6 +257,45 @@ PdoGetName(
     return __PdoGetName(Pdo);
 }
 
+static FORCEINLINE VOID
+__PdoSetRemovable(
+    IN  PXENBUS_PDO     Pdo
+    )
+{
+    HANDLE              ParametersKey;
+    HANDLE              Key;
+    ULONG               Value;
+    NTSTATUS            status;
+
+    Value = 1;
+
+    ParametersKey = DriverGetParametersKey();
+
+    status = RegistryOpenSubKey(ParametersKey,
+                                __PdoGetName(Pdo),
+                                KEY_READ,
+                                &Key);
+    if (!NT_SUCCESS(status))
+        goto done;
+
+    (VOID) RegistryQueryDwordValue(Key,
+                                   "Removable",
+                                   &Value);
+
+    RegistryCloseKey(Key);
+
+done:
+    Pdo->Removable = (Value != 0) ? TRUE : FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__PdoIsRemovable(
+    IN  PXENBUS_PDO     Pdo
+    )
+{
+    return Pdo->Removable;
+}
+
 static NTSTATUS
 PdoAddRevision(
     IN  PXENBUS_PDO Pdo,
@@ -1119,15 +1161,16 @@ PdoQueryCapabilities(
     Capabilities->DeviceD2 = 0;
     Capabilities->LockSupported = 0;
     Capabilities->EjectSupported = 0;
-    Capabilities->Removable = 1;
     Capabilities->DockDevice = 0;
     Capabilities->UniqueID = 1;
     Capabilities->SilentInstall = 1;
     Capabilities->RawDeviceOK = 0;
-    Capabilities->SurpriseRemovalOK = 1;
     Capabilities->HardwareDisabled = 0;
     Capabilities->NoDisplayInUI = 0;
 
+    Capabilities->Removable = __PdoIsRemovable(Pdo) ? 1 : 0;
+    Capabilities->SurpriseRemovalOK = Capabilities->Removable;
+
     Capabilities->Address = 0xffffffff;
     Capabilities->UINumber = 0xffffffff;
 
@@ -2092,6 +2135,7 @@ PdoCreate(
         goto fail4;
 
     __PdoSetName(Pdo, Name);
+    __PdoSetRemovable(Pdo);
 
     status = PdoSetRevisions(Pdo);
     if (!NT_SUCCESS(status))
@@ -2132,6 +2176,8 @@ fail6:
 fail5:
     Error("fail5\n");
 
+    Pdo->Removable = FALSE;
+
     ThreadAlert(Pdo->DevicePowerThread);
     ThreadJoin(Pdo->DevicePowerThread);
     Pdo->DevicePowerThread = NULL;
@@ -2196,6 +2242,8 @@ PdoDestroy(
     Pdo->Revision = NULL;
     Pdo->Count = 0;
 
+    Pdo->Removable = FALSE;
+
     ThreadAlert(Pdo->DevicePowerThread);
     ThreadJoin(Pdo->DevicePowerThread);
     Pdo->DevicePowerThread = NULL;
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Mon Dec 08 15:52:17 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 08 Dec 2014 15:52:17 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xy0bh-0006Q9-Dz; Mon, 08 Dec 2014 15:52:17 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xy0bg-0006Px-JV
	for win-pv-devel@lists.xenproject.org; Mon, 08 Dec 2014 15:52:16 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	C7/EB-19763-F29C5845; Mon, 08 Dec 2014 15:52:15 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-206.messagelabs.com!1418053932!12161876!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 2731 invoked from network); 8 Dec 2014 15:52:15 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	8 Dec 2014 15:52:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,539,1413244800"; d="scan'208";a="201450592"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Mon, 8 Dec 2014 10:52:09 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Xy0bY-000434-T2;
	Mon, 08 Dec 2014 15:52:08 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Mon, 8 Dec 2014 15:52:11 +0000
Message-ID: <1418053931-32740-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>,
	Owen Smith <owen.smith@citrix.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v3] Add registry setting for removable
	capability of PDOs
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

From: Owen Smith <owen.smith-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>

Setting "Removable" to 0 under the key
HKLM/System/CurrentControlSet/services/XENBUS/Parameters/<PDO-Name>
will disable the PDOs removable and surprise removable capability.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 msbuild.bat      | 10 +++++++++-
 src/xenbus/pdo.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/msbuild.bat b/msbuild.bat
index 1b1fbc8..f3f10ac 100644
--- a/msbuild.bat
+++ b/msbuild.bat
@@ -1,7 +1,15 @@
 call "%VS%\VC\vcvarsall.bat" x86
 @echo on
-msbuild.exe /m:1 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" %EXTRA% %FILE%
+
+cov-build --dir cov_dir msbuild.exe /m:1 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" %EXTRA% %FILE%
+
 if errorlevel 1 goto error
+
+cov-analyze --dir cov_dir -j auto --aggressiveness-level high --security --concurrency --preview --all --rule --enable-fnptr --strip-path c:\git\xenbus
+
+cov-commit-defects --dir cov_dir --host dagu-4.uk.xensource.com --port 8080 --user windows --password coverity --stream %PLATFORM%
+
+
 exit 0
 
 :error
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index ad0d4de..65f63e5 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -45,6 +45,7 @@
 #include "bus.h"
 #include "driver.h"
 #include "thread.h"
+#include "registry.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -64,6 +65,8 @@ struct _XENBUS_PDO {
     BOOLEAN                     Missing;
     const CHAR                  *Reason;
 
+    BOOLEAN                     Removable;
+
     PULONG                      Revision;
     ULONG                       Count;
 
@@ -254,6 +257,45 @@ PdoGetName(
     return __PdoGetName(Pdo);
 }
 
+static FORCEINLINE VOID
+__PdoSetRemovable(
+    IN  PXENBUS_PDO     Pdo
+    )
+{
+    HANDLE              ParametersKey;
+    HANDLE              Key;
+    ULONG               Value;
+    NTSTATUS            status;
+
+    Value = 1;
+
+    ParametersKey = DriverGetParametersKey();
+
+    status = RegistryOpenSubKey(ParametersKey,
+                                __PdoGetName(Pdo),
+                                KEY_READ,
+                                &Key);
+    if (!NT_SUCCESS(status))
+        goto done;
+
+    (VOID) RegistryQueryDwordValue(Key,
+                                   "Removable",
+                                   &Value);
+
+    RegistryCloseKey(Key);
+
+done:
+    Pdo->Removable = (Value != 0) ? TRUE : FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__PdoIsRemovable(
+    IN  PXENBUS_PDO     Pdo
+    )
+{
+    return Pdo->Removable;
+}
+
 static NTSTATUS
 PdoAddRevision(
     IN  PXENBUS_PDO Pdo,
@@ -1119,15 +1161,16 @@ PdoQueryCapabilities(
     Capabilities->DeviceD2 = 0;
     Capabilities->LockSupported = 0;
     Capabilities->EjectSupported = 0;
-    Capabilities->Removable = 1;
     Capabilities->DockDevice = 0;
     Capabilities->UniqueID = 1;
     Capabilities->SilentInstall = 1;
     Capabilities->RawDeviceOK = 0;
-    Capabilities->SurpriseRemovalOK = 1;
     Capabilities->HardwareDisabled = 0;
     Capabilities->NoDisplayInUI = 0;
 
+    Capabilities->Removable = __PdoIsRemovable(Pdo) ? 1 : 0;
+    Capabilities->SurpriseRemovalOK = Capabilities->Removable;
+
     Capabilities->Address = 0xffffffff;
     Capabilities->UINumber = 0xffffffff;
 
@@ -2092,6 +2135,7 @@ PdoCreate(
         goto fail4;
 
     __PdoSetName(Pdo, Name);
+    __PdoSetRemovable(Pdo);
 
     status = PdoSetRevisions(Pdo);
     if (!NT_SUCCESS(status))
@@ -2132,6 +2176,8 @@ fail6:
 fail5:
     Error("fail5\n");
 
+    Pdo->Removable = FALSE;
+
     ThreadAlert(Pdo->DevicePowerThread);
     ThreadJoin(Pdo->DevicePowerThread);
     Pdo->DevicePowerThread = NULL;
@@ -2196,6 +2242,8 @@ PdoDestroy(
     Pdo->Revision = NULL;
     Pdo->Count = 0;
 
+    Pdo->Removable = FALSE;
+
     ThreadAlert(Pdo->DevicePowerThread);
     ThreadJoin(Pdo->DevicePowerThread);
     Pdo->DevicePowerThread = NULL;
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 06:16:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 06:16:33 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XyaZc-000362-Tw; Wed, 10 Dec 2014 06:16:32 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XyaZb-00035x-1b
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 06:16:31 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	C5/86-29352-E35E7845; Wed, 10 Dec 2014 06:16:30 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-15.tower-206.messagelabs.com!1418192188!9127618!1
X-Originating-IP: [209.85.192.169]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21460 invoked from network); 10 Dec 2014 06:16:29 -0000
Received: from mail-pd0-f169.google.com (HELO mail-pd0-f169.google.com)
	(209.85.192.169)
	by server-15.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 06:16:29 -0000
Received: by mail-pd0-f169.google.com with SMTP id z10so2164160pdj.0
	for <win-pv-devel@lists.xenproject.org>;
	Tue, 09 Dec 2014 22:16:28 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=296sRYs5l5zA8IbMf72P0Ieg0ztcN5FPA04aVBMlXJA=;
	b=Ui1lsxgGid1yQJu3BVCLcSFcqfghwwNZ/PbGjxjBF0XP4ZPHcJsG8cp10yUmrIRXw4
	VgnW8AvU1JgwlJXI3fEhG985K8lFWjjzqUxsrV/bVmkPc+IZrD6+7cw7qk++NruWyI0y
	WMx3UlQj9yxWvkA6GkyYYcMeqPkKG5TVsguBnZJfESxF/X5vErGAwl/vK4kHy61tfx/f
	qjI29UXrAWvuR/hPRW8ApxLADkX60ky0NdMcuohBPAYO4hqCB26PqKVgOd4j2zE7tpLt
	Tv5hdkxNmT3dPTULseRHCUO9D+MXNpaQ9kaD3lWoChkXtaoYOTI/W72oKAlnQALNt7SB
	kh6w==
X-Received: by 10.68.68.227 with SMTP id z3mr3992549pbt.3.1418192188004;
	Tue, 09 Dec 2014 22:16:28 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-169.amazon.com. [54.240.196.169])
	by mx.google.com with ESMTPSA id i11sm3182442pat.3.2014.12.09.22.16.25
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Tue, 09 Dec 2014 22:16:26 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Tue, 09 Dec 2014 22:16:24 -0800
Date: Tue, 9 Dec 2014 22:16:24 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <paul.durrant@citrix.com>
Message-ID: <20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> The current EvtchnPoll routine in in the shared info code is tied to
> the two level event channel ABI, wheras checking upcall_pending is ABI
> independent. Hence the check should be separated into its own method.
> 
> This patch therefore introduces version 2 of the SHARED_INFO interface,
> which has a new EvtchnUpcallPending method. Version 1 is still
> supported by having its EvtchnPoll variant call EvtchnUpcallPending
> method internally.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  include/shared_info_interface.h |  43 +++++++++-
>  include/xen.h                   |   8 ++
>  src/xen/system.c                |  20 ++++-
>  src/xenbus/evtchn.c             |  16 +++-
>  src/xenbus/shared_info.c        | 174 +++++++++++++++++++++++++++++-----------
>  5 files changed, 207 insertions(+), 54 deletions(-)
> 

[...]
  
> -extern VOID
> +XEN_API
> +ULONG
> +SystemVirtualCpuIndex(
> +    IN  ULONG           Index
> +    )
> +{
> +    PSYSTEM_CONTEXT     Context = &SystemContext;
> +    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
> +
> +    ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
> +
> +    return Cpu->ApicID / 2;

Nack. This will break on EC2 instances that expose CPU topology by
setting the initial APIC ID appropriately (i.e., not according to the
*2 formula.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 06:16:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 06:16:33 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XyaZc-000362-Tw; Wed, 10 Dec 2014 06:16:32 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XyaZb-00035x-1b
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 06:16:31 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	C5/86-29352-E35E7845; Wed, 10 Dec 2014 06:16:30 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-15.tower-206.messagelabs.com!1418192188!9127618!1
X-Originating-IP: [209.85.192.169]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21460 invoked from network); 10 Dec 2014 06:16:29 -0000
Received: from mail-pd0-f169.google.com (HELO mail-pd0-f169.google.com)
	(209.85.192.169)
	by server-15.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 06:16:29 -0000
Received: by mail-pd0-f169.google.com with SMTP id z10so2164160pdj.0
	for <win-pv-devel@lists.xenproject.org>;
	Tue, 09 Dec 2014 22:16:28 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=296sRYs5l5zA8IbMf72P0Ieg0ztcN5FPA04aVBMlXJA=;
	b=Ui1lsxgGid1yQJu3BVCLcSFcqfghwwNZ/PbGjxjBF0XP4ZPHcJsG8cp10yUmrIRXw4
	VgnW8AvU1JgwlJXI3fEhG985K8lFWjjzqUxsrV/bVmkPc+IZrD6+7cw7qk++NruWyI0y
	WMx3UlQj9yxWvkA6GkyYYcMeqPkKG5TVsguBnZJfESxF/X5vErGAwl/vK4kHy61tfx/f
	qjI29UXrAWvuR/hPRW8ApxLADkX60ky0NdMcuohBPAYO4hqCB26PqKVgOd4j2zE7tpLt
	Tv5hdkxNmT3dPTULseRHCUO9D+MXNpaQ9kaD3lWoChkXtaoYOTI/W72oKAlnQALNt7SB
	kh6w==
X-Received: by 10.68.68.227 with SMTP id z3mr3992549pbt.3.1418192188004;
	Tue, 09 Dec 2014 22:16:28 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-169.amazon.com. [54.240.196.169])
	by mx.google.com with ESMTPSA id i11sm3182442pat.3.2014.12.09.22.16.25
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Tue, 09 Dec 2014 22:16:26 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Tue, 09 Dec 2014 22:16:24 -0800
Date: Tue, 9 Dec 2014 22:16:24 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <paul.durrant@citrix.com>
Message-ID: <20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> The current EvtchnPoll routine in in the shared info code is tied to
> the two level event channel ABI, wheras checking upcall_pending is ABI
> independent. Hence the check should be separated into its own method.
> 
> This patch therefore introduces version 2 of the SHARED_INFO interface,
> which has a new EvtchnUpcallPending method. Version 1 is still
> supported by having its EvtchnPoll variant call EvtchnUpcallPending
> method internally.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  include/shared_info_interface.h |  43 +++++++++-
>  include/xen.h                   |   8 ++
>  src/xen/system.c                |  20 ++++-
>  src/xenbus/evtchn.c             |  16 +++-
>  src/xenbus/shared_info.c        | 174 +++++++++++++++++++++++++++++-----------
>  5 files changed, 207 insertions(+), 54 deletions(-)
> 

[...]
  
> -extern VOID
> +XEN_API
> +ULONG
> +SystemVirtualCpuIndex(
> +    IN  ULONG           Index
> +    )
> +{
> +    PSYSTEM_CONTEXT     Context = &SystemContext;
> +    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
> +
> +    ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
> +
> +    return Cpu->ApicID / 2;

Nack. This will break on EC2 instances that expose CPU topology by
setting the initial APIC ID appropriately (i.e., not according to the
*2 formula.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 14:10:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 14:10:52 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xyhye-0001MC-Rw; Wed, 10 Dec 2014 14:10:52 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xyhye-0001M7-7T
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 14:10:52 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	83/97-23865-B6458845; Wed, 10 Dec 2014 14:10:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1418220650!12285712!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8788 invoked from network); 10 Dec 2014 14:10:50 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 14:10:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,552,1413244800"; d="scan'208";a="27729850"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [PATCH 04/10] Separate checking upcall_pending in shared info
	from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVA=
Date: Wed, 10 Dec 2014 14:10:49 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> Sent: 10 December 2014 06:16
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared info
> from EvtchnPoll
> 
> On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> > The current EvtchnPoll routine in in the shared info code is tied to
> > the two level event channel ABI, wheras checking upcall_pending is ABI
> > independent. Hence the check should be separated into its own method.
> >
> > This patch therefore introduces version 2 of the SHARED_INFO interface,
> > which has a new EvtchnUpcallPending method. Version 1 is still
> > supported by having its EvtchnPoll variant call EvtchnUpcallPending
> > method internally.
> >
> > Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> > ---
> >  include/shared_info_interface.h |  43 +++++++++-
> >  include/xen.h                   |   8 ++
> >  src/xen/system.c                |  20 ++++-
> >  src/xenbus/evtchn.c             |  16 +++-
> >  src/xenbus/shared_info.c        | 174 +++++++++++++++++++++++++++++-
> ----------
> >  5 files changed, 207 insertions(+), 54 deletions(-)
> >
> 
> [...]
> 
> > -extern VOID
> > +XEN_API
> > +ULONG
> > +SystemVirtualCpuIndex(
> > +    IN  ULONG           Index
> > +    )
> > +{
> > +    PSYSTEM_CONTEXT     Context = &SystemContext;
> > +    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
> > +
> > +    ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
> > +
> > +    return Cpu->ApicID / 2;
> 
> Nack. This will break on EC2 instances that expose CPU topology by
> setting the initial APIC ID appropriately (i.e., not according to the
> *2 formula.

That's a shame. The code really doesn't have much option but to use this mechanism as Xen provides no explicit way for an HVM guest to get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu id.

  Paul

> 
> --msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 14:10:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 14:10:52 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xyhye-0001MC-Rw; Wed, 10 Dec 2014 14:10:52 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Xyhye-0001M7-7T
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 14:10:52 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	83/97-23865-B6458845; Wed, 10 Dec 2014 14:10:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1418220650!12285712!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8788 invoked from network); 10 Dec 2014 14:10:50 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 14:10:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,552,1413244800"; d="scan'208";a="27729850"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [PATCH 04/10] Separate checking upcall_pending in shared info
	from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVA=
Date: Wed, 10 Dec 2014 14:10:49 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> Sent: 10 December 2014 06:16
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared info
> from EvtchnPoll
> 
> On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> > The current EvtchnPoll routine in in the shared info code is tied to
> > the two level event channel ABI, wheras checking upcall_pending is ABI
> > independent. Hence the check should be separated into its own method.
> >
> > This patch therefore introduces version 2 of the SHARED_INFO interface,
> > which has a new EvtchnUpcallPending method. Version 1 is still
> > supported by having its EvtchnPoll variant call EvtchnUpcallPending
> > method internally.
> >
> > Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> > ---
> >  include/shared_info_interface.h |  43 +++++++++-
> >  include/xen.h                   |   8 ++
> >  src/xen/system.c                |  20 ++++-
> >  src/xenbus/evtchn.c             |  16 +++-
> >  src/xenbus/shared_info.c        | 174 +++++++++++++++++++++++++++++-
> ----------
> >  5 files changed, 207 insertions(+), 54 deletions(-)
> >
> 
> [...]
> 
> > -extern VOID
> > +XEN_API
> > +ULONG
> > +SystemVirtualCpuIndex(
> > +    IN  ULONG           Index
> > +    )
> > +{
> > +    PSYSTEM_CONTEXT     Context = &SystemContext;
> > +    PSYSTEM_CPU         Cpu = &Context->Cpu[Index];
> > +
> > +    ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
> > +
> > +    return Cpu->ApicID / 2;
> 
> Nack. This will break on EC2 instances that expose CPU topology by
> setting the initial APIC ID appropriately (i.e., not according to the
> *2 formula.

That's a shame. The code really doesn't have much option but to use this mechanism as Xen provides no explicit way for an HVM guest to get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu id.

  Paul

> 
> --msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 16:12:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 16:12:21 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XyjsD-0007kb-G9; Wed, 10 Dec 2014 16:12:21 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XyjsC-0007kQ-6C
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 16:12:20 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	3E/E7-22819-3E078845; Wed, 10 Dec 2014 16:12:19 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-206.messagelabs.com!1418227937!12621953!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1975 invoked from network); 10 Dec 2014 16:12:18 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 16:12:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,553,1413244800"; d="scan'208";a="202495580"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Wed, 10 Dec 2014 11:11:09 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Xyjr2-0002re-L4;
	Wed, 10 Dec 2014 16:11:08 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 10 Dec 2014 16:10:58 +0000
Message-ID: <1418227858-3424-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Add missing function type
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/cache.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xenbus/cache.c b/src/xenbus/cache.c
index 0471803..9058d56 100644
--- a/src/xenbus/cache.c
+++ b/src/xenbus/cache.c
@@ -414,7 +414,7 @@ done:
     KeLowerIrql(Irql);
 }
 
-static FORCEINLINE
+static FORCEINLINE VOID
 CacheFlushMagazines(
     IN  PXENBUS_CACHE   Cache
     )
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 16:12:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 16:12:21 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XyjsD-0007kb-G9; Wed, 10 Dec 2014 16:12:21 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XyjsC-0007kQ-6C
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 16:12:20 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	3E/E7-22819-3E078845; Wed, 10 Dec 2014 16:12:19 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-206.messagelabs.com!1418227937!12621953!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1975 invoked from network); 10 Dec 2014 16:12:18 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 16:12:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,553,1413244800"; d="scan'208";a="202495580"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Wed, 10 Dec 2014 11:11:09 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Xyjr2-0002re-L4;
	Wed, 10 Dec 2014 16:11:08 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 10 Dec 2014 16:10:58 +0000
Message-ID: <1418227858-3424-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Add missing function type
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/cache.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xenbus/cache.c b/src/xenbus/cache.c
index 0471803..9058d56 100644
--- a/src/xenbus/cache.c
+++ b/src/xenbus/cache.c
@@ -414,7 +414,7 @@ done:
     KeLowerIrql(Irql);
 }
 
-static FORCEINLINE
+static FORCEINLINE VOID
 CacheFlushMagazines(
     IN  PXENBUS_CACHE   Cache
     )
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 17:26:53 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 17:26:53 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xyl2L-0002ud-6Y; Wed, 10 Dec 2014 17:26:53 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1Xyl2J-0002uN-SU
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 17:26:52 +0000
Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id
	0E/A4-08051-B5288845; Wed, 10 Dec 2014 17:26:51 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-13.tower-27.messagelabs.com!1418232408!14265731!1
X-Originating-IP: [209.85.192.177]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4852 invoked from network); 10 Dec 2014 17:26:50 -0000
Received: from mail-pd0-f177.google.com (HELO mail-pd0-f177.google.com)
	(209.85.192.177)
	by server-13.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 17:26:50 -0000
Received: by mail-pd0-f177.google.com with SMTP id ft15so3119396pdb.8
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 10 Dec 2014 09:26:48 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=km+zoiLFslxEWRdvOVl5TswWY7EDIEF7FiwXSa2BeEE=;
	b=hRkoQ1PDGxudn3ui7Zmig6aAaQjPZjBDMPLWBAmlPera8IjkgxmibCOHHhvW8MIGfu
	syvvYfrHSSoWjXfn2a2LJIMbN2LVJhn0YS9b8tk87h8ALAMxWPNjJR5i04bZzm4Re87b
	GJ8HpXj0RRfs7KFYSzLJ4+4VQHyVXcsPTVO/V/pRCVKODtH7OoXe12P77ATB4VMO4Zzh
	89HeIagYk0JqXwRPVFz0ka5IP1aKskayNaffO5wxiFV6se+SbPQbDxuuMbCc/OFIrJYg
	NhGMKQPd4qddxihj16i1zM6w6AvAtW9t6tOYPO8jfyayCaE3RNM23m8EhsiqxNadbVV5
	QkMQ==
X-Received: by 10.68.222.199 with SMTP id qo7mr9469883pbc.14.1418232408525;
	Wed, 10 Dec 2014 09:26:48 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id nt6sm4786854pdb.26.2014.12.10.09.26.44
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Wed, 10 Dec 2014 09:26:46 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Wed, 10 Dec 2014 09:26:42 -0800
Date: Wed, 10 Dec 2014 09:26:42 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > Sent: 10 December 2014 06:16
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared info
> > from EvtchnPoll
> > 
> > On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:

[...]

> > > +    return Cpu->ApicID / 2;
> > 
> > Nack. This will break on EC2 instances that expose CPU topology by
> > setting the initial APIC ID appropriately (i.e., not according to the
> > *2 formula.
> 
> That's a shame. The code really doesn't have much option but to use
> this mechanism as Xen provides no explicit way for an HVM guest to
> get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> id.

Could you use the ACPI processor object ID number? Or use the initial
APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 17:26:53 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 17:26:53 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xyl2L-0002ud-6Y; Wed, 10 Dec 2014 17:26:53 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1Xyl2J-0002uN-SU
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 17:26:52 +0000
Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id
	0E/A4-08051-B5288845; Wed, 10 Dec 2014 17:26:51 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-13.tower-27.messagelabs.com!1418232408!14265731!1
X-Originating-IP: [209.85.192.177]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4852 invoked from network); 10 Dec 2014 17:26:50 -0000
Received: from mail-pd0-f177.google.com (HELO mail-pd0-f177.google.com)
	(209.85.192.177)
	by server-13.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 17:26:50 -0000
Received: by mail-pd0-f177.google.com with SMTP id ft15so3119396pdb.8
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 10 Dec 2014 09:26:48 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=km+zoiLFslxEWRdvOVl5TswWY7EDIEF7FiwXSa2BeEE=;
	b=hRkoQ1PDGxudn3ui7Zmig6aAaQjPZjBDMPLWBAmlPera8IjkgxmibCOHHhvW8MIGfu
	syvvYfrHSSoWjXfn2a2LJIMbN2LVJhn0YS9b8tk87h8ALAMxWPNjJR5i04bZzm4Re87b
	GJ8HpXj0RRfs7KFYSzLJ4+4VQHyVXcsPTVO/V/pRCVKODtH7OoXe12P77ATB4VMO4Zzh
	89HeIagYk0JqXwRPVFz0ka5IP1aKskayNaffO5wxiFV6se+SbPQbDxuuMbCc/OFIrJYg
	NhGMKQPd4qddxihj16i1zM6w6AvAtW9t6tOYPO8jfyayCaE3RNM23m8EhsiqxNadbVV5
	QkMQ==
X-Received: by 10.68.222.199 with SMTP id qo7mr9469883pbc.14.1418232408525;
	Wed, 10 Dec 2014 09:26:48 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id nt6sm4786854pdb.26.2014.12.10.09.26.44
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Wed, 10 Dec 2014 09:26:46 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Wed, 10 Dec 2014 09:26:42 -0800
Date: Wed, 10 Dec 2014 09:26:42 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > Sent: 10 December 2014 06:16
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared info
> > from EvtchnPoll
> > 
> > On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:

[...]

> > > +    return Cpu->ApicID / 2;
> > 
> > Nack. This will break on EC2 instances that expose CPU topology by
> > setting the initial APIC ID appropriately (i.e., not according to the
> > *2 formula.
> 
> That's a shame. The code really doesn't have much option but to use
> this mechanism as Xen provides no explicit way for an HVM guest to
> get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> id.

Could you use the ACPI processor object ID number? Or use the initial
APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 17:38:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 17:38:11 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XylDG-0003PF-1U; Wed, 10 Dec 2014 17:38:10 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XylDE-0003PA-UB
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 17:38:09 +0000
Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id
	04/A4-18267-00588845; Wed, 10 Dec 2014 17:38:08 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-31.messagelabs.com!1418233085!12446808!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23101 invoked from network); 10 Dec 2014 17:38:05 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-8.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 17:38:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,553,1413244800"; d="scan'208";a="27742092"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
	in shared info from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVCAACc2AIAAEoKg
Date: Wed, 10 Dec 2014 17:38:04 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> Sent: 10 December 2014 17:27
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> in shared info from EvtchnPoll
> 
> On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt
> Wilson
> > > Sent: 10 December 2014 06:16
> > > To: Paul Durrant
> > > Cc: win-pv-devel@lists.xenproject.org
> > > Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared
> info
> > > from EvtchnPoll
> > >
> > > On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> 
> [...]
> 
> > > > +    return Cpu->ApicID / 2;
> > >
> > > Nack. This will break on EC2 instances that expose CPU topology by
> > > setting the initial APIC ID appropriately (i.e., not according to the
> > > *2 formula.
> >
> > That's a shame. The code really doesn't have much option but to use
> > this mechanism as Xen provides no explicit way for an HVM guest to
> > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > id.
> 
> Could you use the ACPI processor object ID number? Or use the initial
> APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> 

Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to number its CPUs so we could trust that value if we know it to match the vcpu id.

  Paul

> --msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 17:38:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 17:38:11 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XylDG-0003PF-1U; Wed, 10 Dec 2014 17:38:10 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XylDE-0003PA-UB
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 17:38:09 +0000
Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id
	04/A4-18267-00588845; Wed, 10 Dec 2014 17:38:08 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-31.messagelabs.com!1418233085!12446808!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23101 invoked from network); 10 Dec 2014 17:38:05 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-8.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 17:38:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,553,1413244800"; d="scan'208";a="27742092"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
	in shared info from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVCAACc2AIAAEoKg
Date: Wed, 10 Dec 2014 17:38:04 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> Sent: 10 December 2014 17:27
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> in shared info from EvtchnPoll
> 
> On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt
> Wilson
> > > Sent: 10 December 2014 06:16
> > > To: Paul Durrant
> > > Cc: win-pv-devel@lists.xenproject.org
> > > Subject: Re: [PATCH 04/10] Separate checking upcall_pending in shared
> info
> > > from EvtchnPoll
> > >
> > > On Thu, Nov 06, 2014 at 02:24:15PM +0000, Paul Durrant wrote:
> 
> [...]
> 
> > > > +    return Cpu->ApicID / 2;
> > >
> > > Nack. This will break on EC2 instances that expose CPU topology by
> > > setting the initial APIC ID appropriately (i.e., not according to the
> > > *2 formula.
> >
> > That's a shame. The code really doesn't have much option but to use
> > this mechanism as Xen provides no explicit way for an HVM guest to
> > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > id.
> 
> Could you use the ACPI processor object ID number? Or use the initial
> APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> 

Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to number its CPUs so we could trust that value if we know it to match the vcpu id.

  Paul

> --msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 18:35:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 18:35:23 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xym6d-0001S2-EC; Wed, 10 Dec 2014 18:35:23 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1Xym6c-0001Rx-4c
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 18:35:22 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	95/4A-02576-96298845; Wed, 10 Dec 2014 18:35:21 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1418236517!14286781!1
X-Originating-IP: [209.85.220.47]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26445 invoked from network); 10 Dec 2014 18:35:19 -0000
Received: from mail-pa0-f47.google.com (HELO mail-pa0-f47.google.com)
	(209.85.220.47)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 18:35:19 -0000
Received: by mail-pa0-f47.google.com with SMTP id kq14so3307835pab.6
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 10 Dec 2014 10:35:17 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=f7TqBA2N+Bbe0OPvIap47J5uDUy/3JjtiS0Q6uwGhyQ=;
	b=c752xpExhXwJIckz132EtIVWG5Y8cJ6Iwm0+MZzumTjVYN0wtCKtxdh2Vs3HlCq1/C
	g5Jn/9bcxcKBs2z2WprapjdPkMHeqLq2VMEPhFfUZ0ig92cJlMv+x10DGmueN6Og7M+6
	GP5ZXecfVWJBenrjPE2hPz4onzF9MQCTSkGZx8PxWkk6hRE/IT+k0muexmZx+ChicUAs
	ntOHVRh+mRR5frsxxnM/BpWsmliuUQJbeQbYgHFqWKmqhFVWF0VEhafLvnI4TJqaUiEh
	E5qanWmWBq8NcL24Dc/YDb9Ij0TW5BgFDmvURrsYmYOS+VyNeurtPta6fIpG6PTIWY/t
	rp1Q==
X-Received: by 10.70.54.1 with SMTP id f1mr9627845pdp.63.1418236517439;
	Wed, 10 Dec 2014 10:35:17 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-185.amazon.com. [54.240.196.185])
	by mx.google.com with ESMTPSA id on1sm4884432pdb.32.2014.12.10.10.35.13
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Wed, 10 Dec 2014 10:35:15 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Wed, 10 Dec 2014 10:35:11 -0800
Date: Wed, 10 Dec 2014 10:35:11 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > Sent: 10 December 2014 17:27
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > in shared info from EvtchnPoll
> > 
> > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:

[...]

> > >
> > > That's a shame. The code really doesn't have much option but to use
> > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > id.
> > 
> > Could you use the ACPI processor object ID number? Or use the initial
> > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > 
> 
> Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> number its CPUs so we could trust that value if we know it to match
> the vcpu id.

Yes, the MADT LAPIC structs have the correct values. The
acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
apic_id field will match the default APIC IDs returned by CPUID input
EAX=1h output EBX[24..31], and input EAX=2b output EDX.

The legacy mptable is also indexed on vCPU ID, and contains the
correct default APIC ID for each processor.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 10 18:35:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 10 Dec 2014 18:35:23 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Xym6d-0001S2-EC; Wed, 10 Dec 2014 18:35:23 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1Xym6c-0001Rx-4c
	for win-pv-devel@lists.xenproject.org; Wed, 10 Dec 2014 18:35:22 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	95/4A-02576-96298845; Wed, 10 Dec 2014 18:35:21 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1418236517!14286781!1
X-Originating-IP: [209.85.220.47]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26445 invoked from network); 10 Dec 2014 18:35:19 -0000
Received: from mail-pa0-f47.google.com (HELO mail-pa0-f47.google.com)
	(209.85.220.47)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Dec 2014 18:35:19 -0000
Received: by mail-pa0-f47.google.com with SMTP id kq14so3307835pab.6
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 10 Dec 2014 10:35:17 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=f7TqBA2N+Bbe0OPvIap47J5uDUy/3JjtiS0Q6uwGhyQ=;
	b=c752xpExhXwJIckz132EtIVWG5Y8cJ6Iwm0+MZzumTjVYN0wtCKtxdh2Vs3HlCq1/C
	g5Jn/9bcxcKBs2z2WprapjdPkMHeqLq2VMEPhFfUZ0ig92cJlMv+x10DGmueN6Og7M+6
	GP5ZXecfVWJBenrjPE2hPz4onzF9MQCTSkGZx8PxWkk6hRE/IT+k0muexmZx+ChicUAs
	ntOHVRh+mRR5frsxxnM/BpWsmliuUQJbeQbYgHFqWKmqhFVWF0VEhafLvnI4TJqaUiEh
	E5qanWmWBq8NcL24Dc/YDb9Ij0TW5BgFDmvURrsYmYOS+VyNeurtPta6fIpG6PTIWY/t
	rp1Q==
X-Received: by 10.70.54.1 with SMTP id f1mr9627845pdp.63.1418236517439;
	Wed, 10 Dec 2014 10:35:17 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-185.amazon.com. [54.240.196.185])
	by mx.google.com with ESMTPSA id on1sm4884432pdb.32.2014.12.10.10.35.13
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Wed, 10 Dec 2014 10:35:15 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Wed, 10 Dec 2014 10:35:11 -0800
Date: Wed, 10 Dec 2014 10:35:11 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > Sent: 10 December 2014 17:27
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > in shared info from EvtchnPoll
> > 
> > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:

[...]

> > >
> > > That's a shame. The code really doesn't have much option but to use
> > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > id.
> > 
> > Could you use the ACPI processor object ID number? Or use the initial
> > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > 
> 
> Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> number its CPUs so we could trust that value if we know it to match
> the vcpu id.

Yes, the MADT LAPIC structs have the correct values. The
acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
apic_id field will match the default APIC IDs returned by CPUID input
EAX=1h output EBX[24..31], and input EAX=2b output EDX.

The legacy mptable is also indexed on vCPU ID, and contains the
correct default APIC ID for each processor.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 00:02:41 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 00:02:41 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzDgt-0006J4-Q7; Fri, 12 Dec 2014 00:02:39 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XzDgs-0006Iz-2D
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 00:02:38 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	59/2A-19763-D903A845; Fri, 12 Dec 2014 00:02:37 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-7.tower-206.messagelabs.com!1418342555!12958823!1
X-Originating-IP: [209.85.220.54]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30921 invoked from network); 12 Dec 2014 00:02:36 -0000
Received: from mail-pa0-f54.google.com (HELO mail-pa0-f54.google.com)
	(209.85.220.54)
	by server-7.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 00:02:36 -0000
Received: by mail-pa0-f54.google.com with SMTP id fb1so6084003pad.27
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 11 Dec 2014 16:02:35 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=h6T44NQCFkxo7a6hrI396yPsBHrxfrIJbTvhDDzOPCE=;
	b=Y20JXYDoUcZtU+vPng65I6PXDkXPMPCiI+vebImpUSfmSdMZw/tdIR+da4BT/h7OlI
	KFnqns2xOd6YjHy5ysRW/D9Nu+FEj37Kl1diCQpFR/+3OKY6PgJqu5tdsxPIZtZxabRr
	Z31mn8aWsSnRFmf+tNsbJ8uRyN7xqBBkrUCLi2NuJ4iyfNlZDUp9leLwvtBMhI6ajDM8
	yrKHaaMq/3MJM3M9/vIMJvSzrXYdYlK70Gg+U0ALvus39idk+EcXgn7icIUOnMqPQeeU
	qY4U3p7oEHStTvLyfvL7O5bTkk0QJyY87ImXutgSsxqQNSGIuLZGW81xnAlWbGUCzQ4g
	Vaow==
X-Received: by 10.70.52.161 with SMTP id u1mr21639382pdo.106.1418342554314;
	Thu, 11 Dec 2014 16:02:34 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id ou9sm2367859pbb.26.2014.12.11.16.02.31
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Thu, 11 Dec 2014 16:02:32 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Thu, 11 Dec 2014 16:02:30 -0800
Date: Thu, 11 Dec 2014 16:02:30 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > > Sent: 10 December 2014 17:27
> > > To: Paul Durrant
> > > Cc: win-pv-devel@lists.xenproject.org
> > > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > > in shared info from EvtchnPoll
> > > 
> > > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> 
> [...]
> 
> > > >
> > > > That's a shame. The code really doesn't have much option but to use
> > > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > > id.
> > > 
> > > Could you use the ACPI processor object ID number? Or use the initial
> > > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > > 
> > 
> > Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> > number its CPUs so we could trust that value if we know it to match
> > the vcpu id.
> 
> Yes, the MADT LAPIC structs have the correct values. The
> acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
> apic_id field will match the default APIC IDs returned by CPUID input
> EAX=1h output EBX[24..31], and input EAX=2b output EDX.
> 
> The legacy mptable is also indexed on vCPU ID, and contains the
> correct default APIC ID for each processor.

What do you think about using the Viridian MSR for Virtual Processor
Index as I mentioned on xen-devel?

  http://lists.xenproject.org/archives/html/xen-devel/2014-12/msg01352.html

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 00:02:41 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 00:02:41 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzDgt-0006J4-Q7; Fri, 12 Dec 2014 00:02:39 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XzDgs-0006Iz-2D
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 00:02:38 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	59/2A-19763-D903A845; Fri, 12 Dec 2014 00:02:37 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-7.tower-206.messagelabs.com!1418342555!12958823!1
X-Originating-IP: [209.85.220.54]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30921 invoked from network); 12 Dec 2014 00:02:36 -0000
Received: from mail-pa0-f54.google.com (HELO mail-pa0-f54.google.com)
	(209.85.220.54)
	by server-7.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 00:02:36 -0000
Received: by mail-pa0-f54.google.com with SMTP id fb1so6084003pad.27
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 11 Dec 2014 16:02:35 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=h6T44NQCFkxo7a6hrI396yPsBHrxfrIJbTvhDDzOPCE=;
	b=Y20JXYDoUcZtU+vPng65I6PXDkXPMPCiI+vebImpUSfmSdMZw/tdIR+da4BT/h7OlI
	KFnqns2xOd6YjHy5ysRW/D9Nu+FEj37Kl1diCQpFR/+3OKY6PgJqu5tdsxPIZtZxabRr
	Z31mn8aWsSnRFmf+tNsbJ8uRyN7xqBBkrUCLi2NuJ4iyfNlZDUp9leLwvtBMhI6ajDM8
	yrKHaaMq/3MJM3M9/vIMJvSzrXYdYlK70Gg+U0ALvus39idk+EcXgn7icIUOnMqPQeeU
	qY4U3p7oEHStTvLyfvL7O5bTkk0QJyY87ImXutgSsxqQNSGIuLZGW81xnAlWbGUCzQ4g
	Vaow==
X-Received: by 10.70.52.161 with SMTP id u1mr21639382pdo.106.1418342554314;
	Thu, 11 Dec 2014 16:02:34 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id ou9sm2367859pbb.26.2014.12.11.16.02.31
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Thu, 11 Dec 2014 16:02:32 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Thu, 11 Dec 2014 16:02:30 -0800
Date: Thu, 11 Dec 2014 16:02:30 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt Wilson
> > > Sent: 10 December 2014 17:27
> > > To: Paul Durrant
> > > Cc: win-pv-devel@lists.xenproject.org
> > > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > > in shared info from EvtchnPoll
> > > 
> > > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> 
> [...]
> 
> > > >
> > > > That's a shame. The code really doesn't have much option but to use
> > > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > > id.
> > > 
> > > Could you use the ACPI processor object ID number? Or use the initial
> > > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > > 
> > 
> > Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> > number its CPUs so we could trust that value if we know it to match
> > the vcpu id.
> 
> Yes, the MADT LAPIC structs have the correct values. The
> acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
> apic_id field will match the default APIC IDs returned by CPUID input
> EAX=1h output EBX[24..31], and input EAX=2b output EDX.
> 
> The legacy mptable is also indexed on vCPU ID, and contains the
> correct default APIC ID for each processor.

What do you think about using the Viridian MSR for Virtual Processor
Index as I mentioned on xen-devel?

  http://lists.xenproject.org/archives/html/xen-devel/2014-12/msg01352.html

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 09:45:13 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 09:45:13 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzMme-0006Sg-38; Fri, 12 Dec 2014 09:45:12 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XzMmc-0006Sb-TD
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 09:45:11 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	4E/00-09842-629BA845; Fri, 12 Dec 2014 09:45:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-21.messagelabs.com!1418377509!14795298!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20776 invoked from network); 12 Dec 2014 09:45:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 09:45:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,561,1413244800"; d="scan'208";a="27822835"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
	in shared info from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVCAACc2AIAAEoKggAAAoICAAe3JAIAAsrXg
Date: Fri, 12 Dec 2014 09:45:07 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
	<20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Matt Wilson
> Sent: 12 December 2014 00:03
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> in shared info from EvtchnPoll
> 
> On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> > On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > > > -----Original Message-----
> > > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt
> Wilson
> > > > Sent: 10 December 2014 17:27
> > > > To: Paul Durrant
> > > > Cc: win-pv-devel@lists.xenproject.org
> > > > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking
> upcall_pending
> > > > in shared info from EvtchnPoll
> > > >
> > > > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> >
> > [...]
> >
> > > > >
> > > > > That's a shame. The code really doesn't have much option but to use
> > > > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > > > id.
> > > >
> > > > Could you use the ACPI processor object ID number? Or use the initial
> > > > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > > >
> > >
> > > Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> > > number its CPUs so we could trust that value if we know it to match
> > > the vcpu id.
> >
> > Yes, the MADT LAPIC structs have the correct values. The
> > acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
> > apic_id field will match the default APIC IDs returned by CPUID input
> > EAX=1h output EBX[24..31], and input EAX=2b output EDX.
> >
> > The legacy mptable is also indexed on vCPU ID, and contains the
> > correct default APIC ID for each processor.
> 
> What do you think about using the Viridian MSR for Virtual Processor
> Index as I mentioned on xen-devel?
> 
>   http://lists.xenproject.org/archives/html/xen-devel/2014-
> 12/msg01352.html
> 

That should work, but if viridian is off then I'll still need a fall-back. Is viridian always on in EC2?

Thanks,

  Paul

> --msw
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 09:45:13 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 09:45:13 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzMme-0006Sg-38; Fri, 12 Dec 2014 09:45:12 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1XzMmc-0006Sb-TD
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 09:45:11 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	4E/00-09842-629BA845; Fri, 12 Dec 2014 09:45:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-21.messagelabs.com!1418377509!14795298!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20776 invoked from network); 12 Dec 2014 09:45:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 09:45:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,561,1413244800"; d="scan'208";a="27822835"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Matt Wilson <msw@linux.com>
Thread-Topic: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
	in shared info from EvtchnPoll
Thread-Index: AQHP+c1yoch+bKh86UuUQIBjLuu7fpyIfUcAgACUEVCAACc2AIAAEoKggAAAoICAAe3JAIAAsrXg
Date: Fri, 12 Dec 2014 09:45:07 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
	<20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
In-Reply-To: <20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Matt Wilson
> Sent: 12 December 2014 00:03
> To: Paul Durrant
> Cc: win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> in shared info from EvtchnPoll
> 
> On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> > On Wed, Dec 10, 2014 at 05:38:04PM +0000, Paul Durrant wrote:
> > > > -----Original Message-----
> > > > From: Matt Wilson [mailto:mswilson@gmail.com] On Behalf Of Matt
> Wilson
> > > > Sent: 10 December 2014 17:27
> > > > To: Paul Durrant
> > > > Cc: win-pv-devel@lists.xenproject.org
> > > > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking
> upcall_pending
> > > > in shared info from EvtchnPoll
> > > >
> > > > On Wed, Dec 10, 2014 at 02:10:49PM +0000, Paul Durrant wrote:
> >
> > [...]
> >
> > > > >
> > > > > That's a shame. The code really doesn't have much option but to use
> > > > > this mechanism as Xen provides no explicit way for an HVM guest to
> > > > > get vcpu ids until my patch "x86/hvm: Extend HVM cpuid leaf with
> > > > > vcpu id" goes in and use of the FIFO ABI requires knowledge of vcpu
> > > > > id.
> > > >
> > > > Could you use the ACPI processor object ID number? Or use the initial
> > > > APIC ID to ACPI processor ID mapping in the LAPIC part of MADT?
> > > >
> > >
> > > Do you fix the ACPI tables up in EC2? I assume Windows uses ACPI to
> > > number its CPUs so we could trust that value if we know it to match
> > > the vcpu id.
> >
> > Yes, the MADT LAPIC structs have the correct values. The
> > acpi_processor_id field will be the index of the vCPU. The MADT LAPIC
> > apic_id field will match the default APIC IDs returned by CPUID input
> > EAX=1h output EBX[24..31], and input EAX=2b output EDX.
> >
> > The legacy mptable is also indexed on vCPU ID, and contains the
> > correct default APIC ID for each processor.
> 
> What do you think about using the Viridian MSR for Virtual Processor
> Index as I mentioned on xen-devel?
> 
>   http://lists.xenproject.org/archives/html/xen-devel/2014-
> 12/msg01352.html
> 

That should work, but if viridian is off then I'll still need a fall-back. Is viridian always on in EC2?

Thanks,

  Paul

> --msw
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 21:39:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 21:39:19 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzXvj-0001lH-2u; Fri, 12 Dec 2014 21:39:19 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XzXvh-0001lC-RB
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 21:39:17 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	45/E6-25547-5806B845; Fri, 12 Dec 2014 21:39:17 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1418420354!12988157!1
X-Originating-IP: [209.85.192.182]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 29303 invoked from network); 12 Dec 2014 21:39:16 -0000
Received: from mail-pd0-f182.google.com (HELO mail-pd0-f182.google.com)
	(209.85.192.182)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 21:39:16 -0000
Received: by mail-pd0-f182.google.com with SMTP id p10so7919674pdj.27
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 12 Dec 2014 13:39:14 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=rdb4QfsNTLder9J9em9d1igdIGaC8+dJW+jsE9nNS8A=;
	b=hUAZC84SICfth5sDP3beQ6IlPHdI8wG5hZ35uyzyIO2SV6kX6ArGI8tclgn0tfZ4eE
	324mEgsj72j63VlkGD//ntZsYzNzkciiqK18tZ5PVgZwFSoYh71Qa31i1SnuXpVGF+MA
	sTF/qHBmnexll5Pj7/dvHI0BBL8Xtg2QnEgLoTeJCeD5ly8jEX4eEfKCRw0aDjxzIMQH
	085wsWYtI/WOEXpvIjYTqZghHNUJCEOd02TeofRNOiqsyOIBcAwt2sCH523dayS1Lmxi
	/QAcmsCFyUu23qmcQchbox64XYhqeqKhBtfKSCaBmyW086Rell+ht4Zfsb98WoFb1lTi
	v2Vw==
X-Received: by 10.68.97.131 with SMTP id ea3mr30128119pbb.144.1418420354457;
	Fri, 12 Dec 2014 13:39:14 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id qh4sm2366042pbb.35.2014.12.12.13.39.11
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Fri, 12 Dec 2014 13:39:12 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Fri, 12 Dec 2014 13:39:05 -0800
Date: Fri, 12 Dec 2014 13:39:05 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141212213900.GA18049@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
	<20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Fri, Dec 12, 2014 at 09:45:07AM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> > bounces@lists.xenproject.org] On Behalf Of Matt Wilson
> > Sent: 12 December 2014 00:03
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > in shared info from EvtchnPoll
> > 
[...]
> > On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> > 
> > What do you think about using the Viridian MSR for Virtual Processor
> > Index as I mentioned on xen-devel?
> > 
> >   http://lists.xenproject.org/archives/html/xen-devel/2014-
> > 12/msg01352.html
> > 
> 
> That should work, but if viridian is off then I'll still need a
> fall-back. Is viridian always on in EC2?

Yes, Viridian is on for Windows in EC2. Using the ACPI processor id
should be a reasonable fallback.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 12 21:39:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 12 Dec 2014 21:39:19 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1XzXvj-0001lH-2u; Fri, 12 Dec 2014 21:39:19 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <mswilson@gmail.com>) id 1XzXvh-0001lC-RB
	for win-pv-devel@lists.xenproject.org; Fri, 12 Dec 2014 21:39:17 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	45/E6-25547-5806B845; Fri, 12 Dec 2014 21:39:17 +0000
X-Env-Sender: mswilson@gmail.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1418420354!12988157!1
X-Originating-IP: [209.85.192.182]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 29303 invoked from network); 12 Dec 2014 21:39:16 -0000
Received: from mail-pd0-f182.google.com (HELO mail-pd0-f182.google.com)
	(209.85.192.182)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Dec 2014 21:39:16 -0000
Received: by mail-pd0-f182.google.com with SMTP id p10so7919674pdj.27
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 12 Dec 2014 13:39:14 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=sender:date:from:to:cc:subject:message-id:references:mime-version
	:content-type:content-disposition:in-reply-to:user-agent;
	bh=rdb4QfsNTLder9J9em9d1igdIGaC8+dJW+jsE9nNS8A=;
	b=hUAZC84SICfth5sDP3beQ6IlPHdI8wG5hZ35uyzyIO2SV6kX6ArGI8tclgn0tfZ4eE
	324mEgsj72j63VlkGD//ntZsYzNzkciiqK18tZ5PVgZwFSoYh71Qa31i1SnuXpVGF+MA
	sTF/qHBmnexll5Pj7/dvHI0BBL8Xtg2QnEgLoTeJCeD5ly8jEX4eEfKCRw0aDjxzIMQH
	085wsWYtI/WOEXpvIjYTqZghHNUJCEOd02TeofRNOiqsyOIBcAwt2sCH523dayS1Lmxi
	/QAcmsCFyUu23qmcQchbox64XYhqeqKhBtfKSCaBmyW086Rell+ht4Zfsb98WoFb1lTi
	v2Vw==
X-Received: by 10.68.97.131 with SMTP id ea3mr30128119pbb.144.1418420354457;
	Fri, 12 Dec 2014 13:39:14 -0800 (PST)
Received: from mswilson@gmail.com (54-240-196-186.amazon.com. [54.240.196.186])
	by mx.google.com with ESMTPSA id qh4sm2366042pbb.35.2014.12.12.13.39.11
	for <multiple recipients>
	(version=TLSv1 cipher=RC4-SHA bits=128/128);
	Fri, 12 Dec 2014 13:39:12 -0800 (PST)
Received: by mswilson@gmail.com (sSMTP sendmail emulation);
	Fri, 12 Dec 2014 13:39:05 -0800
Date: Fri, 12 Dec 2014 13:39:05 -0800
From: Matt Wilson <msw@linux.com>
To: Paul Durrant <Paul.Durrant@citrix.com>
Message-ID: <20141212213900.GA18049@u109add4315675089e695.ant.amazon.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
	<20141210061616.GA29484@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025786B72@AMSPEX01CL01.citrite.net>
	<20141210172637.GA10962@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025787455@AMSPEX01CL01.citrite.net>
	<20141210183511.GB10962@u109add4315675089e695.ant.amazon.com>
	<20141212000230.GA17775@u109add4315675089e695.ant.amazon.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD0257894A5@AMSPEX01CL01.citrite.net>
User-Agent: Mutt/1.5.21 (2010-09-15)
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
 in shared info from EvtchnPoll
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

On Fri, Dec 12, 2014 at 09:45:07AM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> > bounces@lists.xenproject.org] On Behalf Of Matt Wilson
> > Sent: 12 December 2014 00:03
> > To: Paul Durrant
> > Cc: win-pv-devel@lists.xenproject.org
> > Subject: Re: [win-pv-devel] [PATCH 04/10] Separate checking upcall_pending
> > in shared info from EvtchnPoll
> > 
[...]
> > On Wed, Dec 10, 2014 at 10:35:11AM -0800, Matt Wilson wrote:
> > 
> > What do you think about using the Viridian MSR for Virtual Processor
> > Index as I mentioned on xen-devel?
> > 
> >   http://lists.xenproject.org/archives/html/xen-devel/2014-
> > 12/msg01352.html
> > 
> 
> That should work, but if viridian is off then I'll still need a
> fall-back. Is viridian always on in EC2?

Yes, Viridian is on for Windows in EC2. Using the ACPI processor id
should be a reasonable fallback.

--msw

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Mon Dec 15 14:43:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 15 Dec 2014 14:43:15 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0Wrj-0006rL-AJ; Mon, 15 Dec 2014 14:43:15 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0Wrh-0006rG-HU
	for win-pv-devel@lists.xenproject.org; Mon, 15 Dec 2014 14:43:13 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	4C/E4-27623-083FE845; Mon, 15 Dec 2014 14:43:12 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1418654590!13491390!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20936 invoked from network); 15 Dec 2014 14:43:12 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-3.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	15 Dec 2014 14:43:12 -0000
X-IronPort-AV: E=Sophos;i="5.07,580,1413244800"; d="scan'208";a="204456880"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Mon, 15 Dec 2014 09:43:00 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0Wl8-0001Sm-1y;
	Mon, 15 Dec 2014 14:36:26 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Mon, 15 Dec 2014 14:36:22 +0000
Message-ID: <1418654182-7556-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Fix 0xD6 bugcheck found with verifier
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

PdoAddRevision() reads beyond the end of an allocation when copying the old
revision table to the new one. This is becaause it is incorrectly using the
Count stack variable rather then the Count field in the Pdo structure. This
patch fixes the problem.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/pdo.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 65f63e5..aa9e5bc 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -316,7 +316,9 @@ PdoAddRevision(
         goto fail1;
 
     if (Pdo->Revision != NULL) {
-        RtlCopyMemory(Revision, Pdo->Revision, sizeof (ULONG) * Count);
+        RtlCopyMemory(Revision,
+                      Pdo->Revision,
+                      sizeof (ULONG) * Pdo->Count);
         __PdoFree(Pdo->Revision);
     }
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Mon Dec 15 14:43:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 15 Dec 2014 14:43:15 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0Wrj-0006rL-AJ; Mon, 15 Dec 2014 14:43:15 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0Wrh-0006rG-HU
	for win-pv-devel@lists.xenproject.org; Mon, 15 Dec 2014 14:43:13 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	4C/E4-27623-083FE845; Mon, 15 Dec 2014 14:43:12 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1418654590!13491390!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20936 invoked from network); 15 Dec 2014 14:43:12 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-3.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	15 Dec 2014 14:43:12 -0000
X-IronPort-AV: E=Sophos;i="5.07,580,1413244800"; d="scan'208";a="204456880"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Mon, 15 Dec 2014 09:43:00 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0Wl8-0001Sm-1y;
	Mon, 15 Dec 2014 14:36:26 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Mon, 15 Dec 2014 14:36:22 +0000
Message-ID: <1418654182-7556-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Fix 0xD6 bugcheck found with verifier
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

PdoAddRevision() reads beyond the end of an allocation when copying the old
revision table to the new one. This is becaause it is incorrectly using the
Count stack variable rather then the Count field in the Pdo structure. This
patch fixes the problem.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/pdo.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 65f63e5..aa9e5bc 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -316,7 +316,9 @@ PdoAddRevision(
         goto fail1;
 
     if (Pdo->Revision != NULL) {
-        RtlCopyMemory(Revision, Pdo->Revision, sizeof (ULONG) * Count);
+        RtlCopyMemory(Revision,
+                      Pdo->Revision,
+                      sizeof (ULONG) * Pdo->Count);
         __PdoFree(Pdo->Revision);
     }
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Tue Dec 16 11:09:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 16 Dec 2014 11:09:27 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0q0N-00043d-I9; Tue, 16 Dec 2014 11:09:27 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0q0M-00043V-G8
	for win-pv-devel@lists.xenproject.org; Tue, 16 Dec 2014 11:09:26 +0000
Received: from [193.109.254.147] by server-8.bemta-14.messagelabs.com id
	05/90-03148-5E210945; Tue, 16 Dec 2014 11:09:25 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418728162!15358979!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12074 invoked from network); 16 Dec 2014 11:09:24 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	16 Dec 2014 11:09:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,586,1413244800"; d="scan'208";a="205301177"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Tue, 16 Dec 2014 06:09:22 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0q0H-00043K-LL;
	Tue, 16 Dec 2014 11:09:21 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 16 Dec 2014 11:09:17 +0000
Message-ID: <1418728157-7504-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Fix free-at-wrong-IRQL bug
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

The hash table code introduced for the FIFO EVTCHN ABI work tries to free
memory at HIGH IRQL. This causes a bugcheck when verifier is turned on. This
patch re-orders the unlock (which drops IRQL back to DISPATCH) and the free.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/hash_table.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/xenbus/hash_table.c b/src/xenbus/hash_table.c
index b8e27d8..0cf1010 100644
--- a/src/xenbus/hash_table.c
+++ b/src/xenbus/hash_table.c
@@ -264,10 +264,11 @@ HashTableRemove(
 
 found:
     RemoveEntryList(ListEntry);
-    __HashTableFree(Node);
 
     HashTableBucketUnlock(Bucket, TRUE, Irql);
 
+    __HashTableFree(Node);
+
     return STATUS_SUCCESS;
 
 fail1:
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Tue Dec 16 11:09:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 16 Dec 2014 11:09:27 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0q0N-00043d-I9; Tue, 16 Dec 2014 11:09:27 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0q0M-00043V-G8
	for win-pv-devel@lists.xenproject.org; Tue, 16 Dec 2014 11:09:26 +0000
Received: from [193.109.254.147] by server-8.bemta-14.messagelabs.com id
	05/90-03148-5E210945; Tue, 16 Dec 2014 11:09:25 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418728162!15358979!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12074 invoked from network); 16 Dec 2014 11:09:24 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	16 Dec 2014 11:09:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,586,1413244800"; d="scan'208";a="205301177"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Tue, 16 Dec 2014 06:09:22 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0q0H-00043K-LL;
	Tue, 16 Dec 2014 11:09:21 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 16 Dec 2014 11:09:17 +0000
Message-ID: <1418728157-7504-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Fix free-at-wrong-IRQL bug
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

The hash table code introduced for the FIFO EVTCHN ABI work tries to free
memory at HIGH IRQL. This causes a bugcheck when verifier is turned on. This
patch re-orders the unlock (which drops IRQL back to DISPATCH) and the free.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/hash_table.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/xenbus/hash_table.c b/src/xenbus/hash_table.c
index b8e27d8..0cf1010 100644
--- a/src/xenbus/hash_table.c
+++ b/src/xenbus/hash_table.c
@@ -264,10 +264,11 @@ HashTableRemove(
 
 found:
     RemoveEntryList(ListEntry);
-    __HashTableFree(Node);
 
     HashTableBucketUnlock(Bucket, TRUE, Irql);
 
+    __HashTableFree(Node);
+
     return STATUS_SUCCESS;
 
 fail1:
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Tue Dec 16 14:42:55 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 16 Dec 2014 14:42:55 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0tKx-0002Qn-68; Tue, 16 Dec 2014 14:42:55 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0tKw-0002Qh-0A
	for win-pv-devel@lists.xenproject.org; Tue, 16 Dec 2014 14:42:54 +0000
Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id
	20/39-22737-DE440945; Tue, 16 Dec 2014 14:42:53 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1418740970!9528890!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 24217 invoked from network); 16 Dec 2014 14:42:52 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	16 Dec 2014 14:42:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,587,1413244800"; d="scan'208";a="205376003"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Tue, 16 Dec 2014 09:41:46 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0tJp-0000im-Uo;
	Tue, 16 Dec 2014 14:41:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 16 Dec 2014 14:41:42 +0000
Message-ID: <1418740902-11448-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Remove extraneous parameter
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus.inf | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/xenbus.inf b/src/xenbus.inf
index 669e866..5377fd0 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -88,7 +88,6 @@ AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 HKR,"Parameters",,0x00000010
 HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE"
 HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE"
-HKR,"Parameters","ExtraInterrupts",0x00010001,64
 
 [XenBus_Interfaces]
 HKR,"Interfaces",,0x00000010
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Tue Dec 16 14:42:55 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 16 Dec 2014 14:42:55 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y0tKx-0002Qn-68; Tue, 16 Dec 2014 14:42:55 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y0tKw-0002Qh-0A
	for win-pv-devel@lists.xenproject.org; Tue, 16 Dec 2014 14:42:54 +0000
Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id
	20/39-22737-DE440945; Tue, 16 Dec 2014 14:42:53 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1418740970!9528890!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 24217 invoked from network); 16 Dec 2014 14:42:52 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	16 Dec 2014 14:42:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,587,1413244800"; d="scan'208";a="205376003"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Tue, 16 Dec 2014 09:41:46 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y0tJp-0000im-Uo;
	Tue, 16 Dec 2014 14:41:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 16 Dec 2014 14:41:42 +0000
Message-ID: <1418740902-11448-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Remove extraneous parameter
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus.inf | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/xenbus.inf b/src/xenbus.inf
index 669e866..5377fd0 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -88,7 +88,6 @@ AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 HKR,"Parameters",,0x00000010
 HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE"
 HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE"
-HKR,"Parameters","ExtraInterrupts",0x00010001,64
 
 [XenBus_Interfaces]
 HKR,"Interfaces",,0x00000010
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 17 10:57:40 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 17 Dec 2014 10:57:40 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1CIV-00021M-TU; Wed, 17 Dec 2014 10:57:39 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1Y1CIU-00021H-91
	for win-pv-devel@lists.xenproject.org; Wed, 17 Dec 2014 10:57:38 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	54/3F-22777-0A161945; Wed, 17 Dec 2014 10:57:36 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-6.tower-206.messagelabs.com!1418813852!13828600!1
X-Originating-IP: [209.85.212.180]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13785 invoked from network); 17 Dec 2014 10:57:32 -0000
Received: from mail-wi0-f180.google.com (HELO mail-wi0-f180.google.com)
	(209.85.212.180)
	by server-6.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Dec 2014 10:57:32 -0000
Received: by mail-wi0-f180.google.com with SMTP id n3so15592443wiv.13
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 17 Dec 2014 02:57:32 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
	d=1e100.net; s=20130820;
	h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to
	:cc:subject:content-type:content-transfer-encoding;
	bh=ifgJE41anwxbZaJLV6OnY5FsscNgjyxpXS+S2nrUVFQ=;
	b=NLZSE1Bu/hsKaXSZ+G0JU0rnHbgxlrZH0muVfYsEKzMj50I94tmVQcvfJHVadxZ007
	8dMy9l5nusrXd3NL95+AiUNjcY8ttWg1prOhYVRnBI4bXwPv/ULADqjhqkozk5FDa57F
	q41xp/lkQrK2IMuu0dyIpk00UJxozdReeplDoozoN3WWZBVHhZwrEGlr1G6vLzzVFJSz
	nKRqgi55r3nXOclJUyFnpCVCwzbd+/o0VFo/KwAQS+OMmxDj4Xo9iRfo8yvNb4yAWIXR
	gyXVaDsQZLZW2/JiusOx8wvlnds7k++Ndb7BQZgeuIvvAX3RZRLoWjREBsIsjV9jkLor
	D5fg==
X-Gm-Message-State: ALoCoQnYZvgjWqWywHrioJh1/3DaidnCwXN6RbZ6Rl0upkwfndCVj5o40jAzJ27zjaKtamkvvGEK
X-Received: by 10.180.85.33 with SMTP id e1mr13029639wiz.61.1418813851992;
	Wed, 17 Dec 2014 02:57:31 -0800 (PST)
Received: from [192.168.1.15] (ip-73-126.sn2.eutelia.it. [83.211.73.126])
	by mx.google.com with ESMTPSA id nb8sm5662280wic.7.2014.12.17.02.57.30
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Wed, 17 Dec 2014 02:57:31 -0800 (PST)
Message-ID: <549161A0.9040008@m2r.biz>
Date: Wed, 17 Dec 2014 11:57:36 +0100
From: Fabio Fantoni <fabio.fantoni@m2r.biz>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64;
	rv:31.0) Gecko/20100101 Thunderbird/31.3.0
MIME-Version: 1.0
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Cc: "paul.durrant@citrix.com >> Paul Durrant" <paul.durrant@citrix.com>,
	owen.smith@citrix.com
Subject: [win-pv-devel] winpv: Question about "Add registry setting for
 removable capability of PDOs" patch and other questions
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="us-ascii"; Format="flowed"
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Hi, I did and tested new xenbus build and I saw this patch: "Add 
registry setting for removable capability of PDOs"
http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xenbus.git;a=commitdiff;h=e651df382f2e8be5dab6a30be226bb9e47ff6417
I not understand if can be used for disable removable option on emulated 
devices now visible on "windows safetly remove hardware".
Can you tell me something about please?

About these new windows pv drivers are there news about when will be 
available official builds?

Keep looking xen-devel seems that recent pv drivers features require 
these patches still not upstream:
- x86/hvm: Extend HVM cpuid leaf with vcpu id
- x86/hvm: Add per-vcpu evtchn upcalls
Is this correct? For now I build my xen-unstable builds that I use also 
for tests new pv drivers with them.

Thanks for any reply and sorry for my bad english.

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 17 10:57:40 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 17 Dec 2014 10:57:40 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1CIV-00021M-TU; Wed, 17 Dec 2014 10:57:39 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1Y1CIU-00021H-91
	for win-pv-devel@lists.xenproject.org; Wed, 17 Dec 2014 10:57:38 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	54/3F-22777-0A161945; Wed, 17 Dec 2014 10:57:36 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-6.tower-206.messagelabs.com!1418813852!13828600!1
X-Originating-IP: [209.85.212.180]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13785 invoked from network); 17 Dec 2014 10:57:32 -0000
Received: from mail-wi0-f180.google.com (HELO mail-wi0-f180.google.com)
	(209.85.212.180)
	by server-6.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Dec 2014 10:57:32 -0000
Received: by mail-wi0-f180.google.com with SMTP id n3so15592443wiv.13
	for <win-pv-devel@lists.xenproject.org>;
	Wed, 17 Dec 2014 02:57:32 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
	d=1e100.net; s=20130820;
	h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to
	:cc:subject:content-type:content-transfer-encoding;
	bh=ifgJE41anwxbZaJLV6OnY5FsscNgjyxpXS+S2nrUVFQ=;
	b=NLZSE1Bu/hsKaXSZ+G0JU0rnHbgxlrZH0muVfYsEKzMj50I94tmVQcvfJHVadxZ007
	8dMy9l5nusrXd3NL95+AiUNjcY8ttWg1prOhYVRnBI4bXwPv/ULADqjhqkozk5FDa57F
	q41xp/lkQrK2IMuu0dyIpk00UJxozdReeplDoozoN3WWZBVHhZwrEGlr1G6vLzzVFJSz
	nKRqgi55r3nXOclJUyFnpCVCwzbd+/o0VFo/KwAQS+OMmxDj4Xo9iRfo8yvNb4yAWIXR
	gyXVaDsQZLZW2/JiusOx8wvlnds7k++Ndb7BQZgeuIvvAX3RZRLoWjREBsIsjV9jkLor
	D5fg==
X-Gm-Message-State: ALoCoQnYZvgjWqWywHrioJh1/3DaidnCwXN6RbZ6Rl0upkwfndCVj5o40jAzJ27zjaKtamkvvGEK
X-Received: by 10.180.85.33 with SMTP id e1mr13029639wiz.61.1418813851992;
	Wed, 17 Dec 2014 02:57:31 -0800 (PST)
Received: from [192.168.1.15] (ip-73-126.sn2.eutelia.it. [83.211.73.126])
	by mx.google.com with ESMTPSA id nb8sm5662280wic.7.2014.12.17.02.57.30
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Wed, 17 Dec 2014 02:57:31 -0800 (PST)
Message-ID: <549161A0.9040008@m2r.biz>
Date: Wed, 17 Dec 2014 11:57:36 +0100
From: Fabio Fantoni <fabio.fantoni@m2r.biz>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64;
	rv:31.0) Gecko/20100101 Thunderbird/31.3.0
MIME-Version: 1.0
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Cc: "paul.durrant@citrix.com >> Paul Durrant" <paul.durrant@citrix.com>,
	owen.smith@citrix.com
Subject: [win-pv-devel] winpv: Question about "Add registry setting for
 removable capability of PDOs" patch and other questions
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="us-ascii"; Format="flowed"
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Hi, I did and tested new xenbus build and I saw this patch: "Add 
registry setting for removable capability of PDOs"
http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xenbus.git;a=commitdiff;h=e651df382f2e8be5dab6a30be226bb9e47ff6417
I not understand if can be used for disable removable option on emulated 
devices now visible on "windows safetly remove hardware".
Can you tell me something about please?

About these new windows pv drivers are there news about when will be 
available official builds?

Keep looking xen-devel seems that recent pv drivers features require 
these patches still not upstream:
- x86/hvm: Extend HVM cpuid leaf with vcpu id
- x86/hvm: Add per-vcpu evtchn upcalls
Is this correct? For now I build my xen-unstable builds that I use also 
for tests new pv drivers with them.

Thanks for any reply and sorry for my bad english.

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 17 11:10:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 17 Dec 2014 11:10:19 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1CUl-0002M3-8i; Wed, 17 Dec 2014 11:10:19 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1CUj-0002Lx-PM
	for win-pv-devel@lists.xenproject.org; Wed, 17 Dec 2014 11:10:17 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	0A/F9-25276-99461945; Wed, 17 Dec 2014 11:10:17 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1418814616!16150275!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21244 invoked from network); 17 Dec 2014 11:10:16 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Dec 2014 11:10:16 -0000
X-IronPort-AV: E=Sophos;i="5.07,593,1413244800"; d="scan'208";a="27989131"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Fabio Fantoni <fabio.fantoni@m2r.biz>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>
Thread-Topic: [win-pv-devel] winpv: Question about "Add registry setting for
	removable capability of PDOs" patch and other questions
Thread-Index: AQHQGehJy7SftK/sWUqc1MEZPGq/vJyTnxqQ
Date: Wed, 17 Dec 2014 11:10:15 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02578EB10@AMSPEX01CL01.citrite.net>
References: <549161A0.9040008@m2r.biz>
In-Reply-To: <549161A0.9040008@m2r.biz>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] winpv: Question about "Add registry setting for
 removable capability of PDOs" patch and other questions
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Fabio Fantoni
> Sent: 17 December 2014 10:58
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [win-pv-devel] winpv: Question about "Add registry setting for
> removable capability of PDOs" patch and other questions
> 
> Hi, I did and tested new xenbus build and I saw this patch: "Add
> registry setting for removable capability of PDOs"
> http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xenbus.git;a=commitdiff;h
> =e651df382f2e8be5dab6a30be226bb9e47ff6417
> I not understand if can be used for disable removable option on emulated
> devices now visible on "windows safetly remove hardware".
> Can you tell me something about please?

It only affects the removability of the class PDOs created by xenbus, it won't affect any other devices.

> 
> About these new windows pv drivers are there news about when will be
> available official builds?
> 

I actually got infrastructure last week; it took ages for the admins to give me some space to host build output. Now, I need to sanity check the latest builds and get them linked on the project front page.

> Keep looking xen-devel seems that recent pv drivers features require
> these patches still not upstream:
> - x86/hvm: Extend HVM cpuid leaf with vcpu id
> - x86/hvm: Add per-vcpu evtchn upcalls
> Is this correct? For now I build my xen-unstable builds that I use also
> for tests new pv drivers with them.
> 

No, these patches are not required; the drivers should still function without them. Those patches enable use of the FIFO event channel ABI though, so performance should be better with them applied.

  Paul

> Thanks for any reply and sorry for my bad english.
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Wed Dec 17 11:10:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 17 Dec 2014 11:10:19 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1CUl-0002M3-8i; Wed, 17 Dec 2014 11:10:19 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1CUj-0002Lx-PM
	for win-pv-devel@lists.xenproject.org; Wed, 17 Dec 2014 11:10:17 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	0A/F9-25276-99461945; Wed, 17 Dec 2014 11:10:17 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1418814616!16150275!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21244 invoked from network); 17 Dec 2014 11:10:16 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Dec 2014 11:10:16 -0000
X-IronPort-AV: E=Sophos;i="5.07,593,1413244800"; d="scan'208";a="27989131"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Fabio Fantoni <fabio.fantoni@m2r.biz>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>
Thread-Topic: [win-pv-devel] winpv: Question about "Add registry setting for
	removable capability of PDOs" patch and other questions
Thread-Index: AQHQGehJy7SftK/sWUqc1MEZPGq/vJyTnxqQ
Date: Wed, 17 Dec 2014 11:10:15 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02578EB10@AMSPEX01CL01.citrite.net>
References: <549161A0.9040008@m2r.biz>
In-Reply-To: <549161A0.9040008@m2r.biz>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] winpv: Question about "Add registry setting for
 removable capability of PDOs" patch and other questions
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

> -----Original Message-----
> From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-
> bounces@lists.xenproject.org] On Behalf Of Fabio Fantoni
> Sent: 17 December 2014 10:58
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [win-pv-devel] winpv: Question about "Add registry setting for
> removable capability of PDOs" patch and other questions
> 
> Hi, I did and tested new xenbus build and I saw this patch: "Add
> registry setting for removable capability of PDOs"
> http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xenbus.git;a=commitdiff;h
> =e651df382f2e8be5dab6a30be226bb9e47ff6417
> I not understand if can be used for disable removable option on emulated
> devices now visible on "windows safetly remove hardware".
> Can you tell me something about please?

It only affects the removability of the class PDOs created by xenbus, it won't affect any other devices.

> 
> About these new windows pv drivers are there news about when will be
> available official builds?
> 

I actually got infrastructure last week; it took ages for the admins to give me some space to host build output. Now, I need to sanity check the latest builds and get them linked on the project front page.

> Keep looking xen-devel seems that recent pv drivers features require
> these patches still not upstream:
> - x86/hvm: Extend HVM cpuid leaf with vcpu id
> - x86/hvm: Add per-vcpu evtchn upcalls
> Is this correct? For now I build my xen-unstable builds that I use also
> for tests new pv drivers with them.
> 

No, these patches are not required; the drivers should still function without them. Those patches enable use of the FIFO event channel ABI though, so performance should be better with them applied.

  Paul

> Thanks for any reply and sorry for my bad english.
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@lists.xenproject.org
> http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:35 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:35 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4B-0002Bf-7L; Thu, 18 Dec 2014 14:28:35 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4A-0002BU-At
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:34 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	10/F4-09842-194E2945; Thu, 18 Dec 2014 14:28:33 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22098 invoked from network); 18 Dec 2014 14:28:32 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:32 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794978"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:17 +0000
Message-ID: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/7] Add multi-ring support
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Adds support for multiple rings, with traffic split based on
a supplied hash value.
Backend exposes "multi-queue-max-queues" to indicate the maximum number
of queues supported (default 1, i.e. single-queue).
Frontend will write "multi-queue-num-queues" to request multi-queues,
this value must be less than or equal to the smaller of what the backend 
supports and the number of vCPUs exposed to the guest. The guest may limit 
this value with the registry setting "MultiQueueMaxQueues" under the XenVif
service parameters key.

Patches:
1: Dont pass through query interface IRPs, as each interface exposed
   needs to be explicitly declared and accounted for in the revision.
2&3: Switch to an array-of-pointers instead of a LIST_ENTRY for rings.
   Rings are limited to 1 per vCPU for performance so the maximum 
   array size is known (MAXIMUM_PROCESSORS)
4: Remove the notifier object, its an abstraction too far. Make receiver
   own the shared event channel (if used) or the receiver/transmitter own 
   their own event channels
5: Update the interface header for VIF v2. Also updates the transmitter
   code to use the (now-downlevel) VIF v1 structures.
6: Add the new functionality from VIF v2. Adds translation layer for VIF v1
   so that all internal operations are using VIF v2 structures.
7: Add multi-queue functionality and distribute packets to queues based on 
   supplied hash values.

Owen Smith (7):
  Make interface exposure explicit
  Move to transmitter ring pointer array
  Move to receiver ring pointer array
  Remove notifier object
  Update to VIF Interface v2
  Implement VIF Interface v2
  Implement multiple queues

 include/vif_interface.h      |   94 +++-
 src/xenvif/driver.c          |   42 ++
 src/xenvif/driver.h          |    5 +
 src/xenvif/frontend.c        |  185 +++++--
 src/xenvif/frontend.h        |   18 +-
 src/xenvif/notifier.c        |  684 -----------------------
 src/xenvif/notifier.h        |   99 ----
 src/xenvif/pdo.c             |   24 +-
 src/xenvif/receiver.c        |  595 +++++++++++++++-----
 src/xenvif/receiver.h        |   18 +-
 src/xenvif/transmitter.c     | 1238 +++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h     |   26 +-
 src/xenvif/vif.c             |  146 ++++-
 src/xenvif/vif.h             |   17 +-
 vs2012/xenvif/xenvif.vcxproj |    1 -
 vs2013/xenvif/xenvif.vcxproj |    1 -
 16 files changed, 1857 insertions(+), 1336 deletions(-)
 delete mode 100644 src/xenvif/notifier.c
 delete mode 100644 src/xenvif/notifier.h

-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:35 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:35 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4B-0002Bf-7L; Thu, 18 Dec 2014 14:28:35 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4A-0002BU-At
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:34 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	10/F4-09842-194E2945; Thu, 18 Dec 2014 14:28:33 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22098 invoked from network); 18 Dec 2014 14:28:32 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:32 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794978"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:17 +0000
Message-ID: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/7] Add multi-ring support
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Adds support for multiple rings, with traffic split based on
a supplied hash value.
Backend exposes "multi-queue-max-queues" to indicate the maximum number
of queues supported (default 1, i.e. single-queue).
Frontend will write "multi-queue-num-queues" to request multi-queues,
this value must be less than or equal to the smaller of what the backend 
supports and the number of vCPUs exposed to the guest. The guest may limit 
this value with the registry setting "MultiQueueMaxQueues" under the XenVif
service parameters key.

Patches:
1: Dont pass through query interface IRPs, as each interface exposed
   needs to be explicitly declared and accounted for in the revision.
2&3: Switch to an array-of-pointers instead of a LIST_ENTRY for rings.
   Rings are limited to 1 per vCPU for performance so the maximum 
   array size is known (MAXIMUM_PROCESSORS)
4: Remove the notifier object, its an abstraction too far. Make receiver
   own the shared event channel (if used) or the receiver/transmitter own 
   their own event channels
5: Update the interface header for VIF v2. Also updates the transmitter
   code to use the (now-downlevel) VIF v1 structures.
6: Add the new functionality from VIF v2. Adds translation layer for VIF v1
   so that all internal operations are using VIF v2 structures.
7: Add multi-queue functionality and distribute packets to queues based on 
   supplied hash values.

Owen Smith (7):
  Make interface exposure explicit
  Move to transmitter ring pointer array
  Move to receiver ring pointer array
  Remove notifier object
  Update to VIF Interface v2
  Implement VIF Interface v2
  Implement multiple queues

 include/vif_interface.h      |   94 +++-
 src/xenvif/driver.c          |   42 ++
 src/xenvif/driver.h          |    5 +
 src/xenvif/frontend.c        |  185 +++++--
 src/xenvif/frontend.h        |   18 +-
 src/xenvif/notifier.c        |  684 -----------------------
 src/xenvif/notifier.h        |   99 ----
 src/xenvif/pdo.c             |   24 +-
 src/xenvif/receiver.c        |  595 +++++++++++++++-----
 src/xenvif/receiver.h        |   18 +-
 src/xenvif/transmitter.c     | 1238 +++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h     |   26 +-
 src/xenvif/vif.c             |  146 ++++-
 src/xenvif/vif.h             |   17 +-
 vs2012/xenvif/xenvif.vcxproj |    1 -
 vs2013/xenvif/xenvif.vcxproj |    1 -
 16 files changed, 1857 insertions(+), 1336 deletions(-)
 delete mode 100644 src/xenvif/notifier.c
 delete mode 100644 src/xenvif/notifier.h

-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:36 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:36 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4C-0002CE-8E; Thu, 18 Dec 2014 14:28:36 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4A-0002BV-Lv
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:34 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	27/AC-25276-294E2945; Thu, 18 Dec 2014 14:28:34 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22169 invoked from network); 18 Dec 2014 14:28:33 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794979"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:18 +0000
Message-ID: <1418912904-8756-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/7] Make interface exposure explicit
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Add pass-through query for XenBus's Cache interface and
account for interface versions when determining the revision(s).
Do not pass through any other queries, as the revision is not
accounted for.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/pdo.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c
index c07c66e..90c08e9 100644
--- a/src/xenvif/pdo.c
+++ b/src/xenvif/pdo.c
@@ -547,7 +547,7 @@ __PdoSetRevisions(
     IN  PXENVIF_PDO Pdo
     )
 {
-    ULONG           Vif;
+    ULONG           Cache;
     ULONG           Revision;
     NTSTATUS        status;
 
@@ -559,15 +559,20 @@ __PdoSetRevisions(
     // even when a particular combination of interface versions becomes
     // unsupported. (See README.md for API versioning policy).
 
-    for (Vif = 1; Vif <= XENVIF_VIF_INTERFACE_VERSION_MAX; Vif++) {
-        Revision++;
+    for (Cache = 1; Cache <= XENBUS_CACHE_INTERFACE_VERSION_MAX; Cache++) {
+        ULONG       Vif;
 
-        if (Vif >= XENVIF_VIF_INTERFACE_VERSION_MIN) {
-            status = __PdoAddRevision(Pdo, Revision);
-            if (!NT_SUCCESS(status))
-                goto fail1;
+        for (Vif = 1; Vif <= XENVIF_VIF_INTERFACE_VERSION_MAX; Vif++) {
+            Revision++;
+
+            if (Vif >= XENVIF_VIF_INTERFACE_VERSION_MIN &&
+                Cache >= XENBUS_CACHE_INTERFACE_VERSION_MIN) {
+                status = __PdoAddRevision(Pdo, Revision);
+                if (!NT_SUCCESS(status))
+                    goto fail1;
+            }
         }
-    }                             
+    }
 
     ASSERT(Pdo->Count > 0);
     return STATUS_SUCCESS;
@@ -1543,6 +1548,7 @@ struct _INTERFACE_ENTRY {
 struct _INTERFACE_ENTRY PdoInterfaceTable[] = {
     { &GUID_BUS_INTERFACE_STANDARD, "BUS_INTERFACE", PdoQueryBusInterface },
     { &GUID_XENVIF_VIF_INTERFACE, "VIF_INTERFACE", PdoQueryVifInterface },
+    { &GUID_XENBUS_CACHE_INTERFACE, "CACHE_INTERFACE", __PdoDelegateIrp },
     { NULL, NULL, NULL }
 };
 
@@ -1578,8 +1584,6 @@ PdoQueryInterface(
         }
     }
 
-    status = __PdoDelegateIrp(Pdo, Irp);
-
 done:
     Irp->IoStatus.Status = status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:36 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:36 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4C-0002CE-8E; Thu, 18 Dec 2014 14:28:36 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4A-0002BV-Lv
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:34 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	27/AC-25276-294E2945; Thu, 18 Dec 2014 14:28:34 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22169 invoked from network); 18 Dec 2014 14:28:33 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794979"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:18 +0000
Message-ID: <1418912904-8756-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/7] Make interface exposure explicit
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Add pass-through query for XenBus's Cache interface and
account for interface versions when determining the revision(s).
Do not pass through any other queries, as the revision is not
accounted for.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/pdo.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c
index c07c66e..90c08e9 100644
--- a/src/xenvif/pdo.c
+++ b/src/xenvif/pdo.c
@@ -547,7 +547,7 @@ __PdoSetRevisions(
     IN  PXENVIF_PDO Pdo
     )
 {
-    ULONG           Vif;
+    ULONG           Cache;
     ULONG           Revision;
     NTSTATUS        status;
 
@@ -559,15 +559,20 @@ __PdoSetRevisions(
     // even when a particular combination of interface versions becomes
     // unsupported. (See README.md for API versioning policy).
 
-    for (Vif = 1; Vif <= XENVIF_VIF_INTERFACE_VERSION_MAX; Vif++) {
-        Revision++;
+    for (Cache = 1; Cache <= XENBUS_CACHE_INTERFACE_VERSION_MAX; Cache++) {
+        ULONG       Vif;
 
-        if (Vif >= XENVIF_VIF_INTERFACE_VERSION_MIN) {
-            status = __PdoAddRevision(Pdo, Revision);
-            if (!NT_SUCCESS(status))
-                goto fail1;
+        for (Vif = 1; Vif <= XENVIF_VIF_INTERFACE_VERSION_MAX; Vif++) {
+            Revision++;
+
+            if (Vif >= XENVIF_VIF_INTERFACE_VERSION_MIN &&
+                Cache >= XENBUS_CACHE_INTERFACE_VERSION_MIN) {
+                status = __PdoAddRevision(Pdo, Revision);
+                if (!NT_SUCCESS(status))
+                    goto fail1;
+            }
         }
-    }                             
+    }
 
     ASSERT(Pdo->Count > 0);
     return STATUS_SUCCESS;
@@ -1543,6 +1548,7 @@ struct _INTERFACE_ENTRY {
 struct _INTERFACE_ENTRY PdoInterfaceTable[] = {
     { &GUID_BUS_INTERFACE_STANDARD, "BUS_INTERFACE", PdoQueryBusInterface },
     { &GUID_XENVIF_VIF_INTERFACE, "VIF_INTERFACE", PdoQueryVifInterface },
+    { &GUID_XENBUS_CACHE_INTERFACE, "CACHE_INTERFACE", __PdoDelegateIrp },
     { NULL, NULL, NULL }
 };
 
@@ -1578,8 +1584,6 @@ PdoQueryInterface(
         }
     }
 
-    status = __PdoDelegateIrp(Pdo, Irp);
-
 done:
     Irp->IoStatus.Status = status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002Co-9D; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4B-0002Be-Cz
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:35 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	73/50-29352-294E2945; Thu, 18 Dec 2014 14:28:34 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13855 invoked from network); 18 Dec 2014 14:28:33 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268736"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:20 +0000
Message-ID: <1418912904-8756-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/7] Move to receiver ring pointer array
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Replace the list of rings with a maximally sized array of pointers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/receiver.c | 134 ++++++++++++++++++++++----------------------------
 1 file changed, 60 insertions(+), 74 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index c9e865e..1b81b73 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -74,7 +74,6 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT {
 
 typedef struct _XENVIF_RECEIVER_RING {
     PXENVIF_RECEIVER            Receiver;
-    LIST_ENTRY                  ListEntry;
     ULONG                       Index;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
@@ -98,7 +97,7 @@ typedef struct _XENVIF_RECEIVER_RING {
 struct _XENVIF_RECEIVER {
     PXENVIF_FRONTEND        Frontend;
     XENBUS_CACHE_INTERFACE  CacheInterface;
-    LIST_ENTRY              List;
+    PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
     LONG                    Loaned;
     LONG                    Returned;
     KEVENT                  Event;
@@ -2360,7 +2359,6 @@ ReceiverInitialize(
             (*Receiver)->AlwaysPullup = ReceiverAlwaysPullup;
     }
 
-    InitializeListHead(&(*Receiver)->List);
     KeInitializeEvent(&(*Receiver)->Event, NotificationEvent, FALSE);
 
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
@@ -2378,16 +2376,15 @@ ReceiverInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    Index = 0;
-    while (Index < Count) {
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
         if (!NT_SUCCESS(status))
             goto fail3;
 
-        InsertTailList(&(*Receiver)->List, &Ring->ListEntry);
-        Index++;
+        (*Receiver)->Rings[Index] = Ring;
     }
 
     return STATUS_SUCCESS;
@@ -2395,22 +2392,17 @@ ReceiverInitialize(
 fail3:
     Error("fail3\n");
 
-    while (!IsListEmpty(&(*Receiver)->List)) {
-        PLIST_ENTRY             ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        ListEntry = RemoveTailList(&(*Receiver)->List);
-        ASSERT3P(ListEntry, !=, &(*Receiver)->List);
-
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = (*Receiver)->Rings[Index];
+        (*Receiver)->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __ReceiverRingTeardown(Ring);
-
-        --Index;
     }
-    ASSERT3U(Index, ==, 0);
 
     XENBUS_CACHE(Release, &(*Receiver)->CacheInterface);
 
@@ -2429,7 +2421,6 @@ fail2:
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     RtlZeroMemory(&(*Receiver)->Event, sizeof (KEVENT));
-    RtlZeroMemory(&(*Receiver)->List, sizeof (LIST_ENTRY));
 
     (*Receiver)->CalculateChecksums = 0;
     (*Receiver)->AllowGsoPackets = 0;
@@ -2453,7 +2444,7 @@ ReceiverConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
@@ -2466,12 +2457,12 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -2492,22 +2483,17 @@ ReceiverConnect(
 fail4:
     Error("fail4\n");
 
-    ListEntry = &Receiver->List;
-
 fail3:
     Error("fail3\n");
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Receiver->List) {
-        PLIST_ENTRY             Prev = ListEntry->Blink;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisconnect(Ring);
-
-        ListEntry = Prev;
     }
 
     XENBUS_STORE(Release, &Receiver->StoreInterface);
@@ -2614,7 +2600,7 @@ ReceiverStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend;
-    PLIST_ENTRY                     ListEntry;
+    ULONG                           Index;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2657,12 +2643,12 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -2698,17 +2684,17 @@ ReceiverEnable(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingEnable(Ring);
         if (!NT_SUCCESS(status))
@@ -2720,12 +2706,12 @@ ReceiverEnable(
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Receiver->List) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2738,14 +2724,14 @@ ReceiverDisable(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Receiver->List.Blink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2757,7 +2743,7 @@ ReceiverDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
     Frontend = Receiver->Frontend;
 
@@ -2766,12 +2752,12 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    for (ListEntry = Receiver->List.Blink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisconnect(Ring);
     }
@@ -2786,19 +2772,20 @@ ReceiverTeardown(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
+    ULONG                   Index;
+
     ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
 
-    while (!IsListEmpty(&Receiver->List)) {
-        PLIST_ENTRY             ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        ListEntry = RemoveTailList(&Receiver->List);
-        ASSERT3P(ListEntry, !=, &Receiver->List);
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = Receiver->Rings[Index];
+        Receiver->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingTeardown(Ring);
     }
@@ -2817,8 +2804,7 @@ ReceiverTeardown(
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     RtlZeroMemory(&Receiver->Event, sizeof (KEVENT));
-    RtlZeroMemory(&Receiver->List, sizeof (LIST_ENTRY));
 
     Receiver->CalculateChecksums = 0;
     Receiver->AllowGsoPackets = 0;
     Receiver->DisableIpVersion4Gso = 0;
@@ -2836,7 +2822,7 @@ ReceiverSetOffloadOptions(
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
     )
 {
-    PLIST_ENTRY                     ListEntry;
+    ULONG                           Index;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -2844,12 +2830,12 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingSetOffloadOptions(Ring, Options);
     }    
@@ -2939,14 +2925,14 @@ ReceiverNotify(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingNotify(Ring);
     }    
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002Co-9D; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4B-0002Be-Cz
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:35 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	73/50-29352-294E2945; Thu, 18 Dec 2014 14:28:34 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13855 invoked from network); 18 Dec 2014 14:28:33 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268736"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:20 +0000
Message-ID: <1418912904-8756-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/7] Move to receiver ring pointer array
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Replace the list of rings with a maximally sized array of pointers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/receiver.c | 134 ++++++++++++++++++++++----------------------------
 1 file changed, 60 insertions(+), 74 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index c9e865e..1b81b73 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -74,7 +74,6 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT {
 
 typedef struct _XENVIF_RECEIVER_RING {
     PXENVIF_RECEIVER            Receiver;
-    LIST_ENTRY                  ListEntry;
     ULONG                       Index;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
@@ -98,7 +97,7 @@ typedef struct _XENVIF_RECEIVER_RING {
 struct _XENVIF_RECEIVER {
     PXENVIF_FRONTEND        Frontend;
     XENBUS_CACHE_INTERFACE  CacheInterface;
-    LIST_ENTRY              List;
+    PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
     LONG                    Loaned;
     LONG                    Returned;
     KEVENT                  Event;
@@ -2360,7 +2359,6 @@ ReceiverInitialize(
             (*Receiver)->AlwaysPullup = ReceiverAlwaysPullup;
     }
 
-    InitializeListHead(&(*Receiver)->List);
     KeInitializeEvent(&(*Receiver)->Event, NotificationEvent, FALSE);
 
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
@@ -2378,16 +2376,15 @@ ReceiverInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    Index = 0;
-    while (Index < Count) {
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
         if (!NT_SUCCESS(status))
             goto fail3;
 
-        InsertTailList(&(*Receiver)->List, &Ring->ListEntry);
-        Index++;
+        (*Receiver)->Rings[Index] = Ring;
     }
 
     return STATUS_SUCCESS;
@@ -2395,22 +2392,17 @@ ReceiverInitialize(
 fail3:
     Error("fail3\n");
 
-    while (!IsListEmpty(&(*Receiver)->List)) {
-        PLIST_ENTRY             ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        ListEntry = RemoveTailList(&(*Receiver)->List);
-        ASSERT3P(ListEntry, !=, &(*Receiver)->List);
-
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = (*Receiver)->Rings[Index];
+        (*Receiver)->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __ReceiverRingTeardown(Ring);
-
-        --Index;
     }
-    ASSERT3U(Index, ==, 0);
 
     XENBUS_CACHE(Release, &(*Receiver)->CacheInterface);
 
@@ -2429,7 +2421,6 @@ fail2:
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     RtlZeroMemory(&(*Receiver)->Event, sizeof (KEVENT));
-    RtlZeroMemory(&(*Receiver)->List, sizeof (LIST_ENTRY));
 
     (*Receiver)->CalculateChecksums = 0;
     (*Receiver)->AllowGsoPackets = 0;
@@ -2453,7 +2444,7 @@ ReceiverConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
@@ -2466,12 +2457,12 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -2492,22 +2483,17 @@ ReceiverConnect(
 fail4:
     Error("fail4\n");
 
-    ListEntry = &Receiver->List;
-
 fail3:
     Error("fail3\n");
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Receiver->List) {
-        PLIST_ENTRY             Prev = ListEntry->Blink;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisconnect(Ring);
-
-        ListEntry = Prev;
     }
 
     XENBUS_STORE(Release, &Receiver->StoreInterface);
@@ -2614,7 +2600,7 @@ ReceiverStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend;
-    PLIST_ENTRY                     ListEntry;
+    ULONG                           Index;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2657,12 +2643,12 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -2698,17 +2684,17 @@ ReceiverEnable(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __ReceiverRingEnable(Ring);
         if (!NT_SUCCESS(status))
@@ -2720,12 +2706,12 @@ ReceiverEnable(
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Receiver->List) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2738,14 +2724,14 @@ ReceiverDisable(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Receiver->List.Blink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2757,7 +2743,7 @@ ReceiverDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
     Frontend = Receiver->Frontend;
 
@@ -2766,12 +2752,12 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    for (ListEntry = Receiver->List.Blink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingDisconnect(Ring);
     }
@@ -2786,19 +2772,20 @@ ReceiverTeardown(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
+    ULONG                   Index;
+
     ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
 
-    while (!IsListEmpty(&Receiver->List)) {
-        PLIST_ENTRY             ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        ListEntry = RemoveTailList(&Receiver->List);
-        ASSERT3P(ListEntry, !=, &Receiver->List);
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = Receiver->Rings[Index];
+        Receiver->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingTeardown(Ring);
     }
@@ -2817,8 +2804,7 @@ ReceiverTeardown(
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
     RtlZeroMemory(&Receiver->Event, sizeof (KEVENT));
-    RtlZeroMemory(&Receiver->List, sizeof (LIST_ENTRY));
 
     Receiver->CalculateChecksums = 0;
     Receiver->AllowGsoPackets = 0;
     Receiver->DisableIpVersion4Gso = 0;
@@ -2836,7 +2822,7 @@ ReceiverSetOffloadOptions(
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
     )
 {
-    PLIST_ENTRY                     ListEntry;
+    ULONG                           Index;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -2844,12 +2830,12 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingSetOffloadOptions(Ring, Options);
     }    
@@ -2939,14 +2925,14 @@ ReceiverNotify(
     IN  PXENVIF_RECEIVER    Receiver
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Receiver->List.Flink;
-         ListEntry != &Receiver->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        Ring = Receiver->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __ReceiverRingNotify(Ring);
     }    
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002Cu-AT; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4B-0002Bj-Mi
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:35 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	2E/F4-09842-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!3
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22222 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794981"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:22 +0000
Message-ID: <1418912904-8756-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 5/7] Update to VIF Interface v2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Renames XENVIF_TRANSMITTER_PACKET to XENVIF_TRANSMITTER_PACKET_V1 and
adds XENVIF_TRANSMITTER_PACKET_V2 for future patches.
VIF v2 will be implemented in another patch.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  | 94 ++++++++++++++++++++++++++++++++++++++++++++----
 src/xenvif/transmitter.c | 88 +++++++++++++++++++++++++--------------------
 src/xenvif/transmitter.h |  6 ++--
 src/xenvif/vif.c         | 18 +++++-----
 src/xenvif/vif.h         |  6 ++--
 5 files changed, 153 insertions(+), 59 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..d083fd1 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -257,7 +257,7 @@ struct _XENVIF_TRANSMITTER_PACKET_V1 {
     };
 };
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET_V1, *PXENVIF_TRANSMITTER_PACKET_V1;
 
 #pragma warning(pop)
 
@@ -265,6 +265,30 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V2
+    \brief Transmit-side packet structure (v2)
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Hash value set by subscriber */
+    ULONG                                       Value;
+    /*! Packet information passed from subscriber to provider */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Packet information passed from provider to subscriber on packet return */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+    /*! Packet data MDL */
+    PMDL                                        Mdl;
+    /*! Offset into MDL to start of packet */
+    ULONG                                       Offset;
+    /*! Packet length */
+    ULONG                                       Length;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET pointer
@@ -474,16 +498,44 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+    \brief Get the packet headers into supplied buffer
+
+    \param Interface The interface header
+    \param Packet The packet to acquire headers for.
+    \param Headers The buffer to receive headers.
+    \param Info The offsets into Headers for relevant headers
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE                  Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
     \brief Queue transmit side packets at the provider
 
     \param Interface The interface header
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of _XENVIF_TRANSMITTER_PACKET_V1
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \param List List of _XENVIF_TRANSMITTER_PACKET_V2
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)(
+    IN  PINTERFACE  Interface,
+    IN  PLIST_ENTRY List
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -708,7 +760,37 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \struct _XENVIF_VIF_INTERFACE_V2
+    \brief VIF interface version 2
+    \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V2 {
+    INTERFACE                                       Interface;
+    XENVIF_VIF_ACQUIRE                              Acquire;
+    XENVIF_VIF_RELEASE                              Release;
+    XENVIF_VIF_ENABLE                               Enable;
+    XENVIF_VIF_DISABLE                              Disable;
+    XENVIF_VIF_QUERY_STATISTIC                      QueryStatistic;
+    XENVIF_VIF_RECEIVER_RETURN_PACKETS              ReceiverReturnPackets;
+    XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
+    XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
+    XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
+    XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
+    XENVIF_VIF_MAC_QUERY_STATE                      MacQueryState;
+    XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE         MacQueryMaximumFrameSize;
+    XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS          MacQueryPermanentAddress;
+    XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS            MacQueryCurrentAddress;
+    XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES        MacQueryMulticastAddresses;
+    XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
+    XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
+    XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
     \brief Macro at assist in method invocation
@@ -719,6 +801,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
 #endif  // _WINDLL
 
 #define XENVIF_VIF_INTERFACE_VERSION_MIN    1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX    1
+#define XENVIF_VIF_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENVIF_INTERFACE_H
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index e482392..41bab7c 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -89,7 +89,7 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT {
 #define XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID  0x03FF
 
 typedef struct _XENVIF_TRANSMITTER_STATE {
-    PXENVIF_TRANSMITTER_PACKET          Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1       Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -101,8 +101,8 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 #define XENVIF_TRANSMITTER_RING_SIZE   (__CONST_RING_SIZE(netif_tx, PAGE_SIZE))
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
 } XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
 
 typedef struct _XENVIF_TRANSMITTER_RING {
@@ -123,7 +123,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
-    PXENVIF_TRANSMITTER_PACKET      Lock;
+    PVOID                           Lock;
     PKTHREAD                        LockThread;
     XENVIF_TRANSMITTER_PACKET_LIST  Queued;
     XENVIF_TRANSMITTER_STATE        State;
@@ -558,7 +558,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -705,7 +705,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -852,7 +852,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -1129,7 +1129,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET      Packet;
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
         --State->Count;
 
@@ -1185,8 +1185,8 @@ __TransmitterRingUnprepareFragments(
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
 #define OFFSET_EXISTS(_Ring, _Packet, _Type)                                                        \
@@ -1337,13 +1337,13 @@ fail1:
 #undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V1
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1702,7 +1702,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1927,8 +1927,8 @@ __TransmitterRingFakeResponses(
 
 static FORCEINLINE VOID
 __TransmitterRingCompletePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -2026,7 +2026,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET      Packet;
+            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2231,17 +2231,17 @@ __TransmitterRingPushRequests(
 
 static FORCEINLINE ULONG
 __TransmitterReversePacketList(
-    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   *Packet
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
     ULONG                           Count;
 
     HeadPacket = NULL;
     Count = 0;
 
     while (*Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
 
         ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
 
@@ -2266,8 +2266,8 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
@@ -2307,8 +2307,8 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET  Packet;
-        NTSTATUS                    status;
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        NTSTATUS                        status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2402,6 +2402,20 @@ TransmitterRingSchedule(
     __TransmitterRingPushRequests(Ring);
 }
 
+static FORCEINLINE VOID
+__TransmitterReturnPackets(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    )
+{
+    PXENVIF_FRONTEND    Frontend;
+
+    Frontend = Transmitter->Frontend;
+
+    VifTransmitterReturnPacketsV1(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                  HeadPacket);
+}
+
 static FORCEINLINE BOOLEAN
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingTryAcquireLock(
@@ -2499,8 +2513,8 @@ __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
@@ -2525,13 +2539,11 @@ __TransmitterRingReleaseLock(
 
     if (HeadPacket != NULL) {
         PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
 
         Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
 
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+        __TransmitterReturnPackets(Transmitter,
+                                   HeadPacket);
     }
 }
 
@@ -3139,7 +3151,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -3339,11 +3351,11 @@ __TransmitterRingTeardown(
 
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
@@ -3376,7 +3388,7 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
     __TransmitterRingAcquireLock(Ring);
 
@@ -3388,7 +3400,7 @@ __TransmitterRingAbortPackets(
     Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
 
     while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
         
         Next = Packet->Next;
         Packet->Next = NULL;
@@ -3882,9 +3894,9 @@ fail1:
 }
 
 VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+TransmitterQueuePacketsV1(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
     PXENVIF_TRANSMITTER_RING        Ring;
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 9c3bfaa..6a7fcd5 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -108,9 +108,9 @@ TransmitterAdvertiseAddresses(
     );
 
 extern VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+TransmitterQueuePacketsV1(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     );
 
 extern VOID
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index 97ce84a..b858d8f 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -275,9 +275,9 @@ VifReceiverReturnPackets(
 
 
 static NTSTATUS
-VifTransmitterQueuePackets(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterQueuePacketsV1(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
     PXENVIF_VIF_CONTEXT             Context = Interface->Context;
@@ -289,8 +289,8 @@ VifTransmitterQueuePackets(
     if (Context->Enabled == FALSE)
         goto fail1;
 
-    TransmitterQueuePackets(FrontendGetTransmitter(Context->Frontend),
-                            Head);            
+    TransmitterQueuePacketsV1(FrontendGetTransmitter(Context->Frontend),
+                              Head);
 
     ReleaseMrswLockShared(&Context->Lock);
 
@@ -642,7 +642,7 @@ static struct _XENVIF_VIF_INTERFACE_V1 VifInterfaceVersion1 = {
     VifReceiverSetOffloadOptions,
     VifReceiverQueryRingSize,
     VifTransmitterSetPacketOffset,
-    VifTransmitterQueuePackets,
+    VifTransmitterQueuePacketsV1,
     VifTransmitterQueryOffloadOptions,
     VifTransmitterQueryLargePacketSize,
     VifTransmitterQueryRingSize,
@@ -783,9 +783,9 @@ VifReceiverQueuePackets(
 }
 
 VOID
-VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterReturnPacketsV1(
+    IN  PXENVIF_VIF_CONTEXT             Context,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
     Context->Callback(Context->Argument,
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index 17a04db..a26aa1b 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -69,9 +69,9 @@ VifReceiverQueuePackets(
     );
 
 extern VOID
-VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterReturnPacketsV1(
+    IN  PXENVIF_VIF_CONTEXT             Context,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
 extern PXENVIF_THREAD
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002Cu-AT; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4B-0002Bj-Mi
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:35 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	2E/F4-09842-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!3
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22222 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794981"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:22 +0000
Message-ID: <1418912904-8756-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 5/7] Update to VIF Interface v2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Renames XENVIF_TRANSMITTER_PACKET to XENVIF_TRANSMITTER_PACKET_V1 and
adds XENVIF_TRANSMITTER_PACKET_V2 for future patches.
VIF v2 will be implemented in another patch.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  | 94 ++++++++++++++++++++++++++++++++++++++++++++----
 src/xenvif/transmitter.c | 88 +++++++++++++++++++++++++--------------------
 src/xenvif/transmitter.h |  6 ++--
 src/xenvif/vif.c         | 18 +++++-----
 src/xenvif/vif.h         |  6 ++--
 5 files changed, 153 insertions(+), 59 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..d083fd1 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -257,7 +257,7 @@ struct _XENVIF_TRANSMITTER_PACKET_V1 {
     };
 };
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET_V1, *PXENVIF_TRANSMITTER_PACKET_V1;
 
 #pragma warning(pop)
 
@@ -265,6 +265,30 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V2
+    \brief Transmit-side packet structure (v2)
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Hash value set by subscriber */
+    ULONG                                       Value;
+    /*! Packet information passed from subscriber to provider */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Packet information passed from provider to subscriber on packet return */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+    /*! Packet data MDL */
+    PMDL                                        Mdl;
+    /*! Offset into MDL to start of packet */
+    ULONG                                       Offset;
+    /*! Packet length */
+    ULONG                                       Length;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET pointer
@@ -474,16 +498,44 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+    \brief Get the packet headers into supplied buffer
+
+    \param Interface The interface header
+    \param Packet The packet to acquire headers for.
+    \param Headers The buffer to receive headers.
+    \param Info The offsets into Headers for relevant headers
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE                  Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
     \brief Queue transmit side packets at the provider
 
     \param Interface The interface header
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of _XENVIF_TRANSMITTER_PACKET_V1
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \param List List of _XENVIF_TRANSMITTER_PACKET_V2
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)(
+    IN  PINTERFACE  Interface,
+    IN  PLIST_ENTRY List
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -708,7 +760,37 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \struct _XENVIF_VIF_INTERFACE_V2
+    \brief VIF interface version 2
+    \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V2 {
+    INTERFACE                                       Interface;
+    XENVIF_VIF_ACQUIRE                              Acquire;
+    XENVIF_VIF_RELEASE                              Release;
+    XENVIF_VIF_ENABLE                               Enable;
+    XENVIF_VIF_DISABLE                              Disable;
+    XENVIF_VIF_QUERY_STATISTIC                      QueryStatistic;
+    XENVIF_VIF_RECEIVER_RETURN_PACKETS              ReceiverReturnPackets;
+    XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
+    XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
+    XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
+    XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
+    XENVIF_VIF_MAC_QUERY_STATE                      MacQueryState;
+    XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE         MacQueryMaximumFrameSize;
+    XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS          MacQueryPermanentAddress;
+    XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS            MacQueryCurrentAddress;
+    XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES        MacQueryMulticastAddresses;
+    XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
+    XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
+    XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
     \brief Macro at assist in method invocation
@@ -719,6 +801,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
 #endif  // _WINDLL
 
 #define XENVIF_VIF_INTERFACE_VERSION_MIN    1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX    1
+#define XENVIF_VIF_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENVIF_INTERFACE_H
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index e482392..41bab7c 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -89,7 +89,7 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT {
 #define XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID  0x03FF
 
 typedef struct _XENVIF_TRANSMITTER_STATE {
-    PXENVIF_TRANSMITTER_PACKET          Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1       Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -101,8 +101,8 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 #define XENVIF_TRANSMITTER_RING_SIZE   (__CONST_RING_SIZE(netif_tx, PAGE_SIZE))
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
 } XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
 
 typedef struct _XENVIF_TRANSMITTER_RING {
@@ -123,7 +123,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
-    PXENVIF_TRANSMITTER_PACKET      Lock;
+    PVOID                           Lock;
     PKTHREAD                        LockThread;
     XENVIF_TRANSMITTER_PACKET_LIST  Queued;
     XENVIF_TRANSMITTER_STATE        State;
@@ -558,7 +558,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -705,7 +705,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -852,7 +852,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -1129,7 +1129,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET      Packet;
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
         --State->Count;
 
@@ -1185,8 +1185,8 @@ __TransmitterRingUnprepareFragments(
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
 #define OFFSET_EXISTS(_Ring, _Packet, _Type)                                                        \
@@ -1337,13 +1337,13 @@ fail1:
 #undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V1
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1702,7 +1702,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1927,8 +1927,8 @@ __TransmitterRingFakeResponses(
 
 static FORCEINLINE VOID
 __TransmitterRingCompletePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -2026,7 +2026,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET      Packet;
+            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2231,17 +2231,17 @@ __TransmitterRingPushRequests(
 
 static FORCEINLINE ULONG
 __TransmitterReversePacketList(
-    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   *Packet
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
     ULONG                           Count;
 
     HeadPacket = NULL;
     Count = 0;
 
     while (*Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
 
         ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
 
@@ -2266,8 +2266,8 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
@@ -2307,8 +2307,8 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET  Packet;
-        NTSTATUS                    status;
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        NTSTATUS                        status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2402,6 +2402,20 @@ TransmitterRingSchedule(
     __TransmitterRingPushRequests(Ring);
 }
 
+static FORCEINLINE VOID
+__TransmitterReturnPackets(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    )
+{
+    PXENVIF_FRONTEND    Frontend;
+
+    Frontend = Transmitter->Frontend;
+
+    VifTransmitterReturnPacketsV1(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                  HeadPacket);
+}
+
 static FORCEINLINE BOOLEAN
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingTryAcquireLock(
@@ -2499,8 +2513,8 @@ __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
@@ -2525,13 +2539,11 @@ __TransmitterRingReleaseLock(
 
     if (HeadPacket != NULL) {
         PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
 
         Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
 
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+        __TransmitterReturnPackets(Transmitter,
+                                   HeadPacket);
     }
 }
 
@@ -3139,7 +3151,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -3339,11 +3351,11 @@ __TransmitterRingTeardown(
 
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
@@ -3376,7 +3388,7 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
     __TransmitterRingAcquireLock(Ring);
 
@@ -3388,7 +3400,7 @@ __TransmitterRingAbortPackets(
     Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
 
     while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
         
         Next = Packet->Next;
         Packet->Next = NULL;
@@ -3882,9 +3894,9 @@ fail1:
 }
 
 VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+TransmitterQueuePacketsV1(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
     PXENVIF_TRANSMITTER_RING        Ring;
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 9c3bfaa..6a7fcd5 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -108,9 +108,9 @@ TransmitterAdvertiseAddresses(
     );
 
 extern VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+TransmitterQueuePacketsV1(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     );
 
 extern VOID
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index 97ce84a..b858d8f 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -275,9 +275,9 @@ VifReceiverReturnPackets(
 
 
 static NTSTATUS
-VifTransmitterQueuePackets(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterQueuePacketsV1(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
     PXENVIF_VIF_CONTEXT             Context = Interface->Context;
@@ -289,8 +289,8 @@ VifTransmitterQueuePackets(
     if (Context->Enabled == FALSE)
         goto fail1;
 
-    TransmitterQueuePackets(FrontendGetTransmitter(Context->Frontend),
-                            Head);            
+    TransmitterQueuePacketsV1(FrontendGetTransmitter(Context->Frontend),
+                              Head);
 
     ReleaseMrswLockShared(&Context->Lock);
 
@@ -642,7 +642,7 @@ static struct _XENVIF_VIF_INTERFACE_V1 VifInterfaceVersion1 = {
     VifReceiverSetOffloadOptions,
     VifReceiverQueryRingSize,
     VifTransmitterSetPacketOffset,
-    VifTransmitterQueuePackets,
+    VifTransmitterQueuePacketsV1,
     VifTransmitterQueryOffloadOptions,
     VifTransmitterQueryLargePacketSize,
     VifTransmitterQueryRingSize,
@@ -783,9 +783,9 @@ VifReceiverQueuePackets(
 }
 
 VOID
-VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterReturnPacketsV1(
+    IN  PXENVIF_VIF_CONTEXT             Context,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
     Context->Callback(Context->Argument,
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index 17a04db..a26aa1b 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -69,9 +69,9 @@ VifReceiverQueuePackets(
     );
 
 extern VOID
-VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+VifTransmitterReturnPacketsV1(
+    IN  PXENVIF_VIF_CONTEXT             Context,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
 extern PXENVIF_THREAD
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002DD-Bi; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002C3-7w
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:36 +0000
Received: from [85.158.139.211] by server-1.bemta-5.messagelabs.com id
	D2/05-24124-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!2
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14913 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268737"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:19 +0000
Message-ID: <1418912904-8756-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/7] Move to transmitter ring pointer array
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Replace the list of rings with a maximally sized array of pointers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/transmitter.c | 141 ++++++++++++++++++++---------------------------
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..645872b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -106,7 +106,6 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
 
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
-    LIST_ENTRY                      ListEntry;
     ULONG                           Index;
     PXENBUS_CACHE                   BufferCache;
     PXENBUS_CACHE                   FragmentCache;
@@ -146,7 +145,7 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
-    LIST_ENTRY                  List;
+    PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
@@ -3240,8 +3239,6 @@ TransmitterInitialize(
             (*Transmitter)->AlwaysCopy = TransmitterAlwaysCopy;
     }
 
-    InitializeListHead(&(*Transmitter)->List);
-
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Transmitter)->DebugInterface);
 
@@ -3264,16 +3261,15 @@ TransmitterInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    Index = 0;
-    while (Index < Count) {
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
             goto fail4;
 
-        InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
-        Index++;
+        (*Transmitter)->Rings[Index] = Ring;
     }
 
     return STATUS_SUCCESS;
@@ -3281,21 +3277,17 @@ TransmitterInitialize(
 fail4:
     Error("fail4\n");
 
-    while (!IsListEmpty(&(*Transmitter)->List)) {
-        PLIST_ENTRY                 ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        ListEntry = RemoveTailList(&(*Transmitter)->List);
-        ASSERT3P(ListEntry, !=, &(*Transmitter)->List);
-
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = (*Transmitter)->Rings[Index];
+        (*Transmitter)->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingTeardown(Ring);
-        --Index;
     }
-    ASSERT3U(Index, ==, 0);
 
     XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
 
@@ -3321,8 +3313,6 @@ fail2:
     RtlZeroMemory(&(*Transmitter)->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
-    RtlZeroMemory(&(*Transmitter)->List, sizeof (LIST_ENTRY));
-
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
@@ -3342,7 +3332,7 @@ TransmitterConnect(
     )
 {
     PXENVIF_FRONTEND            Frontend;
-    PLIST_ENTRY                 ListEntry;
+    ULONG                       Index;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3355,12 +3345,12 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -3381,22 +3371,17 @@ TransmitterConnect(
 fail4:
     Error("fail4\n");
 
-    ListEntry = &Transmitter->List;
-
 fail3:
     Error("fail3\n");
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Transmitter->List) {
-        PLIST_ENTRY                 Prev = ListEntry->Blink;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingDisconnect(Ring);
-
-        ListEntry = Prev;
     }
 
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
@@ -3418,15 +3403,15 @@ TransmitterStoreWrite(
     IN  PXENBUS_STORE_TRANSACTION   Transaction
     )
 {
-    PLIST_ENTRY                     ListEntry;
     NTSTATUS                        status;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __TransmitterRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -3446,14 +3431,14 @@ TransmitterEnable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingEnable(Ring);
     }    
@@ -3466,14 +3451,14 @@ TransmitterDisable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Blink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingDisable(Ring);
     }
@@ -3485,7 +3470,7 @@ TransmitterDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
     Frontend = Transmitter->Frontend;
 
@@ -3494,12 +3479,12 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    for (ListEntry = Transmitter->List.Blink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3514,18 +3499,19 @@ TransmitterTeardown(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
+    ULONG                   Index;
+
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
-    while (!IsListEmpty(&Transmitter->List)) {
-        PLIST_ENTRY                 ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        ListEntry = RemoveHeadList(&Transmitter->List);
-        ASSERT3P(ListEntry, !=, &Transmitter->List);
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = Transmitter->Rings[Index];
+        Transmitter->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingTeardown(Ring);
     }
@@ -3548,8 +3534,6 @@ TransmitterTeardown(
     RtlZeroMemory(&Transmitter->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
-    RtlZeroMemory(&Transmitter->List, sizeof (LIST_ENTRY));
-
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
@@ -3566,15 +3550,14 @@ TransmitterUpdateAddressTable(
     )
 {
     KIRQL                       Irql;
-    PLIST_ENTRY                 ListEntry;
     PXENVIF_TRANSMITTER_RING    Ring;
 
     // Make sure we don't suspend
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
     // Use the first ring for address advertisment
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingUpdateAddressTable(Ring, Table, Count);
 
@@ -3586,12 +3569,11 @@ TransmitterAdvertiseAddresses(
     IN  PXENVIF_TRANSMITTER     Transmitter
     )
 {
-    PLIST_ENTRY                 ListEntry;
     PXENVIF_TRANSMITTER_RING    Ring;
 
     // Use the first ring for address advertisment
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingAdvertiseAddresses(Ring);
 }
@@ -3625,13 +3607,12 @@ TransmitterQueuePackets(
     IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
     )
 {
-    PLIST_ENTRY                     ListEntry;
     PXENVIF_TRANSMITTER_RING        Ring;
 
     // We need to hash for a ring eventually. Since there is only a
     // single ring for now, we just use that.
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3P(Ring, !=, NULL);
 
     __TransmitterRingQueuePackets(Ring, HeadPacket);
 }
@@ -3641,17 +3622,17 @@ TransmitterAbortPackets(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     KIRQL                   Irql;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingAbortPackets(Ring);
     }    
@@ -3675,14 +3656,14 @@ TransmitterNotify(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingNotify(Ring);
     }    
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002DD-Bi; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002C3-7w
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:36 +0000
Received: from [85.158.139.211] by server-1.bemta-5.messagelabs.com id
	D2/05-24124-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!2
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14913 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268737"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:19 +0000
Message-ID: <1418912904-8756-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/7] Move to transmitter ring pointer array
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Replace the list of rings with a maximally sized array of pointers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/transmitter.c | 141 ++++++++++++++++++++---------------------------
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..645872b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -106,7 +106,6 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
 
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
-    LIST_ENTRY                      ListEntry;
     ULONG                           Index;
     PXENBUS_CACHE                   BufferCache;
     PXENBUS_CACHE                   FragmentCache;
@@ -146,7 +145,7 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
-    LIST_ENTRY                  List;
+    PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
@@ -3240,8 +3239,6 @@ TransmitterInitialize(
             (*Transmitter)->AlwaysCopy = TransmitterAlwaysCopy;
     }
 
-    InitializeListHead(&(*Transmitter)->List);
-
     FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Transmitter)->DebugInterface);
 
@@ -3264,16 +3261,15 @@ TransmitterInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    Index = 0;
-    while (Index < Count) {
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
             goto fail4;
 
-        InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
-        Index++;
+        (*Transmitter)->Rings[Index] = Ring;
     }
 
     return STATUS_SUCCESS;
@@ -3281,21 +3277,17 @@ TransmitterInitialize(
 fail4:
     Error("fail4\n");
 
-    while (!IsListEmpty(&(*Transmitter)->List)) {
-        PLIST_ENTRY                 ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        ListEntry = RemoveTailList(&(*Transmitter)->List);
-        ASSERT3P(ListEntry, !=, &(*Transmitter)->List);
-
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = (*Transmitter)->Rings[Index];
+        (*Transmitter)->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingTeardown(Ring);
-        --Index;
     }
-    ASSERT3U(Index, ==, 0);
 
     XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
 
@@ -3321,8 +3313,6 @@ fail2:
     RtlZeroMemory(&(*Transmitter)->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
-    RtlZeroMemory(&(*Transmitter)->List, sizeof (LIST_ENTRY));
-
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
@@ -3342,7 +3332,7 @@ TransmitterConnect(
     )
 {
     PXENVIF_FRONTEND            Frontend;
-    PLIST_ENTRY                 ListEntry;
+    ULONG                       Index;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3355,12 +3345,12 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -3381,22 +3371,17 @@ TransmitterConnect(
 fail4:
     Error("fail4\n");
 
-    ListEntry = &Transmitter->List;
-
 fail3:
     Error("fail3\n");
 
-    ListEntry = ListEntry->Blink;
-
-    while (ListEntry != &Transmitter->List) {
-        PLIST_ENTRY                 Prev = ListEntry->Blink;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingDisconnect(Ring);
-
-        ListEntry = Prev;
     }
 
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
@@ -3418,15 +3403,15 @@ TransmitterStoreWrite(
     IN  PXENBUS_STORE_TRANSACTION   Transaction
     )
 {
-    PLIST_ENTRY                     ListEntry;
     NTSTATUS                        status;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         status = __TransmitterRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -3446,14 +3431,14 @@ TransmitterEnable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingEnable(Ring);
     }    
@@ -3466,14 +3451,14 @@ TransmitterDisable(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Blink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingDisable(Ring);
     }
@@ -3485,7 +3470,7 @@ TransmitterDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
     Frontend = Transmitter->Frontend;
 
@@ -3494,12 +3479,12 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    for (ListEntry = Transmitter->List.Blink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Blink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3514,18 +3499,19 @@ TransmitterTeardown(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
+    ULONG                   Index;
+
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
-    while (!IsListEmpty(&Transmitter->List)) {
-        PLIST_ENTRY                 ListEntry;
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        ListEntry = RemoveHeadList(&Transmitter->List);
-        ASSERT3P(ListEntry, !=, &Transmitter->List);
-        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+        Ring = Transmitter->Rings[Index];
+        Transmitter->Rings[Index] = NULL;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring == NULL)
+            continue;
 
         __TransmitterRingTeardown(Ring);
     }
@@ -3548,8 +3534,6 @@ TransmitterTeardown(
     RtlZeroMemory(&Transmitter->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
-    RtlZeroMemory(&Transmitter->List, sizeof (LIST_ENTRY));
-
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
@@ -3566,15 +3550,14 @@ TransmitterUpdateAddressTable(
     )
 {
     KIRQL                       Irql;
-    PLIST_ENTRY                 ListEntry;
     PXENVIF_TRANSMITTER_RING    Ring;
 
     // Make sure we don't suspend
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
     // Use the first ring for address advertisment
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingUpdateAddressTable(Ring, Table, Count);
 
@@ -3586,12 +3569,11 @@ TransmitterAdvertiseAddresses(
     IN  PXENVIF_TRANSMITTER     Transmitter
     )
 {
-    PLIST_ENTRY                 ListEntry;
     PXENVIF_TRANSMITTER_RING    Ring;
 
     // Use the first ring for address advertisment
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3U(Ring, !=, NULL);
 
     __TransmitterRingAdvertiseAddresses(Ring);
 }
@@ -3625,13 +3607,12 @@ TransmitterQueuePackets(
     IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
     )
 {
-    PLIST_ENTRY                     ListEntry;
     PXENVIF_TRANSMITTER_RING        Ring;
 
     // We need to hash for a ring eventually. Since there is only a
     // single ring for now, we just use that.
-    ListEntry = Transmitter->List.Flink;
-    Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+    Ring = Transmitter->Rings[0];
+    ASSERT3P(Ring, !=, NULL);
 
     __TransmitterRingQueuePackets(Ring, HeadPacket);
 }
@@ -3641,17 +3622,17 @@ TransmitterAbortPackets(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
     KIRQL                   Irql;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingAbortPackets(Ring);
     }    
@@ -3675,14 +3656,14 @@ TransmitterNotify(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
 {
-    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
 
-    for (ListEntry = Transmitter->List.Flink;
-         ListEntry != &Transmitter->List;
-         ListEntry = ListEntry->Flink) {
+    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
-        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        Ring = Transmitter->Rings[Index];
+        if (Ring == NULL)
+            break;
 
         __TransmitterRingNotify(Ring);
     }    
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002DU-EP; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002C4-76
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:36 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	F3/A9-02953-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-27.messagelabs.com!1418912913!15962346!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20111 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794985"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:23 +0000
Message-ID: <1418912904-8756-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 6/7] Implement VIF Interface v2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Use VIF v2 structures internally, and add translation layer
for VIF v1 calls.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/transmitter.c | 587 +++++++++++++++++++++++++++++++++--------------
 src/xenvif/transmitter.h |  14 ++
 src/xenvif/vif.c         | 128 ++++++++++-
 src/xenvif/vif.h         |  11 +
 4 files changed, 564 insertions(+), 176 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 41bab7c..914e544 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -89,7 +89,7 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT {
 #define XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID  0x03FF
 
 typedef struct _XENVIF_TRANSMITTER_STATE {
-    PXENVIF_TRANSMITTER_PACKET_V1       Packet;
+    PXENVIF_TRANSMITTER_PACKET          Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -100,11 +100,6 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 
 #define XENVIF_TRANSMITTER_RING_SIZE   (__CONST_RING_SIZE(netif_tx, PAGE_SIZE))
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
-} XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
-
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
     ULONG                           Index;
@@ -125,7 +120,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Stopped;
     PVOID                           Lock;
     PKTHREAD                        LockThread;
-    XENVIF_TRANSMITTER_PACKET_LIST  Queued;
+    LIST_ENTRY                      Queued;
     XENVIF_TRANSMITTER_STATE        State;
     ULONG                           PacketsQueued;
     ULONG                           PacketsGranted;
@@ -138,7 +133,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     ULONG                           RequestsPushed;
     ULONG                           ResponsesProcessed;
     ULONG                           PacketsSent;
-    XENVIF_TRANSMITTER_PACKET_LIST  Completed;
+    LIST_ENTRY                      Completed;
     ULONG                           PacketsCompleted;
     PSOCKADDR_INET                  AddressTable;
     ULONG                           AddressCount;
@@ -158,12 +153,15 @@ struct _XENVIF_TRANSMITTER {
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
+    KSPIN_LOCK                  PacketLock;
+    PXENBUS_CACHE               PacketCache;
     XENBUS_STORE_INTERFACE      StoreInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
 };
 
 #define XENVIF_TRANSMITTER_TAG  'NART'
+#define XENVIF_PACKET_CACHE_RESERVATION 32
 
 static FORCEINLINE PVOID
 __TransmitterAllocate(
@@ -181,6 +179,72 @@ __TransmitterFree(
     __FreePoolWithTag(Buffer, XENVIF_TRANSMITTER_TAG);
 }
 
+static VOID
+TransmitterPacketAcquireLock(
+    IN  PVOID                       Argument
+    )
+{
+    PXENVIF_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->PacketLock);
+}
+
+static VOID
+TransmitterPacketReleaseLock(
+    IN  PVOID                       Argument
+    )
+{
+    PXENVIF_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
+}
+
+static NTSTATUS
+TransmitterPacketCtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+TransmitterPacketDtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+__TransmitterGetPacket(
+    IN  PXENVIF_TRANSMITTER         Transmitter
+    )
+{
+    return XENBUS_CACHE(Get,
+                        &Transmitter->CacheInterface,
+                        Transmitter->PacketCache,
+                        TRUE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET));
+
+    XENBUS_CACHE(Put,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 TRUE);
+}
+
 static NTSTATUS
 TransmitterBufferCtor(
     IN  PVOID                   Argument,
@@ -530,26 +594,6 @@ fail1:
     return FALSE;
 }
 
-#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            (*Reference)++;                                         \
-        } while (FALSE)
-
-#define DECREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            ASSERT(*Reference != 0);                                \
-            --(*Reference);                                         \
-        } while (FALSE)
-
-#define PACKET_REFERENCE(_Packet)                                   \
-        (*(PULONG_PTR)&(_Packet)->Next)
-
 static FORCEINLINE NTSTATUS
 __TransmitterRingCopyPayload(
     IN  PXENVIF_TRANSMITTER_RING    Ring
@@ -558,7 +602,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -572,7 +616,7 @@ __TransmitterRingCopyPayload(
 
     Payload = State->Payload;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 1);
+    ASSERT3U(Packet->Value, ==, 1);
 
     while (Payload.Length != 0) {
         PMDL        Mdl;
@@ -587,7 +631,7 @@ __TransmitterRingCopyPayload(
             goto fail1;
 
         Buffer->Context = Packet;
-        INCREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value++;
 
         Mdl = Buffer->Mdl;
 
@@ -649,14 +693,14 @@ fail2:
     ASSERT3P(Buffer->Context, ==, Packet);
     Buffer->Context = NULL;        
 
-    DECREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value--;
 
     __TransmitterPutBuffer(Ring, Buffer);
 
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    while (PACKET_REFERENCE(Packet) != 1) {
+    while (Packet->Value != 1) {
         PLIST_ENTRY         ListEntry;
 
         ASSERT(State->Count != 0);
@@ -689,7 +733,7 @@ fail1:
         ASSERT3P(Buffer->Context, ==, Packet);
         Buffer->Context = NULL;        
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value--;
 
         __TransmitterPutBuffer(Ring, Buffer);
     }
@@ -705,7 +749,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -720,7 +764,7 @@ __TransmitterRingGrantPayload(
     Packet = State->Packet;
     Payload = &State->Payload;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 1);
+    ASSERT3U(Packet->Value, ==, 1);
 
     Mdl = Payload->Mdl;
     Offset = Payload->Offset;
@@ -749,7 +793,7 @@ __TransmitterRingGrantPayload(
 
             Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_PACKET;
             Fragment->Context = Packet;
-            INCREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value++;
 
             Pfn = MmGetMdlPfnArray(Mdl)[MdlOffset / PAGE_SIZE];
             PageOffset = MdlOffset & (PAGE_SIZE - 1);
@@ -801,7 +845,7 @@ fail2:
         Fragment->Context = NULL;
         Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value--;
 
         __TransmitterPutFragment(Ring, Fragment);
     }
@@ -811,7 +855,7 @@ fail1:
 
     ASSERT3P(Fragment, ==, NULL);
 
-    while (PACKET_REFERENCE(Packet) != 1) {
+    while (Packet->Value != 1) {
         PLIST_ENTRY         ListEntry;
 
         ASSERT(State->Count != 0);
@@ -835,7 +879,7 @@ fail1:
         Fragment->Context = NULL;
         Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value;
 
         __TransmitterPutFragment(Ring, Fragment);
     }
@@ -852,7 +896,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -872,7 +916,7 @@ __TransmitterRingPrepareHeader(
     Payload = &State->Payload;
     Info = &State->Info;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 0);
+    ASSERT3U(Packet->Value, ==, 0);
 
     Buffer = __TransmitterGetBuffer(Ring);
 
@@ -881,7 +925,7 @@ __TransmitterRingPrepareHeader(
         goto fail1;
 
     Buffer->Context = Packet;
-    INCREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value++;
 
     Mdl = Buffer->Mdl;
 
@@ -1099,7 +1143,7 @@ fail3:
 fail2:
     Error("fail2\n");
 
-    DECREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value--;
     Buffer->Context = NULL;
 
     __TransmitterPutBuffer(Ring, Buffer);
@@ -1107,7 +1151,7 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 0);
+    ASSERT3U(Packet->Value, ==, 0);
 
     return status;
 }
@@ -1129,7 +1173,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        PXENVIF_TRANSMITTER_PACKET      Packet;
 
         --State->Count;
 
@@ -1179,25 +1223,16 @@ __TransmitterRingUnprepareFragments(
         __TransmitterPutFragment(Ring, Fragment);
 
         if (Packet != NULL)
-            DECREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value--;
     }
 }
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
     IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    IN  PXENVIF_TRANSMITTER_PACKET      Packet
     )
 {
-#define OFFSET_EXISTS(_Ring, _Packet, _Type)                                                        \
-    ((_Ring)->Transmitter->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET] != 0)
-
-#define OFFSET(_Ring, _Packet, _Type)                                                               \
-        ((OFFSET_EXISTS(_Ring, _Packet, _Type)) ?                                                   \
-         (PVOID)((PUCHAR)(_Packet) +                                                                \
-                 (_Ring)->Transmitter->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET]) :    \
-         NULL)
-
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_TRANSMITTER_STATE       State;
     PXENVIF_PACKET_PAYLOAD          Payload;
@@ -1205,7 +1240,6 @@ __TransmitterRingPreparePacket(
     NTSTATUS                        status;
 
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
-    ASSERT3P(Packet->Next, ==, NULL);
 
     Transmitter = Ring->Transmitter;
 
@@ -1217,17 +1251,9 @@ __TransmitterRingPreparePacket(
     RtlZeroMemory(&Packet->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO));
 
     Payload = &State->Payload;
-
-    ASSERT(OFFSET_EXISTS(Ring, Packet, MDL));
-    Payload->Mdl = *(PMDL *)OFFSET(Ring, Packet, MDL);
-
-    if (OFFSET_EXISTS(Ring, Packet, OFFSET))
-        Payload->Offset = *(PULONG)OFFSET(Ring, Packet, OFFSET);
-    else
-        Payload->Offset = 0;
-
-    ASSERT(OFFSET_EXISTS(Ring, Packet, LENGTH));
-    Payload->Length = *(PULONG)OFFSET(Ring, Packet, LENGTH);
+    Payload->Mdl = Packet->Mdl;
+    Payload->Offset = Packet->Offset;
+    Payload->Length = Packet->Length;
 
     InitializeListHead(&State->List);
     ASSERT3U(State->Count, ==, 0);
@@ -1236,7 +1262,7 @@ __TransmitterRingPreparePacket(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+    ASSERT3U(State->Count, ==, Packet->Value);
 
     Info = &State->Info;
 
@@ -1294,7 +1320,7 @@ __TransmitterRingPreparePacket(
 
         if (Transmitter->AlwaysCopy != 0 ||
             (!NT_SUCCESS(status) && status == STATUS_BUFFER_OVERFLOW)) {
-            ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+            ASSERT3U(State->Count, ==, Packet->Value);
 
             status = __TransmitterRingCopyPayload(Ring);
         }
@@ -1303,7 +1329,7 @@ __TransmitterRingPreparePacket(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+    ASSERT3U(State->Count, ==, Packet->Value);
 
     Ring->PacketsPrepared++;
     return STATUS_SUCCESS;
@@ -1332,18 +1358,15 @@ fail1:
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
 
     return status;
-
-#undef  OFFSET
-#undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V1
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1702,7 +1725,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1722,7 +1745,7 @@ __TransmitterRingPostFragments(
     ASSERT(!IsListEmpty(&State->List));
     ASSERT(State->Count != 0);
     ASSERT3U(State->Count, <=, XEN_NETIF_NR_SLOTS_MIN);
-    ASSERT(IMPLY(Packet != NULL, State->Count == PACKET_REFERENCE(Packet)));
+    ASSERT(IMPLY(Packet != NULL, State->Count == Packet->Value));
 
     req_prod = Ring->Front.req_prod_pvt;
     rsp_cons = Ring->Front.rsp_cons;
@@ -1927,8 +1950,8 @@ __TransmitterRingFakeResponses(
 
 static FORCEINLINE VOID
 __TransmitterRingCompletePacket(
-    IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    IN  PXENVIF_TRANSMITTER_RING    Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -1987,10 +2010,7 @@ __TransmitterRingCompletePacket(
         }
     }
 
-    *Ring->Completed.TailPacket = Packet;
-    ASSERT3P(Packet->Next, ==, NULL);
-    Ring->Completed.TailPacket = &Packet->Next;
-
+    InsertTailList(&Ring->Completed, &Packet->ListEntry);
     Ring->PacketsCompleted++;
 }
 
@@ -2026,7 +2046,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+            PXENVIF_TRANSMITTER_PACKET      Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2090,7 +2110,7 @@ TransmitterRingPoll(
                 continue;
             }
 
-            DECREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value--;
 
             if (rsp->status != NETIF_RSP_OKAY &&
                 Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING) {
@@ -2111,7 +2131,7 @@ TransmitterRingPoll(
 
             RtlZeroMemory(rsp, sizeof (netif_tx_response_t));
 
-            if (PACKET_REFERENCE(Packet) != 0)
+            if (Packet->Value != 0)
                 continue;
 
             if (Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING)
@@ -2266,32 +2286,44 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
+    PLIST_ENTRY                     ListEntry;
+    LIST_ENTRY                      List;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
 
+    InitializeListHead(&List);
+
     New = XENVIF_TRANSMITTER_LOCK_BIT;    
     Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock, (PVOID)New);
 
     ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
-    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+    ListEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
 
-    if (HeadPacket == NULL)
+    if (ListEntry == NULL)
         return;
 
     // Packets are held in the atomic packet list in reverse order
     // so that the most recent is always head of the list. This is
     // necessary to allow addition to the list to be done atomically.
 
-    TailPacket = &HeadPacket->Next;
-    Count = __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
+    for (Count = 0; ListEntry != NULL; ++Count) {
+        PLIST_ENTRY     NextEntry;
+
+        NextEntry = ListEntry->Blink;
+        ListEntry->Flink = ListEntry->Blink = ListEntry;
+
+        InsertHeadList(&List, ListEntry);
+
+        ListEntry = NextEntry;
+    }
 
-    *(Ring->Queued.TailPacket) = HeadPacket;
-    Ring->Queued.TailPacket = TailPacket;
-    Ring->PacketsQueued += Count;
+    ListEntry = List.Flink;
+    if (!IsListEmpty(&List)) {
+        RemoveEntryList(&List);
+        AppendTailList(&Ring->Queued, ListEntry);
+        Ring->PacketsQueued += Count;
+    }
 }
 
 static DECLSPEC_NOINLINE VOID
@@ -2307,8 +2339,9 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-        NTSTATUS                        status;
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
+        NTSTATUS                    status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2357,18 +2390,13 @@ TransmitterRingSchedule(
             continue;
         }
 
-        Packet = Ring->Queued.HeadPacket;
-
-        if (Packet == NULL)
+        ListEntry = RemoveHeadList(&Ring->Queued);
+        if (ListEntry == &Ring->Queued)
             break;
 
-        if (Packet->Next == NULL) {
-            Ring->Queued.HeadPacket = NULL;
-            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
-        } else {
-            Ring->Queued.HeadPacket = Packet->Next;
-            Packet->Next = NULL;
-        }
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+        Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
+        Packet->Value = 0;
 
         status = __TransmitterRingPreparePacket(Ring, Packet);
         if (!NT_SUCCESS(status)) {
@@ -2397,23 +2425,63 @@ TransmitterRingSchedule(
         ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
     }
 
-    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring->Queued.TailPacket == &Ring->Queued.HeadPacket));
-
     __TransmitterRingPushRequests(Ring);
 }
 
 static FORCEINLINE VOID
 __TransmitterReturnPackets(
-    IN  PXENVIF_TRANSMITTER             Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     )
 {
-    PXENVIF_FRONTEND    Frontend;
+    PXENVIF_FRONTEND        Frontend;
+    PXENVIF_VIF_CONTEXT     VifContext;
 
     Frontend = Transmitter->Frontend;
+    VifContext = PdoGetVifContext(FrontendGetPdo(Frontend));
+
+    switch (VifGetVersion(VifContext)) {
+    case 1: {
+        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
 
-    VifTransmitterReturnPacketsV1(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                  HeadPacket);
+        HeadPacket = NextPacket = NULL;
+
+        while (!IsListEmpty(List)) {
+            PLIST_ENTRY                 ListEntry;
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+
+            ListEntry = RemoveTailList(List);
+            ASSERT3P(ListEntry, !=, List);
+
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+            Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
+
+            HeadPacket = Packet->Cookie;
+            HeadPacket->Next = NextPacket;
+            NextPacket = HeadPacket;
+
+            HeadPacket->Completion = Packet->Completion;
+
+            __TransmitterPutPacket(Transmitter, Packet);
+        }
+
+        if (HeadPacket != NULL) {
+            VifTransmitterReturnPacketsV1(VifContext, HeadPacket);
+        }
+        break;
+    }
+    case 2: {
+        if (!IsListEmpty(List)) {
+            VifTransmitterReturnPacketsV2(VifContext, List);
+        }
+        break;
+    }
+    default: {
+        ASSERT(FALSE);
+        break;
+    }
+    }
 }
 
 static FORCEINLINE BOOLEAN
@@ -2513,11 +2581,9 @@ __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
-    
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    LIST_ENTRY                      List;
+
+    InitializeListHead(&List);
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
@@ -2527,23 +2593,26 @@ __TransmitterRingReleaseLock(
     // thread could be simuntaneously adding to the list.
 
     do {
+        PLIST_ENTRY     ListEntry;
+
         TransmitterRingSwizzle(Ring);
         TransmitterRingSchedule(Ring);
 
-        *TailPacket = Ring->Completed.HeadPacket;
-        TailPacket = Ring->Completed.TailPacket;
-
-        Ring->Completed.HeadPacket = NULL;
-        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
+        ListEntry = Ring->Completed.Flink;
+        if (!IsListEmpty(&Ring->Completed)) {
+            RemoveEntryList(&Ring->Completed);
+            InitializeListHead(&Ring->Completed);
+            AppendTailList(&List, ListEntry);
+        }
     } while (!__TransmitterRingTryReleaseLock(Ring));
 
-    if (HeadPacket != NULL) {
+    if (!IsListEmpty(&List)) {
         PXENVIF_TRANSMITTER Transmitter;
 
         Transmitter = Ring->Transmitter;
 
         __TransmitterReturnPackets(Transmitter,
-                                   HeadPacket);
+                                   &List);
     }
 }
 
@@ -2792,8 +2861,8 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
-    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
-    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    InitializeListHead(&(*Ring)->Queued);
+    InitializeListHead(&(*Ring)->Completed);
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
     KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
@@ -2929,8 +2998,8 @@ fail2:
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
 
-    (*Ring)->Queued.TailPacket = NULL;
-    (*Ring)->Completed.TailPacket = NULL;
+    RtlZeroMemory(&(*Ring)->Queued, sizeof (LIST_ENTRY));
+    RtlZeroMemory(&(*Ring)->Completed, sizeof (LIST_ENTRY));
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -3151,7 +3220,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -3170,14 +3239,7 @@ __TransmitterRingDisable(
 
     // Put any packet back on the head of the queue
     if (Packet != NULL) {
-        ASSERT3P(Packet->Next, ==, NULL);
-
-        Packet->Next = Ring->Queued.HeadPacket;
-
-        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
-            Ring->Queued.TailPacket = &Packet->Next;
-
-        Ring->Queued.HeadPacket = Packet;
+        InsertHeadList(&Ring->Queued, &Packet->ListEntry);
     }
 
     Ring->AddressIndex = 0;
@@ -3336,11 +3398,11 @@ __TransmitterRingTeardown(
                  Ring->BufferCache);
     Ring->BufferCache = NULL;
 
-    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
-    Ring->Queued.TailPacket = NULL;
+    ASSERT(IsListEmpty(&Ring->Queued));
+    RtlZeroMemory(&Ring->Queued, sizeof (LIST_ENTRY));
 
-    ASSERT3P(Ring->Completed.TailPacket, ==, &Ring->Completed.HeadPacket);
-    Ring->Completed.TailPacket = NULL;
+    ASSERT(IsListEmpty(&Ring->Completed));
+    RtlZeroMemory(&Ring->Completed, sizeof (LIST_ENTRY));
 
     Ring->Index = 0;
     Ring->Transmitter = NULL;
@@ -3351,25 +3413,20 @@ __TransmitterRingTeardown(
 
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
-    IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    IN  PXENVIF_TRANSMITTER_RING    Ring,
+    IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
 
-    TailPacket = &HeadPacket->Next;
-    (VOID) __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
-
     do {
         Old = (ULONG_PTR)Ring->Lock;
         LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
 
-        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
-        New = (ULONG_PTR)HeadPacket;
+        List->Flink->Blink = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+        New = (ULONG_PTR)List->Blink;
         ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
         New |= LockBit;
     } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock, (PVOID)New, (PVOID)Old) != Old);
@@ -3388,22 +3445,19 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-
     __TransmitterRingAcquireLock(Ring);
 
     TransmitterRingSwizzle(Ring);
 
-    Packet = Ring->Queued.HeadPacket;
-
-    Ring->Queued.HeadPacket = NULL;
-    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
-
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET_V1   Next;
+    while (!IsListEmpty(&Ring->Queued)) {
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
         
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        ListEntry = RemoveHeadList(&Ring->Queued);
+        ASSERT3P(ListEntry, !=, &Ring->Queued);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+        Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
 
         // Fake that we prapared and sent this packet
         Ring->PacketsPrepared++;
@@ -3413,8 +3467,6 @@ __TransmitterRingAbortPackets(
         Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
 
         __TransmitterRingCompletePacket(Ring, Packet);
-
-        Packet = Next;
     }
 
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
@@ -3507,6 +3559,7 @@ TransmitterInitialize(
                           &(*Transmitter)->EvtchnInterface);
 
     (*Transmitter)->Frontend = Frontend;
+    KeInitializeSpinLock(&(*Transmitter)->PacketLock);
 
     status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
     if (!NT_SUCCESS(status))
@@ -3556,6 +3609,9 @@ fail2:
 
     (*Transmitter)->Frontend = NULL;
 
+    RtlZeroMemory(&(*Transmitter)->PacketLock,
+                  sizeof (KSPIN_LOCK));
+
     RtlZeroMemory(&(*Transmitter)->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -3605,6 +3661,20 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_CACHE(Create,
+                          &Transmitter->CacheInterface,
+                          "packet_cache",
+                          sizeof (XENVIF_TRANSMITTER_PACKET),
+                          XENVIF_PACKET_CACHE_RESERVATION,
+                          TransmitterPacketCtor,
+                          TransmitterPacketDtor,
+                          TransmitterPacketAcquireLock,
+                          TransmitterPacketReleaseLock,
+                          Transmitter,
+                          &Transmitter->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = XENBUS_STORE(Read,
                           &Transmitter->StoreInterface,
                           NULL,
@@ -3630,7 +3700,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail5;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3640,16 +3710,16 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
 
-fail4:
-    Error("fail4\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3660,6 +3730,14 @@ fail4:
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
     XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 
 fail3:
@@ -3772,6 +3850,11 @@ TransmitterDisconnect(
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
     XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
@@ -3811,6 +3894,9 @@ TransmitterTeardown(
     Transmitter->Frontend = NULL;
     Transmitter->Split = FALSE;
 
+    RtlZeroMemory(&Transmitter->PacketLock,
+                  sizeof (KSPIN_LOCK));
+
     RtlZeroMemory(&Transmitter->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -3893,12 +3979,165 @@ fail1:
     return status;
 }
 
+static BOOLEAN
+__TransmitterGetPacketHeadersPullup(
+    IN      PVOID                   Argument,
+    IN      PUCHAR                  DestinationVa,
+    IN OUT  PXENVIF_PACKET_PAYLOAD  Payload,
+    IN      ULONG                   Length
+    )
+{
+    PMDL                            Mdl;
+    ULONG                           Offset;
+
+    UNREFERENCED_PARAMETER(Argument);
+
+    Mdl = Payload->Mdl;
+    Offset = Payload->Offset;
+
+    if (Payload->Length < Length)
+        goto fail1;
+
+    Payload->Length -= Length;
+
+    while (Length != 0) {
+        PUCHAR  MdlMappedSystemVa;
+        ULONG   MdlByteCount;
+        ULONG   CopyLength;
+
+        ASSERT(Mdl != NULL);
+
+        MdlMappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        ASSERT(MdlMappedSystemVa != NULL);
+
+        MdlMappedSystemVa += Offset;
+
+        MdlByteCount = Mdl->ByteCount - Offset;
+
+        CopyLength = __min(MdlByteCount, Length);
+
+        RtlCopyMemory(DestinationVa, MdlMappedSystemVa, CopyLength);
+        DestinationVa += CopyLength;
+
+        Offset += CopyLength;
+        Length -= CopyLength;
+
+        MdlByteCount -= CopyLength;
+        if (MdlByteCount == 0) {
+            Mdl = Mdl->Next;
+            Offset = 0;
+        }
+    }
+
+    Payload->Mdl = Mdl;
+    Payload->Offset = Offset;
+
+    return TRUE;
+
+fail1:
+    Error("fail1\n");
+
+    return FALSE;
+}
+
+NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    )
+{
+    XENVIF_PACKET_PAYLOAD           Payload;
+    NTSTATUS                        status;
+
+    Payload.Mdl = Packet->Mdl;
+    Payload.Offset = Packet->Offset;
+    Payload.Length = Packet->Length;
+
+    status = ParsePacket(Headers,
+                         __TransmitterGetPacketHeadersPullup,
+                         Transmitter,
+                         &Payload,
+                         Info);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
+
 VOID
 TransmitterQueuePacketsV1(
     IN  PXENVIF_TRANSMITTER             Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
+#define OFFSET_EXISTS(_Transmitter, _Packet, _Type)                                         \
+    ((_Transmitter)->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET] != 0)
+
+#define OFFSET(_Transmitter, _Packet, _Type)                                                \
+        ((OFFSET_EXISTS(_Transmitter, _Packet, _Type)) ?                                    \
+         (PVOID)((PUCHAR)(_Packet) +                                                        \
+                 (_Transmitter)->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET]) :  \
+         NULL)
+
+    LIST_ENTRY                          List;
+    PXENVIF_FRONTEND                    Frontend;
+    PXENVIF_VIF_CONTEXT                 VifContext;
+
+    Frontend = Transmitter->Frontend;
+    VifContext = PdoGetVifContext(FrontendGetPdo(Frontend));
+
+    ASSERT3U(VifGetVersion(VifContext), ==, 1);
+
+    InitializeListHead(&List);
+
+    while (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET      Packet;
+
+        Packet = __TransmitterGetPacket(Transmitter);
+        if (Packet == NULL)
+            break;
+
+        Packet->Cookie = HeadPacket;
+        Packet->Send = HeadPacket->Send;
+
+        ASSERT(OFFSET_EXISTS(Transmitter, HeadPacket, MDL));
+        Packet->Mdl = *(PMDL *)OFFSET(Transmitter, HeadPacket, MDL);
+
+        if (OFFSET_EXISTS(Transmitter, HeadPacket, OFFSET))
+            Packet->Offset = *(PULONG)OFFSET(Transmitter, HeadPacket, OFFSET);
+        else
+            Packet->Offset = 0;
+
+        ASSERT(OFFSET_EXISTS(Transmitter, HeadPacket, LENGTH));
+        Packet->Length = *(PULONG)OFFSET(Transmitter, HeadPacket, LENGTH);
+
+        InsertTailList(&List, &Packet->ListEntry);
+
+        HeadPacket = HeadPacket->Next;
+    }
+
+    if (!IsListEmpty(&List))
+        TransmitterQueuePacketsV2(Transmitter, &List);
+
+    if (HeadPacket != NULL)
+        VifTransmitterReturnPacketsV1(VifContext,
+                                      HeadPacket);
+
+#undef OFFSET
+#undef OFFSET_EXISTS
+}
+
+VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    )
+{
     PXENVIF_TRANSMITTER_RING        Ring;
 
     // We need to hash for a ring eventually. Since there is only a
@@ -3906,7 +4145,7 @@ TransmitterQueuePacketsV1(
     Ring = Transmitter->Rings[0];
     ASSERT3P(Ring, !=, NULL);
 
-    __TransmitterRingQueuePackets(Ring, HeadPacket);
+    __TransmitterRingQueuePackets(Ring, List);
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 6a7fcd5..2ed2786 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -114,6 +114,12 @@ TransmitterQueuePacketsV1(
     );
 
 extern VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    );
+
+extern VOID
 TransmitterQueryOffloadOptions(
     IN  PXENVIF_TRANSMITTER         Transmitter,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
@@ -133,4 +139,12 @@ TransmitterSetPacketOffset(
     IN  LONG_PTR                            Value
     );
 
+extern NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 #endif  // _XENVIF_TRANSMITTER_H
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index b858d8f..24855b6 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -47,7 +47,8 @@ struct _XENVIF_VIF_CONTEXT {
     XENVIF_MRSW_LOCK            Lock;
     LONG                        References;
     PXENVIF_FRONTEND            Frontend;
-    BOOLEAN                     Enabled;    
+    BOOLEAN                     Enabled;
+    ULONG                       Version;
     XENVIF_VIF_CALLBACK         Callback;
     PVOID                       Argument;
     PXENVIF_THREAD              MacThread;
@@ -248,6 +249,7 @@ VifTransmitterSetPacketOffset(
 
     AcquireMrswLockShared(&Context->Lock);
 
+    ASSERT3U(VifGetVersion(Context), ==, 1);
     status = TransmitterSetPacketOffset(FrontendGetTransmitter(Context->Frontend),
                                         Type,
                                         Value);
@@ -273,6 +275,29 @@ VifReceiverReturnPackets(
     ReleaseMrswLockShared(&Context->Lock);
 }
 
+static NTSTATUS
+VifTransmitterGetPacketHeaders(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET      Packet,
+    OUT PVOID                           Headers,
+    OUT PXENVIF_PACKET_INFO             Info
+    )
+{
+    PXENVIF_VIF_CONTEXT                 Context = Interface->Context;
+    NTSTATUS                            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+    status = TransmitterGetPacketHeaders(FrontendGetTransmitter(Context->Frontend),
+                                         Packet,
+                                         Headers,
+                                         Info);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
 
 static NTSTATUS
 VifTransmitterQueuePacketsV1(
@@ -289,6 +314,7 @@ VifTransmitterQueuePacketsV1(
     if (Context->Enabled == FALSE)
         goto fail1;
 
+    ASSERT3U(VifGetVersion(Context), ==, 1);
     TransmitterQueuePacketsV1(FrontendGetTransmitter(Context->Frontend),
                               Head);
 
@@ -302,6 +328,35 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+VifTransmitterQueuePacketsV2(
+    IN  PINTERFACE      Interface,
+    IN  PLIST_ENTRY     List
+    )
+{
+    PXENVIF_VIF_CONTEXT Context = Interface->Context;
+    NTSTATUS            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->Enabled == FALSE)
+        goto fail1;
+
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context->Frontend),
+                              List);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
 static VOID
 VifTransmitterQueryOffloadOptions(
     IN  PINTERFACE                  Interface,
@@ -656,6 +711,31 @@ static struct _XENVIF_VIF_INTERFACE_V1 VifInterfaceVersion1 = {
     VifMacQueryFilterLevel
 };
 
+static struct _XENVIF_VIF_INTERFACE_V2 VifInterfaceVersion2 = {
+    { sizeof (struct _XENVIF_VIF_INTERFACE_V2), 2, NULL, NULL, NULL },
+    VifAcquire,
+    VifRelease,
+    VifEnable,
+    VifDisable,
+    VifQueryStatistic,
+    VifReceiverReturnPackets,
+    VifReceiverSetOffloadOptions,
+    VifReceiverQueryRingSize,
+    VifTransmitterGetPacketHeaders,
+    VifTransmitterQueuePacketsV2,
+    VifTransmitterQueryOffloadOptions,
+    VifTransmitterQueryLargePacketSize,
+    VifTransmitterQueryRingSize,
+    VifMacQueryState,
+    VifMacQueryMaximumFrameSize,
+    VifMacQueryPermanentAddress,
+    VifMacQueryCurrentAddress,
+    VifMacQueryMulticastAddresses,
+    VifMacSetMulticastAddresses,
+    VifMacSetFilterLevel,
+    VifMacQueryFilterLevel
+};
+
 NTSTATUS
 VifInitialize(
     IN  PXENVIF_PDO         Pdo,
@@ -737,11 +817,30 @@ VifGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENVIF_VIF_INTERFACE_V2 *VifInterface;
+
+        VifInterface = (struct _XENVIF_VIF_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENVIF_VIF_INTERFACE_V2))
+            break;
+
+        *VifInterface = VifInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
     }
 
+    Context->Version = Version;
+
     return status;
 }   
 
@@ -753,6 +852,7 @@ VifTeardown(
     Trace("====>\n");
 
     Context->Pdo = NULL;
+    Context->Version = 0;
 
     ThreadAlert(Context->MacThread);
     ThreadJoin(Context->MacThread);
@@ -788,15 +888,39 @@ VifTransmitterReturnPacketsV1(
     IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
+    ASSERT3U(VifGetVersion(Context), ==, 1);
+
     Context->Callback(Context->Argument,
                       XENVIF_TRANSMITTER_RETURN_PACKETS,
                       Head);
 }
 
-extern PXENVIF_THREAD
+VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    )
+{
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+
+    Context->Callback(Context->Argument,
+                      XENVIF_TRANSMITTER_RETURN_PACKETS,
+                      List);
+}
+
+PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
     )
 {
     return Context->MacThread;
 }
+
+ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    )
+{
+    return Context->Version;
+}
+
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index a26aa1b..fc7aabc 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -74,10 +74,21 @@ VifTransmitterReturnPacketsV1(
     IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
+extern VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    );
+
 extern PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
     );
 
+extern ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    );
+
 #endif  // _XENVIF_VIF_H
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:37 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4D-0002DU-EP; Thu, 18 Dec 2014 14:28:37 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002C4-76
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:36 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	F3/A9-02953-394E2945; Thu, 18 Dec 2014 14:28:35 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-27.messagelabs.com!1418912913!15962346!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20111 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794985"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:23 +0000
Message-ID: <1418912904-8756-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 6/7] Implement VIF Interface v2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Use VIF v2 structures internally, and add translation layer
for VIF v1 calls.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/transmitter.c | 587 +++++++++++++++++++++++++++++++++--------------
 src/xenvif/transmitter.h |  14 ++
 src/xenvif/vif.c         | 128 ++++++++++-
 src/xenvif/vif.h         |  11 +
 4 files changed, 564 insertions(+), 176 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 41bab7c..914e544 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -89,7 +89,7 @@ typedef struct _XENVIF_TRANSMITTER_FRAGMENT {
 #define XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID  0x03FF
 
 typedef struct _XENVIF_TRANSMITTER_STATE {
-    PXENVIF_TRANSMITTER_PACKET_V1       Packet;
+    PXENVIF_TRANSMITTER_PACKET          Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -100,11 +100,6 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 
 #define XENVIF_TRANSMITTER_RING_SIZE   (__CONST_RING_SIZE(netif_tx, PAGE_SIZE))
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_LIST {
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
-} XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
-
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
     ULONG                           Index;
@@ -125,7 +120,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Stopped;
     PVOID                           Lock;
     PKTHREAD                        LockThread;
-    XENVIF_TRANSMITTER_PACKET_LIST  Queued;
+    LIST_ENTRY                      Queued;
     XENVIF_TRANSMITTER_STATE        State;
     ULONG                           PacketsQueued;
     ULONG                           PacketsGranted;
@@ -138,7 +133,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     ULONG                           RequestsPushed;
     ULONG                           ResponsesProcessed;
     ULONG                           PacketsSent;
-    XENVIF_TRANSMITTER_PACKET_LIST  Completed;
+    LIST_ENTRY                      Completed;
     ULONG                           PacketsCompleted;
     PSOCKADDR_INET                  AddressTable;
     ULONG                           AddressCount;
@@ -158,12 +153,15 @@ struct _XENVIF_TRANSMITTER {
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
+    KSPIN_LOCK                  PacketLock;
+    PXENBUS_CACHE               PacketCache;
     XENBUS_STORE_INTERFACE      StoreInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
 };
 
 #define XENVIF_TRANSMITTER_TAG  'NART'
+#define XENVIF_PACKET_CACHE_RESERVATION 32
 
 static FORCEINLINE PVOID
 __TransmitterAllocate(
@@ -181,6 +179,72 @@ __TransmitterFree(
     __FreePoolWithTag(Buffer, XENVIF_TRANSMITTER_TAG);
 }
 
+static VOID
+TransmitterPacketAcquireLock(
+    IN  PVOID                       Argument
+    )
+{
+    PXENVIF_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->PacketLock);
+}
+
+static VOID
+TransmitterPacketReleaseLock(
+    IN  PVOID                       Argument
+    )
+{
+    PXENVIF_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
+}
+
+static NTSTATUS
+TransmitterPacketCtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+TransmitterPacketDtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+__TransmitterGetPacket(
+    IN  PXENVIF_TRANSMITTER         Transmitter
+    )
+{
+    return XENBUS_CACHE(Get,
+                        &Transmitter->CacheInterface,
+                        Transmitter->PacketCache,
+                        TRUE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET));
+
+    XENBUS_CACHE(Put,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 TRUE);
+}
+
 static NTSTATUS
 TransmitterBufferCtor(
     IN  PVOID                   Argument,
@@ -530,26 +594,6 @@ fail1:
     return FALSE;
 }
 
-#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            (*Reference)++;                                         \
-        } while (FALSE)
-
-#define DECREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            ASSERT(*Reference != 0);                                \
-            --(*Reference);                                         \
-        } while (FALSE)
-
-#define PACKET_REFERENCE(_Packet)                                   \
-        (*(PULONG_PTR)&(_Packet)->Next)
-
 static FORCEINLINE NTSTATUS
 __TransmitterRingCopyPayload(
     IN  PXENVIF_TRANSMITTER_RING    Ring
@@ -558,7 +602,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -572,7 +616,7 @@ __TransmitterRingCopyPayload(
 
     Payload = State->Payload;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 1);
+    ASSERT3U(Packet->Value, ==, 1);
 
     while (Payload.Length != 0) {
         PMDL        Mdl;
@@ -587,7 +631,7 @@ __TransmitterRingCopyPayload(
             goto fail1;
 
         Buffer->Context = Packet;
-        INCREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value++;
 
         Mdl = Buffer->Mdl;
 
@@ -649,14 +693,14 @@ fail2:
     ASSERT3P(Buffer->Context, ==, Packet);
     Buffer->Context = NULL;        
 
-    DECREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value--;
 
     __TransmitterPutBuffer(Ring, Buffer);
 
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    while (PACKET_REFERENCE(Packet) != 1) {
+    while (Packet->Value != 1) {
         PLIST_ENTRY         ListEntry;
 
         ASSERT(State->Count != 0);
@@ -689,7 +733,7 @@ fail1:
         ASSERT3P(Buffer->Context, ==, Packet);
         Buffer->Context = NULL;        
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value--;
 
         __TransmitterPutBuffer(Ring, Buffer);
     }
@@ -705,7 +749,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -720,7 +764,7 @@ __TransmitterRingGrantPayload(
     Packet = State->Packet;
     Payload = &State->Payload;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 1);
+    ASSERT3U(Packet->Value, ==, 1);
 
     Mdl = Payload->Mdl;
     Offset = Payload->Offset;
@@ -749,7 +793,7 @@ __TransmitterRingGrantPayload(
 
             Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_PACKET;
             Fragment->Context = Packet;
-            INCREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value++;
 
             Pfn = MmGetMdlPfnArray(Mdl)[MdlOffset / PAGE_SIZE];
             PageOffset = MdlOffset & (PAGE_SIZE - 1);
@@ -801,7 +845,7 @@ fail2:
         Fragment->Context = NULL;
         Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value--;
 
         __TransmitterPutFragment(Ring, Fragment);
     }
@@ -811,7 +855,7 @@ fail1:
 
     ASSERT3P(Fragment, ==, NULL);
 
-    while (PACKET_REFERENCE(Packet) != 1) {
+    while (Packet->Value != 1) {
         PLIST_ENTRY         ListEntry;
 
         ASSERT(State->Count != 0);
@@ -835,7 +879,7 @@ fail1:
         Fragment->Context = NULL;
         Fragment->Type = XENVIF_TRANSMITTER_FRAGMENT_TYPE_INVALID;
 
-        DECREMENT_PACKET_REFERENCE(Packet);
+        Packet->Value;
 
         __TransmitterPutFragment(Ring, Fragment);
     }
@@ -852,7 +896,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -872,7 +916,7 @@ __TransmitterRingPrepareHeader(
     Payload = &State->Payload;
     Info = &State->Info;
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 0);
+    ASSERT3U(Packet->Value, ==, 0);
 
     Buffer = __TransmitterGetBuffer(Ring);
 
@@ -881,7 +925,7 @@ __TransmitterRingPrepareHeader(
         goto fail1;
 
     Buffer->Context = Packet;
-    INCREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value++;
 
     Mdl = Buffer->Mdl;
 
@@ -1099,7 +1143,7 @@ fail3:
 fail2:
     Error("fail2\n");
 
-    DECREMENT_PACKET_REFERENCE(Packet);
+    Packet->Value--;
     Buffer->Context = NULL;
 
     __TransmitterPutBuffer(Ring, Buffer);
@@ -1107,7 +1151,7 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    ASSERT3U(PACKET_REFERENCE(Packet), ==, 0);
+    ASSERT3U(Packet->Value, ==, 0);
 
     return status;
 }
@@ -1129,7 +1173,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        PXENVIF_TRANSMITTER_PACKET      Packet;
 
         --State->Count;
 
@@ -1179,25 +1223,16 @@ __TransmitterRingUnprepareFragments(
         __TransmitterPutFragment(Ring, Fragment);
 
         if (Packet != NULL)
-            DECREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value--;
     }
 }
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
     IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    IN  PXENVIF_TRANSMITTER_PACKET      Packet
     )
 {
-#define OFFSET_EXISTS(_Ring, _Packet, _Type)                                                        \
-    ((_Ring)->Transmitter->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET] != 0)
-
-#define OFFSET(_Ring, _Packet, _Type)                                                               \
-        ((OFFSET_EXISTS(_Ring, _Packet, _Type)) ?                                                   \
-         (PVOID)((PUCHAR)(_Packet) +                                                                \
-                 (_Ring)->Transmitter->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET]) :    \
-         NULL)
-
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_TRANSMITTER_STATE       State;
     PXENVIF_PACKET_PAYLOAD          Payload;
@@ -1205,7 +1240,6 @@ __TransmitterRingPreparePacket(
     NTSTATUS                        status;
 
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
-    ASSERT3P(Packet->Next, ==, NULL);
 
     Transmitter = Ring->Transmitter;
 
@@ -1217,17 +1251,9 @@ __TransmitterRingPreparePacket(
     RtlZeroMemory(&Packet->Send, sizeof (XENVIF_TRANSMITTER_PACKET_SEND_INFO));
 
     Payload = &State->Payload;
-
-    ASSERT(OFFSET_EXISTS(Ring, Packet, MDL));
-    Payload->Mdl = *(PMDL *)OFFSET(Ring, Packet, MDL);
-
-    if (OFFSET_EXISTS(Ring, Packet, OFFSET))
-        Payload->Offset = *(PULONG)OFFSET(Ring, Packet, OFFSET);
-    else
-        Payload->Offset = 0;
-
-    ASSERT(OFFSET_EXISTS(Ring, Packet, LENGTH));
-    Payload->Length = *(PULONG)OFFSET(Ring, Packet, LENGTH);
+    Payload->Mdl = Packet->Mdl;
+    Payload->Offset = Packet->Offset;
+    Payload->Length = Packet->Length;
 
     InitializeListHead(&State->List);
     ASSERT3U(State->Count, ==, 0);
@@ -1236,7 +1262,7 @@ __TransmitterRingPreparePacket(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+    ASSERT3U(State->Count, ==, Packet->Value);
 
     Info = &State->Info;
 
@@ -1294,7 +1320,7 @@ __TransmitterRingPreparePacket(
 
         if (Transmitter->AlwaysCopy != 0 ||
             (!NT_SUCCESS(status) && status == STATUS_BUFFER_OVERFLOW)) {
-            ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+            ASSERT3U(State->Count, ==, Packet->Value);
 
             status = __TransmitterRingCopyPayload(Ring);
         }
@@ -1303,7 +1329,7 @@ __TransmitterRingPreparePacket(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    ASSERT3U(State->Count, ==, PACKET_REFERENCE(Packet));
+    ASSERT3U(State->Count, ==, Packet->Value);
 
     Ring->PacketsPrepared++;
     return STATUS_SUCCESS;
@@ -1332,18 +1358,15 @@ fail1:
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
 
     return status;
-
-#undef  OFFSET
-#undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V1
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1702,7 +1725,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1722,7 +1745,7 @@ __TransmitterRingPostFragments(
     ASSERT(!IsListEmpty(&State->List));
     ASSERT(State->Count != 0);
     ASSERT3U(State->Count, <=, XEN_NETIF_NR_SLOTS_MIN);
-    ASSERT(IMPLY(Packet != NULL, State->Count == PACKET_REFERENCE(Packet)));
+    ASSERT(IMPLY(Packet != NULL, State->Count == Packet->Value));
 
     req_prod = Ring->Front.req_prod_pvt;
     rsp_cons = Ring->Front.rsp_cons;
@@ -1927,8 +1950,8 @@ __TransmitterRingFakeResponses(
 
 static FORCEINLINE VOID
 __TransmitterRingCompletePacket(
-    IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    IN  PXENVIF_TRANSMITTER_RING    Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -1987,10 +2010,7 @@ __TransmitterRingCompletePacket(
         }
     }
 
-    *Ring->Completed.TailPacket = Packet;
-    ASSERT3P(Packet->Next, ==, NULL);
-    Ring->Completed.TailPacket = &Packet->Next;
-
+    InsertTailList(&Ring->Completed, &Packet->ListEntry);
     Ring->PacketsCompleted++;
 }
 
@@ -2026,7 +2046,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+            PXENVIF_TRANSMITTER_PACKET      Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2090,7 +2110,7 @@ TransmitterRingPoll(
                 continue;
             }
 
-            DECREMENT_PACKET_REFERENCE(Packet);
+            Packet->Value--;
 
             if (rsp->status != NETIF_RSP_OKAY &&
                 Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING) {
@@ -2111,7 +2131,7 @@ TransmitterRingPoll(
 
             RtlZeroMemory(rsp, sizeof (netif_tx_response_t));
 
-            if (PACKET_REFERENCE(Packet) != 0)
+            if (Packet->Value != 0)
                 continue;
 
             if (Packet->Completion.Status == XENVIF_TRANSMITTER_PACKET_PENDING)
@@ -2266,32 +2286,44 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
+    PLIST_ENTRY                     ListEntry;
+    LIST_ENTRY                      List;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
 
+    InitializeListHead(&List);
+
     New = XENVIF_TRANSMITTER_LOCK_BIT;    
     Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock, (PVOID)New);
 
     ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
-    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+    ListEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
 
-    if (HeadPacket == NULL)
+    if (ListEntry == NULL)
         return;
 
     // Packets are held in the atomic packet list in reverse order
     // so that the most recent is always head of the list. This is
     // necessary to allow addition to the list to be done atomically.
 
-    TailPacket = &HeadPacket->Next;
-    Count = __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
+    for (Count = 0; ListEntry != NULL; ++Count) {
+        PLIST_ENTRY     NextEntry;
+
+        NextEntry = ListEntry->Blink;
+        ListEntry->Flink = ListEntry->Blink = ListEntry;
+
+        InsertHeadList(&List, ListEntry);
+
+        ListEntry = NextEntry;
+    }
 
-    *(Ring->Queued.TailPacket) = HeadPacket;
-    Ring->Queued.TailPacket = TailPacket;
-    Ring->PacketsQueued += Count;
+    ListEntry = List.Flink;
+    if (!IsListEmpty(&List)) {
+        RemoveEntryList(&List);
+        AppendTailList(&Ring->Queued, ListEntry);
+        Ring->PacketsQueued += Count;
+    }
 }
 
 static DECLSPEC_NOINLINE VOID
@@ -2307,8 +2339,9 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-        NTSTATUS                        status;
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
+        NTSTATUS                    status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2357,18 +2390,13 @@ TransmitterRingSchedule(
             continue;
         }
 
-        Packet = Ring->Queued.HeadPacket;
-
-        if (Packet == NULL)
+        ListEntry = RemoveHeadList(&Ring->Queued);
+        if (ListEntry == &Ring->Queued)
             break;
 
-        if (Packet->Next == NULL) {
-            Ring->Queued.HeadPacket = NULL;
-            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
-        } else {
-            Ring->Queued.HeadPacket = Packet->Next;
-            Packet->Next = NULL;
-        }
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+        Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
+        Packet->Value = 0;
 
         status = __TransmitterRingPreparePacket(Ring, Packet);
         if (!NT_SUCCESS(status)) {
@@ -2397,23 +2425,63 @@ TransmitterRingSchedule(
         ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
     }
 
-    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring->Queued.TailPacket == &Ring->Queued.HeadPacket));
-
     __TransmitterRingPushRequests(Ring);
 }
 
 static FORCEINLINE VOID
 __TransmitterReturnPackets(
-    IN  PXENVIF_TRANSMITTER             Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     )
 {
-    PXENVIF_FRONTEND    Frontend;
+    PXENVIF_FRONTEND        Frontend;
+    PXENVIF_VIF_CONTEXT     VifContext;
 
     Frontend = Transmitter->Frontend;
+    VifContext = PdoGetVifContext(FrontendGetPdo(Frontend));
+
+    switch (VifGetVersion(VifContext)) {
+    case 1: {
+        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
 
-    VifTransmitterReturnPacketsV1(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                  HeadPacket);
+        HeadPacket = NextPacket = NULL;
+
+        while (!IsListEmpty(List)) {
+            PLIST_ENTRY                 ListEntry;
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+
+            ListEntry = RemoveTailList(List);
+            ASSERT3P(ListEntry, !=, List);
+
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+            Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
+
+            HeadPacket = Packet->Cookie;
+            HeadPacket->Next = NextPacket;
+            NextPacket = HeadPacket;
+
+            HeadPacket->Completion = Packet->Completion;
+
+            __TransmitterPutPacket(Transmitter, Packet);
+        }
+
+        if (HeadPacket != NULL) {
+            VifTransmitterReturnPacketsV1(VifContext, HeadPacket);
+        }
+        break;
+    }
+    case 2: {
+        if (!IsListEmpty(List)) {
+            VifTransmitterReturnPacketsV2(VifContext, List);
+        }
+        break;
+    }
+    default: {
+        ASSERT(FALSE);
+        break;
+    }
+    }
 }
 
 static FORCEINLINE BOOLEAN
@@ -2513,11 +2581,9 @@ __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
-    
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    LIST_ENTRY                      List;
+
+    InitializeListHead(&List);
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
@@ -2527,23 +2593,26 @@ __TransmitterRingReleaseLock(
     // thread could be simuntaneously adding to the list.
 
     do {
+        PLIST_ENTRY     ListEntry;
+
         TransmitterRingSwizzle(Ring);
         TransmitterRingSchedule(Ring);
 
-        *TailPacket = Ring->Completed.HeadPacket;
-        TailPacket = Ring->Completed.TailPacket;
-
-        Ring->Completed.HeadPacket = NULL;
-        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
+        ListEntry = Ring->Completed.Flink;
+        if (!IsListEmpty(&Ring->Completed)) {
+            RemoveEntryList(&Ring->Completed);
+            InitializeListHead(&Ring->Completed);
+            AppendTailList(&List, ListEntry);
+        }
     } while (!__TransmitterRingTryReleaseLock(Ring));
 
-    if (HeadPacket != NULL) {
+    if (!IsListEmpty(&List)) {
         PXENVIF_TRANSMITTER Transmitter;
 
         Transmitter = Ring->Transmitter;
 
         __TransmitterReturnPackets(Transmitter,
-                                   HeadPacket);
+                                   &List);
     }
 }
 
@@ -2792,8 +2861,8 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
-    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
-    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    InitializeListHead(&(*Ring)->Queued);
+    InitializeListHead(&(*Ring)->Completed);
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
     KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
@@ -2929,8 +2998,8 @@ fail2:
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
 
-    (*Ring)->Queued.TailPacket = NULL;
-    (*Ring)->Completed.TailPacket = NULL;
+    RtlZeroMemory(&(*Ring)->Queued, sizeof (LIST_ENTRY));
+    RtlZeroMemory(&(*Ring)->Completed, sizeof (LIST_ENTRY));
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -3151,7 +3220,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+    PXENVIF_TRANSMITTER_PACKET      Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -3170,14 +3239,7 @@ __TransmitterRingDisable(
 
     // Put any packet back on the head of the queue
     if (Packet != NULL) {
-        ASSERT3P(Packet->Next, ==, NULL);
-
-        Packet->Next = Ring->Queued.HeadPacket;
-
-        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
-            Ring->Queued.TailPacket = &Packet->Next;
-
-        Ring->Queued.HeadPacket = Packet;
+        InsertHeadList(&Ring->Queued, &Packet->ListEntry);
     }
 
     Ring->AddressIndex = 0;
@@ -3336,11 +3398,11 @@ __TransmitterRingTeardown(
                  Ring->BufferCache);
     Ring->BufferCache = NULL;
 
-    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
-    Ring->Queued.TailPacket = NULL;
+    ASSERT(IsListEmpty(&Ring->Queued));
+    RtlZeroMemory(&Ring->Queued, sizeof (LIST_ENTRY));
 
-    ASSERT3P(Ring->Completed.TailPacket, ==, &Ring->Completed.HeadPacket);
-    Ring->Completed.TailPacket = NULL;
+    ASSERT(IsListEmpty(&Ring->Completed));
+    RtlZeroMemory(&Ring->Completed, sizeof (LIST_ENTRY));
 
     Ring->Index = 0;
     Ring->Transmitter = NULL;
@@ -3351,25 +3413,20 @@ __TransmitterRingTeardown(
 
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
-    IN  PXENVIF_TRANSMITTER_RING        Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
+    IN  PXENVIF_TRANSMITTER_RING    Ring,
+    IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
 
-    TailPacket = &HeadPacket->Next;
-    (VOID) __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
-
     do {
         Old = (ULONG_PTR)Ring->Lock;
         LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
 
-        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
-        New = (ULONG_PTR)HeadPacket;
+        List->Flink->Blink = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+        New = (ULONG_PTR)List->Blink;
         ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
         New |= LockBit;
     } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock, (PVOID)New, (PVOID)Old) != Old);
@@ -3388,22 +3445,19 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-
     __TransmitterRingAcquireLock(Ring);
 
     TransmitterRingSwizzle(Ring);
 
-    Packet = Ring->Queued.HeadPacket;
-
-    Ring->Queued.HeadPacket = NULL;
-    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
-
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET_V1   Next;
+    while (!IsListEmpty(&Ring->Queued)) {
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
         
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        ListEntry = RemoveHeadList(&Ring->Queued);
+        ASSERT3P(ListEntry, !=, &Ring->Queued);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+        Packet->ListEntry.Flink = Packet->ListEntry.Blink = NULL;
 
         // Fake that we prapared and sent this packet
         Ring->PacketsPrepared++;
@@ -3413,8 +3467,6 @@ __TransmitterRingAbortPackets(
         Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
 
         __TransmitterRingCompletePacket(Ring, Packet);
-
-        Packet = Next;
     }
 
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
@@ -3507,6 +3559,7 @@ TransmitterInitialize(
                           &(*Transmitter)->EvtchnInterface);
 
     (*Transmitter)->Frontend = Frontend;
+    KeInitializeSpinLock(&(*Transmitter)->PacketLock);
 
     status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
     if (!NT_SUCCESS(status))
@@ -3556,6 +3609,9 @@ fail2:
 
     (*Transmitter)->Frontend = NULL;
 
+    RtlZeroMemory(&(*Transmitter)->PacketLock,
+                  sizeof (KSPIN_LOCK));
+
     RtlZeroMemory(&(*Transmitter)->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -3605,6 +3661,20 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_CACHE(Create,
+                          &Transmitter->CacheInterface,
+                          "packet_cache",
+                          sizeof (XENVIF_TRANSMITTER_PACKET),
+                          XENVIF_PACKET_CACHE_RESERVATION,
+                          TransmitterPacketCtor,
+                          TransmitterPacketDtor,
+                          TransmitterPacketAcquireLock,
+                          TransmitterPacketReleaseLock,
+                          Transmitter,
+                          &Transmitter->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = XENBUS_STORE(Read,
                           &Transmitter->StoreInterface,
                           NULL,
@@ -3630,7 +3700,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail5;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3640,16 +3710,16 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
 
-fail4:
-    Error("fail4\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3660,6 +3730,14 @@ fail4:
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
     XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 
 fail3:
@@ -3772,6 +3850,11 @@ TransmitterDisconnect(
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
     XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
@@ -3811,6 +3894,9 @@ TransmitterTeardown(
     Transmitter->Frontend = NULL;
     Transmitter->Split = FALSE;
 
+    RtlZeroMemory(&Transmitter->PacketLock,
+                  sizeof (KSPIN_LOCK));
+
     RtlZeroMemory(&Transmitter->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -3893,12 +3979,165 @@ fail1:
     return status;
 }
 
+static BOOLEAN
+__TransmitterGetPacketHeadersPullup(
+    IN      PVOID                   Argument,
+    IN      PUCHAR                  DestinationVa,
+    IN OUT  PXENVIF_PACKET_PAYLOAD  Payload,
+    IN      ULONG                   Length
+    )
+{
+    PMDL                            Mdl;
+    ULONG                           Offset;
+
+    UNREFERENCED_PARAMETER(Argument);
+
+    Mdl = Payload->Mdl;
+    Offset = Payload->Offset;
+
+    if (Payload->Length < Length)
+        goto fail1;
+
+    Payload->Length -= Length;
+
+    while (Length != 0) {
+        PUCHAR  MdlMappedSystemVa;
+        ULONG   MdlByteCount;
+        ULONG   CopyLength;
+
+        ASSERT(Mdl != NULL);
+
+        MdlMappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        ASSERT(MdlMappedSystemVa != NULL);
+
+        MdlMappedSystemVa += Offset;
+
+        MdlByteCount = Mdl->ByteCount - Offset;
+
+        CopyLength = __min(MdlByteCount, Length);
+
+        RtlCopyMemory(DestinationVa, MdlMappedSystemVa, CopyLength);
+        DestinationVa += CopyLength;
+
+        Offset += CopyLength;
+        Length -= CopyLength;
+
+        MdlByteCount -= CopyLength;
+        if (MdlByteCount == 0) {
+            Mdl = Mdl->Next;
+            Offset = 0;
+        }
+    }
+
+    Payload->Mdl = Mdl;
+    Payload->Offset = Offset;
+
+    return TRUE;
+
+fail1:
+    Error("fail1\n");
+
+    return FALSE;
+}
+
+NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    )
+{
+    XENVIF_PACKET_PAYLOAD           Payload;
+    NTSTATUS                        status;
+
+    Payload.Mdl = Packet->Mdl;
+    Payload.Offset = Packet->Offset;
+    Payload.Length = Packet->Length;
+
+    status = ParsePacket(Headers,
+                         __TransmitterGetPacketHeadersPullup,
+                         Transmitter,
+                         &Payload,
+                         Info);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
+
 VOID
 TransmitterQueuePacketsV1(
     IN  PXENVIF_TRANSMITTER             Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket
     )
 {
+#define OFFSET_EXISTS(_Transmitter, _Packet, _Type)                                         \
+    ((_Transmitter)->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET] != 0)
+
+#define OFFSET(_Transmitter, _Packet, _Type)                                                \
+        ((OFFSET_EXISTS(_Transmitter, _Packet, _Type)) ?                                    \
+         (PVOID)((PUCHAR)(_Packet) +                                                        \
+                 (_Transmitter)->Offset[XENVIF_TRANSMITTER_PACKET_ ## _Type ## _OFFSET]) :  \
+         NULL)
+
+    LIST_ENTRY                          List;
+    PXENVIF_FRONTEND                    Frontend;
+    PXENVIF_VIF_CONTEXT                 VifContext;
+
+    Frontend = Transmitter->Frontend;
+    VifContext = PdoGetVifContext(FrontendGetPdo(Frontend));
+
+    ASSERT3U(VifGetVersion(VifContext), ==, 1);
+
+    InitializeListHead(&List);
+
+    while (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET      Packet;
+
+        Packet = __TransmitterGetPacket(Transmitter);
+        if (Packet == NULL)
+            break;
+
+        Packet->Cookie = HeadPacket;
+        Packet->Send = HeadPacket->Send;
+
+        ASSERT(OFFSET_EXISTS(Transmitter, HeadPacket, MDL));
+        Packet->Mdl = *(PMDL *)OFFSET(Transmitter, HeadPacket, MDL);
+
+        if (OFFSET_EXISTS(Transmitter, HeadPacket, OFFSET))
+            Packet->Offset = *(PULONG)OFFSET(Transmitter, HeadPacket, OFFSET);
+        else
+            Packet->Offset = 0;
+
+        ASSERT(OFFSET_EXISTS(Transmitter, HeadPacket, LENGTH));
+        Packet->Length = *(PULONG)OFFSET(Transmitter, HeadPacket, LENGTH);
+
+        InsertTailList(&List, &Packet->ListEntry);
+
+        HeadPacket = HeadPacket->Next;
+    }
+
+    if (!IsListEmpty(&List))
+        TransmitterQueuePacketsV2(Transmitter, &List);
+
+    if (HeadPacket != NULL)
+        VifTransmitterReturnPacketsV1(VifContext,
+                                      HeadPacket);
+
+#undef OFFSET
+#undef OFFSET_EXISTS
+}
+
+VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    )
+{
     PXENVIF_TRANSMITTER_RING        Ring;
 
     // We need to hash for a ring eventually. Since there is only a
@@ -3906,7 +4145,7 @@ TransmitterQueuePacketsV1(
     Ring = Transmitter->Rings[0];
     ASSERT3P(Ring, !=, NULL);
 
-    __TransmitterRingQueuePackets(Ring, HeadPacket);
+    __TransmitterRingQueuePackets(Ring, List);
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 6a7fcd5..2ed2786 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -114,6 +114,12 @@ TransmitterQueuePacketsV1(
     );
 
 extern VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    );
+
+extern VOID
 TransmitterQueryOffloadOptions(
     IN  PXENVIF_TRANSMITTER         Transmitter,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
@@ -133,4 +139,12 @@ TransmitterSetPacketOffset(
     IN  LONG_PTR                            Value
     );
 
+extern NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 #endif  // _XENVIF_TRANSMITTER_H
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index b858d8f..24855b6 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -47,7 +47,8 @@ struct _XENVIF_VIF_CONTEXT {
     XENVIF_MRSW_LOCK            Lock;
     LONG                        References;
     PXENVIF_FRONTEND            Frontend;
-    BOOLEAN                     Enabled;    
+    BOOLEAN                     Enabled;
+    ULONG                       Version;
     XENVIF_VIF_CALLBACK         Callback;
     PVOID                       Argument;
     PXENVIF_THREAD              MacThread;
@@ -248,6 +249,7 @@ VifTransmitterSetPacketOffset(
 
     AcquireMrswLockShared(&Context->Lock);
 
+    ASSERT3U(VifGetVersion(Context), ==, 1);
     status = TransmitterSetPacketOffset(FrontendGetTransmitter(Context->Frontend),
                                         Type,
                                         Value);
@@ -273,6 +275,29 @@ VifReceiverReturnPackets(
     ReleaseMrswLockShared(&Context->Lock);
 }
 
+static NTSTATUS
+VifTransmitterGetPacketHeaders(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET      Packet,
+    OUT PVOID                           Headers,
+    OUT PXENVIF_PACKET_INFO             Info
+    )
+{
+    PXENVIF_VIF_CONTEXT                 Context = Interface->Context;
+    NTSTATUS                            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+    status = TransmitterGetPacketHeaders(FrontendGetTransmitter(Context->Frontend),
+                                         Packet,
+                                         Headers,
+                                         Info);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
 
 static NTSTATUS
 VifTransmitterQueuePacketsV1(
@@ -289,6 +314,7 @@ VifTransmitterQueuePacketsV1(
     if (Context->Enabled == FALSE)
         goto fail1;
 
+    ASSERT3U(VifGetVersion(Context), ==, 1);
     TransmitterQueuePacketsV1(FrontendGetTransmitter(Context->Frontend),
                               Head);
 
@@ -302,6 +328,35 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+VifTransmitterQueuePacketsV2(
+    IN  PINTERFACE      Interface,
+    IN  PLIST_ENTRY     List
+    )
+{
+    PXENVIF_VIF_CONTEXT Context = Interface->Context;
+    NTSTATUS            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->Enabled == FALSE)
+        goto fail1;
+
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context->Frontend),
+                              List);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
 static VOID
 VifTransmitterQueryOffloadOptions(
     IN  PINTERFACE                  Interface,
@@ -656,6 +711,31 @@ static struct _XENVIF_VIF_INTERFACE_V1 VifInterfaceVersion1 = {
     VifMacQueryFilterLevel
 };
 
+static struct _XENVIF_VIF_INTERFACE_V2 VifInterfaceVersion2 = {
+    { sizeof (struct _XENVIF_VIF_INTERFACE_V2), 2, NULL, NULL, NULL },
+    VifAcquire,
+    VifRelease,
+    VifEnable,
+    VifDisable,
+    VifQueryStatistic,
+    VifReceiverReturnPackets,
+    VifReceiverSetOffloadOptions,
+    VifReceiverQueryRingSize,
+    VifTransmitterGetPacketHeaders,
+    VifTransmitterQueuePacketsV2,
+    VifTransmitterQueryOffloadOptions,
+    VifTransmitterQueryLargePacketSize,
+    VifTransmitterQueryRingSize,
+    VifMacQueryState,
+    VifMacQueryMaximumFrameSize,
+    VifMacQueryPermanentAddress,
+    VifMacQueryCurrentAddress,
+    VifMacQueryMulticastAddresses,
+    VifMacSetMulticastAddresses,
+    VifMacSetFilterLevel,
+    VifMacQueryFilterLevel
+};
+
 NTSTATUS
 VifInitialize(
     IN  PXENVIF_PDO         Pdo,
@@ -737,11 +817,30 @@ VifGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENVIF_VIF_INTERFACE_V2 *VifInterface;
+
+        VifInterface = (struct _XENVIF_VIF_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENVIF_VIF_INTERFACE_V2))
+            break;
+
+        *VifInterface = VifInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
     }
 
+    Context->Version = Version;
+
     return status;
 }   
 
@@ -753,6 +852,7 @@ VifTeardown(
     Trace("====>\n");
 
     Context->Pdo = NULL;
+    Context->Version = 0;
 
     ThreadAlert(Context->MacThread);
     ThreadJoin(Context->MacThread);
@@ -788,15 +888,39 @@ VifTransmitterReturnPacketsV1(
     IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     )
 {
+    ASSERT3U(VifGetVersion(Context), ==, 1);
+
     Context->Callback(Context->Argument,
                       XENVIF_TRANSMITTER_RETURN_PACKETS,
                       Head);
 }
 
-extern PXENVIF_THREAD
+VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    )
+{
+    ASSERT3U(VifGetVersion(Context), >=, 2);
+
+    Context->Callback(Context->Argument,
+                      XENVIF_TRANSMITTER_RETURN_PACKETS,
+                      List);
+}
+
+PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
     )
 {
     return Context->MacThread;
 }
+
+ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    )
+{
+    return Context->Version;
+}
+
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index a26aa1b..fc7aabc 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -74,10 +74,21 @@ VifTransmitterReturnPacketsV1(
     IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
+extern VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    );
+
 extern PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
     );
 
+extern ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    );
+
 #endif  // _XENVIF_VIF_H
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:38 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4E-0002EL-H6; Thu, 18 Dec 2014 14:28:38 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002CD-Mq
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:37 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	D5/05-09842-494E2945; Thu, 18 Dec 2014 14:28:36 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!4
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22313 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794988"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:21 +0000
Message-ID: <1418912904-8756-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/7] Remove notifier object
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Fold event channels into transmitter/receiver ring objects.
Receiver ring object takes over single event channel case and passes
notifications to transmitter object, tagged with ring index (so that
only the specified ring is executed).
Split notifications are handled independently by each ring object.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c        |  75 ++---
 src/xenvif/frontend.h        |   7 -
 src/xenvif/notifier.c        | 684 -------------------------------------------
 src/xenvif/notifier.h        |  99 -------
 src/xenvif/receiver.c        | 376 +++++++++++++++++++++---
 src/xenvif/receiver.h        |  17 +-
 src/xenvif/transmitter.c     | 352 +++++++++++++++++++---
 src/xenvif/transmitter.h     |   5 +-
 vs2012/xenvif/xenvif.vcxproj |   1 -
 vs2013/xenvif/xenvif.vcxproj |   1 -
 10 files changed, 678 insertions(+), 939 deletions(-)
 delete mode 100644 src/xenvif/notifier.c
 delete mode 100644 src/xenvif/notifier.h

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 305faaf..268bab9 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -44,7 +44,6 @@
 #include "frontend.h"
 #include "names.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
 #include "tcpip.h"
 #include "receiver.h"
@@ -66,7 +65,6 @@ struct _XENVIF_FRONTEND {
     USHORT                      BackendDomain;
 
     PXENVIF_GRANTER             Granter;
-    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_MAC                 Mac;
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_TRANSMITTER         Transmitter;
@@ -221,7 +219,6 @@ FrontendGet ## _Function(                               \
 }
 
 DEFINE_FRONTEND_GET_FUNCTION(Granter, PXENVIF_GRANTER)
-DEFINE_FRONTEND_GET_FUNCTION(Notifier, PXENVIF_NOTIFIER)
 DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC)
 DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER)
 DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER)
@@ -1318,10 +1315,6 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierConnect(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     Attempt = 0;
     do {
         PXENBUS_STORE_TRANSACTION   Transaction;
@@ -1332,11 +1325,6 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             break;
 
-        status = NotifierStoreWrite(__FrontendGetNotifier(Frontend),
-                                    Transaction);
-        if (!NT_SUCCESS(status))
-            goto abort;
-
         status = ReceiverStoreWrite(__FrontendGetReceiver(Frontend),
                                     Transaction);
         if (!NT_SUCCESS(status))
@@ -1365,7 +1353,7 @@ abort:
     } while (status == STATUS_RETRY);
 
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = XENBUS_STORE(Printf,
                           &Frontend->StoreInterface,
@@ -1375,25 +1363,22 @@ abort:
                           "%u",
                           XenbusStateConnected);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     State = XenbusStateInitWait;
     status = __FrontendWaitForStateChange(Frontend, Path, &State);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = STATUS_UNSUCCESSFUL;
     if (State != XenbusStateConnected)
-        goto fail11;
+        goto fail10;
 
     ThreadWake(Frontend->MibThread);
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail11:
-    Error("fail11\n");
-
 fail10:
     Error("fail10\n");
 
@@ -1403,8 +1388,6 @@ fail9:
 fail8:
     Error("fail8\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
-
 fail7:
     Error("fail7\n");
 
@@ -1452,7 +1435,6 @@ __FrontendDisconnect(
 {
     Trace("====>\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
     TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
     ReceiverDisconnect(__FrontendGetReceiver(Frontend));
     MacDisconnect(__FrontendGetMac(Frontend));
@@ -1495,18 +1477,9 @@ __FrontendEnable(
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = NotifierEnable(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
-
-    TransmitterDisable(__FrontendGetTransmitter(Frontend));
-
 fail4:
     Error("fail4\n");
 
@@ -1535,7 +1508,6 @@ __FrontendDisable(
 {
     Trace("====>\n");
 
-    NotifierDisable(__FrontendGetNotifier(Frontend));
     TransmitterDisable(__FrontendGetTransmitter(Frontend));
     ReceiverDisable(__FrontendGetReceiver(Frontend));
     MacDisable(__FrontendGetMac(Frontend));
@@ -1894,64 +1866,54 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail10;
 
     status = ThreadCreate(FrontendMib, *Frontend, &(*Frontend)->MibThread);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail11;
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
-fail12:
-    Error("fail12\n");
+fail11:
+    Error("fail11\n");
 
     ThreadAlert((*Frontend)->EjectThread);
     ThreadJoin((*Frontend)->EjectThread);
     (*Frontend)->EjectThread = NULL;
 
-fail11:
-    Error("fail11\n");
-
-    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
-    (*Frontend)->Transmitter = NULL;
-
 fail10:
     Error("fail10\n");
 
-    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
-    (*Frontend)->Receiver = NULL;
+    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
+    (*Frontend)->Transmitter = NULL;
 
 fail9:
     Error("fail9\n");
 
-    MacTeardown(__FrontendGetMac(*Frontend));
-    (*Frontend)->Mac = NULL;
+    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
+    (*Frontend)->Receiver = NULL;
 
 fail8:
     Error("fail8\n");
 
-    NotifierTeardown(__FrontendGetNotifier(*Frontend));
-    (*Frontend)->Notifier = NULL;
+    MacTeardown(__FrontendGetMac(*Frontend));
+    (*Frontend)->Mac = NULL;
 
 fail7:
     Error("fail7\n");
@@ -2043,9 +2005,6 @@ FrontendTeardown(
     MacTeardown(__FrontendGetMac(Frontend));
     Frontend->Mac = NULL;
 
-    NotifierTeardown(__FrontendGetNotifier(Frontend));
-    Frontend->Notifier = NULL;
-
     GranterTeardown(__FrontendGetGranter(Frontend));
     Frontend->Granter = NULL;
 
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 60c085a..67696d6 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -119,13 +119,6 @@ FrontendGetGranter(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
-#include "notifier.h"
-
-extern PXENVIF_NOTIFIER
-FrontendGetNotifier(
-    IN  PXENVIF_FRONTEND    Frontend
-    );
-
 #include "mac.h"
 
 extern PXENVIF_MAC
diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
deleted file mode 100644
index fc6725a..0000000
--- a/src/xenvif/notifier.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <ntstrsafe.h>
-#include <stdlib.h>
-#include <util.h>
-
-#include "pdo.h"
-#include "frontend.h"
-#include "notifier.h"
-#include "receiver.h"
-#include "transmitter.h"
-#include "dbg_print.h"
-#include "assert.h"
-
-typedef enum _XENVIF_NOTIFIER_EVTCHN {
-    XENVIF_NOTIFIER_EVTCHN_COMBINED = 0,
-    XENVIF_NOTIFIER_EVTCHN_RX,
-    XENVIF_NOTIFIER_EVTCHN_TX,
-    XENVIF_NOTIFIER_EVTCHN_COUNT
-} XENVIF_NOTIFIER_EVTCHN, *PXENVIF_NOTIFIER_EVTCHN;
-
-struct _XENVIF_NOTIFIER {
-    PXENVIF_FRONTEND            Frontend;
-    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
-    PXENBUS_EVTCHN_CHANNEL      Channel[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    KDPC                        Dpc[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Dpcs[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Events[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    BOOLEAN                     Connected;
-    KSPIN_LOCK                  Lock;
-    BOOLEAN                     Split;
-    BOOLEAN                     Enabled;
-    XENBUS_STORE_INTERFACE      StoreInterface;
-    XENBUS_DEBUG_INTERFACE      DebugInterface;
-    PXENBUS_DEBUG_CALLBACK      DebugCallback;
-};
-
-#define XENVIF_NOTIFIER_TAG 'ITON'
-
-static FORCEINLINE PVOID
-__NotifierAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocateNonPagedPoolWithTag(Length, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE VOID
-__NotifierFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN  Index
-    )
-{
-    PXENVIF_FRONTEND            Frontend;
-    BOOLEAN                     Pending;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    Pending = (Notifier->Connected) ?
-              XENBUS_EVTCHN(Unmask,
-                            &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
-                            FALSE) :
-              FALSE;
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return Pending;
-}
-
-__drv_functionClass(KDEFERRED_ROUTINE)
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_minIRQL(DISPATCH_LEVEL)
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__drv_sameIRQL
-static VOID
-NotifierDpc(
-    IN  PKDPC               Dpc,
-    IN  PVOID               Context,
-    IN  PVOID               Argument1,
-    IN  PVOID               Argument2
-    )
-{
-    PXENVIF_NOTIFIER        Notifier = Context;
-    XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
-    PXENVIF_FRONTEND        Frontend;
-    BOOLEAN                 Pending;
-
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Argument2);
-
-    ASSERT(Notifier != NULL);
-
-    Frontend = Notifier->Frontend;
-
-    do {
-        if (Notifier->Enabled) {
-            switch (Index) {
-            case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            default:
-                ASSERT(FALSE);
-                break;
-            }
-        }
-
-        Pending = __NotifierUnmask(Notifier, Index);
-    } while (Pending);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
-    )
-{
-    Notifier->Events[Index]++;
-
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                         (PVOID)(ULONG_PTR)Index,
-                         NULL))
-        Notifier->Dpcs[Index]++;
-
-    return TRUE;
-}
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
-                                                                        \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
-                                                                        \
-BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
-    IN  PKINTERRUPT         InterruptObject,                            \
-    IN  PVOID               Argument                                    \
-    )                                                                   \
-{                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
-                                                                        \
-    UNREFERENCED_PARAMETER(InterruptObject);                            \
-                                                                        \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
-                                    XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
-}
-
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
-
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-};
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
-
-static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
-    )
-{
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
-    ULONG               Index;
-
-    UNREFERENCED_PARAMETER(Crashing);
-
-    Frontend = Notifier->Frontend;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        XENBUS_DEBUG(Printf,
-                     &Notifier->DebugInterface,
-                     "[%s]: Events = %lu Dpcs = %lu\n",
-                     ((Index == XENVIF_NOTIFIER_EVTCHN_COMBINED) ? "COMBINED" :
-                      ((Index == XENVIF_NOTIFIER_EVTCHN_RX) ? "RX" :
-                       ((Index == XENVIF_NOTIFIER_EVTCHN_TX) ? "TX" :
-                        "UNKNOWN"))),
-                     Notifier->Events[Index],
-                     Notifier->Dpcs[Index]);
-}
-
-NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    )
-{
-    ULONG                   Index;
-    NTSTATUS                status;
-
-    *Notifier = __NotifierAllocate(sizeof (XENVIF_NOTIFIER));
-
-    status = STATUS_NO_MEMORY;
-    if (*Notifier == NULL)
-        goto fail1;
-
-    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                          &(*Notifier)->EvtchnInterface);
-
-    FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->DebugInterface);
-
-    FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->StoreInterface);
-
-    (*Notifier)->Frontend = Frontend;
-
-    KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-    PCHAR                   Buffer;
-    NTSTATUS                status;
-
-    Frontend = Notifier->Frontend;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(!Notifier->Connected);
-
-    status = XENBUS_EVTCHN(Acquire, &Notifier->EvtchnInterface);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = XENBUS_DEBUG(Acquire, &Notifier->DebugInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = XENBUS_STORE(Acquire, &Notifier->StoreInterface);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PKSERVICE_ROUTINE   Callback = NotifierEvtchnCallback[Index];
-        BOOLEAN             Pending;
-
-        Notifier->Channel[Index] = XENBUS_EVTCHN(Open,
-                                                &Notifier->EvtchnInterface,
-                                                XENBUS_EVTCHN_TYPE_UNBOUND,
-                                                Callback,
-                                                Notifier,
-                                                FrontendGetBackendDomain(Frontend),
-                                                TRUE);
-
-        status = STATUS_UNSUCCESSFUL;
-        if (Notifier->Channel[Index] == NULL)
-            goto fail4;
-
-        Pending = XENBUS_EVTCHN(Unmask,
-                                &Notifier->EvtchnInterface,
-                                Notifier->Channel[Index],
-                                FALSE);
-        if (Pending)
-            XENBUS_EVTCHN(Trigger,
-                          &Notifier->EvtchnInterface,
-                          Notifier->Channel[Index]);
-    }
-
-    status = XENBUS_DEBUG(Register,
-                          &Notifier->DebugInterface,
-                          __MODULE__ "|NOTIFIER",
-                          NotifierDebugCallback,
-                          Notifier,
-                          &Notifier->DebugCallback);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    status = XENBUS_STORE(Read,
-                          &Notifier->StoreInterface,
-                          NULL,
-                          FrontendGetBackendPath(Frontend),
-                          "feature-split-event-channels",
-                          &Buffer);
-    if (!NT_SUCCESS(status)) {
-        Notifier->Split = FALSE;
-    } else {
-        Notifier->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
-
-        XENBUS_STORE(Free,
-                     &Notifier->StoreInterface,
-                     Buffer);
-    }
-
-    Notifier->Connected = TRUE;
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    Error("fail5\n");
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-fail3:
-    Error("fail3\n");
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-fail2:
-    Error("fail2\n");
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return status;
-}
-
-NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    )
-{
-    PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
-    NTSTATUS                        status;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PCHAR   Node;
-        ULONG   Port;
-
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            Node = "event-channel";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-rx";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-tx";
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
-
-        if (!NT_SUCCESS(status))
-            goto fail1;
-    }
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{   
-    ULONG                   Index;
-
-    ASSERT(!Notifier->Enabled);
-    Notifier->Enabled = TRUE;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            break;
-        }
-
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    ASSERT(Notifier->Enabled);
-    Notifier->Enabled = FALSE;
-}
-
-VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(Notifier->Connected);
-    Notifier->Connected = FALSE;
-
-    Notifier->Split = FALSE;
-
-    XENBUS_DEBUG(Deregister,
-                 &Notifier->DebugInterface,
-                 Notifier->DebugCallback);
-    Notifier->DebugCallback = NULL;
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-}
-
-VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    LONG                    Index;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-    KeFlushQueuedDpcs();
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        Notifier->Dpcs[Index] = 0;
-        RtlZeroMemory(&Notifier->Dpc[Index], sizeof (KDPC));
-    }
-
-    Notifier->Frontend = NULL;
-
-    RtlZeroMemory(&Notifier->StoreInterface,
-                  sizeof (XENBUS_STORE_INTERFACE));
-
-    RtlZeroMemory(&Notifier->DebugInterface,
-                  sizeof (XENBUS_DEBUG_INTERFACE));
-
-    RtlZeroMemory(&Notifier->EvtchnInterface,
-                  sizeof (XENBUS_EVTCHN_INTERFACE));
-
-    RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
-
-    ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
-
-    __NotifierFree(Notifier);
-}
-
-static FORCEINLINE VOID
-__NotifierSend(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Send,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-static FORCEINLINE VOID
-__NotifierTrigger(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Trigger,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
deleted file mode 100644
index 2f06a6f..0000000
--- a/src/xenvif/notifier.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#ifndef _XENVIF_NOTIFIER_H
-#define _XENVIF_NOTIFIER_H
-
-#include <ntddk.h>
-#include <store_interface.h>
-
-#include "frontend.h"
-
-typedef struct _XENVIF_NOTIFIER XENVIF_NOTIFIER, *PXENVIF_NOTIFIER;
-
-extern NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    );
-
-extern NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    );
-
-extern NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-#endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 1b81b73..a11d91e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -37,6 +37,7 @@
 #include <debug_interface.h>
 #include <store_interface.h>
 #include <cache_interface.h>
+#include <evtchn_interface.h>
 
 // This should be in public/io/netif.h
 #define _NETRXF_gso_prefix     (4)
@@ -50,8 +51,8 @@
 #include "checksum.h"
 #include "parse.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
+#include "transmitter.h"
 #include "vif.h"
 #include "receiver.h"
 #include "thread.h"
@@ -82,10 +83,16 @@ typedef struct _XENVIF_RECEIVER_RING {
     netif_rx_front_ring_t       Front;
     netif_rx_sring_t            *Shared;
     XENVIF_GRANTER_HANDLE       Handle;
+    PXENBUS_EVTCHN_CHANNEL      Channel;
+    KDPC                        Dpc;
+    ULONG                       Dpcs;
+    ULONG                       Events;
+    KSPIN_LOCK                  EvtchnLock;
     PXENVIF_RECEIVER_FRAGMENT   Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1];
     ULONG                       RequestsPosted;
     ULONG                       RequestsPushed;
     ULONG                       ResponsesProcessed;
+    BOOLEAN                     Connected;
     BOOLEAN                     Enabled;
     BOOLEAN                     Stopped;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
@@ -97,7 +104,9 @@ typedef struct _XENVIF_RECEIVER_RING {
 struct _XENVIF_RECEIVER {
     PXENVIF_FRONTEND        Frontend;
     XENBUS_CACHE_INTERFACE  CacheInterface;
+    XENBUS_EVTCHN_INTERFACE EvtchnInterface;
     PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
+    BOOLEAN                 Split;
     LONG                    Loaned;
     LONG                    Returned;
     KEVENT                  Event;
@@ -1352,6 +1361,46 @@ __ReceiverRingIsStopped(
 }
 
 static FORCEINLINE VOID
+__ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Trigger,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__ReceiverRingSend(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Send,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __ReceiverRingReturnPacket(
     IN  PXENVIF_RECEIVER_RING   Ring,
     IN  PXENVIF_RECEIVER_PACKET Packet,
@@ -1382,15 +1431,8 @@ __ReceiverRingReturnPacket(
             __ReceiverRingAcquireLock(Ring);
 
         if (__ReceiverRingIsStopped(Ring)) {
-            PXENVIF_RECEIVER    Receiver;
-            PXENVIF_FRONTEND    Frontend;
-
             __ReceiverRingStart(Ring);
-
-            Receiver = Ring->Receiver;
-            Frontend = Receiver->Frontend;
-
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            __ReceiverRingTrigger(Ring);
         }
 
         if (!Locked)
@@ -1464,13 +1506,7 @@ __ReceiverRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_RECEIVER    Receiver;
-        PXENVIF_FRONTEND    Frontend;
-
-        Receiver = Ring->Receiver;
-        Frontend = Receiver->Frontend;
-
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        __ReceiverRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1599,8 +1635,9 @@ ReceiverRingDebugCallback(
 
     XENBUS_DEBUG(Printf,
                  &Receiver->DebugInterface,
-                 "0x%p [%s][%s]\n",
+                 "0x%p [%u] [%s][%s]\n",
                  Ring,
+                 Ring->Index,
                  (Ring->Enabled) ? "ENABLED" : "DISABLED",
                  (__ReceiverRingIsStopped(Ring)) ? "STOPPED" : "RUNNING");
 
@@ -1628,6 +1665,14 @@ ReceiverRingDebugCallback(
                  Ring->RequestsPosted,
                  Ring->RequestsPushed,
                  Ring->ResponsesProcessed);
+
+    // Dump event channel
+    XENBUS_DEBUG(Printf,
+                 &Receiver->DebugInterface,
+                 "[%s]: Events = %lu Dpcs = %lu\n",
+                 Receiver->Split ? "RX" : "COMBINED",
+                 Ring->Events,
+                 Ring->Dpcs);
 }
 
 static DECLSPEC_NOINLINE VOID
@@ -1801,6 +1846,104 @@ ReceiverRingPoll(
 #undef  XENVIF_RECEIVER_BATCH
 }
 
+static FORCEINLINE VOID
+__ReceiverRingNotify(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    __ReceiverRingAcquireLock(Ring);
+    ReceiverRingPoll(Ring);
+    __ReceiverRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__ReceiverRingUnmask(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    PXENVIF_RECEIVER            Receiver;
+    BOOLEAN                     Pending;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+ReceiverRingDpc(
+    IN  PKDPC               Dpc,
+    IN  PVOID               Context,
+    IN  PVOID               Argument1,
+    IN  PVOID               Argument2
+    )
+{
+    PXENVIF_RECEIVER_RING   Ring = Context;
+    PXENVIF_RECEIVER        Receiver;
+    PXENVIF_FRONTEND        Frontend;
+    BOOLEAN                 Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Receiver = Ring->Receiver;
+    Frontend = Receiver->Frontend;
+
+    do {
+        if (Ring->Enabled) {
+            if (Receiver->Split) {
+                __ReceiverRingNotify(Ring);
+            } else {
+                TransmitterRingNotify(FrontendGetTransmitter(Frontend),
+                                      Ring->Index);
+                __ReceiverRingNotify(Ring);
+            }
+        }
+
+        Pending = __ReceiverRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    ReceiverRingEvtchnCallback;
+
+BOOLEAN
+ReceiverRingEvtchnCallback(
+    IN  PKINTERRUPT             InterruptObject,
+    IN  PVOID                   Argument
+    )
+{
+    PXENVIF_RECEIVER_RING       Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -1851,10 +1994,8 @@ ReceiverRingWatchdog(
             if (Ring->Shared->rsp_prod != rsp_prod &&
                 Ring->Front.rsp_cons == rsp_cons) {
                 PXENVIF_RECEIVER    Receiver;
-                PXENVIF_FRONTEND    Frontend;
 
                 Receiver = Ring->Receiver;
-                Frontend = Receiver->Frontend;
 
                 XENBUS_DEBUG(Trigger,
                              &Receiver->DebugInterface,
@@ -1862,7 +2003,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                __ReceiverRingSend(Ring);
             }
 
             KeMemoryBarrier();
@@ -1905,6 +2046,9 @@ __ReceiverRingInitialize(
     (*Ring)->Index = Index;
 
     InitializeListHead(&(*Ring)->PacketList);
+
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -1989,6 +2133,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
     (*Ring)->Index = 0;
@@ -2014,6 +2161,7 @@ __ReceiverRingConnect(
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_FRONTEND            Frontend;
     PFN_NUMBER                  Pfn;
+    BOOLEAN                     Pending;
     CHAR                        Name[MAXNAMELEN];
     NTSTATUS                    status;
 
@@ -2049,6 +2197,38 @@ __ReceiverRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    ASSERT(!Ring->Connected);
+
+    Ring->Channel = XENBUS_EVTCHN(Open,
+                                  &Receiver->EvtchnInterface,
+                                  XENBUS_EVTCHN_TYPE_UNBOUND,
+                                  ReceiverRingEvtchnCallback,
+                                  Ring,
+                                  FrontendGetBackendDomain(Frontend),
+                                  TRUE);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Ring->Channel == NULL) {
+        KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+        goto fail4;
+    }
+
+    Pending = XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE);
+
+    if (Pending)
+        XENBUS_EVTCHN(Trigger,
+                     &Receiver->EvtchnInterface,
+                     Ring->Channel);
+
+    Ring->Connected = TRUE;
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     status = XENBUS_DEBUG(Register,
                           &Receiver->DebugInterface,
                           Name,
@@ -2056,10 +2236,22 @@ __ReceiverRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2094,6 +2286,7 @@ __ReceiverRingStoreWrite(
 {
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -2111,8 +2304,25 @@ __ReceiverRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Receiver->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Receiver->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          Receiver->Split ? "event-channel-rx" : "event-channel",
+                          "%u",
+                          Port);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -2143,6 +2353,9 @@ __ReceiverRingEnable(
 
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __ReceiverRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2183,6 +2396,20 @@ __ReceiverRingDisconnect(
 
     __ReceiverRingEmpty(Ring);
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    ASSERT(Ring->Connected);
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -2216,6 +2443,10 @@ __ReceiverRingTeardown(
 
     Receiver = Ring->Receiver;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     Ring->OffloadOptions.Value = 0;
 
     ThreadAlert(Ring->WatchdogThread);
@@ -2245,16 +2476,6 @@ __ReceiverRingTeardown(
 }
 
 static FORCEINLINE VOID
-__ReceiverRingNotify(
-    IN  PXENVIF_RECEIVER_RING   Ring
-    )
-{
-    __ReceiverRingAcquireLock(Ring);
-    ReceiverRingPoll(Ring);
-    __ReceiverRingReleaseLock(Ring);
-}
-
-static FORCEINLINE VOID
 __ReceiverRingSetOffloadOptions(
     IN  PXENVIF_RECEIVER_RING       Ring,
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
@@ -2313,6 +2534,7 @@ ReceiverInitialize(
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   ReceiverCalculateChecksums;
@@ -2370,6 +2592,9 @@ ReceiverInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Receiver)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Receiver)->EvtchnInterface);
+
     (*Receiver)->Frontend = Frontend;
 
     status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface);
@@ -2411,6 +2636,9 @@ fail2:
 
     (*Receiver)->Frontend = NULL;
 
+    RtlZeroMemory(&(*Receiver)->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     RtlZeroMemory(&(*Receiver)->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -2428,6 +2656,7 @@ fail2:
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     ASSERT(IsZeroMemory(*Receiver, sizeof (XENVIF_RECEIVER)));
     __ReceiverFree(*Receiver);
@@ -2445,6 +2674,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    PCHAR                   Buffer;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
@@ -2457,6 +2687,26 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Receiver->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Receiver->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Receiver->Split = FALSE;
+    } else {
+        Receiver->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Receiver->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2466,7 +2716,7 @@ ReceiverConnect(
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -2476,16 +2726,16 @@ ReceiverConnect(
                           Receiver,
                           &Receiver->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2496,6 +2746,11 @@ fail3:
         __ReceiverRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
 fail2:
@@ -2747,6 +3002,8 @@ ReceiverDisconnect(
 
     Frontend = Receiver->Frontend;
 
+    Receiver->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Receiver->DebugInterface,
                  Receiver->DebugCallback);
@@ -2765,6 +3022,8 @@ ReceiverDisconnect(
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
     XENBUS_DEBUG(Release, &Receiver->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
 }
 
 VOID
@@ -2774,6 +3033,9 @@ ReceiverTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
@@ -2793,6 +3055,10 @@ ReceiverTeardown(
     XENBUS_CACHE(Release, &Receiver->CacheInterface);
 
     Receiver->Frontend = NULL;
+    Receiver->Split = FALSE;
+
+    RtlZeroMemory(&Receiver->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
 
     RtlZeroMemory(&Receiver->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -2921,19 +3187,37 @@ ReceiverWaitForPackets(
 }
 
 VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_RECEIVER_RING   Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __ReceiverRingNotify(Ring);
-    }    
+    __ReceiverRingTrigger(Ring);
+}
+
+VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    )
+{
+    PXENVIF_RECEIVER_RING   Ring;
+
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
+
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
+
+    __ReceiverRingSend(Ring);
 }
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 0497c5b..f926500 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,11 +79,6 @@ ReceiverTeardown(
     );
 
 extern VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
-    );
-
-extern VOID
 ReceiverWaitForPackets(
     IN  PXENVIF_RECEIVER    Receiver
     );
@@ -106,4 +101,16 @@ ReceiverReturnPackets(
     IN  PLIST_ENTRY         List
     );
 
+extern VOID
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
+extern VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
 #endif  // _XENVIF_RECEIVER_H
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 645872b..e482392 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -40,6 +40,7 @@
 #include <cache_interface.h>
 #include <gnttab_interface.h>
 #include <range_set_interface.h>
+#include <evtchn_interface.h>
 
 #include "ethernet.h"
 #include "tcpip.h"
@@ -114,6 +115,11 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     netif_tx_front_ring_t           Front;
     netif_tx_sring_t                *Shared;
     XENVIF_GRANTER_HANDLE           Handle;
+    PXENBUS_EVTCHN_CHANNEL          Channel;
+    KDPC                            Dpc;
+    ULONG                           Dpcs;
+    ULONG                           Events;
+    KSPIN_LOCK                      EvtchnLock;
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
@@ -145,8 +151,10 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
+    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
     PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
+    BOOLEAN                     Split;
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
@@ -2127,6 +2135,72 @@ TransmitterRingPoll(
 }
 
 static FORCEINLINE VOID
+__TransmitterRingTrigger(
+    IN  PXENVIF_TRANSMITTER_RING   Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Trigger,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingTrigger(FrontendGetReceiver(Frontend),
+                                Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__TransmitterRingSend(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Send,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingSend(FrontendGetReceiver(Frontend),
+                             Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __TransmitterRingPushRequests(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
@@ -2145,13 +2219,7 @@ __TransmitterRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
-
-        Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
-
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        __TransmitterRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2475,6 +2543,97 @@ TransmitterRingReleaseLock(
     __TransmitterRingReleaseLock(Ring);
 }
 
+static FORCEINLINE VOID
+__TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    __TransmitterRingAcquireLock(Ring);
+    TransmitterRingPoll(Ring);
+    __TransmitterRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__TransmitterRingUnmask(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    PXENVIF_TRANSMITTER             Transmitter;
+    BOOLEAN                         Pending;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Transmitter->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+TransmitterRingDpc(
+    IN  PKDPC                   Dpc,
+    IN  PVOID                   Context,
+    IN  PVOID                   Argument1,
+    IN  PVOID                   Argument2
+    )
+{
+    PXENVIF_TRANSMITTER_RING    Ring = Context;
+    PXENVIF_TRANSMITTER         Transmitter;
+    BOOLEAN                     Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Transmitter = Ring->Transmitter;
+
+    do {
+        if (Ring->Enabled) {
+            ASSERT(Transmitter->Split);
+            __TransmitterRingNotify(Ring);
+        }
+
+        Pending = __TransmitterRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    TransmitterRingEvtchnCallback;
+
+BOOLEAN
+TransmitterRingEvtchnCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
+    )
+{
+    PXENVIF_TRANSMITTER_RING    Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -2520,17 +2679,15 @@ TransmitterRingWatchdog(
             if (Ring->PacketsQueued == PacketsQueued &&
                 Ring->PacketsCompleted != PacketsQueued) {
                 PXENVIF_TRANSMITTER Transmitter;
-                PXENVIF_FRONTEND    Frontend;
 
                 Transmitter = Ring->Transmitter;
-                Frontend = Transmitter->Frontend;
 
                 XENBUS_DEBUG(Trigger,
                              &Transmitter->DebugInterface,
                              Ring->DebugCallback);
 
                 // Try to move things along
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                __TransmitterRingSend(Ring);
                 TransmitterRingPoll(Ring);
             }
 
@@ -2625,6 +2782,8 @@ __TransmitterRingInitialize(
     (*Ring)->Index = Index;
     (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
     (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -2755,6 +2914,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+
     (*Ring)->Queued.TailPacket = NULL;
     (*Ring)->Completed.TailPacket = NULL;
     (*Ring)->Index = 0;
@@ -2778,6 +2940,7 @@ __TransmitterRingConnect(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PFN_NUMBER                      Pfn;
+    BOOLEAN                         Pending;
     CHAR                            Name[MAXNAMELEN];
     NTSTATUS                        status;
 
@@ -2815,6 +2978,38 @@ __TransmitterRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    if (Transmitter->Split) {
+        Ring->Channel = XENBUS_EVTCHN(Open,
+                                      &Transmitter->EvtchnInterface,
+                                      XENBUS_EVTCHN_TYPE_UNBOUND,
+                                      TransmitterRingEvtchnCallback,
+                                      Ring,
+                                      FrontendGetBackendDomain(Frontend),
+                                      TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Ring->Channel == NULL) {
+            KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+            goto fail4;
+        }
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Transmitter->EvtchnInterface,
+                                Ring->Channel,
+                                FALSE);
+
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Transmitter->EvtchnInterface,
+                          Ring->Channel);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+
     status = XENBUS_DEBUG(Register,
                           &Transmitter->DebugInterface,
                           Name,
@@ -2822,12 +3017,22 @@ __TransmitterRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     Ring->Connected = TRUE;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_EVTCHN(Close,
+                  &Transmitter->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2862,6 +3067,7 @@ __TransmitterRingStoreWrite(
 {
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -2879,8 +3085,29 @@ __TransmitterRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    if (!Transmitter->Split)
+        goto done;
+
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Transmitter->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Transmitter->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          "event-channel-tx",
+                          "%u",
+                          Port);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+done:
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -2897,6 +3124,9 @@ __TransmitterRingEnable(
     ASSERT(!Ring->Enabled);
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __TransmitterRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2992,6 +3222,21 @@ __TransmitterRingDisconnect(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Transmitter->Split = FALSE;
+
+    if (Ring->Channel != NULL) {
+        XENBUS_EVTCHN(Close,
+                      &Transmitter->EvtchnInterface,
+                      Ring->Channel);
+        Ring->Channel = NULL;
+
+        Ring->Events = 0;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -3028,6 +3273,10 @@ __TransmitterRingTeardown(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
     ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
@@ -3164,16 +3413,6 @@ __TransmitterRingAbortPackets(
     __TransmitterRingReleaseLock(Ring);
 }
 
-static FORCEINLINE VOID
-__TransmitterRingNotify(
-    IN  PXENVIF_TRANSMITTER_RING    Ring
-    )
-{
-    __TransmitterRingAcquireLock(Ring);
-    TransmitterRingPoll(Ring);
-    __TransmitterRingReleaseLock(Ring);
-}
-
 static VOID
 TransmitterDebugCallback(
     IN  PVOID           Argument,
@@ -3214,6 +3453,7 @@ TransmitterInitialize(
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
+    (*Transmitter)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   TransmitterDisableIpVersion4Gso;
@@ -3251,6 +3491,9 @@ TransmitterInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Transmitter)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Transmitter)->EvtchnInterface);
+
     (*Transmitter)->Frontend = Frontend;
 
     status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
@@ -3332,6 +3575,7 @@ TransmitterConnect(
     )
 {
     PXENVIF_FRONTEND            Frontend;
+    PCHAR                       Buffer;
     ULONG                       Index;
     NTSTATUS                    status;
 
@@ -3345,6 +3589,26 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Transmitter->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Transmitter->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Transmitter->Split = FALSE;
+    } else {
+        Transmitter->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Transmitter->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3354,7 +3618,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3364,16 +3628,16 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3384,6 +3648,11 @@ fail3:
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
 fail2:
@@ -3474,6 +3743,8 @@ TransmitterDisconnect(
 
     Frontend = Transmitter->Frontend;
 
+    Transmitter->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Transmitter->DebugInterface,
                  Transmitter->DebugCallback);
@@ -3492,6 +3763,8 @@ TransmitterDisconnect(
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
     XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 }
 
 VOID
@@ -3501,6 +3774,9 @@ TransmitterTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
@@ -3521,6 +3797,7 @@ TransmitterTeardown(
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
 
     Transmitter->Frontend = NULL;
+    Transmitter->Split = FALSE;
 
     RtlZeroMemory(&Transmitter->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -3534,6 +3811,9 @@ TransmitterTeardown(
     RtlZeroMemory(&Transmitter->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
+    RtlZeroMemory(&Transmitter->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
@@ -3652,21 +3932,21 @@ TransmitterQueryRingSize(
 }
 
 VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_TRANSMITTER_RING    Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Transmitter->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __TransmitterRingNotify(Ring);
-    }    
+    __TransmitterRingNotify(Ring);
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 5ffb590..9c3bfaa 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,8 +79,9 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/vs2012/xenvif/xenvif.vcxproj b/vs2012/xenvif/xenvif.vcxproj
index a86acff..edd71ea 100644
--- a/vs2012/xenvif/xenvif.vcxproj
+++ b/vs2012/xenvif/xenvif.vcxproj
@@ -96,7 +96,6 @@
 		<ClCompile Include="../../src/xenvif/granter.c" />
 		<ClCompile Include="../../src/xenvif/link.c" />
 		<ClCompile Include="../../src/xenvif/mac.c" />
-		<ClCompile Include="../../src/xenvif/notifier.c" />
 		<ClCompile Include="../../src/xenvif/parse.c" />
 		<ClCompile Include="../../src/xenvif/pdo.c" />
 		<ClCompile Include="../../src/xenvif/receiver.c" />
diff --git a/vs2013/xenvif/xenvif.vcxproj b/vs2013/xenvif/xenvif.vcxproj
index 69cf86a..32a3033 100644
--- a/vs2013/xenvif/xenvif.vcxproj
+++ b/vs2013/xenvif/xenvif.vcxproj
@@ -127,7 +127,6 @@
     <ClCompile Include="../../src/xenvif/granter.c" />
     <ClCompile Include="../../src/xenvif/link.c" />
     <ClCompile Include="../../src/xenvif/mac.c" />
-    <ClCompile Include="../../src/xenvif/notifier.c" />
     <ClCompile Include="../../src/xenvif/parse.c" />
     <ClCompile Include="../../src/xenvif/pdo.c" />
     <ClCompile Include="../../src/xenvif/receiver.c" />
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:38 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4E-0002EL-H6; Thu, 18 Dec 2014 14:28:38 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4C-0002CD-Mq
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:37 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	D5/05-09842-494E2945; Thu, 18 Dec 2014 14:28:36 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1418912911!16496278!4
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22313 invoked from network); 18 Dec 2014 14:28:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205794988"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:21 +0000
Message-ID: <1418912904-8756-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/7] Remove notifier object
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Fold event channels into transmitter/receiver ring objects.
Receiver ring object takes over single event channel case and passes
notifications to transmitter object, tagged with ring index (so that
only the specified ring is executed).
Split notifications are handled independently by each ring object.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c        |  75 ++---
 src/xenvif/frontend.h        |   7 -
 src/xenvif/notifier.c        | 684 -------------------------------------------
 src/xenvif/notifier.h        |  99 -------
 src/xenvif/receiver.c        | 376 +++++++++++++++++++++---
 src/xenvif/receiver.h        |  17 +-
 src/xenvif/transmitter.c     | 352 +++++++++++++++++++---
 src/xenvif/transmitter.h     |   5 +-
 vs2012/xenvif/xenvif.vcxproj |   1 -
 vs2013/xenvif/xenvif.vcxproj |   1 -
 10 files changed, 678 insertions(+), 939 deletions(-)
 delete mode 100644 src/xenvif/notifier.c
 delete mode 100644 src/xenvif/notifier.h

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 305faaf..268bab9 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -44,7 +44,6 @@
 #include "frontend.h"
 #include "names.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
 #include "tcpip.h"
 #include "receiver.h"
@@ -66,7 +65,6 @@ struct _XENVIF_FRONTEND {
     USHORT                      BackendDomain;
 
     PXENVIF_GRANTER             Granter;
-    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_MAC                 Mac;
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_TRANSMITTER         Transmitter;
@@ -221,7 +219,6 @@ FrontendGet ## _Function(                               \
 }
 
 DEFINE_FRONTEND_GET_FUNCTION(Granter, PXENVIF_GRANTER)
-DEFINE_FRONTEND_GET_FUNCTION(Notifier, PXENVIF_NOTIFIER)
 DEFINE_FRONTEND_GET_FUNCTION(Mac, PXENVIF_MAC)
 DEFINE_FRONTEND_GET_FUNCTION(Transmitter, PXENVIF_TRANSMITTER)
 DEFINE_FRONTEND_GET_FUNCTION(Receiver, PXENVIF_RECEIVER)
@@ -1318,10 +1315,6 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierConnect(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     Attempt = 0;
     do {
         PXENBUS_STORE_TRANSACTION   Transaction;
@@ -1332,11 +1325,6 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             break;
 
-        status = NotifierStoreWrite(__FrontendGetNotifier(Frontend),
-                                    Transaction);
-        if (!NT_SUCCESS(status))
-            goto abort;
-
         status = ReceiverStoreWrite(__FrontendGetReceiver(Frontend),
                                     Transaction);
         if (!NT_SUCCESS(status))
@@ -1365,7 +1353,7 @@ abort:
     } while (status == STATUS_RETRY);
 
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = XENBUS_STORE(Printf,
                           &Frontend->StoreInterface,
@@ -1375,25 +1363,22 @@ abort:
                           "%u",
                           XenbusStateConnected);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     State = XenbusStateInitWait;
     status = __FrontendWaitForStateChange(Frontend, Path, &State);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = STATUS_UNSUCCESSFUL;
     if (State != XenbusStateConnected)
-        goto fail11;
+        goto fail10;
 
     ThreadWake(Frontend->MibThread);
 
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail11:
-    Error("fail11\n");
-
 fail10:
     Error("fail10\n");
 
@@ -1403,8 +1388,6 @@ fail9:
 fail8:
     Error("fail8\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
-
 fail7:
     Error("fail7\n");
 
@@ -1452,7 +1435,6 @@ __FrontendDisconnect(
 {
     Trace("====>\n");
 
-    NotifierDisconnect(__FrontendGetNotifier(Frontend));
     TransmitterDisconnect(__FrontendGetTransmitter(Frontend));
     ReceiverDisconnect(__FrontendGetReceiver(Frontend));
     MacDisconnect(__FrontendGetMac(Frontend));
@@ -1495,18 +1477,9 @@ __FrontendEnable(
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = NotifierEnable(__FrontendGetNotifier(Frontend));
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
-
-    TransmitterDisable(__FrontendGetTransmitter(Frontend));
-
 fail4:
     Error("fail4\n");
 
@@ -1535,7 +1508,6 @@ __FrontendDisable(
 {
     Trace("====>\n");
 
-    NotifierDisable(__FrontendGetNotifier(Frontend));
     TransmitterDisable(__FrontendGetTransmitter(Frontend));
     ReceiverDisable(__FrontendGetReceiver(Frontend));
     MacDisable(__FrontendGetMac(Frontend));
@@ -1894,64 +1866,54 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
     status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail7;
 
     status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail8;
 
     status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail9;
 
     status = ThreadCreate(FrontendEject, *Frontend, &(*Frontend)->EjectThread);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail10;
 
     status = ThreadCreate(FrontendMib, *Frontend, &(*Frontend)->MibThread);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail11;
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
-fail12:
-    Error("fail12\n");
+fail11:
+    Error("fail11\n");
 
     ThreadAlert((*Frontend)->EjectThread);
     ThreadJoin((*Frontend)->EjectThread);
     (*Frontend)->EjectThread = NULL;
 
-fail11:
-    Error("fail11\n");
-
-    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
-    (*Frontend)->Transmitter = NULL;
-
 fail10:
     Error("fail10\n");
 
-    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
-    (*Frontend)->Receiver = NULL;
+    TransmitterTeardown(__FrontendGetTransmitter(*Frontend));
+    (*Frontend)->Transmitter = NULL;
 
 fail9:
     Error("fail9\n");
 
-    MacTeardown(__FrontendGetMac(*Frontend));
-    (*Frontend)->Mac = NULL;
+    ReceiverTeardown(__FrontendGetReceiver(*Frontend));
+    (*Frontend)->Receiver = NULL;
 
 fail8:
     Error("fail8\n");
 
-    NotifierTeardown(__FrontendGetNotifier(*Frontend));
-    (*Frontend)->Notifier = NULL;
+    MacTeardown(__FrontendGetMac(*Frontend));
+    (*Frontend)->Mac = NULL;
 
 fail7:
     Error("fail7\n");
@@ -2043,9 +2005,6 @@ FrontendTeardown(
     MacTeardown(__FrontendGetMac(Frontend));
     Frontend->Mac = NULL;
 
-    NotifierTeardown(__FrontendGetNotifier(Frontend));
-    Frontend->Notifier = NULL;
-
     GranterTeardown(__FrontendGetGranter(Frontend));
     Frontend->Granter = NULL;
 
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 60c085a..67696d6 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -119,13 +119,6 @@ FrontendGetGranter(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
-#include "notifier.h"
-
-extern PXENVIF_NOTIFIER
-FrontendGetNotifier(
-    IN  PXENVIF_FRONTEND    Frontend
-    );
-
 #include "mac.h"
 
 extern PXENVIF_MAC
diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
deleted file mode 100644
index fc6725a..0000000
--- a/src/xenvif/notifier.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <ntstrsafe.h>
-#include <stdlib.h>
-#include <util.h>
-
-#include "pdo.h"
-#include "frontend.h"
-#include "notifier.h"
-#include "receiver.h"
-#include "transmitter.h"
-#include "dbg_print.h"
-#include "assert.h"
-
-typedef enum _XENVIF_NOTIFIER_EVTCHN {
-    XENVIF_NOTIFIER_EVTCHN_COMBINED = 0,
-    XENVIF_NOTIFIER_EVTCHN_RX,
-    XENVIF_NOTIFIER_EVTCHN_TX,
-    XENVIF_NOTIFIER_EVTCHN_COUNT
-} XENVIF_NOTIFIER_EVTCHN, *PXENVIF_NOTIFIER_EVTCHN;
-
-struct _XENVIF_NOTIFIER {
-    PXENVIF_FRONTEND            Frontend;
-    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
-    PXENBUS_EVTCHN_CHANNEL      Channel[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    KDPC                        Dpc[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Dpcs[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    ULONG                       Events[XENVIF_NOTIFIER_EVTCHN_COUNT];
-    BOOLEAN                     Connected;
-    KSPIN_LOCK                  Lock;
-    BOOLEAN                     Split;
-    BOOLEAN                     Enabled;
-    XENBUS_STORE_INTERFACE      StoreInterface;
-    XENBUS_DEBUG_INTERFACE      DebugInterface;
-    PXENBUS_DEBUG_CALLBACK      DebugCallback;
-};
-
-#define XENVIF_NOTIFIER_TAG 'ITON'
-
-static FORCEINLINE PVOID
-__NotifierAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocateNonPagedPoolWithTag(Length, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE VOID
-__NotifierFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, XENVIF_NOTIFIER_TAG);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN  Index
-    )
-{
-    PXENVIF_FRONTEND            Frontend;
-    BOOLEAN                     Pending;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    Pending = (Notifier->Connected) ?
-              XENBUS_EVTCHN(Unmask,
-                            &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
-                            FALSE) :
-              FALSE;
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return Pending;
-}
-
-__drv_functionClass(KDEFERRED_ROUTINE)
-__drv_maxIRQL(DISPATCH_LEVEL)
-__drv_minIRQL(DISPATCH_LEVEL)
-__drv_requiresIRQL(DISPATCH_LEVEL)
-__drv_sameIRQL
-static VOID
-NotifierDpc(
-    IN  PKDPC               Dpc,
-    IN  PVOID               Context,
-    IN  PVOID               Argument1,
-    IN  PVOID               Argument2
-    )
-{
-    PXENVIF_NOTIFIER        Notifier = Context;
-    XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
-    PXENVIF_FRONTEND        Frontend;
-    BOOLEAN                 Pending;
-
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Argument2);
-
-    ASSERT(Notifier != NULL);
-
-    Frontend = Notifier->Frontend;
-
-    do {
-        if (Notifier->Enabled) {
-            switch (Index) {
-            case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
-                break;
-
-            default:
-                ASSERT(FALSE);
-                break;
-            }
-        }
-
-        Pending = __NotifierUnmask(Notifier, Index);
-    } while (Pending);
-}
-
-static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
-    )
-{
-    Notifier->Events[Index]++;
-
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                         (PVOID)(ULONG_PTR)Index,
-                         NULL))
-        Notifier->Dpcs[Index]++;
-
-    return TRUE;
-}
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
-                                                                        \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
-                                                                        \
-BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
-    IN  PKINTERRUPT         InterruptObject,                            \
-    IN  PVOID               Argument                                    \
-    )                                                                   \
-{                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
-                                                                        \
-    UNREFERENCED_PARAMETER(InterruptObject);                            \
-                                                                        \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
-                                    XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
-}
-
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
-
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
-};
-
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
-
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
-
-static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
-    )
-{
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
-    ULONG               Index;
-
-    UNREFERENCED_PARAMETER(Crashing);
-
-    Frontend = Notifier->Frontend;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        XENBUS_DEBUG(Printf,
-                     &Notifier->DebugInterface,
-                     "[%s]: Events = %lu Dpcs = %lu\n",
-                     ((Index == XENVIF_NOTIFIER_EVTCHN_COMBINED) ? "COMBINED" :
-                      ((Index == XENVIF_NOTIFIER_EVTCHN_RX) ? "RX" :
-                       ((Index == XENVIF_NOTIFIER_EVTCHN_TX) ? "TX" :
-                        "UNKNOWN"))),
-                     Notifier->Events[Index],
-                     Notifier->Dpcs[Index]);
-}
-
-NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    )
-{
-    ULONG                   Index;
-    NTSTATUS                status;
-
-    *Notifier = __NotifierAllocate(sizeof (XENVIF_NOTIFIER));
-
-    status = STATUS_NO_MEMORY;
-    if (*Notifier == NULL)
-        goto fail1;
-
-    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                          &(*Notifier)->EvtchnInterface);
-
-    FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->DebugInterface);
-
-    FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
-                         &(*Notifier)->StoreInterface);
-
-    (*Notifier)->Frontend = Frontend;
-
-    KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-    PCHAR                   Buffer;
-    NTSTATUS                status;
-
-    Frontend = Notifier->Frontend;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(!Notifier->Connected);
-
-    status = XENBUS_EVTCHN(Acquire, &Notifier->EvtchnInterface);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = XENBUS_DEBUG(Acquire, &Notifier->DebugInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = XENBUS_STORE(Acquire, &Notifier->StoreInterface);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PKSERVICE_ROUTINE   Callback = NotifierEvtchnCallback[Index];
-        BOOLEAN             Pending;
-
-        Notifier->Channel[Index] = XENBUS_EVTCHN(Open,
-                                                &Notifier->EvtchnInterface,
-                                                XENBUS_EVTCHN_TYPE_UNBOUND,
-                                                Callback,
-                                                Notifier,
-                                                FrontendGetBackendDomain(Frontend),
-                                                TRUE);
-
-        status = STATUS_UNSUCCESSFUL;
-        if (Notifier->Channel[Index] == NULL)
-            goto fail4;
-
-        Pending = XENBUS_EVTCHN(Unmask,
-                                &Notifier->EvtchnInterface,
-                                Notifier->Channel[Index],
-                                FALSE);
-        if (Pending)
-            XENBUS_EVTCHN(Trigger,
-                          &Notifier->EvtchnInterface,
-                          Notifier->Channel[Index]);
-    }
-
-    status = XENBUS_DEBUG(Register,
-                          &Notifier->DebugInterface,
-                          __MODULE__ "|NOTIFIER",
-                          NotifierDebugCallback,
-                          Notifier,
-                          &Notifier->DebugCallback);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    status = XENBUS_STORE(Read,
-                          &Notifier->StoreInterface,
-                          NULL,
-                          FrontendGetBackendPath(Frontend),
-                          "feature-split-event-channels",
-                          &Buffer);
-    if (!NT_SUCCESS(status)) {
-        Notifier->Split = FALSE;
-    } else {
-        Notifier->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
-
-        XENBUS_STORE(Free,
-                     &Notifier->StoreInterface,
-                     Buffer);
-    }
-
-    Notifier->Connected = TRUE;
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    Error("fail5\n");
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-fail3:
-    Error("fail3\n");
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-fail2:
-    Error("fail2\n");
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-
-    return status;
-}
-
-NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    )
-{
-    PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
-    NTSTATUS                        status;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        PCHAR   Node;
-        ULONG   Port;
-
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            Node = "event-channel";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-rx";
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            Node = "event-channel-tx";
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
-
-        if (!NT_SUCCESS(status))
-            goto fail1;
-    }
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{   
-    ULONG                   Index;
-
-    ASSERT(!Notifier->Enabled);
-    Notifier->Enabled = TRUE;
-
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
-        switch (Index) {
-        case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-            if (Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_RX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        case XENVIF_NOTIFIER_EVTCHN_TX:
-            if (!Notifier->Split)
-                continue;
-
-            break;
-
-        default:
-            ASSERT(FALSE);
-
-            break;
-        }
-
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
-    }
-
-    return STATUS_SUCCESS;
-}
-
-VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    ASSERT(Notifier->Enabled);
-    Notifier->Enabled = FALSE;
-}
-
-VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
-
-    ASSERT(Notifier->Connected);
-    Notifier->Connected = FALSE;
-
-    Notifier->Split = FALSE;
-
-    XENBUS_DEBUG(Deregister,
-                 &Notifier->DebugInterface,
-                 Notifier->DebugCallback);
-    Notifier->DebugCallback = NULL;
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
-
-        Notifier->Events[Index] = 0;
-    }
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-
-    XENBUS_DEBUG(Release, &Notifier->DebugInterface);
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-
-    KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
-}
-
-VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    LONG                    Index;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-    KeFlushQueuedDpcs();
-
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
-    while (--Index >= 0) {
-        Notifier->Dpcs[Index] = 0;
-        RtlZeroMemory(&Notifier->Dpc[Index], sizeof (KDPC));
-    }
-
-    Notifier->Frontend = NULL;
-
-    RtlZeroMemory(&Notifier->StoreInterface,
-                  sizeof (XENBUS_STORE_INTERFACE));
-
-    RtlZeroMemory(&Notifier->DebugInterface,
-                  sizeof (XENBUS_DEBUG_INTERFACE));
-
-    RtlZeroMemory(&Notifier->EvtchnInterface,
-                  sizeof (XENBUS_EVTCHN_INTERFACE));
-
-    RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
-
-    ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
-
-    __NotifierFree(Notifier);
-}
-
-static FORCEINLINE VOID
-__NotifierSend(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Send,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-static FORCEINLINE VOID
-__NotifierTrigger(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
-    )
-{
-    PXENVIF_FRONTEND        Frontend;
-    KIRQL                   Irql;
-
-    Frontend = Notifier->Frontend;
-
-    KeAcquireSpinLock(&Notifier->Lock, &Irql);
-
-    if (Notifier->Connected)
-        (VOID) XENBUS_EVTCHN(Trigger,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-    KeReleaseSpinLock(&Notifier->Lock, Irql);
-}
-
-VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
-
-VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    )
-{
-    if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
-    else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
-}
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
deleted file mode 100644
index 2f06a6f..0000000
--- a/src/xenvif/notifier.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#ifndef _XENVIF_NOTIFIER_H
-#define _XENVIF_NOTIFIER_H
-
-#include <ntddk.h>
-#include <store_interface.h>
-
-#include "frontend.h"
-
-typedef struct _XENVIF_NOTIFIER XENVIF_NOTIFIER, *PXENVIF_NOTIFIER;
-
-extern NTSTATUS
-NotifierInitialize(
-    IN  PXENVIF_FRONTEND    Frontend,
-    OUT PXENVIF_NOTIFIER    *Notifier
-    );
-
-extern NTSTATUS
-NotifierConnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVIF_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction
-    );
-
-extern NTSTATUS
-NotifierEnable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisable(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierDisconnect(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTeardown(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-extern VOID
-NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
-    );
-
-#endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 1b81b73..a11d91e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -37,6 +37,7 @@
 #include <debug_interface.h>
 #include <store_interface.h>
 #include <cache_interface.h>
+#include <evtchn_interface.h>
 
 // This should be in public/io/netif.h
 #define _NETRXF_gso_prefix     (4)
@@ -50,8 +51,8 @@
 #include "checksum.h"
 #include "parse.h"
 #include "granter.h"
-#include "notifier.h"
 #include "mac.h"
+#include "transmitter.h"
 #include "vif.h"
 #include "receiver.h"
 #include "thread.h"
@@ -82,10 +83,16 @@ typedef struct _XENVIF_RECEIVER_RING {
     netif_rx_front_ring_t       Front;
     netif_rx_sring_t            *Shared;
     XENVIF_GRANTER_HANDLE       Handle;
+    PXENBUS_EVTCHN_CHANNEL      Channel;
+    KDPC                        Dpc;
+    ULONG                       Dpcs;
+    ULONG                       Events;
+    KSPIN_LOCK                  EvtchnLock;
     PXENVIF_RECEIVER_FRAGMENT   Pending[XENVIF_RECEIVER_MAXIMUM_FRAGMENT_ID + 1];
     ULONG                       RequestsPosted;
     ULONG                       RequestsPushed;
     ULONG                       ResponsesProcessed;
+    BOOLEAN                     Connected;
     BOOLEAN                     Enabled;
     BOOLEAN                     Stopped;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
@@ -97,7 +104,9 @@ typedef struct _XENVIF_RECEIVER_RING {
 struct _XENVIF_RECEIVER {
     PXENVIF_FRONTEND        Frontend;
     XENBUS_CACHE_INTERFACE  CacheInterface;
+    XENBUS_EVTCHN_INTERFACE EvtchnInterface;
     PXENVIF_RECEIVER_RING   Rings[MAXIMUM_PROCESSORS];
+    BOOLEAN                 Split;
     LONG                    Loaned;
     LONG                    Returned;
     KEVENT                  Event;
@@ -1352,6 +1361,46 @@ __ReceiverRingIsStopped(
 }
 
 static FORCEINLINE VOID
+__ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Trigger,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__ReceiverRingSend(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    KIRQL                       Irql;
+    PXENVIF_RECEIVER            Receiver;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected)
+        (VOID) XENBUS_EVTCHN(Send,
+                             &Receiver->EvtchnInterface,
+                             Ring->Channel);
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __ReceiverRingReturnPacket(
     IN  PXENVIF_RECEIVER_RING   Ring,
     IN  PXENVIF_RECEIVER_PACKET Packet,
@@ -1382,15 +1431,8 @@ __ReceiverRingReturnPacket(
             __ReceiverRingAcquireLock(Ring);
 
         if (__ReceiverRingIsStopped(Ring)) {
-            PXENVIF_RECEIVER    Receiver;
-            PXENVIF_FRONTEND    Frontend;
-
             __ReceiverRingStart(Ring);
-
-            Receiver = Ring->Receiver;
-            Frontend = Receiver->Frontend;
-
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            __ReceiverRingTrigger(Ring);
         }
 
         if (!Locked)
@@ -1464,13 +1506,7 @@ __ReceiverRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_RECEIVER    Receiver;
-        PXENVIF_FRONTEND    Frontend;
-
-        Receiver = Ring->Receiver;
-        Frontend = Receiver->Frontend;
-
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        __ReceiverRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1599,8 +1635,9 @@ ReceiverRingDebugCallback(
 
     XENBUS_DEBUG(Printf,
                  &Receiver->DebugInterface,
-                 "0x%p [%s][%s]\n",
+                 "0x%p [%u] [%s][%s]\n",
                  Ring,
+                 Ring->Index,
                  (Ring->Enabled) ? "ENABLED" : "DISABLED",
                  (__ReceiverRingIsStopped(Ring)) ? "STOPPED" : "RUNNING");
 
@@ -1628,6 +1665,14 @@ ReceiverRingDebugCallback(
                  Ring->RequestsPosted,
                  Ring->RequestsPushed,
                  Ring->ResponsesProcessed);
+
+    // Dump event channel
+    XENBUS_DEBUG(Printf,
+                 &Receiver->DebugInterface,
+                 "[%s]: Events = %lu Dpcs = %lu\n",
+                 Receiver->Split ? "RX" : "COMBINED",
+                 Ring->Events,
+                 Ring->Dpcs);
 }
 
 static DECLSPEC_NOINLINE VOID
@@ -1801,6 +1846,104 @@ ReceiverRingPoll(
 #undef  XENVIF_RECEIVER_BATCH
 }
 
+static FORCEINLINE VOID
+__ReceiverRingNotify(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    __ReceiverRingAcquireLock(Ring);
+    ReceiverRingPoll(Ring);
+    __ReceiverRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__ReceiverRingUnmask(
+    IN  PXENVIF_RECEIVER_RING   Ring
+    )
+{
+    PXENVIF_RECEIVER            Receiver;
+    BOOLEAN                     Pending;
+
+    Receiver = Ring->Receiver;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+ReceiverRingDpc(
+    IN  PKDPC               Dpc,
+    IN  PVOID               Context,
+    IN  PVOID               Argument1,
+    IN  PVOID               Argument2
+    )
+{
+    PXENVIF_RECEIVER_RING   Ring = Context;
+    PXENVIF_RECEIVER        Receiver;
+    PXENVIF_FRONTEND        Frontend;
+    BOOLEAN                 Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Receiver = Ring->Receiver;
+    Frontend = Receiver->Frontend;
+
+    do {
+        if (Ring->Enabled) {
+            if (Receiver->Split) {
+                __ReceiverRingNotify(Ring);
+            } else {
+                TransmitterRingNotify(FrontendGetTransmitter(Frontend),
+                                      Ring->Index);
+                __ReceiverRingNotify(Ring);
+            }
+        }
+
+        Pending = __ReceiverRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    ReceiverRingEvtchnCallback;
+
+BOOLEAN
+ReceiverRingEvtchnCallback(
+    IN  PKINTERRUPT             InterruptObject,
+    IN  PVOID                   Argument
+    )
+{
+    PXENVIF_RECEIVER_RING       Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -1851,10 +1994,8 @@ ReceiverRingWatchdog(
             if (Ring->Shared->rsp_prod != rsp_prod &&
                 Ring->Front.rsp_cons == rsp_cons) {
                 PXENVIF_RECEIVER    Receiver;
-                PXENVIF_FRONTEND    Frontend;
 
                 Receiver = Ring->Receiver;
-                Frontend = Receiver->Frontend;
 
                 XENBUS_DEBUG(Trigger,
                              &Receiver->DebugInterface,
@@ -1862,7 +2003,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                __ReceiverRingSend(Ring);
             }
 
             KeMemoryBarrier();
@@ -1905,6 +2046,9 @@ __ReceiverRingInitialize(
     (*Ring)->Index = Index;
 
     InitializeListHead(&(*Ring)->PacketList);
+
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, ReceiverRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -1989,6 +2133,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
     (*Ring)->Index = 0;
@@ -2014,6 +2161,7 @@ __ReceiverRingConnect(
     PXENVIF_RECEIVER            Receiver;
     PXENVIF_FRONTEND            Frontend;
     PFN_NUMBER                  Pfn;
+    BOOLEAN                     Pending;
     CHAR                        Name[MAXNAMELEN];
     NTSTATUS                    status;
 
@@ -2049,6 +2197,38 @@ __ReceiverRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    ASSERT(!Ring->Connected);
+
+    Ring->Channel = XENBUS_EVTCHN(Open,
+                                  &Receiver->EvtchnInterface,
+                                  XENBUS_EVTCHN_TYPE_UNBOUND,
+                                  ReceiverRingEvtchnCallback,
+                                  Ring,
+                                  FrontendGetBackendDomain(Frontend),
+                                  TRUE);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Ring->Channel == NULL) {
+        KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+        goto fail4;
+    }
+
+    Pending = XENBUS_EVTCHN(Unmask,
+                            &Receiver->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE);
+
+    if (Pending)
+        XENBUS_EVTCHN(Trigger,
+                     &Receiver->EvtchnInterface,
+                     Ring->Channel);
+
+    Ring->Connected = TRUE;
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     status = XENBUS_DEBUG(Register,
                           &Receiver->DebugInterface,
                           Name,
@@ -2056,10 +2236,22 @@ __ReceiverRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2094,6 +2286,7 @@ __ReceiverRingStoreWrite(
 {
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -2111,8 +2304,25 @@ __ReceiverRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Receiver->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Receiver->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          Receiver->Split ? "event-channel-rx" : "event-channel",
+                          "%u",
+                          Port);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -2143,6 +2353,9 @@ __ReceiverRingEnable(
 
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __ReceiverRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2183,6 +2396,20 @@ __ReceiverRingDisconnect(
 
     __ReceiverRingEmpty(Ring);
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    ASSERT(Ring->Connected);
+    Ring->Connected = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Receiver->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -2216,6 +2443,10 @@ __ReceiverRingTeardown(
 
     Receiver = Ring->Receiver;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     Ring->OffloadOptions.Value = 0;
 
     ThreadAlert(Ring->WatchdogThread);
@@ -2245,16 +2476,6 @@ __ReceiverRingTeardown(
 }
 
 static FORCEINLINE VOID
-__ReceiverRingNotify(
-    IN  PXENVIF_RECEIVER_RING   Ring
-    )
-{
-    __ReceiverRingAcquireLock(Ring);
-    ReceiverRingPoll(Ring);
-    __ReceiverRingReleaseLock(Ring);
-}
-
-static FORCEINLINE VOID
 __ReceiverRingSetOffloadOptions(
     IN  PXENVIF_RECEIVER_RING       Ring,
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
@@ -2313,6 +2534,7 @@ ReceiverInitialize(
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   ReceiverCalculateChecksums;
@@ -2370,6 +2592,9 @@ ReceiverInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Receiver)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Receiver)->EvtchnInterface);
+
     (*Receiver)->Frontend = Frontend;
 
     status = XENBUS_CACHE(Acquire, &(*Receiver)->CacheInterface);
@@ -2411,6 +2636,9 @@ fail2:
 
     (*Receiver)->Frontend = NULL;
 
+    RtlZeroMemory(&(*Receiver)->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     RtlZeroMemory(&(*Receiver)->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
 
@@ -2428,6 +2656,7 @@ fail2:
     (*Receiver)->DisableIpVersion6Gso = 0;
     (*Receiver)->IpAlignOffset = 0;
     (*Receiver)->AlwaysPullup = 0;
+    (*Receiver)->Split = FALSE;
 
     ASSERT(IsZeroMemory(*Receiver, sizeof (XENVIF_RECEIVER)));
     __ReceiverFree(*Receiver);
@@ -2445,6 +2674,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    PCHAR                   Buffer;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
@@ -2457,6 +2687,26 @@ ReceiverConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Receiver->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Receiver->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Receiver->Split = FALSE;
+    } else {
+        Receiver->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Receiver->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2466,7 +2716,7 @@ ReceiverConnect(
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -2476,16 +2726,16 @@ ReceiverConnect(
                           Receiver,
                           &Receiver->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
@@ -2496,6 +2746,11 @@ fail3:
         __ReceiverRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
 fail2:
@@ -2747,6 +3002,8 @@ ReceiverDisconnect(
 
     Frontend = Receiver->Frontend;
 
+    Receiver->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Receiver->DebugInterface,
                  Receiver->DebugCallback);
@@ -2765,6 +3022,8 @@ ReceiverDisconnect(
     XENBUS_STORE(Release, &Receiver->StoreInterface);
 
     XENBUS_DEBUG(Release, &Receiver->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Receiver->EvtchnInterface);
 }
 
 VOID
@@ -2774,6 +3033,9 @@ ReceiverTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     ASSERT3U(Receiver->Returned, ==, Receiver->Loaned);
     Receiver->Loaned = 0;
     Receiver->Returned = 0;
@@ -2793,6 +3055,10 @@ ReceiverTeardown(
     XENBUS_CACHE(Release, &Receiver->CacheInterface);
 
     Receiver->Frontend = NULL;
+    Receiver->Split = FALSE;
+
+    RtlZeroMemory(&Receiver->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
 
     RtlZeroMemory(&Receiver->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -2921,19 +3187,37 @@ ReceiverWaitForPackets(
 }
 
 VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_RECEIVER_RING   Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_RECEIVER_RING   Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Receiver->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __ReceiverRingNotify(Ring);
-    }    
+    __ReceiverRingTrigger(Ring);
+}
+
+VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    )
+{
+    PXENVIF_RECEIVER_RING   Ring;
+
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
+
+    Ring = Receiver->Rings[Index];
+    if (Ring == NULL)
+        return;
+
+    __ReceiverRingSend(Ring);
 }
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 0497c5b..f926500 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,11 +79,6 @@ ReceiverTeardown(
     );
 
 extern VOID
-ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
-    );
-
-extern VOID
 ReceiverWaitForPackets(
     IN  PXENVIF_RECEIVER    Receiver
     );
@@ -106,4 +101,16 @@ ReceiverReturnPackets(
     IN  PLIST_ENTRY         List
     );
 
+extern VOID
+ReceiverRingTrigger(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
+extern VOID
+ReceiverRingSend(
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
+    );
+
 #endif  // _XENVIF_RECEIVER_H
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 645872b..e482392 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -40,6 +40,7 @@
 #include <cache_interface.h>
 #include <gnttab_interface.h>
 #include <range_set_interface.h>
+#include <evtchn_interface.h>
 
 #include "ethernet.h"
 #include "tcpip.h"
@@ -114,6 +115,11 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     netif_tx_front_ring_t           Front;
     netif_tx_sring_t                *Shared;
     XENVIF_GRANTER_HANDLE           Handle;
+    PXENBUS_EVTCHN_CHANNEL          Channel;
+    KDPC                            Dpc;
+    ULONG                           Dpcs;
+    ULONG                           Events;
+    KSPIN_LOCK                      EvtchnLock;
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
@@ -145,8 +151,10 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
+    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
     PXENVIF_TRANSMITTER_RING    Rings[MAXIMUM_PROCESSORS];
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
+    BOOLEAN                     Split;
     ULONG                       DisableIpVersion4Gso;
     ULONG                       DisableIpVersion6Gso;
     ULONG                       AlwaysCopy;
@@ -2127,6 +2135,72 @@ TransmitterRingPoll(
 }
 
 static FORCEINLINE VOID
+__TransmitterRingTrigger(
+    IN  PXENVIF_TRANSMITTER_RING   Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Trigger,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingTrigger(FrontendGetReceiver(Frontend),
+                                Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
+__TransmitterRingSend(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    KIRQL                           Irql;
+    PXENVIF_TRANSMITTER             Transmitter;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLock(&Ring->EvtchnLock, &Irql);
+
+    if (Ring->Connected) {
+        if (Transmitter->Split) {
+            ASSERT(Ring->Channel != NULL);
+
+            (VOID) XENBUS_EVTCHN(Send,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel);
+        } else {
+            PXENVIF_FRONTEND        Frontend;
+
+            ASSERT(Ring->Channel == NULL);
+            Frontend = Transmitter->Frontend;
+
+            ReceiverRingSend(FrontendGetReceiver(Frontend),
+                             Ring->Index);
+        }
+    }
+
+    KeReleaseSpinLock(&Ring->EvtchnLock, Irql);
+}
+
+static FORCEINLINE VOID
 __TransmitterRingPushRequests(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
@@ -2145,13 +2219,7 @@ __TransmitterRingPushRequests(
 #pragma warning (pop)
 
     if (Notify) {
-        PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
-
-        Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
-
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        __TransmitterRingSend(Ring);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2475,6 +2543,97 @@ TransmitterRingReleaseLock(
     __TransmitterRingReleaseLock(Ring);
 }
 
+static FORCEINLINE VOID
+__TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    __TransmitterRingAcquireLock(Ring);
+    TransmitterRingPoll(Ring);
+    __TransmitterRingReleaseLock(Ring);
+}
+
+static FORCEINLINE BOOLEAN
+__TransmitterRingUnmask(
+    IN  PXENVIF_TRANSMITTER_RING    Ring
+    )
+{
+    PXENVIF_TRANSMITTER             Transmitter;
+    BOOLEAN                         Pending;
+
+    Transmitter = Ring->Transmitter;
+
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Pending = (Ring->Connected) ?
+              XENBUS_EVTCHN(Unmask,
+                            &Transmitter->EvtchnInterface,
+                            Ring->Channel,
+                            FALSE) :
+              FALSE;
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+    return Pending;
+}
+
+__drv_functionClass(KDEFERRED_ROUTINE)
+__drv_maxIRQL(DISPATCH_LEVEL)
+__drv_minIRQL(DISPATCH_LEVEL)
+__drv_requiresIRQL(DISPATCH_LEVEL)
+__drv_sameIRQL
+static VOID
+TransmitterRingDpc(
+    IN  PKDPC                   Dpc,
+    IN  PVOID                   Context,
+    IN  PVOID                   Argument1,
+    IN  PVOID                   Argument2
+    )
+{
+    PXENVIF_TRANSMITTER_RING    Ring = Context;
+    PXENVIF_TRANSMITTER         Transmitter;
+    BOOLEAN                     Pending;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Ring != NULL);
+
+    Transmitter = Ring->Transmitter;
+
+    do {
+        if (Ring->Enabled) {
+            ASSERT(Transmitter->Split);
+            __TransmitterRingNotify(Ring);
+        }
+
+        Pending = __TransmitterRingUnmask(Ring);
+    } while (Pending);
+}
+
+KSERVICE_ROUTINE    TransmitterRingEvtchnCallback;
+
+BOOLEAN
+TransmitterRingEvtchnCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
+    )
+{
+    PXENVIF_TRANSMITTER_RING    Ring = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Ring != NULL);
+
+    Ring->Events++;
+
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
+    return TRUE;
+}
+
 #define TIME_US(_us)        ((_us) * 10)
 #define TIME_MS(_ms)        (TIME_US((_ms) * 1000))
 #define TIME_S(_s)          (TIME_MS((_s) * 1000))
@@ -2520,17 +2679,15 @@ TransmitterRingWatchdog(
             if (Ring->PacketsQueued == PacketsQueued &&
                 Ring->PacketsCompleted != PacketsQueued) {
                 PXENVIF_TRANSMITTER Transmitter;
-                PXENVIF_FRONTEND    Frontend;
 
                 Transmitter = Ring->Transmitter;
-                Frontend = Transmitter->Frontend;
 
                 XENBUS_DEBUG(Trigger,
                              &Transmitter->DebugInterface,
                              Ring->DebugCallback);
 
                 // Try to move things along
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                __TransmitterRingSend(Ring);
                 TransmitterRingPoll(Ring);
             }
 
@@ -2625,6 +2782,8 @@ __TransmitterRingInitialize(
     (*Ring)->Index = Index;
     (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
     (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    KeInitializeSpinLock(&(*Ring)->EvtchnLock);
+    KeInitializeDpc(&(*Ring)->Dpc, TransmitterRingDpc, *Ring);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -2755,6 +2914,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
+
     (*Ring)->Queued.TailPacket = NULL;
     (*Ring)->Completed.TailPacket = NULL;
     (*Ring)->Index = 0;
@@ -2778,6 +2940,7 @@ __TransmitterRingConnect(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PFN_NUMBER                      Pfn;
+    BOOLEAN                         Pending;
     CHAR                            Name[MAXNAMELEN];
     NTSTATUS                        status;
 
@@ -2815,6 +2978,38 @@ __TransmitterRingConnect(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    if (Transmitter->Split) {
+        Ring->Channel = XENBUS_EVTCHN(Open,
+                                      &Transmitter->EvtchnInterface,
+                                      XENBUS_EVTCHN_TYPE_UNBOUND,
+                                      TransmitterRingEvtchnCallback,
+                                      Ring,
+                                      FrontendGetBackendDomain(Frontend),
+                                      TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Ring->Channel == NULL) {
+            KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+            goto fail4;
+        }
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Transmitter->EvtchnInterface,
+                                Ring->Channel,
+                                FALSE);
+
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Transmitter->EvtchnInterface,
+                          Ring->Channel);
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
+
     status = XENBUS_DEBUG(Register,
                           &Transmitter->DebugInterface,
                           Name,
@@ -2822,12 +3017,22 @@ __TransmitterRingConnect(
                           Ring,
                           &Ring->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     Ring->Connected = TRUE;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_EVTCHN(Close,
+                  &Transmitter->EvtchnInterface,
+                  Ring->Channel);
+    Ring->Channel = NULL;
+
+    Ring->Events = 0;
+
 fail4:
     Error("fail4\n");
 
@@ -2862,6 +3067,7 @@ __TransmitterRingStoreWrite(
 {
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
+    ULONG                           Port;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -2879,8 +3085,29 @@ __TransmitterRingStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    if (!Transmitter->Split)
+        goto done;
+
+    Port = XENBUS_EVTCHN(GetPort,
+                         &Transmitter->EvtchnInterface,
+                         Ring->Channel);
+
+    status = XENBUS_STORE(Printf,
+                          &Transmitter->StoreInterface,
+                          Transaction,
+                          FrontendGetPath(Frontend),
+                          "event-channel-tx",
+                          "%u",
+                          Port);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+done:
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -2897,6 +3124,9 @@ __TransmitterRingEnable(
     ASSERT(!Ring->Enabled);
     Ring->Enabled = TRUE;
 
+    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
+        Ring->Dpcs++;
+
     __TransmitterRingReleaseLock(Ring);
 
     return STATUS_SUCCESS;
@@ -2992,6 +3222,21 @@ __TransmitterRingDisconnect(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    KeAcquireSpinLockAtDpcLevel(&Ring->EvtchnLock);
+
+    Transmitter->Split = FALSE;
+
+    if (Ring->Channel != NULL) {
+        XENBUS_EVTCHN(Close,
+                      &Transmitter->EvtchnInterface,
+                      Ring->Channel);
+        Ring->Channel = NULL;
+
+        Ring->Events = 0;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&Ring->EvtchnLock);
+
     ASSERT3U(Ring->ResponsesProcessed, ==, Ring->RequestsPushed);
     ASSERT3U(Ring->RequestsPushed, ==, Ring->RequestsPosted);
 
@@ -3028,6 +3273,10 @@ __TransmitterRingTeardown(
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Ring->Dpcs = 0;
+    RtlZeroMemory(&Ring->Dpc, sizeof (KDPC));
+    RtlZeroMemory(&Ring->EvtchnLock, sizeof (KSPIN_LOCK));
+
     ASSERT3U(Ring->PacketsCompleted, ==, Ring->PacketsSent);
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
     ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
@@ -3164,16 +3413,6 @@ __TransmitterRingAbortPackets(
     __TransmitterRingReleaseLock(Ring);
 }
 
-static FORCEINLINE VOID
-__TransmitterRingNotify(
-    IN  PXENVIF_TRANSMITTER_RING    Ring
-    )
-{
-    __TransmitterRingAcquireLock(Ring);
-    TransmitterRingPoll(Ring);
-    __TransmitterRingReleaseLock(Ring);
-}
-
 static VOID
 TransmitterDebugCallback(
     IN  PVOID           Argument,
@@ -3214,6 +3453,7 @@ TransmitterInitialize(
     (*Transmitter)->DisableIpVersion4Gso = 0;
     (*Transmitter)->DisableIpVersion6Gso = 0;
     (*Transmitter)->AlwaysCopy = 0;
+    (*Transmitter)->Split = FALSE;
 
     if (ParametersKey != NULL) {
         ULONG   TransmitterDisableIpVersion4Gso;
@@ -3251,6 +3491,9 @@ TransmitterInitialize(
     FdoGetCacheInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
                          &(*Transmitter)->CacheInterface);
 
+    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
+                          &(*Transmitter)->EvtchnInterface);
+
     (*Transmitter)->Frontend = Frontend;
 
     status = XENBUS_RANGE_SET(Acquire, &(*Transmitter)->RangeSetInterface);
@@ -3332,6 +3575,7 @@ TransmitterConnect(
     )
 {
     PXENVIF_FRONTEND            Frontend;
+    PCHAR                       Buffer;
     ULONG                       Index;
     NTSTATUS                    status;
 
@@ -3345,6 +3589,26 @@ TransmitterConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_EVTCHN(Acquire, &Transmitter->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &Transmitter->StoreInterface,
+                          NULL,
+                          FrontendGetBackendPath(Frontend),
+                          "feature-split-event-channels",
+                          &Buffer);
+    if (!NT_SUCCESS(status)) {
+        Transmitter->Split = FALSE;
+    } else {
+        Transmitter->Split = (BOOLEAN)strtol(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Transmitter->StoreInterface,
+                     Buffer);
+    }
+
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3354,7 +3618,7 @@ TransmitterConnect(
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail4;
     }    
 
     status = XENBUS_DEBUG(Register,
@@ -3364,16 +3628,16 @@ TransmitterConnect(
                           Transmitter,
                           &Transmitter->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
 fail4:
     Error("fail4\n");
 
-fail3:
-    Error("fail3\n");
-
     for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
@@ -3384,6 +3648,11 @@ fail3:
         __TransmitterRingDisconnect(Ring);
     }
 
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
+
+fail3:
+    Error("fail3\n");
+
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
 fail2:
@@ -3474,6 +3743,8 @@ TransmitterDisconnect(
 
     Frontend = Transmitter->Frontend;
 
+    Transmitter->Split = FALSE;
+
     XENBUS_DEBUG(Deregister,
                  &Transmitter->DebugInterface,
                  Transmitter->DebugCallback);
@@ -3492,6 +3763,8 @@ TransmitterDisconnect(
     XENBUS_STORE(Release, &Transmitter->StoreInterface);
 
     XENBUS_DEBUG(Release, &Transmitter->DebugInterface);
+
+    XENBUS_EVTCHN(Release, &Transmitter->EvtchnInterface);
 }
 
 VOID
@@ -3501,6 +3774,9 @@ TransmitterTeardown(
 {
     ULONG                   Index;
 
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
     RtlZeroMemory(Transmitter->Offset,
                   sizeof (LONG_PTR) *  XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT); 
 
@@ -3521,6 +3797,7 @@ TransmitterTeardown(
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
 
     Transmitter->Frontend = NULL;
+    Transmitter->Split = FALSE;
 
     RtlZeroMemory(&Transmitter->CacheInterface,
                   sizeof (XENBUS_CACHE_INTERFACE));
@@ -3534,6 +3811,9 @@ TransmitterTeardown(
     RtlZeroMemory(&Transmitter->DebugInterface,
                   sizeof (XENBUS_DEBUG_INTERFACE));
 
+    RtlZeroMemory(&Transmitter->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
     Transmitter->DisableIpVersion4Gso = 0;
     Transmitter->DisableIpVersion6Gso = 0;
     Transmitter->AlwaysCopy = 0;
@@ -3652,21 +3932,21 @@ TransmitterQueryRingSize(
 }
 
 VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
-    ULONG                   Index;
+    PXENVIF_TRANSMITTER_RING    Ring;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
-        PXENVIF_TRANSMITTER_RING    Ring;
+    if (Index >= MAXIMUM_PROCESSORS)
+        return;
 
-        Ring = Transmitter->Rings[Index];
-        if (Ring == NULL)
-            break;
+    Ring = Transmitter->Rings[Index];
+    if (Ring == NULL)
+        return;
 
-        __TransmitterRingNotify(Ring);
-    }    
+    __TransmitterRingNotify(Ring);
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 5ffb590..9c3bfaa 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,8 +79,9 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+TransmitterRingNotify(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/vs2012/xenvif/xenvif.vcxproj b/vs2012/xenvif/xenvif.vcxproj
index a86acff..edd71ea 100644
--- a/vs2012/xenvif/xenvif.vcxproj
+++ b/vs2012/xenvif/xenvif.vcxproj
@@ -96,7 +96,6 @@
 		<ClCompile Include="../../src/xenvif/granter.c" />
 		<ClCompile Include="../../src/xenvif/link.c" />
 		<ClCompile Include="../../src/xenvif/mac.c" />
-		<ClCompile Include="../../src/xenvif/notifier.c" />
 		<ClCompile Include="../../src/xenvif/parse.c" />
 		<ClCompile Include="../../src/xenvif/pdo.c" />
 		<ClCompile Include="../../src/xenvif/receiver.c" />
diff --git a/vs2013/xenvif/xenvif.vcxproj b/vs2013/xenvif/xenvif.vcxproj
index 69cf86a..32a3033 100644
--- a/vs2013/xenvif/xenvif.vcxproj
+++ b/vs2013/xenvif/xenvif.vcxproj
@@ -127,7 +127,6 @@
     <ClCompile Include="../../src/xenvif/granter.c" />
     <ClCompile Include="../../src/xenvif/link.c" />
     <ClCompile Include="../../src/xenvif/mac.c" />
-    <ClCompile Include="../../src/xenvif/notifier.c" />
     <ClCompile Include="../../src/xenvif/parse.c" />
     <ClCompile Include="../../src/xenvif/pdo.c" />
     <ClCompile Include="../../src/xenvif/receiver.c" />
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:38 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4E-0002Eb-J0; Thu, 18 Dec 2014 14:28:38 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4D-0002Ci-Ab
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:37 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	DE/15-22819-494E2945; Thu, 18 Dec 2014 14:28:36 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!3
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15915 invoked from network); 18 Dec 2014 14:28:35 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268744"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:24 +0000
Message-ID: <1418912904-8756-8-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 7/7] Implement multiple queues
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/driver.c      |  42 ++++++++++
 src/xenvif/driver.h      |   5 ++
 src/xenvif/frontend.c    | 114 ++++++++++++++++++++++++++-
 src/xenvif/frontend.h    |  11 +++
 src/xenvif/receiver.c    | 117 +++++++++++++++++++++-------
 src/xenvif/receiver.h    |   1 -
 src/xenvif/transmitter.c | 198 ++++++++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h |   1 -
 8 files changed, 409 insertions(+), 80 deletions(-)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 6f81620..083fa19 100644
--- a/src/xenvif/driver.c
+++ b/src/xenvif/driver.c
@@ -47,6 +47,7 @@ typedef struct _XENVIF_DRIVER {
     PDRIVER_OBJECT      DriverObject;
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
+    ULONG               MaximumQueues;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -123,6 +124,30 @@ DriverGetAddressesKey(
     return __DriverGetAddressesKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetMaximumQueueCount(
+    IN  ULONG   Count
+    )
+{
+    Driver.MaximumQueues = Count;
+}
+
+static FORCEINLINE ULONG
+__DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return Driver.MaximumQueues;
+}
+
+ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return __DriverGetMaximumQueueCount();
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -148,6 +173,8 @@ DriverUnload(
     ParametersKey = __DriverGetParametersKey();
     __DriverSetParametersKey(NULL);
 
+    __DriverSetMaximumQueueCount(0);
+
     RegistryCloseKey(ParametersKey);
 
     RegistryTeardown();
@@ -254,6 +281,8 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
+    ULONG               MaxQueues;
+    ULONG               Processors;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
@@ -295,6 +324,8 @@ DriverEntry(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    __DriverSetParametersKey(ParametersKey);
+
     status = RegistryCreateSubKey(ServiceKey, 
                                   "Addresses", 
                                   REG_OPTION_VOLATILE, 
@@ -304,6 +335,17 @@ DriverEntry(
 
     __DriverSetAddressesKey(AddressesKey);
 
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "MultiQueueMaxQueues",
+                                     &MaxQueues);
+    if (!NT_SUCCESS(status))
+        MaxQueues = MAXIMUM_PROCESSORS;
+
+    Processors = KeQueryActiveProcessorCount(NULL);
+    __DriverSetMaximumQueueCount(MaxQueues > Processors ?
+                                        Processors :
+                                        MaxQueues);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index cdef7d1..bbea23b 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,6 +52,11 @@ DriverGetAliasesKey(
     VOID
     );
 
+extern ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    );
+
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 268bab9..cfe6220 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -63,6 +63,7 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
+    ULONG                       QueueCount;
 
     PXENVIF_GRANTER             Granter;
     PXENVIF_MAC                 Mac;
@@ -201,6 +202,67 @@ FrontendGetBackendDomain(
     return __FrontendGetBackendDomain(Frontend);
 }
 
+static FORCEINLINE VOID
+__FrontendSetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Count
+    )
+{
+    Frontend->QueueCount = Count;
+}
+
+static FORCEINLINE ULONG
+__FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->QueueCount;
+}
+
+ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetQueueCount(Frontend);
+}
+
+PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    )
+{
+    ULONG                   Length;
+    PCHAR                   Path;
+    NTSTATUS                status;
+
+    Length = (ULONG)strlen(FrontendGetPath(Frontend)) +
+             (ULONG)strlen("/queue-00") +
+             1;
+
+    Path = ExAllocatePoolWithTag(NonPagedPool,
+                                 Length * sizeof(CHAR),
+                                 'HTAP');
+    if (Path == NULL)
+        goto fail1;
+
+    status = RtlStringCchPrintfA(Path,
+                                 Length,
+                                 "%s/queue-%u",
+                                 FrontendGetPath(Frontend),
+                                 Index);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return Path;
+
+fail2:
+    ExFreePoolWithTag(Path, 'HTAP');
+fail1:
+    return NULL;
+}
+
 #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
 static FORCEINLINE _Type                                \
 __FrontendGet ## _Function(                             \
@@ -1274,6 +1336,42 @@ FrontendDebugCallback(
     }
 }
 
+static FORCEINLINE VOID
+__FrontendReadQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    PCHAR                   Buffer;
+    ULONG                   Value;
+    NTSTATUS                status;
+
+    // default to 1 queue.
+    // backend must advertise "multi-queue-max-queues" to enable
+    // multi-queue support.
+    Value = 1;
+
+    status = XENBUS_STORE(Read,
+                          &Frontend->StoreInterface,
+                          NULL,
+                          __FrontendGetBackendPath(Frontend),
+                          "multi-queue-max-queues",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Value = (ULONG)strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Frontend->StoreInterface,
+                     Buffer);
+
+        // set value to minimum of what frontend supports (vCPUs) and
+        // what backend supports (Dom0 vCPUs)
+        if (Value > DriverGetMaximumQueueCount())
+            Value = DriverGetMaximumQueueCount();
+    }
+
+    __FrontendSetQueueCount(Frontend, Value);
+}
+
 static FORCEINLINE NTSTATUS
 __FrontendConnect(
     IN  PXENVIF_FRONTEND    Frontend
@@ -1307,6 +1405,7 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    __FrontendReadQueueCount(Frontend);
     status = ReceiverConnect(__FrontendGetReceiver(Frontend));
     if (!NT_SUCCESS(status))
         goto fail5;
@@ -1335,6 +1434,16 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             goto abort;
 
+        status = XENBUS_STORE(Printf,
+                              &Frontend->StoreInterface,
+                              Transaction,
+                              __FrontendGetPath(Frontend),
+                              "multi-queue-num-queues",
+                              "%u",
+                              __FrontendGetQueueCount(Frontend));
+        if (!NT_SUCCESS(status))
+            goto abort;
+
         status = XENBUS_STORE(TransactionEnd,
                               &Frontend->StoreInterface,
                               Transaction,
@@ -1870,11 +1979,11 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
+    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
+    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
         goto fail9;
 
@@ -2021,6 +2130,7 @@ FrontendTeardown(
     RtlZeroMemory(&Frontend->Lock, sizeof (KSPIN_LOCK));
 
     Frontend->BackendDomain = 0;
+    __FrontendSetQueueCount(Frontend, 0);
 
     __FrontendFree(Frontend->Prefix);
     Frontend->Prefix = NULL;
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 67696d6..5d2905d 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -112,6 +112,17 @@ FrontendGetBackendDomain(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
+extern ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
+extern PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    );
+
 #include "granter.h"
 
 extern PXENVIF_GRANTER
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index a11d91e..aad88e2 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -76,6 +76,7 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT {
 typedef struct _XENVIF_RECEIVER_RING {
     PXENVIF_RECEIVER            Receiver;
     ULONG                       Index;
+    PCHAR                       FrontendPath;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
     PXENBUS_CACHE               FragmentCache;
@@ -2045,6 +2046,11 @@ __ReceiverRingInitialize(
     (*Ring)->Receiver = Receiver;
     (*Ring)->Index = Index;
 
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->PacketList);
     
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2052,10 +2058,11 @@ __ReceiverRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_packet",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_packet",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2073,14 +2080,15 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->PacketCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2098,46 +2106,52 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = ThreadCreate(ReceiverRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
-    
-fail4:
-    Error("fail4\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->PacketCache);
     (*Ring)->PacketCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
-    
-fail2:
-    Error("fail2\n");
 
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
 
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Receiver = NULL;
 
@@ -2216,6 +2230,16 @@ __ReceiverRingConnect(
         goto fail4;
     }
 
+    if (FrontendGetQueueCount(Frontend) > 1) {
+        (VOID) XENBUS_EVTCHN(Bind,
+                                &Receiver->EvtchnInterface,
+                                Ring->Channel,
+                                Ring->Index);
+
+        KeSetTargetProcessorDpc(&Ring->Dpc,
+                                (CCHAR)Ring->Index);
+    }
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Receiver->EvtchnInterface,
                             Ring->Channel,
@@ -2287,15 +2311,20 @@ __ReceiverRingStoreWrite(
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
     Frontend = Receiver->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "rx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -2311,7 +2340,7 @@ __ReceiverRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           Receiver->Split ? "event-channel-rx" : "event-channel",
                           "%u",
                           Port);
@@ -2466,6 +2495,9 @@ __ReceiverRingTeardown(
     ASSERT(IsListEmpty(&Ring->PacketList));
     RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Receiver = NULL;
 
@@ -2512,14 +2544,15 @@ ReceiverDebugCallback(
 NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Receiver = __ReceiverAllocate(sizeof (XENVIF_RECEIVER));
 
     status = STATUS_NO_MEMORY;
@@ -2624,7 +2657,7 @@ fail3:
         (*Receiver)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -2674,6 +2707,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -2707,7 +2741,10 @@ ReceiverConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2736,7 +2773,7 @@ fail5:
 fail4:
     Error("fail4\n");
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2856,6 +2893,7 @@ ReceiverStoreWrite(
 {
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Index;
+    ULONG                           Count;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2898,7 +2936,10 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2940,11 +2981,15 @@ ReceiverEnable(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2961,7 +3006,7 @@ ReceiverEnable(
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2980,8 +3025,12 @@ ReceiverDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2999,6 +3048,7 @@ ReceiverDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Receiver->Frontend;
 
@@ -3009,7 +3059,10 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -3047,7 +3100,7 @@ ReceiverTeardown(
         Receiver->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            break;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -3089,6 +3142,7 @@ ReceiverSetOffloadOptions(
     )
 {
     ULONG                           Index;
+    ULONG                           Count;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -3096,7 +3150,10 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index f926500..1990ac1 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_RECEIVER XENVIF_RECEIVER, *PXENVIF_RECEIVER;
 extern NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     );
 
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 914e544..445fa8b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -103,6 +103,7 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
     ULONG                           Index;
+    PCHAR                           FrontendPath;
     PXENBUS_CACHE                   BufferCache;
     PXENBUS_CACHE                   FragmentCache;
     PXENBUS_RANGE_SET               RangeSet;
@@ -2861,6 +2862,12 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
+
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->Queued);
     InitializeListHead(&(*Ring)->Completed);
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2868,10 +2875,11 @@ __TransmitterRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_buffer",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_buffer",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2889,14 +2897,15 @@ __TransmitterRingInitialize(
                           *Ring,
                           &(*Ring)->BufferCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_req_id",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_req_id",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2907,7 +2916,7 @@ __TransmitterRingInitialize(
                               Name,
                               &(*Ring)->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = XENBUS_RANGE_SET(Put,
                               &Transmitter->RangeSetInterface,
@@ -2915,14 +2924,15 @@ __TransmitterRingInitialize(
                               1,
                               XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail8;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2940,66 +2950,73 @@ __TransmitterRingInitialize(
                           (*Ring),
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = ThreadCreate(TransmitterRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail10;
 
     return STATUS_SUCCESS;
 
-fail9:
-    Error("fail9\n");
+fail10:
+    Error("fail10\n");
 
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail9:
+    Error("fail9\n");
+
 fail8:
     Error("fail8\n");
 
-fail7:
-    Error("fail7\n");
-
     (VOID) XENBUS_RANGE_SET(Get,
                             &Transmitter->RangeSetInterface,
                             (*Ring)->RangeSet,
                             1,
                             XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Transmitter->RangeSetInterface,
                      (*Ring)->RangeSet);
     (*Ring)->RangeSet = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
 
-fail4:
-    Error("fail4\n");
-
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->BufferCache);
     (*Ring)->BufferCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
 
-fail2:
-    Error("fail2\n");
-
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
 
     RtlZeroMemory(&(*Ring)->Queued, sizeof (LIST_ENTRY));
     RtlZeroMemory(&(*Ring)->Completed, sizeof (LIST_ENTRY));
+
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -3077,6 +3094,16 @@ __TransmitterRingConnect(
             goto fail4;
         }
 
+        if (FrontendGetQueueCount(Frontend) > 1) {
+            (VOID) XENBUS_EVTCHN(Bind,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel,
+                                 Ring->Index);
+
+            KeSetTargetProcessorDpc(&Ring->Dpc,
+                                    (CCHAR)Ring->Index);
+        }
+
         Pending = XENBUS_EVTCHN(Unmask,
                                 &Transmitter->EvtchnInterface,
                                 Ring->Channel,
@@ -3149,15 +3176,20 @@ __TransmitterRingStoreWrite(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "tx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -3176,7 +3208,7 @@ __TransmitterRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "event-channel-tx",
                           "%u",
                           Port);
@@ -3404,6 +3436,9 @@ __TransmitterRingTeardown(
     ASSERT(IsListEmpty(&Ring->Completed));
     RtlZeroMemory(&Ring->Completed, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Transmitter = NULL;
 
@@ -3498,14 +3533,15 @@ TransmitterDebugCallback(
 NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Transmitter = __TransmitterAllocate(sizeof (XENVIF_TRANSMITTER));
 
     status = STATUS_NO_MEMORY;
@@ -3592,7 +3628,7 @@ fail4:
         (*Transmitter)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -3645,6 +3681,7 @@ TransmitterConnect(
     PXENVIF_FRONTEND            Frontend;
     PCHAR                       Buffer;
     ULONG                       Index;
+    ULONG                       Count;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3691,7 +3728,10 @@ TransmitterConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3725,7 +3765,7 @@ fail5:
 
         Ring = Transmitter->Rings[Index];
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3763,9 +3803,13 @@ TransmitterStoreWrite(
     )
 {
     NTSTATUS                        status;
-    ULONG                   Index;
+    ULONG                           Index;
+    ULONG                           Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3791,8 +3835,12 @@ TransmitterEnable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3811,8 +3859,12 @@ TransmitterDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3830,6 +3882,7 @@ TransmitterDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Transmitter->Frontend;
 
@@ -3840,7 +3893,10 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3882,7 +3938,7 @@ TransmitterTeardown(
         Transmitter->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -4132,20 +4188,66 @@ TransmitterQueuePacketsV1(
 #undef OFFSET_EXISTS
 }
 
+static FORCEINLINE ULONG
+__GetQueue(
+    IN  ULONG       QueueCount,
+    IN  ULONG       HashValue
+    )
+{
+    return HashValue % QueueCount;
+}
+
 VOID
 TransmitterQueuePacketsV2(
     IN  PXENVIF_TRANSMITTER Transmitter,
     IN  PLIST_ENTRY         List
     )
 {
-    PXENVIF_TRANSMITTER_RING        Ring;
+    PXENVIF_TRANSMITTER_RING    Ring;
+    PXENVIF_FRONTEND            Frontend;
+    ULONG                       QueueCount;
 
-    // We need to hash for a ring eventually. Since there is only a
-    // single ring for now, we just use that.
-    Ring = Transmitter->Rings[0];
-    ASSERT3P(Ring, !=, NULL);
+    Frontend = Transmitter->Frontend;
+
+    QueueCount = FrontendGetQueueCount(Frontend);
+
+    if (QueueCount == 1) {
+        Ring = Transmitter->Rings[0];
+        ASSERT3P(Ring, !=, NULL);
 
-    __TransmitterRingQueuePackets(Ring, List);
+        __TransmitterRingQueuePackets(Ring, List);
+    } else {
+        while (!IsListEmpty(List)) {
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+            PLIST_ENTRY                 ListEntry;
+            LIST_ENTRY                  ListHead;
+            ULONG                       Queue;
+
+            InitializeListHead(&ListHead);
+
+            ListEntry = List->Flink;
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+            Queue = __GetQueue(QueueCount, Packet->Value);
+
+            (VOID) RemoveHeadList(List);
+            InsertTailList(&ListHead, ListEntry);
+
+            while (!IsListEmpty(List)) {
+                ListEntry = List->Flink;
+                Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+                if (Queue != __GetQueue(QueueCount, Packet->Value))
+                    break;
+
+                (VOID) RemoveHeadList(List);
+                InsertTailList(&ListHead, ListEntry);
+            }
+
+            Ring = Transmitter->Rings[Queue];
+            ASSERT3P(Ring, !=, NULL);
+
+            __TransmitterRingQueuePackets(Ring, &ListHead);
+        }
+    }
 }
 
 VOID
@@ -4154,11 +4256,15 @@ TransmitterAbortPackets(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
     KIRQL                   Irql;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 2ed2786..666f049 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_TRANSMITTER XENVIF_TRANSMITTER, *PXENVIF_TRANSMITTER;
 extern NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     );
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 14:28:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 14:28:38 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1c4E-0002Eb-J0; Thu, 18 Dec 2014 14:28:38 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1c4D-0002Ci-Ab
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 14:28:37 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	DE/15-22819-494E2945; Thu, 18 Dec 2014 14:28:36 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1418912912!14156026!3
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15915 invoked from network); 18 Dec 2014 14:28:35 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 14:28:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206268744"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 14:28:24 +0000
Message-ID: <1418912904-8756-8-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
References: <1418912904-8756-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 7/7] Implement multiple queues
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/driver.c      |  42 ++++++++++
 src/xenvif/driver.h      |   5 ++
 src/xenvif/frontend.c    | 114 ++++++++++++++++++++++++++-
 src/xenvif/frontend.h    |  11 +++
 src/xenvif/receiver.c    | 117 +++++++++++++++++++++-------
 src/xenvif/receiver.h    |   1 -
 src/xenvif/transmitter.c | 198 ++++++++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h |   1 -
 8 files changed, 409 insertions(+), 80 deletions(-)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 6f81620..083fa19 100644
--- a/src/xenvif/driver.c
+++ b/src/xenvif/driver.c
@@ -47,6 +47,7 @@ typedef struct _XENVIF_DRIVER {
     PDRIVER_OBJECT      DriverObject;
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
+    ULONG               MaximumQueues;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -123,6 +124,30 @@ DriverGetAddressesKey(
     return __DriverGetAddressesKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetMaximumQueueCount(
+    IN  ULONG   Count
+    )
+{
+    Driver.MaximumQueues = Count;
+}
+
+static FORCEINLINE ULONG
+__DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return Driver.MaximumQueues;
+}
+
+ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    )
+{
+    return __DriverGetMaximumQueueCount();
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -148,6 +173,8 @@ DriverUnload(
     ParametersKey = __DriverGetParametersKey();
     __DriverSetParametersKey(NULL);
 
+    __DriverSetMaximumQueueCount(0);
+
     RegistryCloseKey(ParametersKey);
 
     RegistryTeardown();
@@ -254,6 +281,8 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
+    ULONG               MaxQueues;
+    ULONG               Processors;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
@@ -295,6 +324,8 @@ DriverEntry(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    __DriverSetParametersKey(ParametersKey);
+
     status = RegistryCreateSubKey(ServiceKey, 
                                   "Addresses", 
                                   REG_OPTION_VOLATILE, 
@@ -304,6 +335,17 @@ DriverEntry(
 
     __DriverSetAddressesKey(AddressesKey);
 
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "MultiQueueMaxQueues",
+                                     &MaxQueues);
+    if (!NT_SUCCESS(status))
+        MaxQueues = MAXIMUM_PROCESSORS;
+
+    Processors = KeQueryActiveProcessorCount(NULL);
+    __DriverSetMaximumQueueCount(MaxQueues > Processors ?
+                                        Processors :
+                                        MaxQueues);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index cdef7d1..bbea23b 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,6 +52,11 @@ DriverGetAliasesKey(
     VOID
     );
 
+extern ULONG
+DriverGetMaximumQueueCount(
+    VOID
+    );
+
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 268bab9..cfe6220 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -63,6 +63,7 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
+    ULONG                       QueueCount;
 
     PXENVIF_GRANTER             Granter;
     PXENVIF_MAC                 Mac;
@@ -201,6 +202,67 @@ FrontendGetBackendDomain(
     return __FrontendGetBackendDomain(Frontend);
 }
 
+static FORCEINLINE VOID
+__FrontendSetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Count
+    )
+{
+    Frontend->QueueCount = Count;
+}
+
+static FORCEINLINE ULONG
+__FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->QueueCount;
+}
+
+ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetQueueCount(Frontend);
+}
+
+PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    )
+{
+    ULONG                   Length;
+    PCHAR                   Path;
+    NTSTATUS                status;
+
+    Length = (ULONG)strlen(FrontendGetPath(Frontend)) +
+             (ULONG)strlen("/queue-00") +
+             1;
+
+    Path = ExAllocatePoolWithTag(NonPagedPool,
+                                 Length * sizeof(CHAR),
+                                 'HTAP');
+    if (Path == NULL)
+        goto fail1;
+
+    status = RtlStringCchPrintfA(Path,
+                                 Length,
+                                 "%s/queue-%u",
+                                 FrontendGetPath(Frontend),
+                                 Index);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return Path;
+
+fail2:
+    ExFreePoolWithTag(Path, 'HTAP');
+fail1:
+    return NULL;
+}
+
 #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
 static FORCEINLINE _Type                                \
 __FrontendGet ## _Function(                             \
@@ -1274,6 +1336,42 @@ FrontendDebugCallback(
     }
 }
 
+static FORCEINLINE VOID
+__FrontendReadQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    PCHAR                   Buffer;
+    ULONG                   Value;
+    NTSTATUS                status;
+
+    // default to 1 queue.
+    // backend must advertise "multi-queue-max-queues" to enable
+    // multi-queue support.
+    Value = 1;
+
+    status = XENBUS_STORE(Read,
+                          &Frontend->StoreInterface,
+                          NULL,
+                          __FrontendGetBackendPath(Frontend),
+                          "multi-queue-max-queues",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Value = (ULONG)strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Frontend->StoreInterface,
+                     Buffer);
+
+        // set value to minimum of what frontend supports (vCPUs) and
+        // what backend supports (Dom0 vCPUs)
+        if (Value > DriverGetMaximumQueueCount())
+            Value = DriverGetMaximumQueueCount();
+    }
+
+    __FrontendSetQueueCount(Frontend, Value);
+}
+
 static FORCEINLINE NTSTATUS
 __FrontendConnect(
     IN  PXENVIF_FRONTEND    Frontend
@@ -1307,6 +1405,7 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    __FrontendReadQueueCount(Frontend);
     status = ReceiverConnect(__FrontendGetReceiver(Frontend));
     if (!NT_SUCCESS(status))
         goto fail5;
@@ -1335,6 +1434,16 @@ __FrontendConnect(
         if (!NT_SUCCESS(status))
             goto abort;
 
+        status = XENBUS_STORE(Printf,
+                              &Frontend->StoreInterface,
+                              Transaction,
+                              __FrontendGetPath(Frontend),
+                              "multi-queue-num-queues",
+                              "%u",
+                              __FrontendGetQueueCount(Frontend));
+        if (!NT_SUCCESS(status))
+            goto abort;
+
         status = XENBUS_STORE(TransactionEnd,
                               &Frontend->StoreInterface,
                               Transaction,
@@ -1870,11 +1979,11 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
+    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
+    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
         goto fail9;
 
@@ -2021,6 +2130,7 @@ FrontendTeardown(
     RtlZeroMemory(&Frontend->Lock, sizeof (KSPIN_LOCK));
 
     Frontend->BackendDomain = 0;
+    __FrontendSetQueueCount(Frontend, 0);
 
     __FrontendFree(Frontend->Prefix);
     Frontend->Prefix = NULL;
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 67696d6..5d2905d 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -112,6 +112,17 @@ FrontendGetBackendDomain(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
+extern ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
+extern PCHAR
+FrontendFormatPath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index
+    );
+
 #include "granter.h"
 
 extern PXENVIF_GRANTER
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index a11d91e..aad88e2 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -76,6 +76,7 @@ typedef struct _XENVIF_RECEIVER_FRAGMENT {
 typedef struct _XENVIF_RECEIVER_RING {
     PXENVIF_RECEIVER            Receiver;
     ULONG                       Index;
+    PCHAR                       FrontendPath;
     KSPIN_LOCK                  Lock;
     PXENBUS_CACHE               PacketCache;
     PXENBUS_CACHE               FragmentCache;
@@ -2045,6 +2046,11 @@ __ReceiverRingInitialize(
     (*Ring)->Receiver = Receiver;
     (*Ring)->Index = Index;
 
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->PacketList);
     
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2052,10 +2058,11 @@ __ReceiverRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_packet",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_packet",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2073,14 +2080,15 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->PacketCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_receiver_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_receiver_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2098,46 +2106,52 @@ __ReceiverRingInitialize(
                           *Ring,
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = ThreadCreate(ReceiverRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
-    
-fail4:
-    Error("fail4\n");
 
     XENBUS_CACHE(Destroy,
                  &Receiver->CacheInterface,
                  (*Ring)->PacketCache);
     (*Ring)->PacketCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
-    
-fail2:
-    Error("fail2\n");
 
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
 
     RtlZeroMemory(&(*Ring)->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Receiver = NULL;
 
@@ -2216,6 +2230,16 @@ __ReceiverRingConnect(
         goto fail4;
     }
 
+    if (FrontendGetQueueCount(Frontend) > 1) {
+        (VOID) XENBUS_EVTCHN(Bind,
+                                &Receiver->EvtchnInterface,
+                                Ring->Channel,
+                                Ring->Index);
+
+        KeSetTargetProcessorDpc(&Ring->Dpc,
+                                (CCHAR)Ring->Index);
+    }
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Receiver->EvtchnInterface,
                             Ring->Channel,
@@ -2287,15 +2311,20 @@ __ReceiverRingStoreWrite(
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
     Frontend = Receiver->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "rx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -2311,7 +2340,7 @@ __ReceiverRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           Receiver->Split ? "event-channel-rx" : "event-channel",
                           "%u",
                           Port);
@@ -2466,6 +2495,9 @@ __ReceiverRingTeardown(
     ASSERT(IsListEmpty(&Ring->PacketList));
     RtlZeroMemory(&Ring->PacketList, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Receiver = NULL;
 
@@ -2512,14 +2544,15 @@ ReceiverDebugCallback(
 NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Receiver = __ReceiverAllocate(sizeof (XENVIF_RECEIVER));
 
     status = STATUS_NO_MEMORY;
@@ -2624,7 +2657,7 @@ fail3:
         (*Receiver)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -2674,6 +2707,7 @@ ReceiverConnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -2707,7 +2741,10 @@ ReceiverConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2736,7 +2773,7 @@ fail5:
 fail4:
     Error("fail4\n");
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2856,6 +2893,7 @@ ReceiverStoreWrite(
 {
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Index;
+    ULONG                           Count;
     NTSTATUS                        status;
 
     Frontend = Receiver->Frontend;
@@ -2898,7 +2936,10 @@ ReceiverStoreWrite(
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2940,11 +2981,15 @@ ReceiverEnable(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
     Frontend = Receiver->Frontend;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2961,7 +3006,7 @@ ReceiverEnable(
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2980,8 +3025,12 @@ ReceiverDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -2999,6 +3048,7 @@ ReceiverDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Receiver->Frontend;
 
@@ -3009,7 +3059,10 @@ ReceiverDisconnect(
                  Receiver->DebugCallback);
     Receiver->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
@@ -3047,7 +3100,7 @@ ReceiverTeardown(
         Receiver->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            break;
+            continue; // ensure all rings are destroyed
 
         __ReceiverRingTeardown(Ring);
     }
@@ -3089,6 +3142,7 @@ ReceiverSetOffloadOptions(
     )
 {
     ULONG                           Index;
+    ULONG                           Count;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -3096,7 +3150,10 @@ ReceiverSetOffloadOptions(
         Options.OffloadIpVersion6LargePacket = 0;
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Receiver->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = Receiver->Rings[Index];
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index f926500..1990ac1 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_RECEIVER XENVIF_RECEIVER, *PXENVIF_RECEIVER;
 extern NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     );
 
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 914e544..445fa8b 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -103,6 +103,7 @@ typedef struct _XENVIF_TRANSMITTER_STATE {
 typedef struct _XENVIF_TRANSMITTER_RING {
     PXENVIF_TRANSMITTER             Transmitter;
     ULONG                           Index;
+    PCHAR                           FrontendPath;
     PXENBUS_CACHE                   BufferCache;
     PXENBUS_CACHE                   FragmentCache;
     PXENBUS_RANGE_SET               RangeSet;
@@ -2861,6 +2862,12 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
+
+    (*Ring)->FrontendPath = FrontendFormatPath(Frontend,
+                                               Index);
+    if ((*Ring)->FrontendPath == NULL)
+        goto fail2;
+
     InitializeListHead(&(*Ring)->Queued);
     InitializeListHead(&(*Ring)->Completed);
     KeInitializeSpinLock(&(*Ring)->EvtchnLock);
@@ -2868,10 +2875,11 @@ __TransmitterRingInitialize(
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_buffer",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_buffer",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2889,14 +2897,15 @@ __TransmitterRingInitialize(
                           *Ring,
                           &(*Ring)->BufferCache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_req_id",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_req_id",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2907,7 +2916,7 @@ __TransmitterRingInitialize(
                               Name,
                               &(*Ring)->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     status = XENBUS_RANGE_SET(Put,
                               &Transmitter->RangeSetInterface,
@@ -2915,14 +2924,15 @@ __TransmitterRingInitialize(
                               1,
                               XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail7;
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
-                                "%s_transmitter_fragment",
-                                FrontendGetPath(Frontend));
+                                "%s_%u_transmitter_fragment",
+                                FrontendGetPath(Frontend),
+                                (*Ring)->Index);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail8;
 
     for (Index = 0; Name[Index] != '\0'; Index++)
         if (Name[Index] == '/')
@@ -2940,66 +2950,73 @@ __TransmitterRingInitialize(
                           (*Ring),
                           &(*Ring)->FragmentCache);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = ThreadCreate(TransmitterRingWatchdog,
                           *Ring,
                           &(*Ring)->WatchdogThread);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail10;
 
     return STATUS_SUCCESS;
 
-fail9:
-    Error("fail9\n");
+fail10:
+    Error("fail10\n");
 
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->FragmentCache);
     (*Ring)->FragmentCache = NULL;
 
+fail9:
+    Error("fail9\n");
+
 fail8:
     Error("fail8\n");
 
-fail7:
-    Error("fail7\n");
-
     (VOID) XENBUS_RANGE_SET(Get,
                             &Transmitter->RangeSetInterface,
                             (*Ring)->RangeSet,
                             1,
                             XENVIF_TRANSMITTER_MAXIMUM_FRAGMENT_ID);
 
-fail6:
-    Error("fail6\n");
+fail7:
+    Error("fail7\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Transmitter->RangeSetInterface,
                      (*Ring)->RangeSet);
     (*Ring)->RangeSet = NULL;
 
+fail6:
+    Error("fail6\n");
+
 fail5:
     Error("fail5\n");
 
-fail4:
-    Error("fail4\n");
-
     XENBUS_CACHE(Destroy,
                  &Transmitter->CacheInterface,
                  (*Ring)->BufferCache);
     (*Ring)->BufferCache = NULL;
 
+fail4:
+    Error("fail4\n");
+
 fail3:
     Error("fail3\n");
 
-fail2:
-    Error("fail2\n");
-
     RtlZeroMemory(&(*Ring)->Dpc, sizeof (KDPC));
     RtlZeroMemory(&(*Ring)->EvtchnLock, sizeof (KSPIN_LOCK));
 
     RtlZeroMemory(&(*Ring)->Queued, sizeof (LIST_ENTRY));
     RtlZeroMemory(&(*Ring)->Completed, sizeof (LIST_ENTRY));
+
+    ExFreePool((*Ring)->FrontendPath); // 'HTAP'
+    (*Ring)->FrontendPath = NULL;
+
+fail2:
+    Error("fail2\n");
+
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -3077,6 +3094,16 @@ __TransmitterRingConnect(
             goto fail4;
         }
 
+        if (FrontendGetQueueCount(Frontend) > 1) {
+            (VOID) XENBUS_EVTCHN(Bind,
+                                 &Transmitter->EvtchnInterface,
+                                 Ring->Channel,
+                                 Ring->Index);
+
+            KeSetTargetProcessorDpc(&Ring->Dpc,
+                                    (CCHAR)Ring->Index);
+        }
+
         Pending = XENBUS_EVTCHN(Unmask,
                                 &Transmitter->EvtchnInterface,
                                 Ring->Channel,
@@ -3149,15 +3176,20 @@ __TransmitterRingStoreWrite(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     ULONG                           Port;
+    PCHAR                           Path;
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
     Frontend = Transmitter->Frontend;
 
+    Path = (FrontendGetQueueCount(Frontend) == 1) ?
+                    FrontendGetPath(Frontend) :
+                    Ring->FrontendPath;
+
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "tx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
@@ -3176,7 +3208,7 @@ __TransmitterRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          Path,
                           "event-channel-tx",
                           "%u",
                           Port);
@@ -3404,6 +3436,9 @@ __TransmitterRingTeardown(
     ASSERT(IsListEmpty(&Ring->Completed));
     RtlZeroMemory(&Ring->Completed, sizeof (LIST_ENTRY));
 
+    ExFreePool(Ring->FrontendPath); // 'HTAP'
+    Ring->FrontendPath = NULL;
+
     Ring->Index = 0;
     Ring->Transmitter = NULL;
 
@@ -3498,14 +3533,15 @@ TransmitterDebugCallback(
 NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     )
 {
     HANDLE                  ParametersKey;
     ULONG                   Index;
+    ULONG                   Count;
     NTSTATUS                status;
 
+    Count = DriverGetMaximumQueueCount();
     *Transmitter = __TransmitterAllocate(sizeof (XENVIF_TRANSMITTER));
 
     status = STATUS_NO_MEMORY;
@@ -3592,7 +3628,7 @@ fail4:
         (*Transmitter)->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -3645,6 +3681,7 @@ TransmitterConnect(
     PXENVIF_FRONTEND            Frontend;
     PCHAR                       Buffer;
     ULONG                       Index;
+    ULONG                       Count;
     NTSTATUS                    status;
 
     Frontend = Transmitter->Frontend;
@@ -3691,7 +3728,10 @@ TransmitterConnect(
                      Buffer);
     }
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3725,7 +3765,7 @@ fail5:
 
         Ring = Transmitter->Rings[Index];
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3763,9 +3803,13 @@ TransmitterStoreWrite(
     )
 {
     NTSTATUS                        status;
-    ULONG                   Index;
+    ULONG                           Index;
+    ULONG                           Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3791,8 +3835,12 @@ TransmitterEnable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3811,8 +3859,12 @@ TransmitterDisable(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3830,6 +3882,7 @@ TransmitterDisconnect(
 {
     PXENVIF_FRONTEND        Frontend;
     ULONG                   Index;
+    ULONG                   Count;
 
     Frontend = Transmitter->Frontend;
 
@@ -3840,7 +3893,10 @@ TransmitterDisconnect(
                  Transmitter->DebugCallback);
     Transmitter->DebugCallback = NULL;
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
@@ -3882,7 +3938,7 @@ TransmitterTeardown(
         Transmitter->Rings[Index] = NULL;
 
         if (Ring == NULL)
-            continue;
+            continue; // ensure all rings are destroyed
 
         __TransmitterRingTeardown(Ring);
     }
@@ -4132,20 +4188,66 @@ TransmitterQueuePacketsV1(
 #undef OFFSET_EXISTS
 }
 
+static FORCEINLINE ULONG
+__GetQueue(
+    IN  ULONG       QueueCount,
+    IN  ULONG       HashValue
+    )
+{
+    return HashValue % QueueCount;
+}
+
 VOID
 TransmitterQueuePacketsV2(
     IN  PXENVIF_TRANSMITTER Transmitter,
     IN  PLIST_ENTRY         List
     )
 {
-    PXENVIF_TRANSMITTER_RING        Ring;
+    PXENVIF_TRANSMITTER_RING    Ring;
+    PXENVIF_FRONTEND            Frontend;
+    ULONG                       QueueCount;
 
-    // We need to hash for a ring eventually. Since there is only a
-    // single ring for now, we just use that.
-    Ring = Transmitter->Rings[0];
-    ASSERT3P(Ring, !=, NULL);
+    Frontend = Transmitter->Frontend;
+
+    QueueCount = FrontendGetQueueCount(Frontend);
+
+    if (QueueCount == 1) {
+        Ring = Transmitter->Rings[0];
+        ASSERT3P(Ring, !=, NULL);
 
-    __TransmitterRingQueuePackets(Ring, List);
+        __TransmitterRingQueuePackets(Ring, List);
+    } else {
+        while (!IsListEmpty(List)) {
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+            PLIST_ENTRY                 ListEntry;
+            LIST_ENTRY                  ListHead;
+            ULONG                       Queue;
+
+            InitializeListHead(&ListHead);
+
+            ListEntry = List->Flink;
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+            Queue = __GetQueue(QueueCount, Packet->Value);
+
+            (VOID) RemoveHeadList(List);
+            InsertTailList(&ListHead, ListEntry);
+
+            while (!IsListEmpty(List)) {
+                ListEntry = List->Flink;
+                Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+                if (Queue != __GetQueue(QueueCount, Packet->Value))
+                    break;
+
+                (VOID) RemoveHeadList(List);
+                InsertTailList(&ListHead, ListEntry);
+            }
+
+            Ring = Transmitter->Rings[Queue];
+            ASSERT3P(Ring, !=, NULL);
+
+            __TransmitterRingQueuePackets(Ring, &ListHead);
+        }
+    }
 }
 
 VOID
@@ -4154,11 +4256,15 @@ TransmitterAbortPackets(
     )
 {
     ULONG                   Index;
+    ULONG                   Count;
     KIRQL                   Irql;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
-    for (Index = 0; Index < MAXIMUM_PROCESSORS; ++Index) {
+    Count = FrontendGetQueueCount(Transmitter->Frontend);
+    ASSERT3U(Count, <=, MAXIMUM_PROCESSORS);
+
+    for (Index = 0; Index < Count; ++Index) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = Transmitter->Rings[Index];
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 2ed2786..666f049 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -43,7 +43,6 @@ typedef struct _XENVIF_TRANSMITTER XENVIF_TRANSMITTER, *PXENVIF_TRANSMITTER;
 extern NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     );
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebH-000482-Uu; Thu, 18 Dec 2014 17:10:55 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebH-00047k-0w
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:55 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	26/D0-02702-E9A03945; Thu, 18 Dec 2014 17:10:54 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418922652!16003797!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23139 invoked from network); 18 Dec 2014 17:10:53 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877193"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:27 +0000
Message-ID: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/6] Use VIF v2 interface
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Indirectly adds support for multi-queues by updating to VIF interface v2
Calculates a hash value for XenVif to determine queue (if supported)

Owen Smith (6):
  Dos2Unix line endings
  Move interface registration to coinstaller
  Refactor for more maintainability.
  Query for cache interface
  Switch to VIF interface V2
  Calculate simple hash of IP/Ports

 include/cache_interface.h    |  233 +++
 include/vif_interface.h      |   94 +-
 src/coinst/coinst.c          |  155 ++
 src/xennet.inf               |    6 +-
 src/xennet/adapter.c         | 3549 ++++++++++++++++++------------------------
 src/xennet/adapter.h         |  150 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  533 +++++++
 src/xennet/main.c            |  361 -----
 src/xennet/miniport.c        |   78 +-
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  328 ++--
 src/xennet/receiver.h        |   58 +-
 src/xennet/registry.c        | 1200 --------------
 src/xennet/registry.h        |  168 --
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  695 ++++++---
 src/xennet/transmitter.h     |   51 +-
 vs2012/xennet/xennet.vcxproj |    4 +-
 vs2013/xennet/xennet.vcxproj |  250 ++-
 20 files changed, 3490 insertions(+), 4570 deletions(-)
 create mode 100644 include/cache_interface.h
 delete mode 100644 src/xennet/common.h
 create mode 100644 src/xennet/driver.c
 delete mode 100644 src/xennet/main.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/registry.c
 delete mode 100644 src/xennet/registry.h
 delete mode 100644 src/xennet/std.h

-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebG-00047l-Tq; Thu, 18 Dec 2014 17:10:54 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebF-00047e-Vb
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:54 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	60/67-02697-D9A03945; Thu, 18 Dec 2014 17:10:53 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4681 invoked from network); 18 Dec 2014 17:10:52 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877174"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:33 +0000
Message-ID: <1418921673-6008-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 6/6] Calculate simple hash of IP/Ports
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Pullup the packet headers into a cached buffer, and calculate
a simple hash over the Source/Destination IP Addresses and Ports.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/transmitter.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 229 insertions(+)

diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index c64591d..77bcf1f 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -34,6 +34,7 @@
 #include "adapter.h"
 #include <vif_interface.h>
 #include <cache_interface.h>
+#include <tcpip.h>
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -42,10 +43,14 @@ struct _XENNET_TRANSMITTER {
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
     PXENBUS_CACHE               PacketCache;
     KSPIN_LOCK                  PacketLock;
+    PXENBUS_CACHE               BufferCache;
+    KSPIN_LOCK                  BufferLock;
 };
 
 #define XENNET_PACKET_CACHE_MIN     32
 #define TRANSMITTER_POOL_TAG        'TteN'
+#define BUFFER_CACHE_ITEM_SIZE      512
+#define MAX_HEADERS_LENGTH          (sizeof(IP_ADDRESS) + sizeof(IP_ADDRESS) + sizeof(USHORT) + sizeof(USHORT))
 
 static NTSTATUS
 __TransmitterPacketCtor(
@@ -88,6 +93,47 @@ __TransmitterPacketReleaseLock(
     KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
 }
 
+static NTSTATUS
+__TransmitterBufferCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterBufferDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterBufferAcquireLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->BufferLock);
+}
+
+static VOID
+__TransmitterBufferReleaseLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->BufferLock);
+}
+
 NDIS_STATUS
 TransmitterInitialize (
     IN  PXENNET_ADAPTER     Adapter,
@@ -108,6 +154,7 @@ TransmitterInitialize (
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
     KeInitializeSpinLock(&(*Transmitter)->PacketLock);
+    KeInitializeSpinLock(&(*Transmitter)->BufferLock);
 
     status = XENBUS_CACHE(Create,
                           CacheInterface,
@@ -122,10 +169,30 @@ TransmitterInitialize (
                           &(*Transmitter)->PacketCache);
     if (!NT_SUCCESS(status))
         goto fail2;
+
+    status = XENBUS_CACHE(Create,
+                          CacheInterface,
+                          "buffer_cache",
+                          BUFFER_CACHE_ITEM_SIZE,
+                          0,
+                          __TransmitterBufferCtor,
+                          __TransmitterBufferDtor,
+                          __TransmitterBufferAcquireLock,
+                          __TransmitterBufferReleaseLock,
+                          *Transmitter,
+                          &(*Transmitter)->BufferCache);
+    if (!NT_SUCCESS(status))
+        goto fail3;
     
     return NDIS_STATUS_SUCCESS;
 
+fail3:
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
+                 (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
 fail2:
+    RtlZeroMemory(&(*Transmitter)->BufferLock, sizeof(KSPIN_LOCK));
     RtlZeroMemory(&(*Transmitter)->PacketLock, sizeof(KSPIN_LOCK));
     ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
     *Transmitter = NULL;
@@ -144,10 +211,16 @@ TransmitterTeardown(
 
     Transmitter->Adapter = NULL;
     Transmitter->OffloadOptions.Value = 0;
+    RtlZeroMemory(&Transmitter->BufferLock, sizeof(KSPIN_LOCK));
     RtlZeroMemory(&Transmitter->PacketLock, sizeof(KSPIN_LOCK));
 
     XENBUS_CACHE(Destroy,
                  CacheInterface,
+                 Transmitter->BufferCache);
+    Transmitter->BufferCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
                  Transmitter->PacketCache);
     Transmitter->PacketCache = NULL;
 
@@ -188,6 +261,40 @@ __TransmitterPutPacket(
                  FALSE);
 }
 
+static FORCEINLINE PVOID
+__TransmitterGetBuffer(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface;
+
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    return XENBUS_CACHE(Get,
+                        CacheInterface,
+                        Transmitter->BufferCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutBuffer(
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PVOID               Buffer
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface;
+
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    RtlZeroMemory(Buffer, BUFFER_CACHE_ITEM_SIZE);
+
+    XENBUS_CACHE(Put,
+                 CacheInterface,
+                 Transmitter->BufferCache,
+                 Buffer,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -317,6 +424,127 @@ __TransmitterOffloadOptions(
     }
 }
 
+static ULONG
+__Hash(
+    IN  PVOID                       Buffer,
+    IN  ULONG                       Length
+    )
+{
+    PUCHAR                          Array = (PUCHAR)Buffer;
+    ULONG                           Accumulator;
+    ULONG                           Index;
+
+    Accumulator = 0;
+
+    for (Index = 0; Index < Length; ++Index) {
+        ULONG   Overflow;
+
+        Accumulator = (Accumulator << 4) + Array[Index];
+
+        Overflow = Accumulator & 0x00000f00;
+        if (Overflow != 0) {
+            Accumulator ^= Overflow >> 8;
+            Accumulator ^= Overflow;
+        }
+    }
+
+    return Accumulator;
+}
+
+static ULONG
+__TransmitterCalculateHash(
+    IN  PVOID                       Buffer,
+    IN  PXENVIF_PACKET_INFO         Info
+    )
+{
+    UCHAR       Headers[MAX_HEADERS_LENGTH];
+    PUCHAR      Ptr;
+
+    Ptr = (PUCHAR)Headers;
+
+    if (Info->IpHeader.Length) {
+        PIP_HEADER  Ip = (PIP_HEADER)((PUCHAR)Buffer + Info->IpHeader.Offset);
+
+        switch (Ip->Version) {
+        case 4:
+            RtlCopyMemory(Ptr, &Ip->Version4.SourceAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            RtlCopyMemory(Ptr, &Ip->Version4.DestinationAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            break;
+        case 6:
+            RtlCopyMemory(Ptr, &Ip->Version6.SourceAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            RtlCopyMemory(Ptr, &Ip->Version6.DestinationAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (Info->TcpHeader.Length) {
+        PTCP_HEADER Tcp = (PTCP_HEADER)((PUCHAR)Buffer + Info->TcpHeader.Offset);
+
+        RtlCopyMemory(Ptr, &Tcp->SourcePort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+        RtlCopyMemory(Ptr, &Tcp->DestinationPort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+    } else if (Info->UdpHeader.Length) {
+        PUDP_HEADER Udp = (PUDP_HEADER)((PUCHAR)Buffer + Info->UdpHeader.Offset);
+
+        RtlCopyMemory(Ptr, &Udp->SourcePort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+        RtlCopyMemory(Ptr, &Udp->DestinationPort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+    }
+
+    if (Ptr == (PUCHAR)Headers)
+        return 0;
+
+    return __Hash(Headers, (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)Headers));
+}
+
+static ULONG
+__TransmitterGetHash(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    PXENVIF_VIF_INTERFACE           VifInterface;
+    ULONG                           Hash;
+    XENVIF_PACKET_INFO              Info;
+    PVOID                           Buffer;
+    NTSTATUS                        status;
+
+    Hash = 0;
+    VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
+
+    Buffer = __TransmitterGetBuffer(Transmitter);
+    if (Buffer == NULL)
+        goto fail1;
+
+    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
+
+    status = XENVIF_VIF(TransmitterGetPacketHeaders,
+                        VifInterface,
+                        Packet,
+                        Buffer,
+                        &Info);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    Hash = __TransmitterCalculateHash(Buffer, &Info);
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+    return Hash;
+
+fail2:
+    __TransmitterPutBuffer(Transmitter, Buffer);
+fail1:
+    return 0;
+}
+
 VOID
 TransmitterSendNetBufferLists(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -387,6 +615,7 @@ TransmitterSendNetBufferLists(
             Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
             Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
             Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+            Packet->Value = __TransmitterGetHash(Transmitter, Packet);
 
             InsertTailList(&List, &Packet->ListEntry);
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebH-000486-Vs; Thu, 18 Dec 2014 17:10:55 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebH-00047j-1s
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:55 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	29/67-02697-E9A03945; Thu, 18 Dec 2014 17:10:54 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4744 invoked from network); 18 Dec 2014 17:10:53 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877186"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:31 +0000
Message-ID: <1418921673-6008-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/6] Query for cache interface
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/cache_interface.h | 233 ++++++++++++++++++++++++++++++++++++++++++++++
 src/xennet/adapter.c      |  57 +++++++++---
 src/xennet/adapter.h      |   6 ++
 3 files changed, 283 insertions(+), 13 deletions(-)
 create mode 100644 include/cache_interface.h

diff --git a/include/cache_interface.h b/include/cache_interface.h
new file mode 100644
index 0000000..dae3ac6
--- /dev/null
+++ b/include/cache_interface.h
@@ -0,0 +1,233 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+/*! \file cache_interface.h
+    \brief XENBUS CACHE Interface
+
+    This interface provides access to XENBUS's object cache
+    implementation.
+*/
+
+#ifndef _XENBUS_CACHE_INTERFACE_H
+#define _XENBUS_CACHE_INTERFACE_H
+
+#ifndef _WINDLL
+
+/*! \typedef XENBUS_CACHE
+    \brief Cache handle
+*/
+typedef struct _XENBUS_CACHE    XENBUS_CACHE, *PXENBUS_CACHE;
+
+/*! \typedef XENBUS_CACHE_ACQUIRE
+    \brief Acquire a reference to the CACHE interface
+
+    \param Interface The interface header
+*/  
+typedef NTSTATUS
+(*XENBUS_CACHE_ACQUIRE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CACHE_RELEASE
+    \brief Release a reference to the CACHE interface
+
+    \param Interface The interface header
+*/  
+typedef VOID
+(*XENBUS_CACHE_RELEASE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CACHE_CTOR
+    \brief Object creator callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+    \param Object Newly allocated object
+
+    This callback is invoked just after a new object is allocated and may
+    be used to initialize any object data prior to its insertion into the
+    cache.
+*/
+typedef NTSTATUS
+(*XENBUS_CACHE_CTOR)(
+    IN  PVOID   Argument,
+    IN  PVOID   Object
+    );
+
+/*! \typedef XENBUS_CACHE_DTOR
+    \brief Object destructor callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+    \param Object Object about to be freed
+
+    This callback is invoked just after an object is removed from the
+    cache and before it is freed and may be used to tear down any object data.
+*/
+typedef VOID
+(*XENBUS_CACHE_DTOR)(
+    IN  PVOID   Argument,
+    IN  PVOID   Object
+    );
+
+/*! \typedef XENBUS_CACHE_ACQUIRE_LOCK
+    \brief Cache lock callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+    This callback is invoked if the cache implementation requires mutual
+    exclusion.
+*/
+typedef VOID
+(*XENBUS_CACHE_ACQUIRE_LOCK)(
+    IN  PVOID   Argument
+    );
+
+/*! \typedef XENBUS_CACHE_RELEASE_LOCK
+    \brief Cache unlock callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+    This callback is invoked to release the mutual exclusion lock acquired
+    by a previous invocation of \a XENBUS_CACHE_ACQUIRE_LOCK.
+*/
+typedef VOID
+(*XENBUS_CACHE_RELEASE_LOCK)(
+    IN  PVOID   Argument
+    );
+
+/*! \typedef XENBUS_CACHE_CREATE
+    \brief Create a cache of objects of the given \a Size
+
+    \param Interface The interface header
+    \param Name A name for the cache which will be used in debug output
+    \param Size The size of each object in bytes
+    \param Reservation The target minimum population of the cache
+    \param Ctor A callback which is invoked when a new object created
+    \param Dtor A callback which is invoked when an object is destroyed
+    \param AcquireLock A callback invoked to acquire a spinlock
+    \param ReleaseLock A callback invoked to release the spinlock
+    \param Argument An optional context argument passed to the callbacks
+    \param Cache A pointer to a cache handle to be initialized
+
+    If a non-zero \a Reservation is specified then this method will fail
+    unless that number of objects can be immediately created.
+*/  
+typedef NTSTATUS
+(*XENBUS_CACHE_CREATE)(
+    IN  PINTERFACE                  Interface,
+    IN  const CHAR                  *Name,
+    IN  ULONG                       Size,
+    IN  ULONG                       Reservation,
+    IN  XENBUS_CACHE_CTOR           Ctor,
+    IN  XENBUS_CACHE_DTOR           Dtor,
+    IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
+    IN  XENBUS_CACHE_RELEASE_LOCK   ReleaseLock,
+    IN  PVOID                       Argument OPTIONAL,
+    OUT PXENBUS_CACHE               *Cache
+    );
+
+/*! \typedef XENBUS_CACHE_GET
+    \brief Get an object from a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+    \param Locked If mutually exclusive access to the cache is already
+    guaranteed then set this to TRUE
+*/
+typedef PVOID
+(*XENBUS_CACHE_GET)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache,
+    IN  BOOLEAN         Locked
+    );
+
+/*! \typedef XENBUS_CACHE_PUT
+    \brief Return an object to a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+    \param Locked If mutually exclusive access to the cache is already
+    guaranteed then set this to TRUE
+*/
+typedef VOID
+(*XENBUS_CACHE_PUT)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache,
+    IN  PVOID           Object,
+    IN  BOOLEAN         Locked
+    );
+
+/*! \typedef XENBUS_CACHE_DESTROY
+    \brief Destroy a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+
+    All objects must have been returned to the cache prior to destruction
+*/
+typedef VOID
+(*XENBUS_CACHE_DESTROY)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache
+    );
+
+// {A98DFD78-416A-4949-92A5-E084F2F4B44E}
+DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE, 
+0xa98dfd78, 0x416a, 0x4949, 0x92, 0xa5, 0xe0, 0x84, 0xf2, 0xf4, 0xb4, 0x4e);
+
+/*! \struct _XENBUS_CACHE_INTERFACE_V1
+    \brief CACHE interface version 1
+    \ingroup interfaces
+*/
+struct _XENBUS_CACHE_INTERFACE_V1 {
+    INTERFACE               Interface;
+    XENBUS_CACHE_ACQUIRE    CacheAcquire;
+    XENBUS_CACHE_RELEASE    CacheRelease;
+    XENBUS_CACHE_CREATE     CacheCreate;
+    XENBUS_CACHE_GET        CacheGet;
+    XENBUS_CACHE_PUT        CachePut;
+    XENBUS_CACHE_DESTROY    CacheDestroy;
+};
+
+typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE_INTERFACE;
+
+/*! \def XENBUS_CACHE
+    \brief Macro at assist in method invocation
+*/
+#define XENBUS_CACHE(_Method, _Interface, ...)    \
+    (_Interface)->Cache ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+
+#endif  // _WINDLL
+
+#define XENBUS_CACHE_INTERFACE_VERSION_MIN  1
+#define XENBUS_CACHE_INTERFACE_VERSION_MAX  1
+
+#endif  // _XENBUS_CACHE_INTERFACE_H
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index a718a82..2f10b35 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -34,12 +34,14 @@
 #include "transmitter.h"
 #include "receiver.h"
 #include <vif_interface.h>
+#include <cache_interface.h>
 #include <version.h>
 #include "dbg_print.h"
 #include "assert.h"
 
 struct _XENNET_ADAPTER {
     XENVIF_VIF_INTERFACE    VifInterface;
+    XENBUS_CACHE_INTERFACE  CacheInterface;
 
     ULONG                   MaximumFrameSize;
     ULONG                   CurrentLookahead;
@@ -921,6 +923,14 @@ AdapterGetVifInterface(
     return &Adapter->VifInterface;
 }
 
+PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return &Adapter->CacheInterface;
+}
+
 PXENNET_TRANSMITTER
 AdapterGetTransmitter(
     IN  PXENNET_ADAPTER     Adapter
@@ -2011,36 +2021,50 @@ AdapterInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = __QueryInterface(DeviceObject,
+                              &GUID_XENBUS_CACHE_INTERFACE,
+                              XENBUS_CACHE_INTERFACE_VERSION_MAX,
+                              (PINTERFACE)&(*Adapter)->CacheInterface,
+                              sizeof(XENBUS_CACHE_INTERFACE),
+                              FALSE);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = XENVIF_VIF(Acquire,
                         &(*Adapter)->VifInterface);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
+
+    status = XENBUS_CACHE(Acquire,
+                          &(*Adapter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
     (*Adapter)->NdisAdapterHandle = Handle;
 
     ndisStatus = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail4;
+        goto fail6;
 
     ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail5;
+        goto fail7;
 
     ndisStatus = AdapterGetAdvancedSettings(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail6;
+        goto fail8;
     
     ndisStatus = AdapterSetRegistrationAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail7;
+        goto fail9;
     
     ndisStatus = AdapterSetGeneralAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail8;
+        goto fail10;
 
     ndisStatus = AdapterSetOffloadAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail9;
+        goto fail11;
 
     RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION));
     Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
@@ -2059,27 +2083,31 @@ AdapterInitialize(
 
     ndisStatus = AdapterEnable(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail10;
+        goto fail12;
 
     return NDIS_STATUS_SUCCESS;
 
-fail10:
+fail12:
     if ((*Adapter)->NdisDmaHandle)
         NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
     (*Adapter)->NdisDmaHandle = NULL;
+fail11:
+fail10:
 fail9:
 fail8:
-fail7:
-fail6:
     ReceiverTeardown((*Adapter)->Receiver);
     (*Adapter)->Receiver = NULL;
-fail5:
+fail7:
     TransmitterTeardown((*Adapter)->Transmitter);
     (*Adapter)->Transmitter = NULL;
-fail4:
+fail6:
     (*Adapter)->NdisAdapterHandle = NULL;
 
+    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
+fail5:
     XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail4:
+    RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
 fail3:
     RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 fail2:
@@ -2103,6 +2131,9 @@ AdapterTeardown(
         NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
     Adapter->NdisDmaHandle = NULL;
 
+    XENBUS_CACHE(Release, &Adapter->CacheInterface);
+    RtlZeroMemory(&Adapter->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+
     XENVIF_VIF(Release, &Adapter->VifInterface);
     RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index 6c60aad..042b863 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -89,6 +89,12 @@ AdapterGetVifInterface(
     IN  PXENNET_ADAPTER     Adapter
     );
 
+#include <cache_interface.h>
+extern PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    );
+
 #include "transmitter.h"
 extern PXENNET_TRANSMITTER
 AdapterGetTransmitter(
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebH-000482-Uu; Thu, 18 Dec 2014 17:10:55 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebH-00047k-0w
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:55 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	26/D0-02702-E9A03945; Thu, 18 Dec 2014 17:10:54 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418922652!16003797!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23139 invoked from network); 18 Dec 2014 17:10:53 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877193"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:27 +0000
Message-ID: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/6] Use VIF v2 interface
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Indirectly adds support for multi-queues by updating to VIF interface v2
Calculates a hash value for XenVif to determine queue (if supported)

Owen Smith (6):
  Dos2Unix line endings
  Move interface registration to coinstaller
  Refactor for more maintainability.
  Query for cache interface
  Switch to VIF interface V2
  Calculate simple hash of IP/Ports

 include/cache_interface.h    |  233 +++
 include/vif_interface.h      |   94 +-
 src/coinst/coinst.c          |  155 ++
 src/xennet.inf               |    6 +-
 src/xennet/adapter.c         | 3549 ++++++++++++++++++------------------------
 src/xennet/adapter.h         |  150 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  533 +++++++
 src/xennet/main.c            |  361 -----
 src/xennet/miniport.c        |   78 +-
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  328 ++--
 src/xennet/receiver.h        |   58 +-
 src/xennet/registry.c        | 1200 --------------
 src/xennet/registry.h        |  168 --
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  695 ++++++---
 src/xennet/transmitter.h     |   51 +-
 vs2012/xennet/xennet.vcxproj |    4 +-
 vs2013/xennet/xennet.vcxproj |  250 ++-
 20 files changed, 3490 insertions(+), 4570 deletions(-)
 create mode 100644 include/cache_interface.h
 delete mode 100644 src/xennet/common.h
 create mode 100644 src/xennet/driver.c
 delete mode 100644 src/xennet/main.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/registry.c
 delete mode 100644 src/xennet/registry.h
 delete mode 100644 src/xennet/std.h

-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebG-00047l-Tq; Thu, 18 Dec 2014 17:10:54 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebF-00047e-Vb
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:54 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	60/67-02697-D9A03945; Thu, 18 Dec 2014 17:10:53 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4681 invoked from network); 18 Dec 2014 17:10:52 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877174"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:33 +0000
Message-ID: <1418921673-6008-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 6/6] Calculate simple hash of IP/Ports
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Pullup the packet headers into a cached buffer, and calculate
a simple hash over the Source/Destination IP Addresses and Ports.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/transmitter.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 229 insertions(+)

diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index c64591d..77bcf1f 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -34,6 +34,7 @@
 #include "adapter.h"
 #include <vif_interface.h>
 #include <cache_interface.h>
+#include <tcpip.h>
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -42,10 +43,14 @@ struct _XENNET_TRANSMITTER {
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
     PXENBUS_CACHE               PacketCache;
     KSPIN_LOCK                  PacketLock;
+    PXENBUS_CACHE               BufferCache;
+    KSPIN_LOCK                  BufferLock;
 };
 
 #define XENNET_PACKET_CACHE_MIN     32
 #define TRANSMITTER_POOL_TAG        'TteN'
+#define BUFFER_CACHE_ITEM_SIZE      512
+#define MAX_HEADERS_LENGTH          (sizeof(IP_ADDRESS) + sizeof(IP_ADDRESS) + sizeof(USHORT) + sizeof(USHORT))
 
 static NTSTATUS
 __TransmitterPacketCtor(
@@ -88,6 +93,47 @@ __TransmitterPacketReleaseLock(
     KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
 }
 
+static NTSTATUS
+__TransmitterBufferCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterBufferDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterBufferAcquireLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->BufferLock);
+}
+
+static VOID
+__TransmitterBufferReleaseLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->BufferLock);
+}
+
 NDIS_STATUS
 TransmitterInitialize (
     IN  PXENNET_ADAPTER     Adapter,
@@ -108,6 +154,7 @@ TransmitterInitialize (
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
     KeInitializeSpinLock(&(*Transmitter)->PacketLock);
+    KeInitializeSpinLock(&(*Transmitter)->BufferLock);
 
     status = XENBUS_CACHE(Create,
                           CacheInterface,
@@ -122,10 +169,30 @@ TransmitterInitialize (
                           &(*Transmitter)->PacketCache);
     if (!NT_SUCCESS(status))
         goto fail2;
+
+    status = XENBUS_CACHE(Create,
+                          CacheInterface,
+                          "buffer_cache",
+                          BUFFER_CACHE_ITEM_SIZE,
+                          0,
+                          __TransmitterBufferCtor,
+                          __TransmitterBufferDtor,
+                          __TransmitterBufferAcquireLock,
+                          __TransmitterBufferReleaseLock,
+                          *Transmitter,
+                          &(*Transmitter)->BufferCache);
+    if (!NT_SUCCESS(status))
+        goto fail3;
     
     return NDIS_STATUS_SUCCESS;
 
+fail3:
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
+                 (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
 fail2:
+    RtlZeroMemory(&(*Transmitter)->BufferLock, sizeof(KSPIN_LOCK));
     RtlZeroMemory(&(*Transmitter)->PacketLock, sizeof(KSPIN_LOCK));
     ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
     *Transmitter = NULL;
@@ -144,10 +211,16 @@ TransmitterTeardown(
 
     Transmitter->Adapter = NULL;
     Transmitter->OffloadOptions.Value = 0;
+    RtlZeroMemory(&Transmitter->BufferLock, sizeof(KSPIN_LOCK));
     RtlZeroMemory(&Transmitter->PacketLock, sizeof(KSPIN_LOCK));
 
     XENBUS_CACHE(Destroy,
                  CacheInterface,
+                 Transmitter->BufferCache);
+    Transmitter->BufferCache = NULL;
+
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
                  Transmitter->PacketCache);
     Transmitter->PacketCache = NULL;
 
@@ -188,6 +261,40 @@ __TransmitterPutPacket(
                  FALSE);
 }
 
+static FORCEINLINE PVOID
+__TransmitterGetBuffer(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface;
+
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    return XENBUS_CACHE(Get,
+                        CacheInterface,
+                        Transmitter->BufferCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutBuffer(
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PVOID               Buffer
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface;
+
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    RtlZeroMemory(Buffer, BUFFER_CACHE_ITEM_SIZE);
+
+    XENBUS_CACHE(Put,
+                 CacheInterface,
+                 Transmitter->BufferCache,
+                 Buffer,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -317,6 +424,127 @@ __TransmitterOffloadOptions(
     }
 }
 
+static ULONG
+__Hash(
+    IN  PVOID                       Buffer,
+    IN  ULONG                       Length
+    )
+{
+    PUCHAR                          Array = (PUCHAR)Buffer;
+    ULONG                           Accumulator;
+    ULONG                           Index;
+
+    Accumulator = 0;
+
+    for (Index = 0; Index < Length; ++Index) {
+        ULONG   Overflow;
+
+        Accumulator = (Accumulator << 4) + Array[Index];
+
+        Overflow = Accumulator & 0x00000f00;
+        if (Overflow != 0) {
+            Accumulator ^= Overflow >> 8;
+            Accumulator ^= Overflow;
+        }
+    }
+
+    return Accumulator;
+}
+
+static ULONG
+__TransmitterCalculateHash(
+    IN  PVOID                       Buffer,
+    IN  PXENVIF_PACKET_INFO         Info
+    )
+{
+    UCHAR       Headers[MAX_HEADERS_LENGTH];
+    PUCHAR      Ptr;
+
+    Ptr = (PUCHAR)Headers;
+
+    if (Info->IpHeader.Length) {
+        PIP_HEADER  Ip = (PIP_HEADER)((PUCHAR)Buffer + Info->IpHeader.Offset);
+
+        switch (Ip->Version) {
+        case 4:
+            RtlCopyMemory(Ptr, &Ip->Version4.SourceAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            RtlCopyMemory(Ptr, &Ip->Version4.DestinationAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            break;
+        case 6:
+            RtlCopyMemory(Ptr, &Ip->Version6.SourceAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            RtlCopyMemory(Ptr, &Ip->Version6.DestinationAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (Info->TcpHeader.Length) {
+        PTCP_HEADER Tcp = (PTCP_HEADER)((PUCHAR)Buffer + Info->TcpHeader.Offset);
+
+        RtlCopyMemory(Ptr, &Tcp->SourcePort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+        RtlCopyMemory(Ptr, &Tcp->DestinationPort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+    } else if (Info->UdpHeader.Length) {
+        PUDP_HEADER Udp = (PUDP_HEADER)((PUCHAR)Buffer + Info->UdpHeader.Offset);
+
+        RtlCopyMemory(Ptr, &Udp->SourcePort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+        RtlCopyMemory(Ptr, &Udp->DestinationPort, sizeof(USHORT));
+        Ptr += sizeof(USHORT);
+    }
+
+    if (Ptr == (PUCHAR)Headers)
+        return 0;
+
+    return __Hash(Headers, (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)Headers));
+}
+
+static ULONG
+__TransmitterGetHash(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    PXENVIF_VIF_INTERFACE           VifInterface;
+    ULONG                           Hash;
+    XENVIF_PACKET_INFO              Info;
+    PVOID                           Buffer;
+    NTSTATUS                        status;
+
+    Hash = 0;
+    VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
+
+    Buffer = __TransmitterGetBuffer(Transmitter);
+    if (Buffer == NULL)
+        goto fail1;
+
+    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
+
+    status = XENVIF_VIF(TransmitterGetPacketHeaders,
+                        VifInterface,
+                        Packet,
+                        Buffer,
+                        &Info);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    Hash = __TransmitterCalculateHash(Buffer, &Info);
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+    return Hash;
+
+fail2:
+    __TransmitterPutBuffer(Transmitter, Buffer);
+fail1:
+    return 0;
+}
+
 VOID
 TransmitterSendNetBufferLists(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -387,6 +615,7 @@ TransmitterSendNetBufferLists(
             Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
             Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
             Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+            Packet->Value = __TransmitterGetHash(Transmitter, Packet);
 
             InsertTailList(&List, &Packet->ListEntry);
 
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebH-000486-Vs; Thu, 18 Dec 2014 17:10:55 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebH-00047j-1s
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:55 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	29/67-02697-E9A03945; Thu, 18 Dec 2014 17:10:54 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4744 invoked from network); 18 Dec 2014 17:10:53 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877186"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:31 +0000
Message-ID: <1418921673-6008-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/6] Query for cache interface
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/cache_interface.h | 233 ++++++++++++++++++++++++++++++++++++++++++++++
 src/xennet/adapter.c      |  57 +++++++++---
 src/xennet/adapter.h      |   6 ++
 3 files changed, 283 insertions(+), 13 deletions(-)
 create mode 100644 include/cache_interface.h

diff --git a/include/cache_interface.h b/include/cache_interface.h
new file mode 100644
index 0000000..dae3ac6
--- /dev/null
+++ b/include/cache_interface.h
@@ -0,0 +1,233 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+/*! \file cache_interface.h
+    \brief XENBUS CACHE Interface
+
+    This interface provides access to XENBUS's object cache
+    implementation.
+*/
+
+#ifndef _XENBUS_CACHE_INTERFACE_H
+#define _XENBUS_CACHE_INTERFACE_H
+
+#ifndef _WINDLL
+
+/*! \typedef XENBUS_CACHE
+    \brief Cache handle
+*/
+typedef struct _XENBUS_CACHE    XENBUS_CACHE, *PXENBUS_CACHE;
+
+/*! \typedef XENBUS_CACHE_ACQUIRE
+    \brief Acquire a reference to the CACHE interface
+
+    \param Interface The interface header
+*/  
+typedef NTSTATUS
+(*XENBUS_CACHE_ACQUIRE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CACHE_RELEASE
+    \brief Release a reference to the CACHE interface
+
+    \param Interface The interface header
+*/  
+typedef VOID
+(*XENBUS_CACHE_RELEASE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CACHE_CTOR
+    \brief Object creator callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+    \param Object Newly allocated object
+
+    This callback is invoked just after a new object is allocated and may
+    be used to initialize any object data prior to its insertion into the
+    cache.
+*/
+typedef NTSTATUS
+(*XENBUS_CACHE_CTOR)(
+    IN  PVOID   Argument,
+    IN  PVOID   Object
+    );
+
+/*! \typedef XENBUS_CACHE_DTOR
+    \brief Object destructor callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+    \param Object Object about to be freed
+
+    This callback is invoked just after an object is removed from the
+    cache and before it is freed and may be used to tear down any object data.
+*/
+typedef VOID
+(*XENBUS_CACHE_DTOR)(
+    IN  PVOID   Argument,
+    IN  PVOID   Object
+    );
+
+/*! \typedef XENBUS_CACHE_ACQUIRE_LOCK
+    \brief Cache lock callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+    This callback is invoked if the cache implementation requires mutual
+    exclusion.
+*/
+typedef VOID
+(*XENBUS_CACHE_ACQUIRE_LOCK)(
+    IN  PVOID   Argument
+    );
+
+/*! \typedef XENBUS_CACHE_RELEASE_LOCK
+    \brief Cache unlock callback
+
+    \param Argument Context \a Argument supplied to \a XENBUS_CACHE_CREATE
+
+    This callback is invoked to release the mutual exclusion lock acquired
+    by a previous invocation of \a XENBUS_CACHE_ACQUIRE_LOCK.
+*/
+typedef VOID
+(*XENBUS_CACHE_RELEASE_LOCK)(
+    IN  PVOID   Argument
+    );
+
+/*! \typedef XENBUS_CACHE_CREATE
+    \brief Create a cache of objects of the given \a Size
+
+    \param Interface The interface header
+    \param Name A name for the cache which will be used in debug output
+    \param Size The size of each object in bytes
+    \param Reservation The target minimum population of the cache
+    \param Ctor A callback which is invoked when a new object created
+    \param Dtor A callback which is invoked when an object is destroyed
+    \param AcquireLock A callback invoked to acquire a spinlock
+    \param ReleaseLock A callback invoked to release the spinlock
+    \param Argument An optional context argument passed to the callbacks
+    \param Cache A pointer to a cache handle to be initialized
+
+    If a non-zero \a Reservation is specified then this method will fail
+    unless that number of objects can be immediately created.
+*/  
+typedef NTSTATUS
+(*XENBUS_CACHE_CREATE)(
+    IN  PINTERFACE                  Interface,
+    IN  const CHAR                  *Name,
+    IN  ULONG                       Size,
+    IN  ULONG                       Reservation,
+    IN  XENBUS_CACHE_CTOR           Ctor,
+    IN  XENBUS_CACHE_DTOR           Dtor,
+    IN  XENBUS_CACHE_ACQUIRE_LOCK   AcquireLock,
+    IN  XENBUS_CACHE_RELEASE_LOCK   ReleaseLock,
+    IN  PVOID                       Argument OPTIONAL,
+    OUT PXENBUS_CACHE               *Cache
+    );
+
+/*! \typedef XENBUS_CACHE_GET
+    \brief Get an object from a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+    \param Locked If mutually exclusive access to the cache is already
+    guaranteed then set this to TRUE
+*/
+typedef PVOID
+(*XENBUS_CACHE_GET)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache,
+    IN  BOOLEAN         Locked
+    );
+
+/*! \typedef XENBUS_CACHE_PUT
+    \brief Return an object to a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+    \param Locked If mutually exclusive access to the cache is already
+    guaranteed then set this to TRUE
+*/
+typedef VOID
+(*XENBUS_CACHE_PUT)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache,
+    IN  PVOID           Object,
+    IN  BOOLEAN         Locked
+    );
+
+/*! \typedef XENBUS_CACHE_DESTROY
+    \brief Destroy a \a Cache
+
+    \param Interface The interface header
+    \param Cache The cache handle
+
+    All objects must have been returned to the cache prior to destruction
+*/
+typedef VOID
+(*XENBUS_CACHE_DESTROY)(
+    IN  PINTERFACE      Interface,
+    IN  PXENBUS_CACHE   Cache
+    );
+
+// {A98DFD78-416A-4949-92A5-E084F2F4B44E}
+DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE, 
+0xa98dfd78, 0x416a, 0x4949, 0x92, 0xa5, 0xe0, 0x84, 0xf2, 0xf4, 0xb4, 0x4e);
+
+/*! \struct _XENBUS_CACHE_INTERFACE_V1
+    \brief CACHE interface version 1
+    \ingroup interfaces
+*/
+struct _XENBUS_CACHE_INTERFACE_V1 {
+    INTERFACE               Interface;
+    XENBUS_CACHE_ACQUIRE    CacheAcquire;
+    XENBUS_CACHE_RELEASE    CacheRelease;
+    XENBUS_CACHE_CREATE     CacheCreate;
+    XENBUS_CACHE_GET        CacheGet;
+    XENBUS_CACHE_PUT        CachePut;
+    XENBUS_CACHE_DESTROY    CacheDestroy;
+};
+
+typedef struct _XENBUS_CACHE_INTERFACE_V1 XENBUS_CACHE_INTERFACE, *PXENBUS_CACHE_INTERFACE;
+
+/*! \def XENBUS_CACHE
+    \brief Macro at assist in method invocation
+*/
+#define XENBUS_CACHE(_Method, _Interface, ...)    \
+    (_Interface)->Cache ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+
+#endif  // _WINDLL
+
+#define XENBUS_CACHE_INTERFACE_VERSION_MIN  1
+#define XENBUS_CACHE_INTERFACE_VERSION_MAX  1
+
+#endif  // _XENBUS_CACHE_INTERFACE_H
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index a718a82..2f10b35 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -34,12 +34,14 @@
 #include "transmitter.h"
 #include "receiver.h"
 #include <vif_interface.h>
+#include <cache_interface.h>
 #include <version.h>
 #include "dbg_print.h"
 #include "assert.h"
 
 struct _XENNET_ADAPTER {
     XENVIF_VIF_INTERFACE    VifInterface;
+    XENBUS_CACHE_INTERFACE  CacheInterface;
 
     ULONG                   MaximumFrameSize;
     ULONG                   CurrentLookahead;
@@ -921,6 +923,14 @@ AdapterGetVifInterface(
     return &Adapter->VifInterface;
 }
 
+PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return &Adapter->CacheInterface;
+}
+
 PXENNET_TRANSMITTER
 AdapterGetTransmitter(
     IN  PXENNET_ADAPTER     Adapter
@@ -2011,36 +2021,50 @@ AdapterInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = __QueryInterface(DeviceObject,
+                              &GUID_XENBUS_CACHE_INTERFACE,
+                              XENBUS_CACHE_INTERFACE_VERSION_MAX,
+                              (PINTERFACE)&(*Adapter)->CacheInterface,
+                              sizeof(XENBUS_CACHE_INTERFACE),
+                              FALSE);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = XENVIF_VIF(Acquire,
                         &(*Adapter)->VifInterface);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
+
+    status = XENBUS_CACHE(Acquire,
+                          &(*Adapter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
     (*Adapter)->NdisAdapterHandle = Handle;
 
     ndisStatus = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail4;
+        goto fail6;
 
     ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail5;
+        goto fail7;
 
     ndisStatus = AdapterGetAdvancedSettings(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail6;
+        goto fail8;
     
     ndisStatus = AdapterSetRegistrationAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail7;
+        goto fail9;
     
     ndisStatus = AdapterSetGeneralAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail8;
+        goto fail10;
 
     ndisStatus = AdapterSetOffloadAttributes(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail9;
+        goto fail11;
 
     RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION));
     Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
@@ -2059,27 +2083,31 @@ AdapterInitialize(
 
     ndisStatus = AdapterEnable(*Adapter);
     if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail10;
+        goto fail12;
 
     return NDIS_STATUS_SUCCESS;
 
-fail10:
+fail12:
     if ((*Adapter)->NdisDmaHandle)
         NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
     (*Adapter)->NdisDmaHandle = NULL;
+fail11:
+fail10:
 fail9:
 fail8:
-fail7:
-fail6:
     ReceiverTeardown((*Adapter)->Receiver);
     (*Adapter)->Receiver = NULL;
-fail5:
+fail7:
     TransmitterTeardown((*Adapter)->Transmitter);
     (*Adapter)->Transmitter = NULL;
-fail4:
+fail6:
     (*Adapter)->NdisAdapterHandle = NULL;
 
+    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
+fail5:
     XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail4:
+    RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
 fail3:
     RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 fail2:
@@ -2103,6 +2131,9 @@ AdapterTeardown(
         NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
     Adapter->NdisDmaHandle = NULL;
 
+    XENBUS_CACHE(Release, &Adapter->CacheInterface);
+    RtlZeroMemory(&Adapter->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+
     XENVIF_VIF(Release, &Adapter->VifInterface);
     RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index 6c60aad..042b863 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -89,6 +89,12 @@ AdapterGetVifInterface(
     IN  PXENNET_ADAPTER     Adapter
     );
 
+#include <cache_interface.h>
+extern PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    );
+
 #include "transmitter.h"
 extern PXENNET_TRANSMITTER
 AdapterGetTransmitter(
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:58 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebK-00049F-1X; Thu, 18 Dec 2014 17:10:58 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebI-000481-EL
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:56 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	24/77-02697-F9A03945; Thu, 18 Dec 2014 17:10:55 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!3
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4816 invoked from network); 18 Dec 2014 17:10:54 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877202"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:28 +0000
Message-ID: <1418921673-6008-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
Content-Length: 19700
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

U2lnbmVkLW9mZi1ieTogT3dlbiBTbWl0aCA8b3dlbi5zbWl0aEBjaXRyaXguY29tPgotLS0KIHZz
MjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2ogfCAyNTIgKysrKysrKysrKysrKysrKysrKysrLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLQogMSBmaWxlIGNoYW5nZWQsIDEyNiBpbnNlcnRpb25zKCspLCAx
MjYgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJv
aiBiL3ZzMjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2oKaW5kZXggOTA4YmMyZC4uMGQ5OGYzYSAx
MDA2NDQKLS0tIGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJvagorKysgYi92czIwMTMveGVu
bmV0L3hlbm5ldC52Y3hwcm9qCkBAIC0xLDEzMSArMSwxMzEgQEAKLe+7vzw/eG1sIHZlcnNpb249
IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+Ci08UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQi
IFRvb2xzVmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20v
ZGV2ZWxvcGVyL21zYnVpbGQvMjAwMyI+Ci0gIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5w
cm9wcyIgLz4KLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4KLSAgICA8
Q29uZmlndXJhdGlvblR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4KLSAgICA8RHJpdmVy
VHlwZT5XRE08L0RyaXZlclR5cGU+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAgPFByb3BlcnR5R3Jv
dXAgTGFiZWw9Ikdsb2JhbHMiPgotICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlzdGEgRGVi
dWc8L0NvbmZpZ3VyYXRpb24+Ci0gICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0p
JyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPgotICAgIDxEZWJ1Z2dlckZsYXZvcj5EYmdlbmdLZXJu
ZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAgPEltcG9y
dCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAuRGVmYXVsdC5wcm9wcyIg
Lz4KLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQo
Q29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4IFJlbGVhc2V8eDY0JyI+Ci0g
ICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1U
b29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25m
aWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dp
bmRvd3MgOCBSZWxlYXNlfFdpbjMyJyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2Vy
bmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0g
IDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZp
Z3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+Ci0gICAg
PFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29s
c2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgVmlzdGEgRGVidWd8V2luMzInIj4KLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJu
ZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAg
PFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmln
dXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxlYXNlfHg2NCciPgotICAg
IDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9v
bHNldD4KLSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmln
dXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5k
b3dzIFZpc3RhIFJlbGVhc2V8V2luMzInIj4KLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NL
ZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Ci0gIDwvUHJvcGVydHlHcm91cD4K
LSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29u
ZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+Ci0gICAg
PFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29s
c2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgNyBSZWxlYXNlfFdpbjMyJyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPgotICAgIDxQbGF0Zm9y
bVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3xXaW4zMiciPgotICAgIDxQbGF0
Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4K
LSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlv
biIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcg
RGVidWd8eDY0JyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZl
cjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQo
UGxhdGZvcm0pJz09J1dpbmRvd3MgOCBEZWJ1Z3xXaW4zMiciPgotICAgIDxQbGF0Zm9ybVRvb2xz
ZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4KLSAgPC9Qcm9w
ZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0
aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0
JyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxh
dGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVs
PSJHbG9iYWxzIj4KLSAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMtNDg4Qy1CNTEyLUM5
NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxJbXBvcnQg
UHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4KLSAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFy
Z2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+Ci0gIDxQcm9wZXJ0eUdyb3VwPgotICAg
IDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQoSW5jbHVkZVBhdGgpPC9JbmNsdWRlUGF0aD4K
LSAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8L1J1bkNvZGVBbmFseXNpcz4KLSAgICA8RW5hYmxl
SW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5mMmNhdD4KLSAgICA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJn
ZXRzPkNsQ29tcGlsZTtTdGFtcEluZjwvQ3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPgotICAgIDxJ
bnREaXI+Li5cJChQcm9qZWN0TmFtZSlcJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlc
PC9JbnREaXI+Ci0gICAgPE91dERpcj4uLlwkKENvbmZpZ3VyYXRpb25OYW1lKVwkKFBsYXRmb3Jt
KVw8L091dERpcj4KLSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8SXRlbURlZmluaXRpb25Hcm91cD4K
LSAgICA8Q3VzdG9tQnVpbGRTdGVwPgor77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
dXRmLTgiPz4KKzxQcm9qZWN0IERlZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIx
Mi4wIiB4bWxucz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWls
ZC8yMDAzIj4KKyAgPEltcG9ydCBQcm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgorICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iUHJvcGVydHlTaGVldHMiPgorICAgIDxDb25maWd1cmF0aW9uVHlw
ZT5Ecml2ZXI8L0NvbmZpZ3VyYXRpb25UeXBlPgorICAgIDxEcml2ZXJUeXBlPldETTwvRHJpdmVy
VHlwZT4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91cCBMYWJlbD0iR2xvYmFs
cyI+CisgICAgPENvbmZpZ3VyYXRpb24+V2luZG93cyBWaXN0YSBEZWJ1ZzwvQ29uZmlndXJhdGlv
bj4KKyAgICA8UGxhdGZvcm0gQ29uZGl0aW9uPSInJChQbGF0Zm9ybSknID09ICcnIj5XaW4zMjwv
UGxhdGZvcm0+CisgICAgPERlYnVnZ2VyRmxhdm9yPkRiZ2VuZ0tlcm5lbERlYnVnZ2VyPC9EZWJ1
Z2dlckZsYXZvcj4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8SW1wb3J0IFByb2plY3Q9IiQoVkNU
YXJnZXRzUGF0aClcTWljcm9zb2Z0LkNwcC5EZWZhdWx0LnByb3BzIiAvPgorICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwk
KFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggUmVsZWFzZXx4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29s
c2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJv
cGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRp
dGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4IFJlbGVhc2V8
V2luMzInIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4x
PC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0
Zm9ybSknPT0nV2luZG93cyBWaXN0YSBEZWJ1Z3x4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0
PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVy
dHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlv
bj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBEZWJ1Z3xX
aW4zMiciPgorICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91cCBM
YWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRm
b3JtKSc9PSdXaW5kb3dzIFZpc3RhIFJlbGVhc2V8eDY0JyI+CisgICAgPFBsYXRmb3JtVG9vbHNl
dD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3Bl
cnR5R3JvdXA+CisgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRp
b249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgUmVsZWFz
ZXxXaW4zMiciPgorICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4
LjE8L1BsYXRmb3JtVG9vbHNldD4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91
cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBs
YXRmb3JtKSc9PSdXaW5kb3dzIDcgUmVsZWFzZXx4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0
PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVy
dHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlv
bj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8V2lu
MzInIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9Q
bGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93czggRGVidWd8eDY0JyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD52MTIwPC9Q
bGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93cyA3IERlYnVnfFdpbjMyJyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5k
b3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3BlcnR5R3Jv
dXA+CisgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249Iick
KENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3x4NjQnIj4KKyAg
ICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRv
b2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZp
Z3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2lu
ZG93cyA4IERlYnVnfFdpbjMyJyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3BlcnR5R3JvdXA+CisgIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBEZWJ1Z3x4NjQnIj4KKyAgICA8UGxhdGZv
cm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Cisg
IDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgorICAg
IDxQcm9qZWN0R3VpZD57OTdEOTk0MkItNUVBMy00ODhDLUI1MTItQzk2RTVEMDc3RjhFfTwvUHJv
amVjdEd1aWQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPEltcG9ydCBQcm9qZWN0PSIuLlx0YXJn
ZXRzLnByb3BzIiAvPgorICA8SW1wb3J0IFByb2plY3Q9IiQoVkNUYXJnZXRzUGF0aClcTWljcm9z
b2Z0LkNwcC5wcm9wcyIgLz4KKyAgPFByb3BlcnR5R3JvdXA+CisgICAgPEluY2x1ZGVQYXRoPi4u
XC4uXGluY2x1ZGU7JChJbmNsdWRlUGF0aCk8L0luY2x1ZGVQYXRoPgorICAgIDxSdW5Db2RlQW5h
bHlzaXM+dHJ1ZTwvUnVuQ29kZUFuYWx5c2lzPgorICAgIDxFbmFibGVJbmYyY2F0PmZhbHNlPC9F
bmFibGVJbmYyY2F0PgorICAgIDxDdXN0b21CdWlsZEJlZm9yZVRhcmdldHM+Q2xDb21waWxlO1N0
YW1wSW5mPC9DdXN0b21CdWlsZEJlZm9yZVRhcmdldHM+CisgICAgPEludERpcj4uLlwkKFByb2pl
Y3ROYW1lKVwkKENvbmZpZ3VyYXRpb25OYW1lKVwkKFBsYXRmb3JtKVw8L0ludERpcj4KKyAgICA8
T3V0RGlyPi4uXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvT3V0RGlyPgorICA8
L1Byb3BlcnR5R3JvdXA+CisgIDxJdGVtRGVmaW5pdGlvbkdyb3VwPgorICAgIDxDdXN0b21CdWls
ZFN0ZXA+CiAgICAgICA8Q29tbWFuZD5lY2hvICJCdWlsZCBJbmYiCiAgICAgICAgICAgICAgICAg
cG93ZXJzaGVsbCAtQ29tbWFuZCAiKEdldC1Db250ZW50IC4uXC4uXHNyY1x4ZW5uZXQuaW5mKSAt
cmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFKT1JfVkVSU0lPTiknIC1yZXBsYWNlICdA
TUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9OKScgLXJlcGxhY2UgJ0BNSUNST19WRVJT
SU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNlICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJ
TERfTlVNQkVSKScgLXJlcGxhY2UgJ0BDT01QQU5ZX05BTUVAJywnJChDT01QQU5ZX05BTUUpJyAt
cmVwbGFjZSAnQFBST0RVQ1RfTkFNRUAnLCckKFBST0RVQ1RfTkFNRSknIHwgU2V0LUNvbnRlbnQg
Li5ceGVubmV0LmluZiIKICAgICAgICAgICAgICAgICBlY2hvICJCdWlsZCB2ZXJzaW9uIGhlYWRl
ciIKICAgICAgICAgICAgICAgICBwb3dlcnNoZWxsIC1Db21tYW5kICIoR2V0LUNvbnRlbnQgLi5c
Li5caW5jbHVkZVx2ZXJzaW9uLmh4KSAtcmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFK
T1JfVkVSU0lPTiknIC1yZXBsYWNlICdATUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9O
KScgLXJlcGxhY2UgJ0BNSUNST19WRVJTSU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNl
ICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJTERfTlVNQkVSKScgLXJlcGxhY2UgJ0BDT01QQU5ZX05B
TUVAJywnJChDT01QQU5ZX05BTUUpJyAtcmVwbGFjZSAnQFBST0RVQ1RfTkFNRUAnLCckKFBST0RV
Q1RfTkFNRSknIC1yZXBsYWNlICdAREFZQCcsJTI0KEdldC1EYXRlIC1mb3JtYXQgJTI1JTI1ZCkg
LXJlcGxhY2UgJ0BNT05USEAnLCUyNChHZXQtRGF0ZSAtZm9ybWF0ICUyNSUyNU0pIC1yZXBsYWNl
ICdAWUVBUkAnLCUyNChHZXQtRGF0ZSAtZm9ybWF0IHl5eXkpIHwgU2V0LUNvbnRlbnQgLi5cLi5c
aW5jbHVkZVx2ZXJzaW9uLmgiCi0gICAgICAgICAgICA8L0NvbW1hbmQ+Ci0gICAgICA8T3V0cHV0
cz4uLlx4ZW5uZXQuaW5mOy4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oPC9PdXRwdXRzPgotICAgICAg
PElucHV0cz4uLlwuLlxzcmNceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaHg8L0lu
cHV0cz4KLSAgICA8L0N1c3RvbUJ1aWxkU3RlcD4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFBy
ZXByb2Nlc3NvckRlZmluaXRpb25zPl9fTU9EVUxFX189IlhFTk5FVCI7TkRJU19NSU5JUE9SVF9E
UklWRVI7TkRJUzYwX01JTklQT1JUPTE7UE9PTF9OWF9PUFRJTj0xOyUoUHJlcHJvY2Vzc29yRGVm
aW5pdGlvbnMpPC9QcmVwcm9jZXNzb3JEZWZpbml0aW9ucz4KLSAgICAgIDxXYXJuaW5nTGV2ZWw+
RW5hYmxlQWxsV2FybmluZ3M8L1dhcm5pbmdMZXZlbD4KLSAgICAgIDxEaXNhYmxlU3BlY2lmaWNX
YXJuaW5ncz40NzExOzQ1NDg7NDgyMDs0NjY4OzQyNTU7NjAwMTs2MDU0OzI4MTk2OyUoRGlzYWJs
ZVNwZWNpZmljV2FybmluZ3MpPC9EaXNhYmxlU3BlY2lmaWNXYXJuaW5ncz4KLSAgICAgIDxNdWx0
aVByb2Nlc3NvckNvbXBpbGF0aW9uPnRydWU8L011bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+Ci0g
ICAgICA8RW5hYmxlUFJFZmFzdD50cnVlPC9FbmFibGVQUkVmYXN0PgotICAgIDwvQ2xDb21waWxl
PgotICAgIDxMaW5rPgotICAgICAgPEltYWdlSGFzU2FmZUV4Y2VwdGlvbkhhbmRsZXJzPmZhbHNl
PC9JbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5kbGVycz4KLSAgICAgIDxBZGRpdGlvbmFsRGVwZW5k
ZW5jaWVzPiQoRERLX0xJQl9QQVRIKVxuZGlzLmxpYjslKEFkZGl0aW9uYWxEZXBlbmRlbmNpZXMp
PC9BZGRpdGlvbmFsRGVwZW5kZW5jaWVzPgotICAgICAgPEVuYWJsZUNPTURBVEZvbGRpbmc+ZmFs
c2U8L0VuYWJsZUNPTURBVEZvbGRpbmc+Ci0gICAgPC9MaW5rPgotICAgIDxJbmY+Ci0gICAgICA8
U3BlY2lmeUFyY2hpdGVjdHVyZT50cnVlPC9TcGVjaWZ5QXJjaGl0ZWN0dXJlPgotICAgICAgPFNw
ZWNpZnlEcml2ZXJWZXJEaXJlY3RpdmVWZXJzaW9uPnRydWU8L1NwZWNpZnlEcml2ZXJWZXJEaXJl
Y3RpdmVWZXJzaW9uPgotICAgICAgPFRpbWVTdGFtcD4kKE1BSk9SX1ZFUlNJT04pLiQoTUlOT1Jf
VkVSU0lPTikuJChNSUNST19WRVJTSU9OKS4kKEJVSUxEX05VTUJFUik8L1RpbWVTdGFtcD4KLSAg
ICAgIDxFbmFibGVWZXJib3NlPnRydWU8L0VuYWJsZVZlcmJvc2U+Ci0gICAgPC9JbmY+Ci0gIDwv
SXRlbURlZmluaXRpb25Hcm91cD4KLSAgPEl0ZW1EZWZpbml0aW9uR3JvdXAgQ29uZGl0aW9uPSIn
JChQbGF0Zm9ybSknPT0nV2luMzInIj4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFByZXByb2Nl
c3NvckRlZmluaXRpb25zPl9faTM4Nl9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9QcmVw
cm9jZXNzb3JEZWZpbml0aW9ucz4KLSAgICA8L0NsQ29tcGlsZT4KLSAgICA8SW5mPgotICAgICAg
PEFyY2hpdGVjdHVyZT54ODY8L0FyY2hpdGVjdHVyZT4KLSAgICA8L0luZj4KLSAgPC9JdGVtRGVm
aW5pdGlvbkdyb3VwPgotICA8SXRlbURlZmluaXRpb25Hcm91cCBDb25kaXRpb249IickKFBsYXRm
b3JtKSc9PSd4NjQnIj4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFByZXByb2Nlc3NvckRlZmlu
aXRpb25zPl9feDg2XzY0X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXByb2Nlc3Nv
ckRlZmluaXRpb25zPgotICAgIDwvQ2xDb21waWxlPgotICAgIDxJbmY+Ci0gICAgICA8QXJjaGl0
ZWN0dXJlPmFtZDY0PC9BcmNoaXRlY3R1cmU+Ci0gICAgPC9JbmY+Ci0gIDwvSXRlbURlZmluaXRp
b25Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iJChU
YXJnZXRQYXRoKSIgLz4KLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iJChPdXREaXIpJChU
YXJnZXROYW1lKS5wZGIiIC8+Ci0gICAgPEZpbGVzVG9QYWNrYWdlIEluY2x1ZGU9IkAoSW5mLT4n
JShDb3B5T3V0cHV0KScpIiBDb25kaXRpb249IidAKEluZiknIT0nJyIgLz4KLSAgPC9JdGVtR3Jv
dXA+Ci0gIDxJdGVtR3JvdXA+Ci0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVu
bmV0L3JlZ2lzdHJ5LmMiIC8+Ci0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVu
bmV0L2FkYXB0ZXIuYyIgLz4KLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5u
ZXQvbWFpbi5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9t
aW5pcG9ydC5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9y
ZWNlaXZlci5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC90
cmFuc21pdHRlci5jIiAvPgotICA8L0l0ZW1Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8UmVz
b3VyY2VDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5uZXRceGVubmV0LnJjIiAvPgotICA8
L0l0ZW1Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8SW5mIEluY2x1ZGU9Ii4uXHhlbm5ldC5p
bmYiIC8+Ci0gIDwvSXRlbUdyb3VwPgotICA8SW1wb3J0IFByb2plY3Q9IiQoVkNUYXJnZXRzUGF0
aClcTWljcm9zb2Z0LkNwcC50YXJnZXRzIiAvPgorICAgICAgICAgICAgPC9Db21tYW5kPgorICAg
ICAgPE91dHB1dHM+Li5ceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaDwvT3V0cHV0
cz4KKyAgICAgIDxJbnB1dHM+Li5cLi5cc3JjXHhlbm5ldC5pbmY7Li5cLi5caW5jbHVkZVx2ZXJz
aW9uLmh4PC9JbnB1dHM+CisgICAgPC9DdXN0b21CdWlsZFN0ZXA+CisgICAgPENsQ29tcGlsZT4K
KyAgICAgIDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX01PRFVMRV9fPSJYRU5ORVQiO05ESVNf
TUlOSVBPUlRfRFJJVkVSO05ESVM2MF9NSU5JUE9SVD0xO1BPT0xfTlhfT1BUSU49MTslKFByZXBy
b2Nlc3NvckRlZmluaXRpb25zKTwvUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+CisgICAgICA8V2Fy
bmluZ0xldmVsPkVuYWJsZUFsbFdhcm5pbmdzPC9XYXJuaW5nTGV2ZWw+CisgICAgICA8RGlzYWJs
ZVNwZWNpZmljV2FybmluZ3M+NDcxMTs0NTQ4OzQ4MjA7NDY2ODs0MjU1OzYwMDE7NjA1NDsyODE5
NjslKERpc2FibGVTcGVjaWZpY1dhcm5pbmdzKTwvRGlzYWJsZVNwZWNpZmljV2FybmluZ3M+Cisg
ICAgICA8TXVsdGlQcm9jZXNzb3JDb21waWxhdGlvbj50cnVlPC9NdWx0aVByb2Nlc3NvckNvbXBp
bGF0aW9uPgorICAgICAgPEVuYWJsZVBSRWZhc3Q+dHJ1ZTwvRW5hYmxlUFJFZmFzdD4KKyAgICA8
L0NsQ29tcGlsZT4KKyAgICA8TGluaz4KKyAgICAgIDxJbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5k
bGVycz5mYWxzZTwvSW1hZ2VIYXNTYWZlRXhjZXB0aW9uSGFuZGxlcnM+CisgICAgICA8QWRkaXRp
b25hbERlcGVuZGVuY2llcz4kKERES19MSUJfUEFUSClcbmRpcy5saWI7JShBZGRpdGlvbmFsRGVw
ZW5kZW5jaWVzKTwvQWRkaXRpb25hbERlcGVuZGVuY2llcz4KKyAgICAgIDxFbmFibGVDT01EQVRG
b2xkaW5nPmZhbHNlPC9FbmFibGVDT01EQVRGb2xkaW5nPgorICAgIDwvTGluaz4KKyAgICA8SW5m
PgorICAgICAgPFNwZWNpZnlBcmNoaXRlY3R1cmU+dHJ1ZTwvU3BlY2lmeUFyY2hpdGVjdHVyZT4K
KyAgICAgIDxTcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbj50cnVlPC9TcGVjaWZ5RHJp
dmVyVmVyRGlyZWN0aXZlVmVyc2lvbj4KKyAgICAgIDxUaW1lU3RhbXA+JChNQUpPUl9WRVJTSU9O
KS4kKE1JTk9SX1ZFUlNJT04pLiQoTUlDUk9fVkVSU0lPTikuJChCVUlMRF9OVU1CRVIpPC9UaW1l
U3RhbXA+CisgICAgICA8RW5hYmxlVmVyYm9zZT50cnVlPC9FbmFibGVWZXJib3NlPgorICAgIDwv
SW5mPgorICA8L0l0ZW1EZWZpbml0aW9uR3JvdXA+CisgIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENv
bmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09J1dpbjMyJyI+CisgICAgPENsQ29tcGlsZT4KKyAgICAg
IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX2kzODZfXzslKFByZXByb2Nlc3NvckRlZmluaXRp
b25zKTwvUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+CisgICAgPC9DbENvbXBpbGU+CisgICAgPElu
Zj4KKyAgICAgIDxBcmNoaXRlY3R1cmU+eDg2PC9BcmNoaXRlY3R1cmU+CisgICAgPC9JbmY+Cisg
IDwvSXRlbURlZmluaXRpb25Hcm91cD4KKyAgPEl0ZW1EZWZpbml0aW9uR3JvdXAgQ29uZGl0aW9u
PSInJChQbGF0Zm9ybSknPT0neDY0JyI+CisgICAgPENsQ29tcGlsZT4KKyAgICAgIDxQcmVwcm9j
ZXNzb3JEZWZpbml0aW9ucz5fX3g4Nl82NF9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9Q
cmVwcm9jZXNzb3JEZWZpbml0aW9ucz4KKyAgICA8L0NsQ29tcGlsZT4KKyAgICA8SW5mPgorICAg
ICAgPEFyY2hpdGVjdHVyZT5hbWQ2NDwvQXJjaGl0ZWN0dXJlPgorICAgIDwvSW5mPgorICA8L0l0
ZW1EZWZpbml0aW9uR3JvdXA+CisgIDxJdGVtR3JvdXA+CisgICAgPEZpbGVzVG9QYWNrYWdlIElu
Y2x1ZGU9IiQoVGFyZ2V0UGF0aCkiIC8+CisgICAgPEZpbGVzVG9QYWNrYWdlIEluY2x1ZGU9IiQo
T3V0RGlyKSQoVGFyZ2V0TmFtZSkucGRiIiAvPgorICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRl
PSJAKEluZi0+JyUoQ29weU91dHB1dCknKSIgQ29uZGl0aW9uPSInQChJbmYpJyE9JyciIC8+Cisg
IDwvSXRlbUdyb3VwPgorICA8SXRlbUdyb3VwPgorICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4v
Li4vc3JjL3hlbm5ldC9yZWdpc3RyeS5jIiAvPgorICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4v
Li4vc3JjL3hlbm5ldC9hZGFwdGVyLmMiIC8+CisgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8u
Li9zcmMveGVubmV0L21haW4uYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvbWluaXBvcnQuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvcmVjZWl2ZXIuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvdHJhbnNtaXR0ZXIuYyIgLz4KKyAgPC9JdGVtR3JvdXA+CisgIDxJdGVtR3JvdXA+
CisgICAgPFJlc291cmNlQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVubmV0XHhlbm5ldC5y
YyIgLz4KKyAgPC9JdGVtR3JvdXA+CisgIDxJdGVtR3JvdXA+CisgICAgPEluZiBJbmNsdWRlPSIu
Llx4ZW5uZXQuaW5mIiAvPgorICA8L0l0ZW1Hcm91cD4KKyAgPEltcG9ydCBQcm9qZWN0PSIkKFZD
VGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAudGFyZ2V0cyIgLz4KIDwvUHJvamVjdD4KXCBObyBu
ZXdsaW5lIGF0IGVuZCBvZiBmaWxlCi0tIAoxLjkuNC5tc3lzZ2l0LjEKCgpfX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBs
aXN0Cndpbi1wdi1kZXZlbEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJv
amVjdC5vcmcvY2dpLWJpbi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:58 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebK-00049F-1X; Thu, 18 Dec 2014 17:10:58 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebI-000481-EL
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:56 +0000
Received: from [85.158.139.211] by server-13.bemta-5.messagelabs.com id
	24/77-02697-F9A03945; Thu, 18 Dec 2014 17:10:55 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1418922650!8771390!3
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4816 invoked from network); 18 Dec 2014 17:10:54 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877202"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:28 +0000
Message-ID: <1418921673-6008-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
Content-Length: 19700
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

U2lnbmVkLW9mZi1ieTogT3dlbiBTbWl0aCA8b3dlbi5zbWl0aEBjaXRyaXguY29tPgotLS0KIHZz
MjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2ogfCAyNTIgKysrKysrKysrKysrKysrKysrKysrLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLQogMSBmaWxlIGNoYW5nZWQsIDEyNiBpbnNlcnRpb25zKCspLCAx
MjYgZGVsZXRpb25zKC0pCgpkaWZmIC0tZ2l0IGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJv
aiBiL3ZzMjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2oKaW5kZXggOTA4YmMyZC4uMGQ5OGYzYSAx
MDA2NDQKLS0tIGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJvagorKysgYi92czIwMTMveGVu
bmV0L3hlbm5ldC52Y3hwcm9qCkBAIC0xLDEzMSArMSwxMzEgQEAKLe+7vzw/eG1sIHZlcnNpb249
IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+Ci08UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQi
IFRvb2xzVmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20v
ZGV2ZWxvcGVyL21zYnVpbGQvMjAwMyI+Ci0gIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5w
cm9wcyIgLz4KLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4KLSAgICA8
Q29uZmlndXJhdGlvblR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4KLSAgICA8RHJpdmVy
VHlwZT5XRE08L0RyaXZlclR5cGU+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAgPFByb3BlcnR5R3Jv
dXAgTGFiZWw9Ikdsb2JhbHMiPgotICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlzdGEgRGVi
dWc8L0NvbmZpZ3VyYXRpb24+Ci0gICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0p
JyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPgotICAgIDxEZWJ1Z2dlckZsYXZvcj5EYmdlbmdLZXJu
ZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAgPEltcG9y
dCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAuRGVmYXVsdC5wcm9wcyIg
Lz4KLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQo
Q29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4IFJlbGVhc2V8eDY0JyI+Ci0g
ICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1U
b29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25m
aWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dp
bmRvd3MgOCBSZWxlYXNlfFdpbjMyJyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2Vy
bmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0g
IDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZp
Z3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+Ci0gICAg
PFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29s
c2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgVmlzdGEgRGVidWd8V2luMzInIj4KLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJu
ZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Ci0gIDwvUHJvcGVydHlHcm91cD4KLSAg
PFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmln
dXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxlYXNlfHg2NCciPgotICAg
IDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9v
bHNldD4KLSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmln
dXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5k
b3dzIFZpc3RhIFJlbGVhc2V8V2luMzInIj4KLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NL
ZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Ci0gIDwvUHJvcGVydHlHcm91cD4K
LSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29u
ZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+Ci0gICAg
PFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29s
c2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgNyBSZWxlYXNlfFdpbjMyJyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPgotICAgIDxQbGF0Zm9y
bVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3xXaW4zMiciPgotICAgIDxQbGF0
Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4K
LSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlv
biIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcg
RGVidWd8eDY0JyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZl
cjguMTwvUGxhdGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQo
UGxhdGZvcm0pJz09J1dpbmRvd3MgOCBEZWJ1Z3xXaW4zMiciPgotICAgIDxQbGF0Zm9ybVRvb2xz
ZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4KLSAgPC9Qcm9w
ZXJ0eUdyb3VwPgotICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0
aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0
JyI+Ci0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxh
dGZvcm1Ub29sc2V0PgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxQcm9wZXJ0eUdyb3VwIExhYmVs
PSJHbG9iYWxzIj4KLSAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMtNDg4Qy1CNTEyLUM5
NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPgotICA8L1Byb3BlcnR5R3JvdXA+Ci0gIDxJbXBvcnQg
UHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4KLSAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFy
Z2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+Ci0gIDxQcm9wZXJ0eUdyb3VwPgotICAg
IDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQoSW5jbHVkZVBhdGgpPC9JbmNsdWRlUGF0aD4K
LSAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8L1J1bkNvZGVBbmFseXNpcz4KLSAgICA8RW5hYmxl
SW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5mMmNhdD4KLSAgICA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJn
ZXRzPkNsQ29tcGlsZTtTdGFtcEluZjwvQ3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPgotICAgIDxJ
bnREaXI+Li5cJChQcm9qZWN0TmFtZSlcJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlc
PC9JbnREaXI+Ci0gICAgPE91dERpcj4uLlwkKENvbmZpZ3VyYXRpb25OYW1lKVwkKFBsYXRmb3Jt
KVw8L091dERpcj4KLSAgPC9Qcm9wZXJ0eUdyb3VwPgotICA8SXRlbURlZmluaXRpb25Hcm91cD4K
LSAgICA8Q3VzdG9tQnVpbGRTdGVwPgor77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
dXRmLTgiPz4KKzxQcm9qZWN0IERlZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIx
Mi4wIiB4bWxucz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWls
ZC8yMDAzIj4KKyAgPEltcG9ydCBQcm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgorICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iUHJvcGVydHlTaGVldHMiPgorICAgIDxDb25maWd1cmF0aW9uVHlw
ZT5Ecml2ZXI8L0NvbmZpZ3VyYXRpb25UeXBlPgorICAgIDxEcml2ZXJUeXBlPldETTwvRHJpdmVy
VHlwZT4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91cCBMYWJlbD0iR2xvYmFs
cyI+CisgICAgPENvbmZpZ3VyYXRpb24+V2luZG93cyBWaXN0YSBEZWJ1ZzwvQ29uZmlndXJhdGlv
bj4KKyAgICA8UGxhdGZvcm0gQ29uZGl0aW9uPSInJChQbGF0Zm9ybSknID09ICcnIj5XaW4zMjwv
UGxhdGZvcm0+CisgICAgPERlYnVnZ2VyRmxhdm9yPkRiZ2VuZ0tlcm5lbERlYnVnZ2VyPC9EZWJ1
Z2dlckZsYXZvcj4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8SW1wb3J0IFByb2plY3Q9IiQoVkNU
YXJnZXRzUGF0aClcTWljcm9zb2Z0LkNwcC5EZWZhdWx0LnByb3BzIiAvPgorICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwk
KFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggUmVsZWFzZXx4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29s
c2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJv
cGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRp
dGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4IFJlbGVhc2V8
V2luMzInIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4x
PC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0
Zm9ybSknPT0nV2luZG93cyBWaXN0YSBEZWJ1Z3x4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0
PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVy
dHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlv
bj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBEZWJ1Z3xX
aW4zMiciPgorICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91cCBM
YWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRm
b3JtKSc9PSdXaW5kb3dzIFZpc3RhIFJlbGVhc2V8eDY0JyI+CisgICAgPFBsYXRmb3JtVG9vbHNl
dD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3Bl
cnR5R3JvdXA+CisgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRp
b249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgUmVsZWFz
ZXxXaW4zMiciPgorICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4
LjE8L1BsYXRmb3JtVG9vbHNldD4KKyAgPC9Qcm9wZXJ0eUdyb3VwPgorICA8UHJvcGVydHlHcm91
cCBMYWJlbD0iQ29uZmlndXJhdGlvbiIgQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBs
YXRmb3JtKSc9PSdXaW5kb3dzIDcgUmVsZWFzZXx4NjQnIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0
PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVy
dHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlv
bj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8V2lu
MzInIj4KKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9Q
bGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93czggRGVidWd8eDY0JyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD52MTIwPC9Q
bGF0Zm9ybVRvb2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9IkNvbmZpZ3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93cyA3IERlYnVnfFdpbjMyJyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5k
b3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3BlcnR5R3Jv
dXA+CisgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249Iick
KENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3x4NjQnIj4KKyAg
ICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRv
b2xzZXQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZp
Z3VyYXRpb24iIENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2lu
ZG93cyA4IERlYnVnfFdpbjMyJyI+CisgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0PgorICA8L1Byb3BlcnR5R3JvdXA+CisgIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIiBDb25kaXRpb249IickKENvbmZpZ3Vy
YXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBEZWJ1Z3x4NjQnIj4KKyAgICA8UGxhdGZv
cm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+Cisg
IDwvUHJvcGVydHlHcm91cD4KKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgorICAg
IDxQcm9qZWN0R3VpZD57OTdEOTk0MkItNUVBMy00ODhDLUI1MTItQzk2RTVEMDc3RjhFfTwvUHJv
amVjdEd1aWQ+CisgIDwvUHJvcGVydHlHcm91cD4KKyAgPEltcG9ydCBQcm9qZWN0PSIuLlx0YXJn
ZXRzLnByb3BzIiAvPgorICA8SW1wb3J0IFByb2plY3Q9IiQoVkNUYXJnZXRzUGF0aClcTWljcm9z
b2Z0LkNwcC5wcm9wcyIgLz4KKyAgPFByb3BlcnR5R3JvdXA+CisgICAgPEluY2x1ZGVQYXRoPi4u
XC4uXGluY2x1ZGU7JChJbmNsdWRlUGF0aCk8L0luY2x1ZGVQYXRoPgorICAgIDxSdW5Db2RlQW5h
bHlzaXM+dHJ1ZTwvUnVuQ29kZUFuYWx5c2lzPgorICAgIDxFbmFibGVJbmYyY2F0PmZhbHNlPC9F
bmFibGVJbmYyY2F0PgorICAgIDxDdXN0b21CdWlsZEJlZm9yZVRhcmdldHM+Q2xDb21waWxlO1N0
YW1wSW5mPC9DdXN0b21CdWlsZEJlZm9yZVRhcmdldHM+CisgICAgPEludERpcj4uLlwkKFByb2pl
Y3ROYW1lKVwkKENvbmZpZ3VyYXRpb25OYW1lKVwkKFBsYXRmb3JtKVw8L0ludERpcj4KKyAgICA8
T3V0RGlyPi4uXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvT3V0RGlyPgorICA8
L1Byb3BlcnR5R3JvdXA+CisgIDxJdGVtRGVmaW5pdGlvbkdyb3VwPgorICAgIDxDdXN0b21CdWls
ZFN0ZXA+CiAgICAgICA8Q29tbWFuZD5lY2hvICJCdWlsZCBJbmYiCiAgICAgICAgICAgICAgICAg
cG93ZXJzaGVsbCAtQ29tbWFuZCAiKEdldC1Db250ZW50IC4uXC4uXHNyY1x4ZW5uZXQuaW5mKSAt
cmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFKT1JfVkVSU0lPTiknIC1yZXBsYWNlICdA
TUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9OKScgLXJlcGxhY2UgJ0BNSUNST19WRVJT
SU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNlICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJ
TERfTlVNQkVSKScgLXJlcGxhY2UgJ0BDT01QQU5ZX05BTUVAJywnJChDT01QQU5ZX05BTUUpJyAt
cmVwbGFjZSAnQFBST0RVQ1RfTkFNRUAnLCckKFBST0RVQ1RfTkFNRSknIHwgU2V0LUNvbnRlbnQg
Li5ceGVubmV0LmluZiIKICAgICAgICAgICAgICAgICBlY2hvICJCdWlsZCB2ZXJzaW9uIGhlYWRl
ciIKICAgICAgICAgICAgICAgICBwb3dlcnNoZWxsIC1Db21tYW5kICIoR2V0LUNvbnRlbnQgLi5c
Li5caW5jbHVkZVx2ZXJzaW9uLmh4KSAtcmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFK
T1JfVkVSU0lPTiknIC1yZXBsYWNlICdATUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9O
KScgLXJlcGxhY2UgJ0BNSUNST19WRVJTSU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNl
ICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJTERfTlVNQkVSKScgLXJlcGxhY2UgJ0BDT01QQU5ZX05B
TUVAJywnJChDT01QQU5ZX05BTUUpJyAtcmVwbGFjZSAnQFBST0RVQ1RfTkFNRUAnLCckKFBST0RV
Q1RfTkFNRSknIC1yZXBsYWNlICdAREFZQCcsJTI0KEdldC1EYXRlIC1mb3JtYXQgJTI1JTI1ZCkg
LXJlcGxhY2UgJ0BNT05USEAnLCUyNChHZXQtRGF0ZSAtZm9ybWF0ICUyNSUyNU0pIC1yZXBsYWNl
ICdAWUVBUkAnLCUyNChHZXQtRGF0ZSAtZm9ybWF0IHl5eXkpIHwgU2V0LUNvbnRlbnQgLi5cLi5c
aW5jbHVkZVx2ZXJzaW9uLmgiCi0gICAgICAgICAgICA8L0NvbW1hbmQ+Ci0gICAgICA8T3V0cHV0
cz4uLlx4ZW5uZXQuaW5mOy4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oPC9PdXRwdXRzPgotICAgICAg
PElucHV0cz4uLlwuLlxzcmNceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaHg8L0lu
cHV0cz4KLSAgICA8L0N1c3RvbUJ1aWxkU3RlcD4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFBy
ZXByb2Nlc3NvckRlZmluaXRpb25zPl9fTU9EVUxFX189IlhFTk5FVCI7TkRJU19NSU5JUE9SVF9E
UklWRVI7TkRJUzYwX01JTklQT1JUPTE7UE9PTF9OWF9PUFRJTj0xOyUoUHJlcHJvY2Vzc29yRGVm
aW5pdGlvbnMpPC9QcmVwcm9jZXNzb3JEZWZpbml0aW9ucz4KLSAgICAgIDxXYXJuaW5nTGV2ZWw+
RW5hYmxlQWxsV2FybmluZ3M8L1dhcm5pbmdMZXZlbD4KLSAgICAgIDxEaXNhYmxlU3BlY2lmaWNX
YXJuaW5ncz40NzExOzQ1NDg7NDgyMDs0NjY4OzQyNTU7NjAwMTs2MDU0OzI4MTk2OyUoRGlzYWJs
ZVNwZWNpZmljV2FybmluZ3MpPC9EaXNhYmxlU3BlY2lmaWNXYXJuaW5ncz4KLSAgICAgIDxNdWx0
aVByb2Nlc3NvckNvbXBpbGF0aW9uPnRydWU8L011bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+Ci0g
ICAgICA8RW5hYmxlUFJFZmFzdD50cnVlPC9FbmFibGVQUkVmYXN0PgotICAgIDwvQ2xDb21waWxl
PgotICAgIDxMaW5rPgotICAgICAgPEltYWdlSGFzU2FmZUV4Y2VwdGlvbkhhbmRsZXJzPmZhbHNl
PC9JbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5kbGVycz4KLSAgICAgIDxBZGRpdGlvbmFsRGVwZW5k
ZW5jaWVzPiQoRERLX0xJQl9QQVRIKVxuZGlzLmxpYjslKEFkZGl0aW9uYWxEZXBlbmRlbmNpZXMp
PC9BZGRpdGlvbmFsRGVwZW5kZW5jaWVzPgotICAgICAgPEVuYWJsZUNPTURBVEZvbGRpbmc+ZmFs
c2U8L0VuYWJsZUNPTURBVEZvbGRpbmc+Ci0gICAgPC9MaW5rPgotICAgIDxJbmY+Ci0gICAgICA8
U3BlY2lmeUFyY2hpdGVjdHVyZT50cnVlPC9TcGVjaWZ5QXJjaGl0ZWN0dXJlPgotICAgICAgPFNw
ZWNpZnlEcml2ZXJWZXJEaXJlY3RpdmVWZXJzaW9uPnRydWU8L1NwZWNpZnlEcml2ZXJWZXJEaXJl
Y3RpdmVWZXJzaW9uPgotICAgICAgPFRpbWVTdGFtcD4kKE1BSk9SX1ZFUlNJT04pLiQoTUlOT1Jf
VkVSU0lPTikuJChNSUNST19WRVJTSU9OKS4kKEJVSUxEX05VTUJFUik8L1RpbWVTdGFtcD4KLSAg
ICAgIDxFbmFibGVWZXJib3NlPnRydWU8L0VuYWJsZVZlcmJvc2U+Ci0gICAgPC9JbmY+Ci0gIDwv
SXRlbURlZmluaXRpb25Hcm91cD4KLSAgPEl0ZW1EZWZpbml0aW9uR3JvdXAgQ29uZGl0aW9uPSIn
JChQbGF0Zm9ybSknPT0nV2luMzInIj4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFByZXByb2Nl
c3NvckRlZmluaXRpb25zPl9faTM4Nl9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9QcmVw
cm9jZXNzb3JEZWZpbml0aW9ucz4KLSAgICA8L0NsQ29tcGlsZT4KLSAgICA8SW5mPgotICAgICAg
PEFyY2hpdGVjdHVyZT54ODY8L0FyY2hpdGVjdHVyZT4KLSAgICA8L0luZj4KLSAgPC9JdGVtRGVm
aW5pdGlvbkdyb3VwPgotICA8SXRlbURlZmluaXRpb25Hcm91cCBDb25kaXRpb249IickKFBsYXRm
b3JtKSc9PSd4NjQnIj4KLSAgICA8Q2xDb21waWxlPgotICAgICAgPFByZXByb2Nlc3NvckRlZmlu
aXRpb25zPl9feDg2XzY0X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXByb2Nlc3Nv
ckRlZmluaXRpb25zPgotICAgIDwvQ2xDb21waWxlPgotICAgIDxJbmY+Ci0gICAgICA8QXJjaGl0
ZWN0dXJlPmFtZDY0PC9BcmNoaXRlY3R1cmU+Ci0gICAgPC9JbmY+Ci0gIDwvSXRlbURlZmluaXRp
b25Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iJChU
YXJnZXRQYXRoKSIgLz4KLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iJChPdXREaXIpJChU
YXJnZXROYW1lKS5wZGIiIC8+Ci0gICAgPEZpbGVzVG9QYWNrYWdlIEluY2x1ZGU9IkAoSW5mLT4n
JShDb3B5T3V0cHV0KScpIiBDb25kaXRpb249IidAKEluZiknIT0nJyIgLz4KLSAgPC9JdGVtR3Jv
dXA+Ci0gIDxJdGVtR3JvdXA+Ci0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVu
bmV0L3JlZ2lzdHJ5LmMiIC8+Ci0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVu
bmV0L2FkYXB0ZXIuYyIgLz4KLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5u
ZXQvbWFpbi5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9t
aW5pcG9ydC5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9y
ZWNlaXZlci5jIiAvPgotICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC90
cmFuc21pdHRlci5jIiAvPgotICA8L0l0ZW1Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8UmVz
b3VyY2VDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5uZXRceGVubmV0LnJjIiAvPgotICA8
L0l0ZW1Hcm91cD4KLSAgPEl0ZW1Hcm91cD4KLSAgICA8SW5mIEluY2x1ZGU9Ii4uXHhlbm5ldC5p
bmYiIC8+Ci0gIDwvSXRlbUdyb3VwPgotICA8SW1wb3J0IFByb2plY3Q9IiQoVkNUYXJnZXRzUGF0
aClcTWljcm9zb2Z0LkNwcC50YXJnZXRzIiAvPgorICAgICAgICAgICAgPC9Db21tYW5kPgorICAg
ICAgPE91dHB1dHM+Li5ceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaDwvT3V0cHV0
cz4KKyAgICAgIDxJbnB1dHM+Li5cLi5cc3JjXHhlbm5ldC5pbmY7Li5cLi5caW5jbHVkZVx2ZXJz
aW9uLmh4PC9JbnB1dHM+CisgICAgPC9DdXN0b21CdWlsZFN0ZXA+CisgICAgPENsQ29tcGlsZT4K
KyAgICAgIDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX01PRFVMRV9fPSJYRU5ORVQiO05ESVNf
TUlOSVBPUlRfRFJJVkVSO05ESVM2MF9NSU5JUE9SVD0xO1BPT0xfTlhfT1BUSU49MTslKFByZXBy
b2Nlc3NvckRlZmluaXRpb25zKTwvUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+CisgICAgICA8V2Fy
bmluZ0xldmVsPkVuYWJsZUFsbFdhcm5pbmdzPC9XYXJuaW5nTGV2ZWw+CisgICAgICA8RGlzYWJs
ZVNwZWNpZmljV2FybmluZ3M+NDcxMTs0NTQ4OzQ4MjA7NDY2ODs0MjU1OzYwMDE7NjA1NDsyODE5
NjslKERpc2FibGVTcGVjaWZpY1dhcm5pbmdzKTwvRGlzYWJsZVNwZWNpZmljV2FybmluZ3M+Cisg
ICAgICA8TXVsdGlQcm9jZXNzb3JDb21waWxhdGlvbj50cnVlPC9NdWx0aVByb2Nlc3NvckNvbXBp
bGF0aW9uPgorICAgICAgPEVuYWJsZVBSRWZhc3Q+dHJ1ZTwvRW5hYmxlUFJFZmFzdD4KKyAgICA8
L0NsQ29tcGlsZT4KKyAgICA8TGluaz4KKyAgICAgIDxJbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5k
bGVycz5mYWxzZTwvSW1hZ2VIYXNTYWZlRXhjZXB0aW9uSGFuZGxlcnM+CisgICAgICA8QWRkaXRp
b25hbERlcGVuZGVuY2llcz4kKERES19MSUJfUEFUSClcbmRpcy5saWI7JShBZGRpdGlvbmFsRGVw
ZW5kZW5jaWVzKTwvQWRkaXRpb25hbERlcGVuZGVuY2llcz4KKyAgICAgIDxFbmFibGVDT01EQVRG
b2xkaW5nPmZhbHNlPC9FbmFibGVDT01EQVRGb2xkaW5nPgorICAgIDwvTGluaz4KKyAgICA8SW5m
PgorICAgICAgPFNwZWNpZnlBcmNoaXRlY3R1cmU+dHJ1ZTwvU3BlY2lmeUFyY2hpdGVjdHVyZT4K
KyAgICAgIDxTcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbj50cnVlPC9TcGVjaWZ5RHJp
dmVyVmVyRGlyZWN0aXZlVmVyc2lvbj4KKyAgICAgIDxUaW1lU3RhbXA+JChNQUpPUl9WRVJTSU9O
KS4kKE1JTk9SX1ZFUlNJT04pLiQoTUlDUk9fVkVSU0lPTikuJChCVUlMRF9OVU1CRVIpPC9UaW1l
U3RhbXA+CisgICAgICA8RW5hYmxlVmVyYm9zZT50cnVlPC9FbmFibGVWZXJib3NlPgorICAgIDwv
SW5mPgorICA8L0l0ZW1EZWZpbml0aW9uR3JvdXA+CisgIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENv
bmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09J1dpbjMyJyI+CisgICAgPENsQ29tcGlsZT4KKyAgICAg
IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX2kzODZfXzslKFByZXByb2Nlc3NvckRlZmluaXRp
b25zKTwvUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+CisgICAgPC9DbENvbXBpbGU+CisgICAgPElu
Zj4KKyAgICAgIDxBcmNoaXRlY3R1cmU+eDg2PC9BcmNoaXRlY3R1cmU+CisgICAgPC9JbmY+Cisg
IDwvSXRlbURlZmluaXRpb25Hcm91cD4KKyAgPEl0ZW1EZWZpbml0aW9uR3JvdXAgQ29uZGl0aW9u
PSInJChQbGF0Zm9ybSknPT0neDY0JyI+CisgICAgPENsQ29tcGlsZT4KKyAgICAgIDxQcmVwcm9j
ZXNzb3JEZWZpbml0aW9ucz5fX3g4Nl82NF9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9Q
cmVwcm9jZXNzb3JEZWZpbml0aW9ucz4KKyAgICA8L0NsQ29tcGlsZT4KKyAgICA8SW5mPgorICAg
ICAgPEFyY2hpdGVjdHVyZT5hbWQ2NDwvQXJjaGl0ZWN0dXJlPgorICAgIDwvSW5mPgorICA8L0l0
ZW1EZWZpbml0aW9uR3JvdXA+CisgIDxJdGVtR3JvdXA+CisgICAgPEZpbGVzVG9QYWNrYWdlIElu
Y2x1ZGU9IiQoVGFyZ2V0UGF0aCkiIC8+CisgICAgPEZpbGVzVG9QYWNrYWdlIEluY2x1ZGU9IiQo
T3V0RGlyKSQoVGFyZ2V0TmFtZSkucGRiIiAvPgorICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRl
PSJAKEluZi0+JyUoQ29weU91dHB1dCknKSIgQ29uZGl0aW9uPSInQChJbmYpJyE9JyciIC8+Cisg
IDwvSXRlbUdyb3VwPgorICA8SXRlbUdyb3VwPgorICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4v
Li4vc3JjL3hlbm5ldC9yZWdpc3RyeS5jIiAvPgorICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4v
Li4vc3JjL3hlbm5ldC9hZGFwdGVyLmMiIC8+CisgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8u
Li9zcmMveGVubmV0L21haW4uYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvbWluaXBvcnQuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvcmVjZWl2ZXIuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvdHJhbnNtaXR0ZXIuYyIgLz4KKyAgPC9JdGVtR3JvdXA+CisgIDxJdGVtR3JvdXA+
CisgICAgPFJlc291cmNlQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVubmV0XHhlbm5ldC5y
YyIgLz4KKyAgPC9JdGVtR3JvdXA+CisgIDxJdGVtR3JvdXA+CisgICAgPEluZiBJbmNsdWRlPSIu
Llx4ZW5uZXQuaW5mIiAvPgorICA8L0l0ZW1Hcm91cD4KKyAgPEltcG9ydCBQcm9qZWN0PSIkKFZD
VGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAudGFyZ2V0cyIgLz4KIDwvUHJvamVjdD4KXCBObyBu
ZXdsaW5lIGF0IGVuZCBvZiBmaWxlCi0tIAoxLjkuNC5tc3lzZ2l0LjEKCgpfX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBs
aXN0Cndpbi1wdi1kZXZlbEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJv
amVjdC5vcmcvY2dpLWJpbi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:59 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:59 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebL-00049c-2q; Thu, 18 Dec 2014 17:10:59 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebJ-000492-47
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:57 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	4A/9C-15461-0AA03945; Thu, 18 Dec 2014 17:10:56 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-16.tower-21.messagelabs.com!1418922653!13136393!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31705 invoked from network); 18 Dec 2014 17:10:54 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877211"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:30 +0000
Message-ID: <1418921673-6008-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/6] Refactor for more maintainability.
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/adapter.c         | 3515 ++++++++++++++++++------------------------
 src/xennet/adapter.h         |  148 +-
 src/xennet/common.h          |   36 -
 src/xennet/main.c            |  348 -----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  328 ++--
 src/xennet/receiver.h        |   58 +-
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  301 ++--
 src/xennet/transmitter.h     |   50 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 12 files changed, 1963 insertions(+), 2938 deletions(-)
 delete mode 100644 src/xennet/common.h
 delete mode 100644 src/xennet/main.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/std.h

diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index 7cc49fb..a718a82 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -29,50 +29,31 @@
  * SUCH DAMAGE.
  */
 
+#include <ndis.h>
+#include "adapter.h"
+#include "transmitter.h"
+#include "receiver.h"
+#include <vif_interface.h>
 #include <version.h>
-#include "common.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_ADAPTER {
+    XENVIF_VIF_INTERFACE    VifInterface;
 
-//
-// List of supported OIDs.
-//
+    ULONG                   MaximumFrameSize;
+    ULONG                   CurrentLookahead;
 
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static NDIS_STATUS
-AdapterSetOffloadAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
-static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
-    );
-
-static NDIS_STATUS
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+    NDIS_HANDLE             NdisAdapterHandle;
+    NDIS_HANDLE             NdisDmaHandle;
+    NDIS_PNP_CAPABILITIES   Capabilities;
+    NDIS_OFFLOAD            Offload;
+    PROPERTIES              Properties;
 
-static NDIS_STATUS
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+    PXENNET_RECEIVER        Receiver;
+    PXENNET_TRANSMITTER     Transmitter;
+    BOOLEAN                 Enabled;
+};
 
 static NDIS_OID XennetSupportedOids[] =
 {
@@ -129,28 +110,25 @@ static NDIS_OID XennetSupportedOids[] =
     OID_PNP_SET_POWER,
 };
 
-#define INITIALIZE_NDIS_OBJ_HEADER(obj, type) do {               \
-    (obj).Header.Type = NDIS_OBJECT_TYPE_ ## type ;              \
-    (obj).Header.Revision = NDIS_ ## type ## _REVISION_1;        \
-    (obj).Header.Size = sizeof(obj);                             \
-} while (0)
+#define ADAPTER_POOL_TAG    'AteN'
 
-NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
+__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
+static VOID
+AdapterProcessSGList(
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PVOID                Reserved,
+    IN PSCATTER_GATHER_LIST SGL,
+    IN PVOID                Context
+    )
 {
-    if (Adapter == NULL)
-        return STATUS_INVALID_PARAMETER;
-
-    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof (ADAPTER), ' TEN');
-    if (*Adapter == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Reserved);
+    UNREFERENCED_PARAMETER(SGL);
+    UNREFERENCED_PARAMETER(Context);
 
-    return STATUS_SUCCESS;
+    ASSERT(FALSE);
 }
 
-//
-// Scatter gather allocate handler callback.
-// Should never get called.
-//
 __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
 static VOID
 AdapterAllocateComplete (
@@ -168,140 +146,17 @@ AdapterAllocateComplete (
     UNREFERENCED_PARAMETER(Context);
 
     ASSERT(FALSE);
-
-    return;
-}
-
-//
-// Required NDIS6 handler.
-// Should never get called.
-//
-VOID
-AdapterCancelOidRequest (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       RequestId
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-    UNREFERENCED_PARAMETER(RequestId);
-
-    return;
-}
-
-//
-// Required NDIS6 handler.
-// Should never get called.
-//
-
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-    UNREFERENCED_PARAMETER(CancelId);
-
-    return;
-}
-
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-
-    return FALSE;
-}
-
-//
-// Frees resources obtained by AdapterInitialize.
-//
-VOID
-AdapterCleanup (
-    IN  PADAPTER Adapter
-    )
-{
-    Trace("====>\n");
-
-    TransmitterDelete(&Adapter->Transmitter);
-    ReceiverCleanup(&Adapter->Receiver);
-
-    if (Adapter->NdisDmaHandle != NULL)
-        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
-
-    XENVIF_VIF(Release, &Adapter->VifInterface);
-    Adapter->AcquiredInterfaces = FALSE;
-
-    Trace("<====\n");
-    return;
-}
-
-static VOID
-AdapterMediaStateChange(
-    IN  PADAPTER                Adapter
-    )
-{
-    NDIS_LINK_STATE             LinkState;
-    NDIS_STATUS_INDICATION      StatusIndication;
-
-    NdisZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
-
-    LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
-    LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    LinkState.Header.Size = sizeof(NDIS_LINK_STATE);
-
-    XENVIF_VIF(MacQueryState,
-               &Adapter->VifInterface,
-               &LinkState.MediaConnectState,
-               &LinkState.RcvLinkSpeed,
-               &LinkState.MediaDuplexState);
-
-    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
-        Info("LINK: STATE UNKNOWN\n");
-    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
-        Info("LINK: DOWN\n");
-    } else {
-        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
-
-        if (LinkState.MediaDuplexState == MediaDuplexStateHalf) 
-            Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed);
-        else if (LinkState.MediaDuplexState == MediaDuplexStateFull)
-            Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed);
-        else
-            Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed);
-    }
-
-    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
-
-    NdisZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
-
-    StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
-    StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
-    StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION);
-    StatusIndication.SourceHandle = Adapter->NdisAdapterHandle;
-    StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
-    StatusIndication.StatusBuffer = &LinkState;
-    StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE);
-
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
 }
 
-
-//
-// Initializes adapter by allocating required resources and connects to 
-// netback.
-//
-
 static VOID
 AdapterVifCallback(
     IN  PVOID                       Context,
     IN  XENVIF_VIF_CALLBACK_TYPE    Type,
-    ...)
+    ...
+    )
 {
-    PADAPTER                        Adapter = Context;
-    va_list                         Arguments;
+    PXENNET_ADAPTER     Adapter = Context;
+    va_list             Arguments;
 
     va_start(Arguments, Type);
 
@@ -319,7 +174,7 @@ AdapterVifCallback(
 
         List = va_arg(Arguments, PLIST_ENTRY);
 
-        ReceiverReceivePackets(&Adapter->Receiver, List);
+        ReceiverReceivePackets(Adapter->Receiver, List);
         break;
     }
     case XENVIF_MAC_STATE_CHANGE: {
@@ -331,2247 +186,1925 @@ AdapterVifCallback(
     va_end(Arguments);
 }
 
-NDIS_STATUS
-AdapterGetAdvancedSettings(
-    IN PADAPTER pAdapter
+static VOID
+AdapterIndicateOffloadChanged(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    NDIS_CONFIGURATION_OBJECT configObject;
-    NDIS_HANDLE hConfigurationHandle;
-    NDIS_STRING ndisValue;
-    PNDIS_CONFIGURATION_PARAMETER pNdisData;
-    NDIS_STATUS ndisStatus;
-    NTSTATUS status;
-
-    configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
-    configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
-    configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
-    configObject.NdisHandle = pAdapter->NdisAdapterHandle;
-    configObject.Flags = 0;
+    NDIS_STATUS_INDICATION      Status;
+    NDIS_OFFLOAD                Offload;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
 
-    ndisStatus = NdisOpenConfigurationEx(&configObject, &hConfigurationHandle);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
 
-    status = STATUS_UNSUCCESSFUL;
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail1;
-
-#define read_property(field, name, default_val) \
-    do { \
-        RtlInitUnicodeString(&ndisValue, name); \
-        NdisReadConfiguration(&ndisStatus, &pNdisData, hConfigurationHandle, &ndisValue, NdisParameterInteger); \
-        if (ndisStatus == NDIS_STATUS_SUCCESS) { \
-            pAdapter->Properties.field = pNdisData->ParameterData.IntegerData; \
-        } else { \
-            pAdapter->Properties.field = default_val; \
-        } \
-    } while (FALSE);
-
-    read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
-    read_property(tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3);
-    read_property(udpv4_csum, L"*UDPChecksumOffloadIPv4", 3);
-    read_property(tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3);
-    read_property(udpv6_csum, L"*UDPChecksumOffloadIPv6", 3);
-    read_property(lsov4, L"*LSOv2IPv4", 1);
-    read_property(lsov6, L"*LSOv2IPv6", 1);
-    read_property(lrov4, L"LROIPv4", 1);
-    read_property(lrov6, L"LROIPv6", 1);
-    read_property(need_csum_value, L"NeedChecksumValue", 1);
-
-    NdisCloseConfiguration(hConfigurationHandle);
-
-    return NDIS_STATUS_SUCCESS;
-
-fail1:
-    Error("fail1\n");
-    return NDIS_STATUS_FAILURE;
-}
+    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
+    Offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
+    Offload.Header.Revision = NDIS_OFFLOAD_REVISION_1;
+    Offload.Header.Size = sizeof(NDIS_OFFLOAD);
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
-    )
-{
-    NDIS_STATUS ndisStatus;
-    NDIS_SG_DMA_DESCRIPTION DmaDescription;
-    NTSTATUS status;
+    Offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
-    if (!NT_SUCCESS(status))
-        return NDIS_STATUS_FAILURE;
+    if (RxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Receive.IpChecksum = 1;
+        Offload.Checksum.IPv4Receive.IpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Receive.UdpChecksum = 1;
+    }
 
-    Adapter->AcquiredInterfaces = TRUE;
+    Offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
 
-    Trace("====>\n");
+    if (RxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
+    }
 
-    Adapter->NdisAdapterHandle = AdapterHandle;
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
+    Offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    Adapter->Transmitter = (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSMITTER), ' TEN');
-    if (!Adapter->Transmitter) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto exit;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
     }
-
-    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
-
-    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
     }
-
-    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
     }
 
-    ndisStatus = AdapterGetAdvancedSettings(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
-    }
+    Offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
 
-    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
     }
-
-    ndisStatus = AdapterSetGeneralAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
     }
 
-    ndisStatus = AdapterSetOffloadAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   4,
+                   &Offload.LsoV2.IPv4.MaxOffLoadSize);
+        Offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Offload.LsoV2.IPv4.MinSegmentCount = 2;
     }
 
-    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
-
-    DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
-    DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
-    DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);
-    DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;
-    DmaDescription.MaximumPhysicalMapping = 65536;    
-    DmaDescription.ProcessSGListHandler = AdapterProcessSGList;
-    DmaDescription.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
-
-    ndisStatus = NdisMRegisterScatterGatherDma(Adapter->NdisAdapterHandle,
-                                               &DmaDescription,
-                                               &Adapter->NdisDmaHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        Adapter->NdisDmaHandle = NULL;
+    if (TxOptions->OffloadIpVersion6LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   6,
+                   &Offload.LsoV2.IPv6.MaxOffLoadSize);
+        Offload.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Offload.LsoV2.IPv6.MinSegmentCount = 2;
+        Offload.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        Offload.LsoV2.IPv6.TcpOptionsSupported = 1;
+    }
 
-    ASSERT(!Adapter->Enabled);
-    status = XENVIF_VIF(Enable,
-                        &Adapter->VifInterface,
-                        AdapterVifCallback,
-                        Adapter);
-    if (NT_SUCCESS(status)) {
-        TransmitterEnable(Adapter->Transmitter);
-        Adapter->Enabled = TRUE;
-        ndisStatus = NDIS_STATUS_SUCCESS;
-    } else {
-        ndisStatus = NDIS_STATUS_FAILURE;
+    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof(NDIS_OFFLOAD))) {
+        Adapter->Offload = Offload;
+        // DISPPLAY_OFFLOAD(Offload);
     }
 
-exit:
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Status, sizeof(NDIS_STATUS_INDICATION));
+    Status.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    Status.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    Status.Header.Size = sizeof(NDIS_STATUS_INDICATION);
+    Status.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    Status.StatusBuffer = &Offload;
+    Status.StatusBufferSize = sizeof(Offload);
 
-    Trace("<==== (%08x)\n", ndisStatus);
-    return ndisStatus;
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &Status);
 }
 
-//
-// Scatter gather process handler callback.
-// Should never get called.
-//
 static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
+AdapterGetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PULONG                  PacketFilter
     )
 {
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Reserved);
-    UNREFERENCED_PARAMETER(SGL);
-    UNREFERENCED_PARAMETER(Context);
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    ASSERT(FALSE);
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               &UnicastFilterLevel);
 
-    return;
-}
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               &MulticastFilterLevel);
 
-//
-// Get\Set OID handler.
-//
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    NDIS_STATUS ndisStatus;
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_BROADCAST,
+               &BroadcastFilterLevel);
 
-    switch (NdisRequest->RequestType) {
-        case NdisRequestSetInformation:            
-            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
-            break;
-                
-        case NdisRequestQueryInformation:
-        case NdisRequestQueryStatistics:
-            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
-            break;
+    *PacketFilter = 0;
 
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+    if (UnicastFilterLevel == XENVIF_MAC_FILTER_ALL) {
+        ASSERT3U(MulticastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
+        ASSERT3U(BroadcastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
 
-    return ndisStatus;
+        *PacketFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+        return;
+    } else if (UnicastFilterLevel == XENVIF_MAC_FILTER_MATCHING) {
+        *PacketFilter |= NDIS_PACKET_TYPE_DIRECTED;
+    }
+
+    if (MulticastFilterLevel == XENVIF_MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+    else if (MulticastFilterLevel == XENVIF_MAC_FILTER_MATCHING)
+        *PacketFilter |= NDIS_PACKET_TYPE_MULTICAST;
+
+    if (BroadcastFilterLevel == XENVIF_MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
 }
 
-//
-// Temporarily pauses adapter.
-//
-NDIS_STATUS
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+static NDIS_STATUS
+AdapterSetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PULONG                  PacketFilter
     )
 {
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
-    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    Trace("====>\n");
+    if (*PacketFilter & ~XENNET_SUPPORTED_PACKET_FILTERS)
+        return NDIS_STATUS_INVALID_PARAMETER;
 
-    if (!Adapter->Enabled)
+    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
         goto done;
+    }
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
+        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-    AdapterMediaStateChange(Adapter);
+    if (*PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else if (*PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
+        MulticastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        MulticastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-    Adapter->Enabled = FALSE;
+    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
 done:
-    Trace("<====\n");
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               UnicastFilterLevel);
+
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               MulticastFilterLevel);
+
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_BROADCAST,
+               BroadcastFilterLevel);
+
     return NDIS_STATUS_SUCCESS;
 }
 
-//
-// Handles PNP and Power events. NOP.
-//
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+static NDIS_STATUS
+AdapterGetOffloadEncapsulation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OFFLOAD_ENCAPSULATION Offload
     )
 {
-    UNREFERENCED_PARAMETER(NdisHandle);
+    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
 
+    if (Offload->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Offload->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto invalid_parameter;
 
-    switch (NetDevicePnPEvent->DevicePnPEvent) {
-        case NdisDevicePnPEventQueryRemoved:
-            break;
+    if (Offload->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Offload->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto invalid_parameter;
 
-        case NdisDevicePnPEventRemoved:
-            break;       
-
-        case NdisDevicePnPEventSurpriseRemoved:
-            break;
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
 
-        case NdisDevicePnPEventQueryStopped:
-            break;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    TxOptions->Value = 0;
+    TxOptions->OffloadTagManipulation = 1;
+
+    if (Adapter->Properties.lsov4 && Options.OffloadIpVersion4LargePacket)
+        TxOptions->OffloadIpVersion4LargePacket = 1;
+    if (Adapter->Properties.lsov6 && Options.OffloadIpVersion6LargePacket)
+        TxOptions->OffloadIpVersion6LargePacket = 1;
+    if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
+        TxOptions->OffloadIpVersion4HeaderChecksum = 1;
+    if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
+        TxOptions->OffloadIpVersion4TcpChecksum = 1;
+    if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
+        TxOptions->OffloadIpVersion4UdpChecksum = 1;
+    if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
+        TxOptions->OffloadIpVersion6TcpChecksum = 1;
+    if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
+        TxOptions->OffloadIpVersion6UdpChecksum = 1;
+
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
 
-        case NdisDevicePnPEventStopped:
-            break;      
-            
-        case NdisDevicePnPEventPowerProfileChanged:
-            break;      
-            
-        default:
-            break;         
-    };
+    if (Adapter->Properties.need_csum_value)
+        RxOptions->NeedChecksumValue = 1;
+    if (Adapter->Properties.lrov4)
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+    if (Adapter->Properties.lrov4)
+        RxOptions->NeedLargePacketSplit = 1;
+    if (Adapter->Properties.lrov6)
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+    if (Adapter->Properties.lrov6)
+        RxOptions->NeedLargePacketSplit = 1;
+    if (Adapter->Properties.ipv4_csum & 2)
+        RxOptions->OffloadIpVersion4HeaderChecksum = 1;
+    if (Adapter->Properties.tcpv4_csum & 2)
+        RxOptions->OffloadIpVersion4TcpChecksum = 1;
+    if (Adapter->Properties.udpv4_csum & 2)
+        RxOptions->OffloadIpVersion4UdpChecksum = 1;
+    if (Adapter->Properties.tcpv6_csum & 2)
+        RxOptions->OffloadIpVersion6TcpChecksum = 1;
+    if (Adapter->Properties.udpv6_csum & 2)
+        RxOptions->OffloadIpVersion6UdpChecksum = 1;
+
+    AdapterIndicateOffloadChanged(Adapter);
+    return NDIS_STATUS_SUCCESS;
 
-    return;
+invalid_parameter:
+    return NDIS_STATUS_INVALID_PARAMETER;
 }
 
-//
-// Reports general statistics to NDIS.
-//
-static NDIS_STATUS 
-AdapterQueryGeneralStatistics (
-    IN  PADAPTER                Adapter,
-    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
+#define NO_CHANGE(x)    ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
+#define RX_ENABLED(x)   ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||            \
+                         (x) == NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED)
+#define TX_ENABLED(x)   ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||            \
+                         (x) == NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED)
+#define CHANGE(x, y)    (((x) == (y)) ? 0 : (((x) = (y)) != (y)))
+
+static NDIS_STATUS
+AdapterGetTcpOffloadParameters(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OFFLOAD_PARAMETERS    Offload
     )
 {
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    ULONGLONG   Value;
+    XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS     TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS     RxOptions;
+    BOOLEAN                         Changed;
+
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
+
+    if (!NO_CHANGE(Offload->IPsecV1))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV1))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->TcpConnectionIPv4))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->TcpConnectionIPv6))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV2IPv4) &&
+        !(Options.OffloadIpVersion4LargePacket))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV2IPv6) &&
+        !(Options.OffloadIpVersion6LargePacket))
+        goto invalid_parameter;
+
+    Changed = FALSE;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+
+    if (Offload->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion4LargePacket, 1);
+    } else if (Offload->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion4LargePacket, 0);
+    }
+
+    if (Offload->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion6LargePacket, 1);
+    } else if (Offload->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion6LargePacket, 0);
+    }
 
-    NdisZeroMemory(NdisStatisticsInfo, sizeof(NDIS_STATISTICS_INFO));
-    NdisStatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;
-    NdisStatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    NdisStatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4HeaderChecksum, TX_ENABLED(Offload->IPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4TcpChecksum, TX_ENABLED(Offload->TCPIPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4UdpChecksum, TX_ENABLED(Offload->UDPIPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion6TcpChecksum, TX_ENABLED(Offload->TCPIPv6Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion6UdpChecksum, TX_ENABLED(Offload->UDPIPv6Checksum));
+
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4HeaderChecksum, RX_ENABLED(Offload->IPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4TcpChecksum, RX_ENABLED(Offload->TCPIPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4UdpChecksum, RX_ENABLED(Offload->UDPIPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion6TcpChecksum, RX_ENABLED(Offload->TCPIPv6Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion6UdpChecksum, RX_ENABLED(Offload->UDPIPv6Checksum));
+
+    if (Changed)
+        AdapterIndicateOffloadChanged(Adapter);
+
+    return NDIS_STATUS_SUCCESS;
+
+invalid_parameter:
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
+
+#undef NO_CHANGE
+#undef RX_ENABLED
+#undef TX_ENABLED
+#undef CHANGE
+
+static NDIS_STATUS
+AdapterQueryGeneralStatistics(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_STATISTICS_INFO   Info
+    )
+{
+    ULONGLONG   Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    RtlZeroMemory(Info, sizeof(NDIS_STATISTICS_INFO));
+    Info->Header.Revision = NDIS_OBJECT_REVISION_1;
+    Info->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Info->Header.Size = sizeof(NDIS_STATISTICS_INFO);
 
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BACKEND_ERRORS,
                       &Value);
-
-    NdisStatisticsInfo->ifInErrors = Value;
-
+    Info->ifInErrors = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_FRONTEND_ERRORS,
                       &Value);
+    Info->ifInErrors += Value;
 
-    NdisStatisticsInfo->ifInErrors += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_PACKETS_DROPPED,
                       &Value);
+    Info->ifInDiscards = Value;
 
-    NdisStatisticsInfo->ifInDiscards = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInOctets = Value;
-
+    Info->ifHCInOctets = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInOctets += Value;
-
+    Info->ifHCInOctets += Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCInOctets += Value;
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_OCTETS,
                       &Value);
+    Info->ifHCInUcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInUcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_PACKETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInUcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
-
+    Info->ifHCInUcastPkts = Value;
+    
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_OCTETS,
                       &Value);
+    Info->ifHCInMulticastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_PACKETS,
                       &Value);
+    Info->ifHCInMulticastPkts = Value;
 
-    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCInBroadcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_PACKETS,
                       &Value);
+    Info->ifHCInBroadcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
                       &Value);
-
-    NdisStatisticsInfo->ifOutErrors = Value;
-
+    Info->ifOutErrors = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
                       &Value);
+    Info->ifOutErrors += Value;
 
-    NdisStatisticsInfo->ifOutErrors += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCOutOctets = Value;
-
+    Info->ifHCOutOctets = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCOutOctets += Value;
-
+    Info->ifHCOutOctets += Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCOutOctets += Value;
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
                       &Value);
+    Info->ifHCOutUcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
                       &Value);
+    Info->ifHCOutUcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
                       &Value);
+    Info->ifHCOutMulticastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
                       &Value);
+    Info->ifHCOutMulticastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCOutBroadcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
                       &Value);
+    Info->ifHCOutBroadcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
+    Info->ifOutDiscards = 0;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
-    NdisStatisticsInfo->ifOutDiscards = 0;
+    return NDIS_STATUS_SUCCESS;
+}
 
+static NDIS_STATUS
+AdapterQueryMulticastList(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN OUT PULONG           BytesNeeded
+    )
+{
+    ULONG       Count;
+    NDIS_STATUS ndisStatus;
+    NTSTATUS    status;
+
+    XENVIF_VIF(MacQueryMulticastAddresses,
+               &Adapter->VifInterface,
+               NULL,
+               &Count);
+    *BytesNeeded = Count * ETHERNET_ADDRESS_LENGTH;
+
+    ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+    if (BufferLength < *BytesNeeded) 
+        goto fail1;
+    
+    status = XENVIF_VIF(MacQueryMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Buffer,
+                        &Count);
+    ndisStatus = NDIS_STATUS_FAILURE;
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail2:
+fail1:
     return ndisStatus;
 }
 
-static VOID
-GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
+static FORCEINLINE NDIS_STATUS
+AdapterSetMulticastAddresses(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PETHERNET_ADDRESS   Address,
+    IN  ULONG               Count
+    )
 {
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
+    NTSTATUS        status;
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               &UnicastFilterLevel);
+    status = XENVIF_VIF(MacSetMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Address,
+                        Count);
+    if (!NT_SUCCESS(status))
+        return NDIS_STATUS_INVALID_DATA;
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               &MulticastFilterLevel);
+    return NDIS_STATUS_SUCCESS;
+}
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               &BroadcastFilterLevel);
+static NDIS_STATUS
+AdapterGetXmitOk(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONGLONG          Buffer
+    )
+{
+    ULONGLONG   Value;
 
-    *PacketFilter = 0;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                &Value);
 
-    if (UnicastFilterLevel == XENVIF_MAC_FILTER_ALL) {
-        ASSERT3U(MulticastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
-        ASSERT3U(BroadcastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
+    *Buffer = (ULONG)Value;
 
-        *PacketFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
-        return;
-    } else if (UnicastFilterLevel == XENVIF_MAC_FILTER_MATCHING) {
-        *PacketFilter |= NDIS_PACKET_TYPE_DIRECTED;
-    }
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-    if (MulticastFilterLevel == XENVIF_MAC_FILTER_ALL)
-        *PacketFilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-    else if (MulticastFilterLevel == XENVIF_MAC_FILTER_MATCHING)
-        *PacketFilter |= NDIS_PACKET_TYPE_MULTICAST;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-    if (BroadcastFilterLevel == XENVIF_MAC_FILTER_ALL)
-        *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
+    return NDIS_STATUS_SUCCESS;
 }
 
-#define MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))
-
-//
-// Handles OID queries.
-//
-#pragma warning(push)
-#pragma warning(disable:6262)
-static NDIS_STATUS 
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+static NDIS_STATUS
+AdapterGetRcvOk(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONGLONG          Buffer
     )
 {
-    ULONG bytesAvailable = 0;
-    ULONG bytesNeeded = 0;
-    ULONG bytesWritten = 0;
-    BOOLEAN doCopy = TRUE;
-    PVOID info = NULL;
-    ULONGLONG infoData;
-    ULONG informationBufferLength;
-    PVOID informationBuffer;
-    NDIS_INTERRUPT_MODERATION_PARAMETERS intModParams;
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    NDIS_OID oid;
-
-    informationBuffer = NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
-    informationBufferLength = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
-    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
-    switch (oid) {
-        case OID_PNP_CAPABILITIES:
-            Trace("PNP_CAPABILITIES\n");
-
-            info = &Adapter->Capabilities;
-            bytesAvailable = sizeof(Adapter->Capabilities);
-            break;
-
-        case OID_PNP_QUERY_POWER:
-            Trace("QUERY_POWER\n");
-
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
-
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Trace("D0\n");
-                    break;
-
-                case NdisDeviceStateD1:
-                    Trace("D1\n");
-                    break;
-
-                case NdisDeviceStateD2:
-                    Trace("D2\n");
-                    break;
-
-                case NdisDeviceStateD3:
-                    Trace("D3\n");
-                    break;
-                }
-            }
-            break;
-
-        case OID_GEN_SUPPORTED_LIST:
-            info = &XennetSupportedOids[0];
-            bytesAvailable = sizeof(XennetSupportedOids);
-            break;
-
-        case OID_GEN_HARDWARE_STATUS:
-            infoData = NdisHardwareStatusReady;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MEDIA_SUPPORTED:
-        case OID_GEN_MEDIA_IN_USE:
-            infoData = XENNET_MEDIA_TYPE;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAXIMUM_LOOKAHEAD:
-            infoData = Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_BUFFER_SPACE:
-            XENVIF_VIF(TransmitterQueryRingSize,
-                       &Adapter->VifInterface,
-                       (PULONG)&infoData);
-            infoData *= Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_RECEIVE_BUFFER_SPACE:
-            XENVIF_VIF(TransmitterQueryRingSize,
-                       &Adapter->VifInterface,
-                       (PULONG)&infoData);
-            infoData *= Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-        case OID_GEN_RECEIVE_BLOCK_SIZE:
-            infoData = Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_VENDOR_DESCRIPTION:
-            info = COMPANY_NAME_STR;
-            bytesAvailable = (ULONG)strlen(info) + 1;
-            break;
-
-        case OID_GEN_VENDOR_DRIVER_VERSION:
-            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_DRIVER_VERSION:
-            infoData = (6 << 8) | 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAC_OPTIONS:
-            infoData = XENNET_MAC_OPTIONS;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        
-        case OID_GEN_STATISTICS:
-            doCopy = FALSE;
-
-            bytesAvailable = sizeof(NDIS_STATISTICS_INFO);
-            if (informationBufferLength >= bytesAvailable) {
-                ndisStatus = AdapterQueryGeneralStatistics(Adapter, 
-                                                           informationBuffer);
-
-            }
-
-            break;
-
-        case OID_802_3_MULTICAST_LIST: {
-            ULONG Count;
-
-            doCopy = FALSE;
-
-            XENVIF_VIF(MacQueryMulticastAddresses,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &Count);
-            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
+    ULONGLONG   Value;
 
-            if (informationBufferLength >= bytesAvailable) {
-                NTSTATUS status;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_UNICAST_PACKETS,
+                &Value);
 
-                status = XENVIF_VIF(MacQueryMulticastAddresses,
-                                    &Adapter->VifInterface,
-                                    informationBuffer,
-                                    &Count);
-                if (!NT_SUCCESS(status))
-                    ndisStatus = NDIS_STATUS_FAILURE;
-            }
+    *Buffer = (ULONG)Value;
 
-            break;
-        }
-        case OID_802_3_PERMANENT_ADDRESS:
-            XENVIF_VIF(MacQueryPermanentAddress,
-                       &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
-            break;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_MULTICAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-        case OID_802_3_CURRENT_ADDRESS:
-            XENVIF_VIF(MacQueryCurrentAddress,
-                       &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
-            break;
-
-        case OID_GEN_MAXIMUM_FRAME_SIZE:
-            infoData = Adapter->MaximumFrameSize -
-                       sizeof (ETHERNET_TAGGED_HEADER);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAXIMUM_TOTAL_SIZE:
-            infoData = Adapter->MaximumFrameSize -
-                       sizeof (ETHERNET_TAGGED_HEADER) +
-                       sizeof (ETHERNET_UNTAGGED_HEADER);
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            infoData = Adapter->CurrentLookahead;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_VENDOR_ID:
-            infoData = 0x5853;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_LINK_SPEED: {
-            ULONG64 LinkSpeed;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BROADCAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &LinkSpeed,
-                       NULL);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData = (ULONG)(LinkSpeed / 100);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MEDIA_CONNECT_STATUS:
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
-                       NULL,
-                       NULL);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        case OID_GEN_MAXIMUM_SEND_PACKETS:
-            infoData = 16;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            GetPacketFilter(Adapter, (PULONG)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_XMIT_OK: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
+static NDIS_STATUS
+AdapterGetXmitError(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONG              Buffer
+    )
+{
+    ULONGLONG   Value;
 
-            infoData = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                &Value);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
+    *Buffer = (ULONG)Value;
 
-            infoData += Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData += Value;
+static FORCEINLINE NDIS_STATUS
+AdapterGetRcvError(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONG              Buffer
+    )
+{
+    ULONGLONG   Value;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_RCV_OK: {
-            ULONGLONG   Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BACKEND_ERRORS,
+                &Value);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
+    *Buffer = (ULONG)Value;
 
-            infoData = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_FRONTEND_ERRORS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData += Value;
+static FORCEINLINE NDIS_STATUS
+AdapterInterruptModeration(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_INTERRUPT_MODERATION_PARAMETERS   Params
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
+    Params->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Params->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+    Params->Header.Size = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
 
-            infoData += Value;
+    Params->Flags = 0;
+    Params->InterruptModeration = NdisInterruptModerationNotSupported;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_XMIT_ERROR: {
-            ULONGLONG   Value;
+    return NDIS_STATUS_SUCCESS;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                       &Value);
+NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->NdisAdapterHandle;
+}
 
-            infoData = Value;
+PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return &Adapter->VifInterface;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                       &Value);
+PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->Transmitter;
+}
 
-            infoData += Value;
+PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->Receiver;
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_ERROR: {
-            ULONGLONG   Value;
+NDIS_STATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    NTSTATUS        status;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BACKEND_ERRORS,
-                       &Value);
+    if (Adapter->Enabled)
+        return NDIS_STATUS_SUCCESS;
 
-            infoData = Value;
+    status = XENVIF_VIF(Enable,
+                        &Adapter->VifInterface,
+                        AdapterVifCallback,
+                        Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_FRONTEND_ERRORS,
-                       &Value);
+    TransmitterEnable(Adapter->Transmitter);
+    Adapter->Enabled = TRUE;
 
-            infoData += Value;
+    return NDIS_STATUS_SUCCESS;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_NO_BUFFER:
-            infoData = 0;   // We'd need to query VIF TX drop stats from dom0
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_802_3_MAXIMUM_LIST_SIZE:
-            infoData = 32;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_IP4_OFFLOAD_STATS:
-        case OID_IP6_OFFLOAD_STATS:
-        case OID_GEN_SUPPORTED_GUIDS:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        case OID_GEN_RCV_CRC_ERROR:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_802_3_RCV_ERROR_ALIGNMENT:
-        case OID_802_3_XMIT_ONE_COLLISION:
-        case OID_802_3_XMIT_MORE_COLLISIONS:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_DIRECTED_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                       &Value);
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
 
-            infoData = Value;
+BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    if (!Adapter->Enabled)
+        return FALSE;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_XMIT: {
-            ULONGLONG   Value;
+    XENVIF_VIF(Disable,
+               &Adapter->VifInterface);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
+    AdapterMediaStateChange(Adapter);
 
-            infoData = Value;
+    Adapter->Enabled = FALSE;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_XMIT: {
-            ULONGLONG   Value;
+    return TRUE;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                       &Value);
+VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    NDIS_LINK_STATE         LinkState;
+    NDIS_STATUS_INDICATION  StatusIndication;
 
-            infoData = Value;
+    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
+    LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
+    LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    LinkState.Header.Size = sizeof(NDIS_LINK_STATE);
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
+    XENVIF_VIF(MacQueryState,
+               &Adapter->VifInterface,
+               &LinkState.MediaConnectState,
+               &LinkState.RcvLinkSpeed,
+               &LinkState.MediaDuplexState);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
+    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
+        Info("LINK: STATE UNKNOWN\n");
+    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
+        Info("LINK: DOWN\n");
+    } else {
+        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
 
-            infoData = Value;
+        if (LinkState.MediaDuplexState == MediaDuplexStateHalf) 
+            Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed);
+        else if (LinkState.MediaDuplexState == MediaDuplexStateFull)
+            Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed);
+        else
+            Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed);
+    }
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_XMIT: {
-            ULONGLONG   Value;
+    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                       &Value);
+    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
+    StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION);
+
+    StatusIndication.SourceHandle = Adapter->NdisAdapterHandle;
+    StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
+    StatusIndication.StatusBuffer = &LinkState;
+    StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE);
 
-            infoData = Value;
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded;
+    ULONG           BytesRead;
+    NDIS_STATUS     ndisStatus;
+
+    Buffer = Request->DATA.SET_INFORMATION.InformationBuffer;
+    BufferLength = Request->DATA.SET_INFORMATION.InformationBufferLength;
+    BytesNeeded = BytesRead = 0;
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    switch (Request->DATA.SET_INFORMATION.Oid) {
+    case OID_PNP_SET_POWER:
+        BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+        // do nothing
+        break;
+
+    case OID_GEN_CURRENT_LOOKAHEAD:
+        BytesNeeded = sizeof(ULONG);
+        Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
+        if (BufferLength == BytesNeeded) {
+            Adapter->CurrentLookahead = *(PULONG)Buffer;
+            BytesRead = sizeof(ULONG);
+        }            
+        break;
+
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        BytesNeeded = sizeof(ULONG);
+        if (BufferLength == BytesNeeded) {
+            AdapterSetPacketFilter(Adapter,
+                                   (PULONG)Buffer);
+            BytesRead = sizeof(ULONG);
         }
-        case OID_GEN_BROADCAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
+    case OID_802_3_MULTICAST_LIST:
+        BytesNeeded = ETHERNET_ADDRESS_LENGTH;
+        if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
+            ndisStatus = AdapterSetMulticastAddresses(Adapter,
+                                                      Buffer,
+                                                      BufferLength / ETHERNET_ADDRESS_LENGTH);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = BufferLength;
+        } else {
+            ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+        }
+        break;
 
-            infoData = Value;
+    case OID_OFFLOAD_ENCAPSULATION:
+        BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetOffloadEncapsulation(Adapter,
+                                                        (PNDIS_OFFLOAD_ENCAPSULATION)Buffer);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+        }
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_TCP_OFFLOAD_PARAMETERS:
+        BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetTcpOffloadParameters(Adapter,
+                                                        (PNDIS_OFFLOAD_PARAMETERS)Buffer);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
         }
-        case OID_GEN_DIRECTED_BYTES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_OCTETS,
-                       &Value);
+    case OID_GEN_INTERRUPT_MODERATION:
+    case OID_GEN_MACHINE_NAME:
+    default:
+        ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        break;
+    }
+
+    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
+    if (ndisStatus == NDIS_STATUS_SUCCESS)
+        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
 
-            infoData = Value;
+    return ndisStatus;
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+static FORCEINLINE NDIS_STATUS
+__CopyBuffer(
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN  PVOID               Source,
+    IN OUT PULONG           SourceLength
+    )
+{
+    if (BufferLength >= *SourceLength) {
+        RtlCopyMemory(Buffer, Source, *SourceLength);
+        return NDIS_STATUS_SUCCESS;
+    } else {
+        *SourceLength = BufferLength;
+        RtlCopyMemory(Buffer, Source, *SourceLength);
+        return NDIS_STATUS_BUFFER_TOO_SHORT;
+    }
+}
+
+static FORCEINLINE NDIS_STATUS
+__SetUlong(
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN  ULONG               Source,
+    IN OUT PULONG           SourceLength
+    )
+{
+    if (BufferLength >= sizeof(ULONG)) {
+        *(PULONG)Buffer = Source;
+        *SourceLength = sizeof(ULONG);
+        return NDIS_STATUS_SUCCESS;
+    } else {
+        *SourceLength = 0;
+        return NDIS_STATUS_BUFFER_TOO_SHORT;
+    }
+}
+
+NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded;
+    ULONG           BytesWritten;
+    ULONG           Value32;
+    ULONGLONG       Value64;
+    NDIS_STATUS     ndisStatus;
+
+    Buffer = Request->DATA.QUERY_INFORMATION.InformationBuffer;
+    BufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength;
+    BytesNeeded = BytesWritten = sizeof(ULONG);
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+    case OID_PNP_CAPABILITIES:
+        BytesNeeded = BytesWritten = sizeof(Adapter->Capabilities);
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  &Adapter->Capabilities,
+                                  &BytesWritten);
+        break;
+
+    case OID_PNP_QUERY_POWER:
+        BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+        // do nothing
+        break;
+
+    case OID_GEN_SUPPORTED_LIST:
+        BytesNeeded = BytesWritten = sizeof(XennetSupportedOids);
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  &XennetSupportedOids[0],
+                                  &BytesWritten);
+        break;
+
+    case OID_GEN_HARDWARE_STATUS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                NdisHardwareStatusReady,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MEDIA_SUPPORTED:
+    case OID_GEN_MEDIA_IN_USE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                XENNET_MEDIA_TYPE,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MAXIMUM_LOOKAHEAD:
+    case OID_GEN_TRANSMIT_BLOCK_SIZE:
+    case OID_GEN_RECEIVE_BLOCK_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_TRANSMIT_BUFFER_SPACE:
+    case OID_GEN_RECEIVE_BUFFER_SPACE:
+        XENVIF_VIF(TransmitterQueryRingSize,
+                    &Adapter->VifInterface,
+                    (PULONG)&Value32);
+        Value32 *= Adapter->MaximumFrameSize;
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Value32,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_DESCRIPTION:
+        BytesNeeded = BytesWritten = (ULONG)strlen(COMPANY_NAME_STR) + 1;
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  COMPANY_NAME_STR,
+                                  &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_DRIVER_VERSION:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DRIVER_VERSION:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (6 << 8) | 0, // NDIS 6.0
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MAC_OPTIONS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                XENNET_MAC_OPTIONS,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_STATISTICS:
+        BytesNeeded = BytesWritten = sizeof(NDIS_STATISTICS_INFO);
+        if (BufferLength >= BytesNeeded)
+            ndisStatus = AdapterQueryGeneralStatistics(Adapter,
+                                                       (PNDIS_STATISTICS_INFO)Buffer);
+        break;
+
+    case OID_802_3_MULTICAST_LIST:
+        ndisStatus = AdapterQueryMulticastList(Adapter,
+                                               Buffer,
+                                               BufferLength,
+                                               &BytesNeeded);
+        BytesWritten = BytesNeeded;
+        break;
+
+    case OID_802_3_PERMANENT_ADDRESS:
+        BytesNeeded = BytesWritten = sizeof(ETHERNET_ADDRESS);
+        if (BufferLength >= BytesNeeded) {
+            XENVIF_VIF(MacQueryPermanentAddress,
+                       &Adapter->VifInterface,
+                       (PETHERNET_ADDRESS)Buffer);
         }
-        case OID_GEN_DIRECTED_FRAMES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
+    case OID_802_3_CURRENT_ADDRESS:
+        BytesNeeded = BytesWritten = sizeof(ETHERNET_ADDRESS);
+        if (BufferLength >= BytesNeeded) {
+            XENVIF_VIF(MacQueryCurrentAddress,
                        &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
+                       (PETHERNET_ADDRESS)Buffer);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_MAXIMUM_FRAME_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize - sizeof(ETHERNET_TAGGED_HEADER),
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_RCV: {
-            ULONGLONG   Value;
+    case OID_GEN_MAXIMUM_TOTAL_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize -
+                                    sizeof(ETHERNET_TAGGED_HEADER) +
+                                    sizeof (ETHERNET_UNTAGGED_HEADER),
+                                &BytesWritten);
+        break;
 
-            XENVIF_VIF(QueryStatistic,
+    case OID_GEN_CURRENT_LOOKAHEAD:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->CurrentLookahead,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_ID:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                0x5853,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_LINK_SPEED:
+        XENVIF_VIF(MacQueryState,
+                   &Adapter->VifInterface,
+                   NULL,
+                   &Value64,
+                   NULL);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)(Value64 / 100),
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MEDIA_CONNECT_STATUS:
+        if (BufferLength >= sizeof(ULONG)) {
+            XENVIF_VIF(MacQueryState,
                        &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_OCTETS,
-                       &Value);
+                       (PNET_IF_MEDIA_CONNECT_STATE)Buffer,
+                       NULL,
+                       NULL);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_MAXIMUM_SEND_PACKETS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                16,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        if (BufferLength >= sizeof(ULONG)) {
+            AdapterGetPacketFilter(Adapter,
+                                   (PULONG)Buffer);
         }
-        case OID_GEN_MULTICAST_FRAMES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
+    case OID_GEN_XMIT_OK:
+        BytesNeeded = BytesWritten = sizeof(ULONGLONG);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetXmitOk(Adapter,
+                                          (PULONGLONG)Buffer);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_RCV_OK:
+        BytesNeeded = BytesWritten = sizeof(ULONGLONG);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetRcvOk(Adapter,
+                                          (PULONGLONG)Buffer);
+        }
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_XMIT_ERROR:
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetXmitError(Adapter,
+                                             (PULONG)Buffer);
         }
-        case OID_GEN_BROADCAST_BYTES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_OCTETS,
-                       &Value);
+    case OID_GEN_RCV_ERROR:
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetRcvError(Adapter,
+                                            (PULONG)Buffer);
+        }
+        break;
+
+    case OID_GEN_RCV_NO_BUFFER:
+    case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+    case OID_GEN_RCV_CRC_ERROR:
+    case OID_802_3_RCV_ERROR_ALIGNMENT:
+    case OID_802_3_XMIT_ONE_COLLISION:
+    case OID_802_3_XMIT_MORE_COLLISIONS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                0,
+                                &BytesWritten);
+        break;
+
+    case OID_802_3_MAXIMUM_LIST_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                32,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MULTICAST_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MULTICAST_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_BROADCAST_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_BROADCAST_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_UNICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_UNICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            infoData = Value;
+    case OID_GEN_MULTICAST_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_MULTICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_RCV: {
-            ULONGLONG   Value;
+    case OID_GEN_MULTICAST_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_MULTICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
+    case OID_GEN_BROADCAST_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_BROADCAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            infoData = Value;
+    case OID_GEN_BROADCAST_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_BROADCAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_INTERRUPT_MODERATION:
+        BytesNeeded = BytesWritten = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+        if (BufferLength >= BytesWritten) {
+            ndisStatus = AdapterInterruptModeration(Adapter,
+                                                    (PNDIS_INTERRUPT_MODERATION_PARAMETERS)Buffer);
         }
-        case OID_GEN_INTERRUPT_MODERATION:
-            intModParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-            intModParams.Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
-            intModParams.Header.Size = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
-            intModParams.Flags = 0;
-            intModParams.InterruptModeration = NdisInterruptModerationNotSupported;
-            info = &intModParams;
-            bytesAvailable = sizeof(intModParams);
-            break;
+        break;
+
+    case OID_IP4_OFFLOAD_STATS:
+    case OID_IP6_OFFLOAD_STATS:
+    case OID_GEN_SUPPORTED_GUIDS:
 
         // We don't handle these since NDIS 6.0 is supposed to do this for us
-        case OID_GEN_MAC_ADDRESS:
-        case OID_GEN_MAX_LINK_SPEED:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-		// ignore these common unwanted OIDs
-		case OID_GEN_INIT_TIME_MS:
-		case OID_GEN_RESET_COUNTS:
-		case OID_GEN_MEDIA_SENSE_COUNTS:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
-
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        if (bytesAvailable <= informationBufferLength) {
-            bytesNeeded = bytesAvailable;
-            bytesWritten = bytesAvailable;
-        } else {
-            bytesNeeded = bytesAvailable;
-            bytesWritten = informationBufferLength;
-            ndisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
-        }
+    case OID_GEN_MAC_ADDRESS:
+    case OID_GEN_MAX_LINK_SPEED:
 
-        if (bytesWritten && doCopy) {
-            NdisMoveMemory(informationBuffer, info, bytesWritten);
+        // ignore these common unwanted OIDs
+	case OID_GEN_INIT_TIME_MS:
+	case OID_GEN_RESET_COUNTS:
+	case OID_GEN_MEDIA_SENSE_COUNTS:
 
-            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
-                ndisStatus = NDIS_STATUS_SUCCESS;
-        }
+    default:
+        ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        BytesNeeded = 0;
+        break;
     }
-    
-    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = bytesWritten;
-    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = bytesNeeded;
+
+    if (ndisStatus == NDIS_STATUS_SUCCESS)
+        Request->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+    Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
     return ndisStatus;
 }
-#pragma warning(pop)
 
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
+static NTSTATUS
+__QueryInterface(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  const GUID      *Guid,
+    IN  ULONG           Version,
+    OUT PINTERFACE      Interface,
+    IN  ULONG           Size,
+    IN  BOOLEAN         Optional
     )
 {
-    UNREFERENCED_PARAMETER(MiniportAdapterContext);
-
+    KEVENT              Event;
+    IO_STATUS_BLOCK     StatusBlock;
+    PIRP                Irp;
+    PIO_STACK_LOCATION  StackLocation;
+    NTSTATUS            status;
 
-    *AddressingReset = FALSE;
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    return NDIS_STATUS_SUCCESS;
-}
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
 
-//
-// Restarts a paused adapter.
-//
-NDIS_STATUS
-AdapterRestart (
-    IN  NDIS_HANDLE                         MiniportAdapterContext,
-    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
-    )
-{
-    NTSTATUS				     status;
-    NDIS_STATUS			     ndisStatus;
-    PADAPTER				     Adapter = (PADAPTER)MiniportAdapterContext;
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
 
-    UNREFERENCED_PARAMETER(MiniportRestartParameters);
+    status = STATUS_UNSUCCESSFUL;
+    if (Irp == NULL)
+        goto fail1;
 
-    Trace("====>\n");
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
 
-    if (Adapter->Enabled) {
-        ndisStatus = NDIS_STATUS_SUCCESS;
-        goto done;
+    StackLocation->Parameters.QueryInterface.InterfaceType = Guid;
+    StackLocation->Parameters.QueryInterface.Size = (USHORT)Size;
+    StackLocation->Parameters.QueryInterface.Version = (USHORT)Version;
+    StackLocation->Parameters.QueryInterface.Interface = Interface;
+    
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    status = IoCallDriver(DeviceObject, Irp);
+    if (status == STATUS_PENDING) {
+        (VOID) KeWaitForSingleObject(&Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        status = StatusBlock.Status;
     }
 
-    status = XENVIF_VIF(Enable,
-                 &Adapter->VifInterface,
-                 AdapterVifCallback,
-                 Adapter);
-    if (NT_SUCCESS(status)) {
-        TransmitterEnable(Adapter->Transmitter);
-        Adapter->Enabled = TRUE;
-        ndisStatus = NDIS_STATUS_SUCCESS;
-    } else {
-        ndisStatus = NDIS_STATUS_FAILURE;
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_NOT_SUPPORTED && Optional)
+            goto done;
+
+        goto fail2;
     }
 
 done:
-    Trace("<====\n");
-    return ndisStatus;
-}
+    return STATUS_SUCCESS;
 
-//
-// Recycle of received net buffer lists.
-//
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+fail2:
+    Error("fail2\n");
 
-    ReceiverReturnNetBufferLists(&Adapter->Receiver,
-                                 NetBufferLists,
-                                 ReturnFlags);
+fail1:
+    Error("fail1 (%08x)\n", status);
 
-    return;
+    return status;
 }
 
-//
-// Used to send net buffer lists.
-//
-VOID 
-AdapterSendNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+#define READ_PROPERTY(field, name, defaultval, handle)  \
+    do {                                                \
+        NDIS_STATUS                     _Status;        \
+        NDIS_STRING                     _Value;         \
+        PNDIS_CONFIGURATION_PARAMETER   _Data;          \
+        RtlInitUnicodeString(&_Value, name);            \
+        NdisReadConfiguration(&_Status, &_Data, handle, \
+                        &_Value, NdisParameterInteger); \
+        if (_Status == NDIS_STATUS_SUCCESS)             \
+            field = _Data->ParameterData.IntegerData;   \
+        else                                            \
+            field = defaultval;                         \
+    } while (FALSE);
+
+static NDIS_STATUS
+AdapterGetAdvancedSettings(
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+    NDIS_CONFIGURATION_OBJECT   Config;
+    NDIS_HANDLE                 Handle;
+    NDIS_STATUS                 ndisStatus;
+
+    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
+    Config.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    Config.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    Config.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);
+    Config.NdisHandle = Adapter->NdisAdapterHandle;
+    Config.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&Config, &Handle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
 
-    TransmitterSendNetBufferLists(Adapter->Transmitter,
-                                  NetBufferList,
-                                  PortNumber,
-                                  SendFlags);
-}
+    READ_PROPERTY(Adapter->Properties.ipv4_csum, L"*IPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.udpv4_csum, L"*UDPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.udpv6_csum, L"*UDPChecksumOffloadIPv6", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.lsov4, L"*LSOv2IPv4", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lsov6, L"*LSOv2IPv6", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle);
+
+    NdisCloseConfiguration(Handle);
 
-#define XENNET_MEDIA_MAX_SPEED 1000000000ull
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
 
-#define XENNET_SUPPORTED_PACKET_FILTERS     \
-        (NDIS_PACKET_TYPE_DIRECTED |        \
-         NDIS_PACKET_TYPE_MULTICAST |       \
-         NDIS_PACKET_TYPE_ALL_MULTICAST |   \
-         NDIS_PACKET_TYPE_BROADCAST |       \
-         NDIS_PACKET_TYPE_PROMISCUOUS)
+#undef READ_PROPERTY
 
-//
-// Sets general adapter attributes. 
-//
 static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
+AdapterSetRegistrationAttributes(
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
-    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES   Attribs;
+    NDIS_STATUS                                     ndisStatus;
+
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    Attribs.MiniportAdapterContext = (NDIS_HANDLE)Adapter;
+    Attribs.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER |
+                             NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
+    Attribs.CheckForHangTimeInSeconds = 0;
+    Attribs.InterfaceType = XENNET_INTERFACE_TYPE;
 
-    NdisZeroMemory(&generalAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
-
-    generalAttributes.Header.Type = 
-                    NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 
-    generalAttributes.Header.Revision = 
-                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    return ndisStatus;
+}
 
-    generalAttributes.Header.Size = 
-                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+static NDIS_STATUS
+AdapterSetGeneralAttributes(
+    IN  PXENNET_ADAPTER Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
+    NDIS_STATUS                                 ndisStatus;
 
-    generalAttributes.MediaType = XENNET_MEDIA_TYPE;
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+    Attribs.MediaType = XENNET_MEDIA_TYPE;
 
     XENVIF_VIF(MacQueryMaximumFrameSize,
                &Adapter->VifInterface,
                (PULONG)&Adapter->MaximumFrameSize);
 
-    generalAttributes.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER);
-    generalAttributes.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.MediaConnectState = MediaConnectStateConnected;
-    generalAttributes.MediaDuplexState = MediaDuplexStateFull;
-    generalAttributes.LookaheadSize = Adapter->MaximumFrameSize;
-    generalAttributes.PowerManagementCapabilities = &Adapter->Capabilities;
-    generalAttributes.MacOptions = XENNET_MAC_OPTIONS;
-
-    generalAttributes.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS;
-        
-    generalAttributes.MaxMulticastListSize = 32;
-    generalAttributes.MacAddressLength = ETHERNET_ADDRESS_LENGTH;
+    Attribs.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER);
+    Attribs.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.MediaConnectState = MediaConnectStateConnected;
+    Attribs.MediaDuplexState = MediaDuplexStateFull;
+    Attribs.LookaheadSize = Adapter->MaximumFrameSize;
+    Attribs.PowerManagementCapabilities = &Adapter->Capabilities;
+    Attribs.MacOptions = XENNET_MAC_OPTIONS;
+    Attribs.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS;
+    Attribs.MaxMulticastListSize = 32;
+    Attribs.MacAddressLength = ETHERNET_ADDRESS_LENGTH;
 
     XENVIF_VIF(MacQueryPermanentAddress,
                &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.PermanentMacAddress);
+               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
     XENVIF_VIF(MacQueryCurrentAddress,
                &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.CurrentMacAddress);
-
-    generalAttributes.PhysicalMediumType = NdisPhysicalMedium802_3;
-    generalAttributes.RecvScaleCapabilities = NULL;
-    generalAttributes.AccessType = NET_IF_ACCESS_BROADCAST;
-    generalAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
-    generalAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
-    generalAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; 
-    generalAttributes.IfConnectorPresent = TRUE;
-
-    generalAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |
-                                            NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_RCV_OK_SUPPORTED |
-                                            NDIS_STATISTICS_RCV_ERROR_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;
+               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
+
+    Attribs.PhysicalMediumType = NdisPhysicalMedium802_3;
+    Attribs.RecvScaleCapabilities = NULL;
+    Attribs.AccessType = NET_IF_ACCESS_BROADCAST;
+    Attribs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
+    Attribs.ConnectionType = NET_IF_CONNECTION_DEDICATED;
+    Attribs.IfType = IF_TYPE_ETHERNET_CSMACD; 
+    Attribs.IfConnectorPresent = TRUE;
+    Attribs.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |
+                                  NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_RCV_OK_SUPPORTED |
+                                  NDIS_STATISTICS_RCV_ERROR_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;
                       
-    generalAttributes.SupportedOidList = XennetSupportedOids;
-    generalAttributes.SupportedOidListLength = sizeof(XennetSupportedOids);
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
-
+    Attribs.SupportedOidList = XennetSupportedOids;
+    Attribs.SupportedOidListLength = sizeof(XennetSupportedOids);
+                
     ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 
     return ndisStatus;
 }
 
-#define DISPLAY_OFFLOAD(_Offload)                                   \
-        do {                                                        \
-            if ((_Offload).Checksum.IPv4Receive.IpChecksum)         \
-                Info("Checksum.IPv4Receive.IpChecksum ON\n");       \
-            else                                                    \
-                Info("Checksum.IPv4Receive.IpChecksum OFF\n");      \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Receive.TcpChecksum)        \
-                Info("Checksum.IPv4Receive.TcpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Receive.TcpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Receive.UdpChecksum)        \
-                Info("Checksum.IPv4Receive.UdpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Receive.UdpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Receive.TcpChecksum)        \
-                Info("Checksum.IPv6Receive.TcpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv6Receive.TcpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Receive.UdpChecksum)        \
-                Info("Checksum.IPv6Receive.UdpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv6Receive.UdpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.IpChecksum)        \
-                Info("Checksum.IPv4Transmit.IpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.IpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.TcpChecksum)       \
-                Info("Checksum.IPv4Transmit.TcpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.TcpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.UdpChecksum)       \
-                Info("Checksum.IPv4Transmit.UdpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.UdpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Transmit.TcpChecksum)       \
-                Info("Checksum.IPv6Transmit.TcpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv6Transmit.TcpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Transmit.UdpChecksum)       \
-                Info("Checksum.IPv6Transmit.UdpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv6Transmit.UdpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).LsoV2.IPv4.MaxOffLoadSize != 0)          \
-                Info("LsoV2.IPv4.MaxOffLoadSize = %u\n",            \
-                     (_Offload).LsoV2.IPv4.MaxOffLoadSize);         \
-            else                                                    \
-                Info("LsoV2.IPv4 OFF\n");                           \
-                                                                    \
-            if ((_Offload).LsoV2.IPv6.MaxOffLoadSize != 0)          \
-                Info("LsoV2.IPv6.MaxOffLoadSize = %u\n",            \
-                     (_Offload).LsoV2.IPv6.MaxOffLoadSize);         \
-            else                                                    \
-                Info("LsoV2.IPv6 OFF\n");                           \
-        } while (FALSE)
-
 static NDIS_STATUS
 AdapterSetOffloadAttributes(
-    IN  PADAPTER Adapter
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES offloadAttributes;
-    XENVIF_VIF_OFFLOAD_OPTIONS Options;
-    NDIS_OFFLOAD current;
-    NDIS_OFFLOAD supported;
-    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
+    XENVIF_VIF_OFFLOAD_OPTIONS                  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
+    NDIS_OFFLOAD                                Default;
+    NDIS_OFFLOAD                                Supported;
+    NDIS_STATUS                                 ndisStatus;
+
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    Adapter->Receiver.OffloadOptions.Value = 0;
-    Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+    TxOptions->Value = 0;
+    TxOptions->OffloadTagManipulation = 1;
+
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
 
     if (Adapter->Properties.need_csum_value)
-        Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+        RxOptions->NeedChecksumValue = 1;
 
     if (Adapter->Properties.lrov4) {
-        Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
 
     if (Adapter->Properties.lrov6) {
-        Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
 
-    Adapter->Transmitter->OffloadOptions.Value = 0;
-    Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
-
-    NdisZeroMemory(&offloadAttributes, sizeof(offloadAttributes));
-    NdisZeroMemory(&current, sizeof(current));
-    NdisZeroMemory(&supported, sizeof(supported));
-    
     XENVIF_VIF(ReceiverSetOffloadOptions,
                &Adapter->VifInterface,
-               Adapter->Receiver.OffloadOptions);
+               *RxOptions);
 
-    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
-    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
-    supported.Header.Size = sizeof(supported);
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
 
-    supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
+    Supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
+    Supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
+    Supported.Header.Size = sizeof(NDIS_OFFLOAD);
 
-    supported.Checksum.IPv4Receive.IpChecksum = 1;
-    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
+    Supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv4Receive.TcpChecksum = 1;
-    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+    Supported.Checksum.IPv4Receive.IpChecksum = 1;
+    Supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
 
-    supported.Checksum.IPv4Receive.UdpChecksum = 1;
+    Supported.Checksum.IPv4Receive.TcpChecksum = 1;
+    Supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
 
-    supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Receive.UdpChecksum = 1;
 
-    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv6Receive.TcpChecksum = 1;
-    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
 
-    supported.Checksum.IPv6Receive.UdpChecksum = 1;
+    Supported.Checksum.IPv6Receive.TcpChecksum = 1;
+    Supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
 
-    XENVIF_VIF(TransmitterQueryOffloadOptions,
-               &Adapter->VifInterface,
-               &Options);
+    Supported.Checksum.IPv6Receive.UdpChecksum = 1;
 
-    supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
     if (Options.OffloadIpVersion4HeaderChecksum) {
-        supported.Checksum.IPv4Transmit.IpChecksum = 1;
-        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+        Supported.Checksum.IPv4Transmit.IpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion4TcpChecksum) {
-        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+        Supported.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion4UdpChecksum)
-        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.UdpChecksum = 1;
 
-    supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
 
     if (Options.OffloadIpVersion6TcpChecksum) {
-        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+        Supported.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion6UdpChecksum)
-        supported.Checksum.IPv6Transmit.UdpChecksum = 1;
+        Supported.Checksum.IPv6Transmit.UdpChecksum = 1;
 
     if (Options.OffloadIpVersion4LargePacket) {
-        ULONG Size;
-
         XENVIF_VIF(TransmitterQueryLargePacketSize,
                    &Adapter->VifInterface,
                    4,
-                   &Size);
-
-        supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        supported.LsoV2.IPv4.MaxOffLoadSize = Size;
-        supported.LsoV2.IPv4.MinSegmentCount = 2;
+                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
+        Supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv4.MinSegmentCount = 2;
     }
 
     if (Options.OffloadIpVersion6LargePacket) {
-        ULONG Size;
-
         XENVIF_VIF(TransmitterQueryLargePacketSize,
                    &Adapter->VifInterface,
                    6,
-                   &Size);
-
-        supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        supported.LsoV2.IPv6.MaxOffLoadSize = Size;
-        supported.LsoV2.IPv6.MinSegmentCount = 2;
-        supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
-        supported.LsoV2.IPv6.TcpOptionsSupported = 1;
+                   &Supported.LsoV2.IPv6.MaxOffLoadSize);
+        Supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv6.MinSegmentCount = 2;
+        Supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        Supported.LsoV2.IPv6.TcpOptionsSupported = 1;
     }
 
-    current = supported;
+    Default = Supported;
 
     if (!(Adapter->Properties.ipv4_csum & 2))
-        current.Checksum.IPv4Receive.IpChecksum = 0;
+        Default.Checksum.IPv4Receive.IpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv4_csum & 2))
-        current.Checksum.IPv4Receive.TcpChecksum = 0;
+        Default.Checksum.IPv4Receive.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv4_csum & 2))
-        current.Checksum.IPv4Receive.UdpChecksum = 0;
+        Default.Checksum.IPv4Receive.UdpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv6_csum & 2))
-        current.Checksum.IPv6Receive.TcpChecksum = 0;
+        Default.Checksum.IPv6Receive.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv6_csum & 2))
-        current.Checksum.IPv6Receive.UdpChecksum = 0;
+        Default.Checksum.IPv6Receive.UdpChecksum = 0;
 
     if (!(Adapter->Properties.ipv4_csum & 1))
-        current.Checksum.IPv4Transmit.IpChecksum = 0;
+        Default.Checksum.IPv4Transmit.IpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv4_csum & 1))
-        current.Checksum.IPv4Transmit.TcpChecksum = 0;
+        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv4_csum & 1))
-        current.Checksum.IPv4Transmit.UdpChecksum = 0;
+        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv6_csum & 1))
-        current.Checksum.IPv6Transmit.TcpChecksum = 0;
+        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv6_csum & 1))
-        current.Checksum.IPv6Transmit.UdpChecksum = 0;
+        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
 
     if (!(Adapter->Properties.lsov4)) {
-        current.LsoV2.IPv4.MaxOffLoadSize = 0;
-        current.LsoV2.IPv4.MinSegmentCount = 0;
+        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv4.MinSegmentCount = 0;
     }
 
     if (!(Adapter->Properties.lsov6)) {
-        current.LsoV2.IPv6.MaxOffLoadSize = 0;
-        current.LsoV2.IPv6.MinSegmentCount = 0;
+        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv6.MinSegmentCount = 0;
     }
 
-    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = current;
-
-        DISPLAY_OFFLOAD(current);
+    if (!RtlEqualMemory(&Adapter->Offload, &Default, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = Default;
+        //DISPLAY_OFFLOAD(Default);
     }
 
-    offloadAttributes.Header.Type =
-        NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
-    offloadAttributes.Header.Revision =
-        NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
-    offloadAttributes.Header.Size = sizeof(offloadAttributes);
-    offloadAttributes.DefaultOffloadConfiguration = &current;
-    offloadAttributes.HardwareOffloadCapabilities = &supported;
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(Attribs);
+    Attribs.DefaultOffloadConfiguration = &Default;
+    Attribs.HardwareOffloadCapabilities = &Supported;
 
-    adapterAttributes =
-        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
     ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
     return ndisStatus;
 }
 
-static void
-AdapterIndicateOffloadChanged (
-    IN  PADAPTER Adapter
+NDIS_STATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE         Handle,
+    OUT PXENNET_ADAPTER     *Adapter
     )
 {
-    NDIS_STATUS_INDICATION indication;
-    NDIS_OFFLOAD offload;
-
-    NdisZeroMemory(&offload, sizeof(offload));
-    INITIALIZE_NDIS_OBJ_HEADER(offload, OFFLOAD);
-
-    offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-        offload.Checksum.IPv4Receive.IpChecksum = 1;
-        offload.Checksum.IPv4Receive.IpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-        offload.Checksum.IPv4Receive.TcpChecksum = 1;
-        offload.Checksum.IPv4Receive.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-        offload.Checksum.IPv4Receive.UdpChecksum = 1;
-    }
-
-    offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-        offload.Checksum.IPv6Receive.TcpChecksum = 1;
-        offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-        offload.Checksum.IPv6Receive.UdpChecksum = 1;
-    }
+    NDIS_STATUS             ndisStatus;
+    NTSTATUS                status;
+    PDEVICE_OBJECT          DeviceObject;
+    NDIS_SG_DMA_DESCRIPTION Dma;
 
-    XENVIF_VIF(ReceiverSetOffloadOptions,
-               &Adapter->VifInterface,
-               Adapter->Receiver.OffloadOptions);
-
-    offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-        offload.Checksum.IPv4Transmit.IpChecksum = 1;
-        offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-        offload.Checksum.IPv4Transmit.TcpChecksum = 1;
-        offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-        offload.Checksum.IPv4Transmit.UdpChecksum = 1;
-    }
-
-    offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-        offload.Checksum.IPv6Transmit.TcpChecksum = 1;
-        offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-        offload.Checksum.IPv6Transmit.UdpChecksum = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-        ULONG Size;
-
-        XENVIF_VIF(TransmitterQueryLargePacketSize,
-                   &Adapter->VifInterface,
-                   4,
-                   &Size);
-
-        offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        offload.LsoV2.IPv4.MaxOffLoadSize = Size;
-        offload.LsoV2.IPv4.MinSegmentCount = 2;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-        ULONG Size;
-
-        XENVIF_VIF(TransmitterQueryLargePacketSize,
-                   &Adapter->VifInterface,
-                   6,
-                   &Size);
-
-        offload.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        offload.LsoV2.IPv6.MaxOffLoadSize = Size;
-        offload.LsoV2.IPv6.MinSegmentCount = 2;
-        offload.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
-        offload.LsoV2.IPv6.TcpOptionsSupported = 1;
-    }
-
-    if (!RtlEqualMemory(&Adapter->Offload, &offload, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = offload;
-
-        DISPLAY_OFFLOAD(offload);
-    }
+    *Adapter = ExAllocatePoolWithTag(NonPagedPool,
+                                     sizeof(XENNET_ADAPTER),
+                                     ADAPTER_POOL_TAG);
 
-    NdisZeroMemory(&indication, sizeof(indication));
-    INITIALIZE_NDIS_OBJ_HEADER(indication, STATUS_INDICATION);
-    indication.SourceHandle = Adapter->NdisAdapterHandle;
-    indication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
-    indication.StatusBuffer = &offload;
-    indication.StatusBufferSize = sizeof(offload);
+    ndisStatus = NDIS_STATUS_RESOURCES;
+    if (*Adapter == NULL)
+        goto fail1;
 
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
+    RtlZeroMemory(*Adapter, sizeof (XENNET_ADAPTER));
 
-}
+    NdisMGetDeviceProperty(Handle,
+                           &DeviceObject,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
 
-static NDIS_STATUS
-SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address, ULONG Count)
-{
-    NTSTATUS status;
+    status = __QueryInterface(DeviceObject,
+                              &GUID_XENVIF_VIF_INTERFACE,
+                              XENVIF_VIF_INTERFACE_VERSION_MAX,
+                              (PINTERFACE)&(*Adapter)->VifInterface,
+                              sizeof(XENVIF_VIF_INTERFACE),
+                              FALSE);
 
-    status = XENVIF_VIF(MacSetMulticastAddresses,
-                        &Adapter->VifInterface,
-                        Address,
-                        Count);
+    ndisStatus = NDIS_STATUS_FAILURE;
     if (!NT_SUCCESS(status))
-        return NDIS_STATUS_INVALID_DATA;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-static NDIS_STATUS
-SetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
-{
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
-
-    if (*PacketFilter & ~XENNET_SUPPORTED_PACKET_FILTERS)
-        return NDIS_STATUS_INVALID_PARAMETER;
+        goto fail2;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
-        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        goto done;
-    }
+    status = XENVIF_VIF(Acquire,
+                        &(*Adapter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
-        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    (*Adapter)->NdisAdapterHandle = Handle;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else if (*PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
-        MulticastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        MulticastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    ndisStatus = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail4;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail5;
 
-done:
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               UnicastFilterLevel);
+    ndisStatus = AdapterGetAdvancedSettings(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail6;
+    
+    ndisStatus = AdapterSetRegistrationAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail7;
+    
+    ndisStatus = AdapterSetGeneralAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail8;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               MulticastFilterLevel);
+    ndisStatus = AdapterSetOffloadAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail9;
+
+    RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION));
+    Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
+    Dma.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
+    Dma.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);
+    Dma.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;
+    Dma.MaximumPhysicalMapping = 65536;    
+    Dma.ProcessSGListHandler = AdapterProcessSGList;
+    Dma.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
+
+    ndisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisAdapterHandle,
+                                               &Dma,
+                                               &(*Adapter)->NdisDmaHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        (*Adapter)->NdisDmaHandle = NULL;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               BroadcastFilterLevel);
+    ndisStatus = AdapterEnable(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail10;
 
     return NDIS_STATUS_SUCCESS;
-}
-
-//
-// Set OID handler.
-//
-static NDIS_STATUS 
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    ULONG addressCount;
-    ULONG bytesNeeded = 0;
-    ULONG bytesRead = 0;
-    PVOID informationBuffer;
-    ULONG informationBufferLength;
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    NDIS_OID oid;
-    BOOLEAN offloadChanged;
-
-    informationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
-    informationBufferLength = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
-    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
-    switch (oid) {
-        case OID_PNP_SET_POWER:
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
-
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Info("SET_POWER: D0\n");
-                    break;
-
-                case NdisDeviceStateD1:
-                    Info("SET_POWER: D1\n");
-                    break;
-
-                case NdisDeviceStateD2:
-                    Info("SET_POWER: D2\n");
-                    break;
-
-                case NdisDeviceStateD3:
-                    Info("SET_POWER: D3\n");
-                    break;
-                }
-            }
-            break;
-
-        case OID_GEN_MACHINE_NAME:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            bytesNeeded = sizeof(ULONG);
-            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
-            if (informationBufferLength == sizeof(ULONG)) {
-                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
-                bytesRead = sizeof(ULONG);
-            }
-
-            break;
-
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            bytesNeeded = sizeof(ULONG);
-            if (informationBufferLength == sizeof(ULONG)) {
-                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
-                bytesRead = sizeof(ULONG);
-            }
-
-            break;
-
-        case OID_802_3_MULTICAST_LIST:
-            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
-            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
-                addressCount = informationBufferLength / ETHERNET_ADDRESS_LENGTH;
-
-                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer, addressCount);
-                if (ndisStatus == NDIS_STATUS_SUCCESS)
-                    bytesRead = informationBufferLength;
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-
-            break;
-
-        case OID_GEN_INTERRUPT_MODERATION:
-            ndisStatus = NDIS_STATUS_INVALID_DATA;
-            break;
-
-        case OID_OFFLOAD_ENCAPSULATION: {
-            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
-
-            bytesNeeded = sizeof(*offloadEncapsulation);
-            if (informationBufferLength >= bytesNeeded) {
-                XENVIF_VIF_OFFLOAD_OPTIONS Options;
-
-                bytesRead = bytesNeeded;
-                offloadEncapsulation = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
-
-                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                XENVIF_VIF(TransmitterQueryOffloadOptions,
-                           &Adapter->VifInterface,
-                           &Options);
-                
-                Adapter->Transmitter->OffloadOptions.Value = 0;
-                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
-
-                if ((Adapter->Properties.lsov4) && (Options.OffloadIpVersion4LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
-
-                if ((Adapter->Properties.lsov6) && (Options.OffloadIpVersion6LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
-
-                if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-
-                if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-
-                Adapter->Receiver.OffloadOptions.Value = 0;
-                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
-
-                if (Adapter->Properties.need_csum_value)
-                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
-
-                if (Adapter->Properties.lrov4) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
-
-                if (Adapter->Properties.lrov6) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
-
-                if (Adapter->Properties.ipv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if (Adapter->Properties.tcpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if (Adapter->Properties.udpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-
-                if (Adapter->Properties.tcpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if (Adapter->Properties.udpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-
-                AdapterIndicateOffloadChanged(Adapter);
-            }
-            break;
-        }
-        case OID_TCP_OFFLOAD_PARAMETERS: {
-            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
-
-            bytesNeeded = sizeof(*offloadParameters);
-            if (informationBufferLength >= bytesNeeded) {
-                bytesRead = bytesNeeded;
-                offloadParameters = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
-
-#define no_change(x)  ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
-
-                if (!no_change(offloadParameters->IPsecV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                    
-                if (!no_change(offloadParameters->LsoV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->TcpConnectionIPv4))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->TcpConnectionIPv6))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->LsoV2IPv4)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
-
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
-
-                    if (!(Options.OffloadIpVersion4LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                if (!no_change(offloadParameters->LsoV2IPv6)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
-
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
-
-                    if (!(Options.OffloadIpVersion6LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-#define rx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
-                       (x) == NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED)
-#define tx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
-                       (x) == NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED)
-
-                if (ndisStatus == NDIS_STATUS_SUCCESS) {
-                    offloadChanged = FALSE;
-
-                    if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->IPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->TCPIPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->UDPIPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->TCPIPv6Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->UDPIPv6Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->IPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->TCPIPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->UDPIPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->TCPIPv6Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->UDPIPv6Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-#undef tx_enabled
-#undef rx_enabled
-#undef no_change
-
-                    if (offloadChanged)
-                        AdapterIndicateOffloadChanged(Adapter);
-                }
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-            break;
-        }
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
-
-    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
-    }
-
-    return ndisStatus;
-}
-
-//
-// Sets miniport registration attributes.
-//
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    )
-{
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registrationAttributes;
-    NDIS_STATUS ndisStatus;
-
-
-    NdisZeroMemory(&registrationAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
-
-    registrationAttributes.Header.Type = 
-                NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
-
-    registrationAttributes.Header.Revision = 
-                NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
-
-    registrationAttributes.Header.Size = 
-                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
-
-    registrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)Adapter;
-    registrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER |
-                                            NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
-    
-    registrationAttributes.CheckForHangTimeInSeconds = 0;
-    registrationAttributes.InterfaceType = XENNET_INTERFACE_TYPE;
-
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
-
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
 
+fail10:
+    if ((*Adapter)->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
+    (*Adapter)->NdisDmaHandle = NULL;
+fail9:
+fail8:
+fail7:
+fail6:
+    ReceiverTeardown((*Adapter)->Receiver);
+    (*Adapter)->Receiver = NULL;
+fail5:
+    TransmitterTeardown((*Adapter)->Transmitter);
+    (*Adapter)->Transmitter = NULL;
+fail4:
+    (*Adapter)->NdisAdapterHandle = NULL;
+
+    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail3:
+    RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
+fail2:
+    ExFreePoolWithTag(*Adapter, ADAPTER_POOL_TAG);
+fail1:
     return ndisStatus;
 }
 
-//
-// Shuts down adapter.
-//
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER     Adapter
     )
 {
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    UNREFERENCED_PARAMETER(ShutdownAction);
-
-    if (ShutdownAction != NdisShutdownBugCheck)
-        AdapterStop(Adapter);
-
-    return;
-}
-
-//
-// Stops adapter. Waits for currently transmitted packets to complete.
-// Stops transmission of new packets.
-// Stops received packet indication to NDIS.
-//
-NDIS_STATUS
-AdapterStop (
-IN  PADAPTER    Adapter
-)
-{
-    Trace("====>\n");
+    TransmitterTeardown(Adapter->Transmitter);
+    Adapter->Transmitter = NULL;
 
-    if (!Adapter->Enabled)
-        goto done;
+    ReceiverTeardown(Adapter->Receiver);
+    Adapter->Receiver = NULL;
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    if (Adapter->NdisDmaHandle != NULL)
+        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
+    Adapter->NdisDmaHandle = NULL;
 
-    Adapter->Enabled = FALSE;
+    XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 
-done:
-    Trace("<====\n");
-    return NDIS_STATUS_SUCCESS;
+    ExFreePoolWithTag(Adapter, ADAPTER_POOL_TAG);
 }
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index e64e40d..6c60aad 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -29,7 +29,10 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_ADAPTER_H_
+#define _XENNET_ADAPTER_H_
+
+#include <ndis.h>
 
 #define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
 
@@ -41,6 +44,14 @@
                                          NDIS_MAC_OPTION_8021P_PRIORITY |       \
                                          NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
 
+#define XENNET_MEDIA_MAX_SPEED          1000000000ull
+
+#define XENNET_SUPPORTED_PACKET_FILTERS (NDIS_PACKET_TYPE_DIRECTED |        \
+                                         NDIS_PACKET_TYPE_MULTICAST |       \
+                                         NDIS_PACKET_TYPE_ALL_MULTICAST |   \
+                                         NDIS_PACKET_TYPE_BROADCAST |       \
+                                         NDIS_PACKET_TYPE_PROMISCUOUS)
+
 typedef struct _PROPERTIES {
     int ipv4_csum;
     int tcpv4_csum;
@@ -54,120 +65,67 @@ typedef struct _PROPERTIES {
     int lrov6;
 } PROPERTIES, *PPROPERTIES;
 
-struct _ADAPTER {
-    LIST_ENTRY              ListEntry;
-    XENVIF_VIF_INTERFACE    VifInterface;
-    BOOLEAN                 AcquiredInterfaces;
-    ULONG                   MaximumFrameSize;
-    ULONG                   CurrentLookahead;
-    NDIS_HANDLE             NdisAdapterHandle;
-    NDIS_HANDLE             NdisDmaHandle;
-    NDIS_PNP_CAPABILITIES   Capabilities;
-    PROPERTIES              Properties;
-    RECEIVER                Receiver;
-    PTRANSMITTER            Transmitter;
-    BOOLEAN                 Enabled;
-    NDIS_OFFLOAD            Offload;
-};
-
-MINIPORT_CANCEL_OID_REQUEST AdapterCancelOidRequest;
-VOID
-AdapterCancelOidRequest (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       RequestId
-    );
+typedef struct _XENNET_ADAPTER XENNET_ADAPTER, *PXENNET_ADAPTER;
 
-MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
+extern NDIS_STATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE         Handle,
+    OUT PXENNET_ADAPTER     *Adapter
     );
 
-MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    );
-
-VOID
-AdapterCleanup (
-    IN PADAPTER Adapter
-    );
-
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+extern VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_OID_REQUEST AdapterOidRequest;
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+extern NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_PAUSE AdapterPause;
-NDIS_STATUS 
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+#include <vif_interface.h>
+extern PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+#include "transmitter.h"
+extern PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RESET AdapterReset;
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
+#include "receiver.h"
+extern PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RESTART AdapterRestart;
-NDIS_STATUS 
-AdapterRestart (
-    IN  NDIS_HANDLE                         MiniportAdapterContext,
-    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+extern NDIS_STATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
+extern BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_SEND_NET_BUFFER_LISTS AdapterSendNetBufferLists;
-VOID 
-AdapterSendNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+extern VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-NDIS_STATUS
-AdapterStop (
-    IN  PADAPTER    Adapter
+extern NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
     );
 
-MINIPORT_SHUTDOWN AdapterShutdown;
-
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+extern NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
     );
 
-extern VOID
-ReceiverReceivePackets(
-    IN  PRECEIVER   Receiver,
-    IN  PLIST_ENTRY List
-    );
+#endif // _XENNET_ADAPTER_H_
diff --git a/src/xennet/common.h b/src/xennet/common.h
deleted file mode 100644
index 4d4c04a..0000000
--- a/src/xennet/common.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-#pragma once
-
-#include "std.h"
-#include "project.h"
-#include "dbg_print.h"
-#include "assert.h"
diff --git a/src/xennet/main.c b/src/xennet/main.c
deleted file mode 100644
index e193e0e..0000000
--- a/src/xennet/main.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <version.h>
-
-#include "common.h"
-
-#pragma NDIS_INIT_FUNCTION(DriverEntry)
-
-//
-// Global miniport data.
-//
-
-static NDIS_HANDLE MiniportDriverHandle;
-
-extern MINIPORT_INITIALIZE MiniportInitialize;
-
-extern NDIS_STATUS 
-MiniportInitialize (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HANDLE                        MiniportDriverContext,
-    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
-    );
-
-MINIPORT_HALT MiniportHalt;
-
-extern VOID 
-MiniportHalt (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HALT_ACTION                   HaltAction
-    );
-
-typedef struct _XENNET_CONTEXT {
-    PDEVICE_CAPABILITIES    Capabilities;
-    PIO_COMPLETION_ROUTINE  CompletionRoutine;
-    PVOID                   CompletionContext;
-    UCHAR                   CompletionControl;
-} XENNET_CONTEXT, *PXENNET_CONTEXT;
-
-static NTSTATUS (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
-
-__drv_functionClass(IO_COMPLETION_ROUTINE)
-static NTSTATUS
-__QueryCapabilities(
-    IN  PDEVICE_OBJECT      DeviceObject,
-    IN  PIRP                Irp,
-    IN  PVOID               _Context
-    )
-{
-    PXENNET_CONTEXT         Context = _Context;
-    NTSTATUS                status;
-
-    Trace("====>\n");
-
-    Context->Capabilities->SurpriseRemovalOK = 1;
-
-    if (Context->CompletionRoutine != NULL &&
-        (Context->CompletionControl & SL_INVOKE_ON_SUCCESS))
-        status = Context->CompletionRoutine(DeviceObject, Irp, Context->CompletionContext);
-    else
-        status = STATUS_SUCCESS;
-
-    ExFreePool(Context);
-
-    Trace("<====\n");
-
-    return status;
-}
-
-NTSTATUS 
-QueryCapabilities(
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PIRP                 Irp
-    )
-{
-    PIO_STACK_LOCATION      StackLocation;
-    PXENNET_CONTEXT         Context;
-    NTSTATUS                status;
-
-    Trace("====>\n");
-
-    Trace("%p\n", DeviceObject); 
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-
-    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof (XENNET_CONTEXT), ' TEN');
-    if (Context != NULL) {
-        Context->Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities;
-        Context->CompletionRoutine = StackLocation->CompletionRoutine;
-        Context->CompletionContext = StackLocation->Context;
-        Context->CompletionControl = StackLocation->Control;
-
-        StackLocation->CompletionRoutine = __QueryCapabilities;
-        StackLocation->Context = Context;
-        StackLocation->Control = SL_INVOKE_ON_SUCCESS;
-    }
-
-    status = NdisDispatchPnp(DeviceObject, Irp);
-
-    Trace("<====\n");
-
-    return status;    
-}
-
-DRIVER_DISPATCH DispatchPnp;
-
-NTSTATUS 
-DispatchPnp(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    UCHAR               MinorFunction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    MinorFunction = StackLocation->MinorFunction;
-
-    switch (StackLocation->MinorFunction) {
-    case IRP_MN_QUERY_CAPABILITIES:
-        status = QueryCapabilities(DeviceObject, Irp);
-        break;
-
-    default:
-        status = NdisDispatchPnp(DeviceObject, Irp);
-        break;
-    }
-
-    return status;
-}
-
-DRIVER_DISPATCH DispatchFail;
-
-NTSTATUS 
-DispatchFail(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp
-    )
-{
-    NTSTATUS            status;
-
-    UNREFERENCED_PARAMETER(DeviceObject);
-
-    Trace("%p\n", Irp);
-
-    status = STATUS_UNSUCCESSFUL;
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-DRIVER_INITIALIZE   DriverEntry;
-
-NTSTATUS 
-DriverEntry (
-    IN  PDRIVER_OBJECT   DriverObject,
-    IN  PUNICODE_STRING  RegistryPath
-    )
-{
-    NDIS_STATUS ndisStatus;
-    NDIS_MINIPORT_DRIVER_CHARACTERISTICS mpChars;
-    NDIS_CONFIGURATION_OBJECT ConfigurationObject;
-    NDIS_HANDLE ConfigurationHandle;
-    NDIS_STRING ParameterName;
-    PNDIS_CONFIGURATION_PARAMETER ParameterValue;
-    ULONG FailCreateClose;
-    ULONG FailDeviceControl;
-
-    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
-
-    Trace("====>\n");
-
-    if (*InitSafeBootMode > 0)
-        return NDIS_STATUS_SUCCESS;
-
-    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
-         MAJOR_VERSION,
-         MINOR_VERSION,
-         MICRO_VERSION,
-         BUILD_NUMBER,
-         DAY,
-         MONTH,
-         YEAR);
-
-    //
-    // Register miniport with NDIS.
-    //
-
-    NdisZeroMemory(&mpChars, sizeof(mpChars));
-    mpChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
-    mpChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
-    mpChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
-
-    mpChars.MajorNdisVersion = 6;
-    mpChars.MinorNdisVersion = 0;
-    mpChars.MajorDriverVersion = MAJOR_VERSION;
-    mpChars.MinorDriverVersion = MINOR_VERSION;
-
-    mpChars.CancelOidRequestHandler = AdapterCancelOidRequest;
-    mpChars.CancelSendHandler = AdapterCancelSendNetBufferLists;
-    mpChars.CheckForHangHandlerEx = AdapterCheckForHang;
-    mpChars.InitializeHandlerEx = MiniportInitialize;
-    mpChars.HaltHandlerEx = MiniportHalt;
-    mpChars.OidRequestHandler = AdapterOidRequest;    
-    mpChars.PauseHandler = AdapterPause;      
-    mpChars.DevicePnPEventNotifyHandler  = AdapterPnPEventHandler;
-    mpChars.ResetHandlerEx = AdapterReset;
-    mpChars.RestartHandler = AdapterRestart;    
-    mpChars.ReturnNetBufferListsHandler  = AdapterReturnNetBufferLists;
-    mpChars.SendNetBufferListsHandler = AdapterSendNetBufferLists;
-    mpChars.ShutdownHandlerEx = AdapterShutdown;
-    mpChars.UnloadHandler = DriverUnload;
-
-    MiniportDriverHandle = NULL;
-    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
-                                             RegistryPath,
-                                             NULL,
-                                             &mpChars,
-                                             &MiniportDriverHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        Error("Failed (0x%08X) to register miniport.\n", ndisStatus);
-        goto fail;
-    }
-
-    ConfigurationObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
-    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
-    ConfigurationObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
-    ConfigurationObject.NdisHandle = MiniportDriverHandle;
-    ConfigurationObject.Flags = 0;
-
-    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        Error("Failed (0x%08X) to open driver configuration.\n", ndisStatus);
-        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
-        goto fail;
-    }
-
-    RtlInitUnicodeString(&ParameterName, L"FailCreateClose");
-
-    NdisReadConfiguration(&ndisStatus,
-                          &ParameterValue,
-                          ConfigurationHandle,
-                          &ParameterName,
-                          NdisParameterInteger);
-    if (ndisStatus == NDIS_STATUS_SUCCESS &&
-        ParameterValue->ParameterType == NdisParameterInteger)
-        FailCreateClose = ParameterValue->ParameterData.IntegerData;
-    else
-        FailCreateClose = 0;
-
-    RtlInitUnicodeString(&ParameterName, L"FailDeviceControl");
-
-    NdisReadConfiguration(&ndisStatus,
-                          &ParameterValue,
-                          ConfigurationHandle,
-                          &ParameterName,
-                          NdisParameterInteger);
-    if (ndisStatus == NDIS_STATUS_SUCCESS &&
-        ParameterValue->ParameterType == NdisParameterInteger)
-        FailDeviceControl = ParameterValue->ParameterData.IntegerData;
-    else
-        FailDeviceControl = 0;
-
-    NdisCloseConfiguration(ConfigurationHandle);
-    ndisStatus = NDIS_STATUS_SUCCESS;
-
-    NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
-
-    if (FailCreateClose != 0) {
-#pragma prefast(suppress:28168) // No matching__drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
-    }
-
-    if (FailDeviceControl != 0) {
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
-    }
-
-    Trace("<====\n");
-    return ndisStatus;
-
-fail:
-    Error("fail\n");
-    return ndisStatus;
-}
-
-VOID 
-DriverUnload (
-    IN  PDRIVER_OBJECT  DriverObject
-    )
-{
-    UNREFERENCED_PARAMETER(DriverObject);
-
-    Trace("====>\n");
-
-    if (*InitSafeBootMode > 0)
-        goto done;
-
-    if (MiniportDriverHandle)
-        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
-
-    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
-         MAJOR_VERSION,
-         MINOR_VERSION,
-         MICRO_VERSION,
-         BUILD_NUMBER,
-         DAY,
-         MONTH,
-         YEAR);
-
-done:
-    Trace("<====\n");
-}
diff --git a/src/xennet/project.h b/src/xennet/project.h
deleted file mode 100644
index 981cb0e..0000000
--- a/src/xennet/project.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <util.h>
-#include <ethernet.h>
-#include <tcpip.h>
-#include <vif_interface.h>
-
-typedef struct _ADAPTER ADAPTER, *PADAPTER;
-
-DRIVER_INITIALIZE DriverEntry;
-NTSTATUS 
-DriverEntry (
-    IN  PDRIVER_OBJECT   DriverObject,
-    IN  PUNICODE_STRING  RegistryPath
-    );
-
-MINIPORT_UNLOAD DriverUnload;
-VOID 
-DriverUnload (
-    IN  PDRIVER_OBJECT  DriverObject
-    );
-
-NDIS_STATUS
-MpSetAdapterSettings(
-    IN PADAPTER Adapter
-    );
-
-NDIS_STATUS
-MpGetAdvancedSettings(
-    IN PADAPTER Adapter
-    );
-
-#include "transmitter.h"
-#include "receiver.h"
-#include "adapter.h"
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index 54bdc15..49320a5 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -29,100 +29,35 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include "receiver.h"
+#include "adapter.h"
+#include <util.h>
+#include "dbg_print.h"
+#include "assert.h"
+
+struct _XENNET_RECEIVER {
+    PXENNET_ADAPTER             Adapter;
+    NDIS_HANDLE                 NetBufferListPool;
+    PNET_BUFFER_LIST            PutList;
+    PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
+    LONG                        InNDIS;
+    LONG                        InNDISMax;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
+
+#define RECEIVER_POOL_TAG       'RteN'
+#define IN_NDIS_MAX             1024
 
-#pragma warning(disable:4711)
-
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER                   Receiver
-    )
-{
-    PADAPTER                        Adapter;
-    NDIS_STATUS                     ndisStatus = NDIS_STATUS_SUCCESS;
-    NET_BUFFER_LIST_POOL_PARAMETERS poolParameters;
-    ULONG                           Cpu;
-
-    Receiver->PutList = NULL;
-    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++)
-        Receiver->GetList[Cpu] = NULL;
-
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    NdisZeroMemory(&poolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
-    poolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    poolParameters.Header.Revision =
-        NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
-    poolParameters.Header.Size = sizeof(poolParameters);
-    poolParameters.ProtocolId = 0;
-    poolParameters.ContextSize = 0;
-    poolParameters.fAllocateNetBuffer = TRUE;
-    poolParameters.PoolTag = ' TEN';
-
-    Receiver->NetBufferListPool =
-        NdisAllocateNetBufferListPool(Adapter->NdisAdapterHandle,
-                                      &poolParameters);
-
-    if (!Receiver->NetBufferListPool)
-        ndisStatus = NDIS_STATUS_RESOURCES;
-
-    return ndisStatus;
-}
-
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER       Receiver
-    )
-{
-    ULONG               Cpu;
-    PNET_BUFFER_LIST    NetBufferList;
-
-    ASSERT(Receiver != NULL);
-
-    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
-        NetBufferList = Receiver->GetList[Cpu];
-        while (NetBufferList != NULL) {
-            PNET_BUFFER_LIST    Next;
-
-            Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-            NdisFreeNetBufferList(NetBufferList);
-
-            NetBufferList = Next;
-        }
-    }
-
-    NetBufferList = Receiver->PutList;
-    while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST    Next;
-
-        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-        NdisFreeNetBufferList(NetBufferList);
-
-        NetBufferList = Next;
-    }
-
-    if (Receiver->NetBufferListPool) {
-        NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
-        Receiver->NetBufferListPool = NULL;
-    }
-
-    return;
-}
-
-PNET_BUFFER_LIST
-ReceiverAllocateNetBufferList(
-    IN  PRECEIVER       Receiver,
-    IN  PMDL            Mdl,
-    IN  ULONG           Offset,
-    IN  ULONG           Length
+static PNET_BUFFER_LIST
+__ReceiverAllocateNetBufferList(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length
     )
 {
-    ULONG               Cpu;
-    PNET_BUFFER_LIST    NetBufferList;
+    ULONG                   Cpu;
+    PNET_BUFFER_LIST        NetBufferList;
 
     Cpu = KeGetCurrentProcessorNumber();
 
@@ -158,9 +93,9 @@ ReceiverAllocateNetBufferList(
     return NetBufferList;
 }        
 
-VOID
-ReceiverReleaseNetBufferList(
-    IN  PRECEIVER           Receiver,
+static VOID
+__ReceiverReleaseNetBufferList(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  BOOLEAN             Cache
     )
@@ -184,17 +119,16 @@ ReceiverReleaseNetBufferList(
 
 static FORCEINLINE ULONG
 __ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  BOOLEAN             Cache
     )
 {
-    PADAPTER                Adapter;
+    PXENVIF_VIF_INTERFACE   VifInterface;
     LIST_ENTRY              List;
     ULONG                   Count;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
+    VifInterface = AdapterGetVifInterface(Receiver->Adapter);
     InitializeListHead(&List);
 
     Count = 0;
@@ -212,7 +146,7 @@ __ReceiverReturnNetBufferLists(
 
         Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
 
-        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
+        __ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
 
         Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
 
@@ -224,51 +158,33 @@ __ReceiverReturnNetBufferLists(
 
     if (Count != 0)
         XENVIF_VIF(ReceiverReturnPackets,
-                   &Adapter->VifInterface,
+                   VifInterface,
                    &List);
 
     return Count;
 }
 
-VOID
-ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    HeadNetBufferList,
-    IN  ULONG               Flags
-    )
-{
-    ULONG                   Count;
-
-    UNREFERENCED_PARAMETER(Flags);
-
-    Count = __ReceiverReturnNetBufferLists(Receiver, HeadNetBufferList, TRUE);
-    (VOID) __InterlockedSubtract(&Receiver->InNDIS, Count);
-}
-
 static PNET_BUFFER_LIST
-ReceiverReceivePacket(
-    IN  PRECEIVER                               Receiver,
-    IN  PMDL                                    Mdl,
-    IN  ULONG                                   Offset,
-    IN  ULONG                                   Length,
-    IN  XENVIF_PACKET_CHECKSUM_FLAGS            Flags,
-    IN  USHORT                                  TagControlInformation
+__ReceiverReceivePacket(
+    IN  PXENNET_RECEIVER                Receiver,
+    IN  PMDL                            Mdl,
+    IN  ULONG                           Offset,
+    IN  ULONG                           Length,
+    IN  XENVIF_PACKET_CHECKSUM_FLAGS    Flags,
+    IN  USHORT                          TagControlInformation
     )
 {
-    PADAPTER                                    Adapter;
     PNET_BUFFER_LIST                            NetBufferList;
     NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    NetBufferList = ReceiverAllocateNetBufferList(Receiver,
-                                                  Mdl,
-                                                  Offset,
-                                                  Length);
+    NetBufferList = __ReceiverAllocateNetBufferList(Receiver,
+                                                    Mdl,
+                                                    Offset,
+                                                    Length);
     if (NetBufferList == NULL)
         goto fail1;
 
-    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
+    NetBufferList->SourceHandle = AdapterGetHandle(Receiver->Adapter);
 
     csumInfo.Value = 0;
 
@@ -300,26 +216,23 @@ ReceiverReceivePacket(
     return NetBufferList;
 
 fail2:
-    ReceiverReleaseNetBufferList(Receiver, NetBufferList, TRUE);
+    __ReceiverReleaseNetBufferList(Receiver, NetBufferList, TRUE);
 
 fail1:
     return NULL;
 }
 
 static VOID
-ReceiverPushPackets(
-    IN  PRECEIVER           Receiver,
+__ReceiverPushPackets(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               Count,
     IN  BOOLEAN             LowResources
     )
 {
-    PADAPTER                Adapter;
     ULONG                   Flags;
     LONG                    InNDIS;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
     InNDIS = Receiver->InNDIS;
 
     Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
@@ -342,7 +255,7 @@ ReceiverPushPackets(
             break;
     }
 
-    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
+    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Receiver->Adapter),
                                        NetBufferList,
                                        NDIS_DEFAULT_PORT_NUMBER,
                                        Count,
@@ -352,21 +265,121 @@ ReceiverPushPackets(
         (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
 }
 
-#define IN_NDIS_MAX 1024
+NDIS_STATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_RECEIVER    *Receiver
+    )
+{
+    NET_BUFFER_LIST_POOL_PARAMETERS Params;
+    NDIS_STATUS                     status;
+
+    *Receiver = ExAllocatePoolWithTag(NonPagedPool,
+                                      sizeof(XENNET_RECEIVER),
+                                      RECEIVER_POOL_TAG);
+
+    status = NDIS_STATUS_RESOURCES;
+    if (*Receiver == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
+    (*Receiver)->Adapter = Adapter;
+
+    RtlZeroMemory(&Params, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
+    Params.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Params.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    Params.Header.Size = sizeof(Params);
+    Params.ProtocolId = 0;
+    Params.ContextSize = 0;
+    Params.fAllocateNetBuffer = TRUE;
+    Params.PoolTag = 'PteN';
+
+    (*Receiver)->NetBufferListPool = NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
+                                                                   &Params);
+
+    status = NDIS_STATUS_RESOURCES;
+    if ((*Receiver)->NetBufferListPool == NULL)
+        goto fail2;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail2:
+fail1:
+    return status;
+}
+
+VOID
+ReceiverTeardown(
+    IN  PXENNET_RECEIVER    Receiver
+    )
+{
+    ULONG               Cpu;
+    PNET_BUFFER_LIST    NetBufferList;
+
+    ASSERT(Receiver != NULL);
+
+    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
+        NetBufferList = Receiver->GetList[Cpu];
+        while (NetBufferList != NULL) {
+            PNET_BUFFER_LIST    Next;
+
+            Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+            NdisFreeNetBufferList(NetBufferList);
+
+            NetBufferList = Next;
+        }
+    }
+
+    NetBufferList = Receiver->PutList;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST    Next;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NdisFreeNetBufferList(NetBufferList);
+
+        NetBufferList = Next;
+    }
+
+    NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
+    Receiver->NetBufferListPool = NULL;
+
+    Receiver->Adapter = NULL;
+
+    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
+}
+
+VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  ULONG               ReturnFlags
+    )
+{
+    ULONG                   Count;
+
+    UNREFERENCED_PARAMETER(ReturnFlags);
+
+    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferList, TRUE);
+    (VOID) __InterlockedSubtract(&Receiver->InNDIS, Count);
+}
 
 VOID
 ReceiverReceivePackets(
-    IN  PRECEIVER       Receiver,
-    IN  PLIST_ENTRY     List
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PLIST_ENTRY         List
     )
 {
-    PADAPTER            Adapter;
-    PNET_BUFFER_LIST    HeadNetBufferList;
-    PNET_BUFFER_LIST    *TailNetBufferList;
-    ULONG               Count;
-    BOOLEAN             LowResources;
+    PXENVIF_VIF_INTERFACE   VifInterface;
+    PNET_BUFFER_LIST        HeadNetBufferList;
+    PNET_BUFFER_LIST        *TailNetBufferList;
+    ULONG                   Count;
+    BOOLEAN                 LowResources;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    VifInterface = AdapterGetVifInterface(Receiver->Adapter);
     LowResources = FALSE;
 
 again:
@@ -404,28 +417,28 @@ again:
 
         TagControlInformation = Info->TagControlInformation;
 
-        NetBufferList = ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
+        NetBufferList = __ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
 
         if (NetBufferList != NULL) {
             *TailNetBufferList = NetBufferList;
             TailNetBufferList = &NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
             Count++;
         } else {
-            LIST_ENTRY  List;
+            LIST_ENTRY  PacketList;
 
-            InitializeListHead(&List);
-            InsertTailList(&List, &Packet->ListEntry);
+            InitializeListHead(&PacketList);
+            InsertTailList(&PacketList, &Packet->ListEntry);
 
             XENVIF_VIF(ReceiverReturnPackets,
-                       &Adapter->VifInterface,
-                       &List);
+                       VifInterface,
+                       &PacketList);
         }
     }
 
     if (Count != 0) {
         ASSERT(HeadNetBufferList != NULL);
 
-        ReceiverPushPackets(Receiver, HeadNetBufferList, Count, LowResources);
+        __ReceiverPushPackets(Receiver, HeadNetBufferList, Count, LowResources);
     }
 
     if (!IsListEmpty(List)) {
@@ -434,3 +447,12 @@ again:
         goto again;
     }
 }
+
+PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER    Receiver
+    )
+{
+    return &Receiver->OffloadOptions;
+}
+
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
index 1a58053..fb69b96 100644
--- a/src/xennet/receiver.h
+++ b/src/xennet/receiver.h
@@ -29,49 +29,41 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_RECEIVER_H_
+#define _XENNET_RECEIVER_H_
 
-typedef struct _RECEIVER {
-    NDIS_HANDLE                 NetBufferListPool;
-    PNET_BUFFER_LIST            PutList;
-    PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
-    LONG                        InNDIS;
-    LONG                        InNDISMax;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} RECEIVER, *PRECEIVER;
+#include <ndis.h>
 
-VOID
-ReceiverDebugDump (
-    IN PRECEIVER Receiver
-    );
-
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER Receiver
-    );
+typedef struct _XENNET_RECEIVER XENNET_RECEIVER, *PXENNET_RECEIVER;
 
-VOID
-ReceiverHandleNotification (
-    IN  PRECEIVER Receiver
+#include "adapter.h"
+extern NDIS_STATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_RECEIVER    *Receiver
     );
 
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER   Receiver
+extern VOID
+ReceiverTeardown(
+    IN  PXENNET_RECEIVER    Receiver
     );
 
-VOID 
-ReceiverReturnNetBufferLists (
-    IN  PRECEIVER           Receiver,
+extern VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               ReturnFlags
     );
 
-VOID
-ReceiverWaitForPacketReturn(
-    IN  PRECEIVER   Receiver,
-    IN  BOOLEAN     Locked
+extern VOID
+ReceiverReceivePackets(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PLIST_ENTRY         List
+    );
+
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER    Receiver
     );
 
-void ReceiverPause(PRECEIVER receiver);
-void ReceiverUnpause(PRECEIVER receiver);
+#endif // _XENNET_RECEIVER_H_
diff --git a/src/xennet/std.h b/src/xennet/std.h
deleted file mode 100644
index c72325a..0000000
--- a/src/xennet/std.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-#pragma warning(disable:4214)   // bit field types other than int
-
-#pragma warning(disable:4201)   // nameless struct/union
-#pragma warning(disable:4115)   // named type definition in parentheses
-#pragma warning(disable:4127)   // conditional expression is constant
-#pragma warning(disable:4054)   // cast of function pointer to PVOID
-#pragma warning(disable:4206)   // translation unit is empty
-
-#include <ndis.h>
-#include <ntstrsafe.h>
-
-extern PULONG InitSafeBootMode;
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 6a18a19..0c89f76 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -29,60 +29,78 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include <ndis.h>
+#include "transmitter.h"
+#include "adapter.h"
+#include <vif_interface.h>
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_TRANSMITTER {
+    PXENNET_ADAPTER             Adapter;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
+
+#define TRANSMITTER_POOL_TAG        'TteN'
 
 NDIS_STATUS
-TransmitterInitialize(
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+TransmitterInitialize (
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_TRANSMITTER *Transmitter
     )
 {
-    Transmitter->Adapter = Adapter;
-
+    *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
+                                         sizeof(XENNET_TRANSMITTER),
+                                         TRANSMITTER_POOL_TAG);
+    if (*Transmitter == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
+    (*Transmitter)->Adapter = Adapter;
+    
     return NDIS_STATUS_SUCCESS;
+
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
+
+VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    Transmitter->Adapter = NULL;
+    Transmitter->OffloadOptions.Value = 0;
+
+    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
 VOID
 TransmitterEnable(
-    IN  PTRANSMITTER    Transmitter
+    IN  PXENNET_TRANSMITTER Transmitter
     )
 {
-    PADAPTER            Adapter = Transmitter->Adapter;
+    PXENVIF_VIF_INTERFACE   VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
                       (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 }
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER *Transmitter
-    )
-{
-    ASSERT(Transmitter != NULL);
-
-    if (*Transmitter) {
-        ExFreePool(*Transmitter);
-        *Transmitter = NULL;
-    }
-}
-
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -97,24 +115,37 @@ typedef struct _NET_BUFFER_RESERVED {
 C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
 
 static VOID
-TransmitterAbortNetBufferList(
-    IN  PTRANSMITTER        Transmitter,
-    IN  PNET_BUFFER_LIST    NetBufferList
+__TransmitterCompleteNetBufferList(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_STATUS             Status
     )
 {
     ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_NOT_ACCEPTED;
+    NET_BUFFER_LIST_STATUS(NetBufferList) = Status;
+
+    if (Status == NDIS_STATUS_SUCCESS) {
+        PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+
+        LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)
+                                &NET_BUFFER_LIST_INFO(NetBufferList,
+                                                      TcpLargeSendNetBufferListInfo);
+        if (LargeSendInfo->LsoV2Transmit.MSS != 0)
+            LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
+    }
 
-    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+    NdisMSendNetBufferListsComplete(AdapterGetHandle(Transmitter->Adapter),
                                     NetBufferList,
                                     NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
 }
 
-VOID
-TransmitterAbortPackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+
+static VOID
+__TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    IN  NDIS_STATUS                 Status
     )
 {
     while (Packet != NULL) {
@@ -135,21 +166,86 @@ TransmitterAbortPackets(
 
         ASSERT(ListReserved->Reference != 0);
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
+            __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
 
         Packet = Next;
+    }    
+}
+
+static VOID
+__TransmitterOffloadOptions(
+    IN  PNET_BUFFER_LIST            NetBufferList,
+    OUT PXENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions,
+    OUT PUSHORT                     TagControlInformation,
+    OUT PUSHORT                     MaximumSegmentSize
+    )
+{
+    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+    PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO          ChecksumInfo;
+    PNDIS_NET_BUFFER_LIST_8021Q_INFO                    Ieee8021QInfo;
+
+    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                                TcpLargeSendNetBufferListInfo);
+    ChecksumInfo = (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                        TcpIpChecksumNetBufferListInfo);
+    Ieee8021QInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBufferList, 
+                                                                            Ieee8021QNetBufferListInfo);
+
+    OffloadOptions->Value = 0;
+    *TagControlInformation = 0;
+    *MaximumSegmentSize = 0;
+
+    if (ChecksumInfo->Transmit.IsIPv4) {
+        if (ChecksumInfo->Transmit.IpHeaderChecksum)
+            OffloadOptions->OffloadIpVersion4HeaderChecksum = 1;
+
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            OffloadOptions->OffloadIpVersion4TcpChecksum = 1;
+
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            OffloadOptions->OffloadIpVersion4UdpChecksum = 1;
+    }
+
+    if (ChecksumInfo->Transmit.IsIPv6) {
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            OffloadOptions->OffloadIpVersion6TcpChecksum = 1;
+
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            OffloadOptions->OffloadIpVersion6UdpChecksum = 1;
+    }
+
+    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
+        OffloadOptions->OffloadTagManipulation = 1;
+
+        ASSERT3U(Ieee8021QInfo->TagHeader.CanonicalFormatId, ==, 0);
+        ASSERT3U(Ieee8021QInfo->TagHeader.VlanId, ==, 0);
+
+        PACK_TAG_CONTROL_INFORMATION(*TagControlInformation,
+                                        Ieee8021QInfo->TagHeader.UserPriority,
+                                        Ieee8021QInfo->TagHeader.CanonicalFormatId,
+                                        Ieee8021QInfo->TagHeader.VlanId);
+    }
+
+    if (LargeSendInfo->LsoV2Transmit.MSS != 0) {
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4)
+            OffloadOptions->OffloadIpVersion4LargePacket = 1;
+
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
+            OffloadOptions->OffloadIpVersion6LargePacket = 1;
+
+        ASSERT3U(LargeSendInfo->LsoV2Transmit.MSS >> 16, ==, 0);
+        *MaximumSegmentSize = (USHORT)LargeSendInfo->LsoV2Transmit.MSS;
     }
 }
 
 VOID
 TransmitterSendNetBufferLists(
-    IN  PTRANSMITTER            Transmitter,
+    IN  PXENNET_TRANSMITTER     Transmitter,
     IN  PNET_BUFFER_LIST        NetBufferList,
     IN  NDIS_PORT_NUMBER        PortNumber,
     IN  ULONG                   SendFlags
     )
 {
-    PADAPTER                    Adapter = Transmitter->Adapter;
     PXENVIF_TRANSMITTER_PACKET  HeadPacket;
     PXENVIF_TRANSMITTER_PACKET  *TailPacket;
     KIRQL                       Irql;
@@ -167,26 +263,24 @@ TransmitterSendNetBufferLists(
     }
 
     while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST                                    ListNext;
-        PNET_BUFFER_LIST_RESERVED                           ListReserved;
-        PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
-        PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO          ChecksumInfo;
-        PNDIS_NET_BUFFER_LIST_8021Q_INFO                    Ieee8021QInfo;
-        PNET_BUFFER                                         NetBuffer;
+        PNET_BUFFER_LIST            ListNext;
+        PNET_BUFFER_LIST_RESERVED   ListReserved;
+        PNET_BUFFER                 NetBuffer;
+        XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+        USHORT                      TagControlInformation;
+        USHORT                      MaximumSegmentSize;
 
         ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
         NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
 
+        __TransmitterOffloadOptions(NetBufferList,
+                                    &OffloadOptions,
+                                    &TagControlInformation,
+                                    &MaximumSegmentSize);
+
         ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
         RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
 
-        LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                                 TcpLargeSendNetBufferListInfo);
-        ChecksumInfo = (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                         TcpIpChecksumNetBufferListInfo);
-        Ieee8021QInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBufferList, 
-                                                                                Ieee8021QNetBufferListInfo);
-
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
             PNET_BUFFER_RESERVED        Reserved;
@@ -199,50 +293,9 @@ TransmitterSendNetBufferLists(
             ListReserved->Reference++;
 
             Packet = &Reserved->Packet;
-
-            if (ChecksumInfo->Transmit.IsIPv4) {
-                if (ChecksumInfo->Transmit.IpHeaderChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if (ChecksumInfo->Transmit.TcpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if (ChecksumInfo->Transmit.UdpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-            }
-
-            if (ChecksumInfo->Transmit.IsIPv6) {
-                if (ChecksumInfo->Transmit.TcpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if (ChecksumInfo->Transmit.UdpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-            }
-
-            if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
-                Packet->Send.OffloadOptions.OffloadTagManipulation = 1;
-
-                ASSERT3U(Ieee8021QInfo->TagHeader.CanonicalFormatId, ==, 0);
-                ASSERT3U(Ieee8021QInfo->TagHeader.VlanId, ==, 0);
-
-                PACK_TAG_CONTROL_INFORMATION(Packet->Send.TagControlInformation,
-                                             Ieee8021QInfo->TagHeader.UserPriority,
-                                             Ieee8021QInfo->TagHeader.CanonicalFormatId,
-                                             Ieee8021QInfo->TagHeader.VlanId);
-            }
-
-            if (LargeSendInfo->LsoV2Transmit.MSS != 0) {
-                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-
-                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-
-                ASSERT3U(LargeSendInfo->LsoV2Transmit.MSS >> 16, ==, 0);
-                Packet->Send.MaximumSegmentSize = (USHORT)LargeSendInfo->LsoV2Transmit.MSS;
-            }
-
-            Packet->Send.OffloadOptions.Value &= Transmitter->OffloadOptions.Value;
+            Packet->Send.OffloadOptions.Value = OffloadOptions.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
+            Packet->Send.TagControlInformation = TagControlInformation;
 
             ASSERT3P(Packet->Next, ==, NULL);
             *TailPacket = Packet;
@@ -258,65 +311,29 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            &Adapter->VifInterface,
+                            AdapterGetVifInterface(Transmitter->Adapter),
                             HeadPacket);
         if (!NT_SUCCESS(status))
-            TransmitterAbortPackets(Transmitter, HeadPacket);
+            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
     }
 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
 }
 
-static VOID
-TransmitterCompleteNetBufferList(
-    IN  PTRANSMITTER                                    Transmitter,
-    IN  PNET_BUFFER_LIST                                NetBufferList
-    )
-{
-    PADAPTER                                            Adapter = Transmitter->Adapter;
-    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
-
-    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
-
-    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                             TcpLargeSendNetBufferListInfo);
-
-    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
-        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
-
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
-
-    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
-                                    NetBufferList,
-                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
-}
-
 VOID
 TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
+    IN  PXENNET_TRANSMITTER         Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
-
-        Next = Packet->Next;
-        Packet->Next = NULL;
-
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
-
-        NetBufferList = Reserved->NetBufferList;
-        ASSERT(NetBufferList != NULL);
-
-        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
-
-        ASSERT(ListReserved->Reference != 0);
-        if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
+    __TransmitterCompletePackets(Transmitter, Packet, NDIS_STATUS_SUCCESS);
+}
 
-        Packet = Next;
-    }
+PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    return &Transmitter->OffloadOptions;
 }
+
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index 8dc7e8d..f63a2a0 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -29,47 +29,47 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_TRANSMITTER_H_
+#define _XENNET_TRANSMITTER_H_
 
-typedef struct _TRANSMITTER {
-    PADAPTER                    Adapter;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} TRANSMITTER, *PTRANSMITTER;
+#include <ndis.h>
 
-VOID 
-TransmitterCleanup (
-    IN OUT PTRANSMITTER* Transmitter
-    );
+typedef struct _XENNET_TRANSMITTER XENNET_TRANSMITTER, *PXENNET_TRANSMITTER;
 
-NDIS_STATUS
-TransmitterInitialize (
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+#include "adapter.h"
+extern NDIS_STATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_TRANSMITTER *Transmitter
     );
 
-VOID
-TransmitterEnable (
-    IN  PTRANSMITTER    Transmitter
+extern VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER Transmitter
     );
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER* Transmitter
+extern VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER Transmitter
     );
 
-VOID
+extern VOID
 TransmitterSendNetBufferLists (
-    IN  PTRANSMITTER        Transmitter,
+    IN  PXENNET_TRANSMITTER Transmitter,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  NDIS_PORT_NUMBER    PortNumber,
     IN  ULONG               SendFlags
     );
 
-VOID
+extern VOID
 TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
+    IN  PXENNET_TRANSMITTER         Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET  Packet
     );
 
-void TransmitterPause(PTRANSMITTER Transmitter);
-void TransmitterUnpause(PTRANSMITTER Transmitter);
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER Transmitter
+    );
+
+#endif // _XENNET_TRANSMITTER_H_
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index aab91d2..03ddf91 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -84,8 +84,7 @@
 	</ItemGroup>
 	<ItemGroup>
 		<ClCompile Include="../../src/xennet/adapter.c" />
-		<ClCompile Include="../../src/xennet/main.c" />
-		<ClCompile Include="../../src/xennet/miniport.c" />
+		<ClCompile Include="../../src/xennet/driver.c" />
 		<ClCompile Include="../../src/xennet/receiver.c" />
 		<ClCompile Include="../../src/xennet/transmitter.c" />
 	</ItemGroup>
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index 9401b99..60c79f7 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -115,8 +115,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="../../src/xennet/adapter.c" />
-    <ClCompile Include="../../src/xennet/main.c" />
-    <ClCompile Include="../../src/xennet/miniport.c" />
+    <ClCompile Include="../../src/xennet/driver.c" />
     <ClCompile Include="../../src/xennet/receiver.c" />
     <ClCompile Include="../../src/xennet/transmitter.c" />
   </ItemGroup>
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:59 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:59 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebL-00049c-2q; Thu, 18 Dec 2014 17:10:59 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebJ-000492-47
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:57 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	4A/9C-15461-0AA03945; Thu, 18 Dec 2014 17:10:56 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-16.tower-21.messagelabs.com!1418922653!13136393!1
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31705 invoked from network); 18 Dec 2014 17:10:54 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877211"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:30 +0000
Message-ID: <1418921673-6008-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/6] Refactor for more maintainability.
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/adapter.c         | 3515 ++++++++++++++++++------------------------
 src/xennet/adapter.h         |  148 +-
 src/xennet/common.h          |   36 -
 src/xennet/main.c            |  348 -----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  328 ++--
 src/xennet/receiver.h        |   58 +-
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  301 ++--
 src/xennet/transmitter.h     |   50 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 12 files changed, 1963 insertions(+), 2938 deletions(-)
 delete mode 100644 src/xennet/common.h
 delete mode 100644 src/xennet/main.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/std.h

diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index 7cc49fb..a718a82 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -29,50 +29,31 @@
  * SUCH DAMAGE.
  */
 
+#include <ndis.h>
+#include "adapter.h"
+#include "transmitter.h"
+#include "receiver.h"
+#include <vif_interface.h>
 #include <version.h>
-#include "common.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_ADAPTER {
+    XENVIF_VIF_INTERFACE    VifInterface;
 
-//
-// List of supported OIDs.
-//
+    ULONG                   MaximumFrameSize;
+    ULONG                   CurrentLookahead;
 
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static NDIS_STATUS
-AdapterSetOffloadAttributes (
-    IN  PADAPTER Adapter
-    );
-
-static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
-static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
-    );
-
-static NDIS_STATUS
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+    NDIS_HANDLE             NdisAdapterHandle;
+    NDIS_HANDLE             NdisDmaHandle;
+    NDIS_PNP_CAPABILITIES   Capabilities;
+    NDIS_OFFLOAD            Offload;
+    PROPERTIES              Properties;
 
-static NDIS_STATUS
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+    PXENNET_RECEIVER        Receiver;
+    PXENNET_TRANSMITTER     Transmitter;
+    BOOLEAN                 Enabled;
+};
 
 static NDIS_OID XennetSupportedOids[] =
 {
@@ -129,28 +110,25 @@ static NDIS_OID XennetSupportedOids[] =
     OID_PNP_SET_POWER,
 };
 
-#define INITIALIZE_NDIS_OBJ_HEADER(obj, type) do {               \
-    (obj).Header.Type = NDIS_OBJECT_TYPE_ ## type ;              \
-    (obj).Header.Revision = NDIS_ ## type ## _REVISION_1;        \
-    (obj).Header.Size = sizeof(obj);                             \
-} while (0)
+#define ADAPTER_POOL_TAG    'AteN'
 
-NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
+__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
+static VOID
+AdapterProcessSGList(
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PVOID                Reserved,
+    IN PSCATTER_GATHER_LIST SGL,
+    IN PVOID                Context
+    )
 {
-    if (Adapter == NULL)
-        return STATUS_INVALID_PARAMETER;
-
-    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof (ADAPTER), ' TEN');
-    if (*Adapter == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Reserved);
+    UNREFERENCED_PARAMETER(SGL);
+    UNREFERENCED_PARAMETER(Context);
 
-    return STATUS_SUCCESS;
+    ASSERT(FALSE);
 }
 
-//
-// Scatter gather allocate handler callback.
-// Should never get called.
-//
 __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
 static VOID
 AdapterAllocateComplete (
@@ -168,140 +146,17 @@ AdapterAllocateComplete (
     UNREFERENCED_PARAMETER(Context);
 
     ASSERT(FALSE);
-
-    return;
-}
-
-//
-// Required NDIS6 handler.
-// Should never get called.
-//
-VOID
-AdapterCancelOidRequest (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       RequestId
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-    UNREFERENCED_PARAMETER(RequestId);
-
-    return;
-}
-
-//
-// Required NDIS6 handler.
-// Should never get called.
-//
-
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-    UNREFERENCED_PARAMETER(CancelId);
-
-    return;
-}
-
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    )
-{
-    UNREFERENCED_PARAMETER(NdisHandle);
-
-    return FALSE;
-}
-
-//
-// Frees resources obtained by AdapterInitialize.
-//
-VOID
-AdapterCleanup (
-    IN  PADAPTER Adapter
-    )
-{
-    Trace("====>\n");
-
-    TransmitterDelete(&Adapter->Transmitter);
-    ReceiverCleanup(&Adapter->Receiver);
-
-    if (Adapter->NdisDmaHandle != NULL)
-        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
-
-    XENVIF_VIF(Release, &Adapter->VifInterface);
-    Adapter->AcquiredInterfaces = FALSE;
-
-    Trace("<====\n");
-    return;
-}
-
-static VOID
-AdapterMediaStateChange(
-    IN  PADAPTER                Adapter
-    )
-{
-    NDIS_LINK_STATE             LinkState;
-    NDIS_STATUS_INDICATION      StatusIndication;
-
-    NdisZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
-
-    LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
-    LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    LinkState.Header.Size = sizeof(NDIS_LINK_STATE);
-
-    XENVIF_VIF(MacQueryState,
-               &Adapter->VifInterface,
-               &LinkState.MediaConnectState,
-               &LinkState.RcvLinkSpeed,
-               &LinkState.MediaDuplexState);
-
-    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
-        Info("LINK: STATE UNKNOWN\n");
-    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
-        Info("LINK: DOWN\n");
-    } else {
-        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
-
-        if (LinkState.MediaDuplexState == MediaDuplexStateHalf) 
-            Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed);
-        else if (LinkState.MediaDuplexState == MediaDuplexStateFull)
-            Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed);
-        else
-            Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed);
-    }
-
-    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
-
-    NdisZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
-
-    StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
-    StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
-    StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION);
-    StatusIndication.SourceHandle = Adapter->NdisAdapterHandle;
-    StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
-    StatusIndication.StatusBuffer = &LinkState;
-    StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE);
-
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
 }
 
-
-//
-// Initializes adapter by allocating required resources and connects to 
-// netback.
-//
-
 static VOID
 AdapterVifCallback(
     IN  PVOID                       Context,
     IN  XENVIF_VIF_CALLBACK_TYPE    Type,
-    ...)
+    ...
+    )
 {
-    PADAPTER                        Adapter = Context;
-    va_list                         Arguments;
+    PXENNET_ADAPTER     Adapter = Context;
+    va_list             Arguments;
 
     va_start(Arguments, Type);
 
@@ -319,7 +174,7 @@ AdapterVifCallback(
 
         List = va_arg(Arguments, PLIST_ENTRY);
 
-        ReceiverReceivePackets(&Adapter->Receiver, List);
+        ReceiverReceivePackets(Adapter->Receiver, List);
         break;
     }
     case XENVIF_MAC_STATE_CHANGE: {
@@ -331,2247 +186,1925 @@ AdapterVifCallback(
     va_end(Arguments);
 }
 
-NDIS_STATUS
-AdapterGetAdvancedSettings(
-    IN PADAPTER pAdapter
+static VOID
+AdapterIndicateOffloadChanged(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    NDIS_CONFIGURATION_OBJECT configObject;
-    NDIS_HANDLE hConfigurationHandle;
-    NDIS_STRING ndisValue;
-    PNDIS_CONFIGURATION_PARAMETER pNdisData;
-    NDIS_STATUS ndisStatus;
-    NTSTATUS status;
-
-    configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
-    configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
-    configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
-    configObject.NdisHandle = pAdapter->NdisAdapterHandle;
-    configObject.Flags = 0;
+    NDIS_STATUS_INDICATION      Status;
+    NDIS_OFFLOAD                Offload;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
 
-    ndisStatus = NdisOpenConfigurationEx(&configObject, &hConfigurationHandle);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
 
-    status = STATUS_UNSUCCESSFUL;
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail1;
-
-#define read_property(field, name, default_val) \
-    do { \
-        RtlInitUnicodeString(&ndisValue, name); \
-        NdisReadConfiguration(&ndisStatus, &pNdisData, hConfigurationHandle, &ndisValue, NdisParameterInteger); \
-        if (ndisStatus == NDIS_STATUS_SUCCESS) { \
-            pAdapter->Properties.field = pNdisData->ParameterData.IntegerData; \
-        } else { \
-            pAdapter->Properties.field = default_val; \
-        } \
-    } while (FALSE);
-
-    read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
-    read_property(tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3);
-    read_property(udpv4_csum, L"*UDPChecksumOffloadIPv4", 3);
-    read_property(tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3);
-    read_property(udpv6_csum, L"*UDPChecksumOffloadIPv6", 3);
-    read_property(lsov4, L"*LSOv2IPv4", 1);
-    read_property(lsov6, L"*LSOv2IPv6", 1);
-    read_property(lrov4, L"LROIPv4", 1);
-    read_property(lrov6, L"LROIPv6", 1);
-    read_property(need_csum_value, L"NeedChecksumValue", 1);
-
-    NdisCloseConfiguration(hConfigurationHandle);
-
-    return NDIS_STATUS_SUCCESS;
-
-fail1:
-    Error("fail1\n");
-    return NDIS_STATUS_FAILURE;
-}
+    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
+    Offload.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
+    Offload.Header.Revision = NDIS_OFFLOAD_REVISION_1;
+    Offload.Header.Size = sizeof(NDIS_OFFLOAD);
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
-    )
-{
-    NDIS_STATUS ndisStatus;
-    NDIS_SG_DMA_DESCRIPTION DmaDescription;
-    NTSTATUS status;
+    Offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
-    if (!NT_SUCCESS(status))
-        return NDIS_STATUS_FAILURE;
+    if (RxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Receive.IpChecksum = 1;
+        Offload.Checksum.IPv4Receive.IpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Receive.UdpChecksum = 1;
+    }
 
-    Adapter->AcquiredInterfaces = TRUE;
+    Offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
 
-    Trace("====>\n");
+    if (RxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
+    }
 
-    Adapter->NdisAdapterHandle = AdapterHandle;
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
+    Offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    Adapter->Transmitter = (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSMITTER), ' TEN');
-    if (!Adapter->Transmitter) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto exit;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
     }
-
-    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
-
-    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
     }
-
-    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
     }
 
-    ndisStatus = AdapterGetAdvancedSettings(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
-    }
+    Offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
 
-    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
     }
-
-    ndisStatus = AdapterSetGeneralAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
     }
 
-    ndisStatus = AdapterSetOffloadAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   4,
+                   &Offload.LsoV2.IPv4.MaxOffLoadSize);
+        Offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Offload.LsoV2.IPv4.MinSegmentCount = 2;
     }
 
-    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
-
-    DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
-    DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
-    DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);
-    DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;
-    DmaDescription.MaximumPhysicalMapping = 65536;    
-    DmaDescription.ProcessSGListHandler = AdapterProcessSGList;
-    DmaDescription.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
-
-    ndisStatus = NdisMRegisterScatterGatherDma(Adapter->NdisAdapterHandle,
-                                               &DmaDescription,
-                                               &Adapter->NdisDmaHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        Adapter->NdisDmaHandle = NULL;
+    if (TxOptions->OffloadIpVersion6LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   6,
+                   &Offload.LsoV2.IPv6.MaxOffLoadSize);
+        Offload.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Offload.LsoV2.IPv6.MinSegmentCount = 2;
+        Offload.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        Offload.LsoV2.IPv6.TcpOptionsSupported = 1;
+    }
 
-    ASSERT(!Adapter->Enabled);
-    status = XENVIF_VIF(Enable,
-                        &Adapter->VifInterface,
-                        AdapterVifCallback,
-                        Adapter);
-    if (NT_SUCCESS(status)) {
-        TransmitterEnable(Adapter->Transmitter);
-        Adapter->Enabled = TRUE;
-        ndisStatus = NDIS_STATUS_SUCCESS;
-    } else {
-        ndisStatus = NDIS_STATUS_FAILURE;
+    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof(NDIS_OFFLOAD))) {
+        Adapter->Offload = Offload;
+        // DISPPLAY_OFFLOAD(Offload);
     }
 
-exit:
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Status, sizeof(NDIS_STATUS_INDICATION));
+    Status.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    Status.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    Status.Header.Size = sizeof(NDIS_STATUS_INDICATION);
+    Status.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    Status.StatusBuffer = &Offload;
+    Status.StatusBufferSize = sizeof(Offload);
 
-    Trace("<==== (%08x)\n", ndisStatus);
-    return ndisStatus;
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &Status);
 }
 
-//
-// Scatter gather process handler callback.
-// Should never get called.
-//
 static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
+AdapterGetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PULONG                  PacketFilter
     )
 {
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Reserved);
-    UNREFERENCED_PARAMETER(SGL);
-    UNREFERENCED_PARAMETER(Context);
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    ASSERT(FALSE);
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               &UnicastFilterLevel);
 
-    return;
-}
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               &MulticastFilterLevel);
 
-//
-// Get\Set OID handler.
-//
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    NDIS_STATUS ndisStatus;
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_BROADCAST,
+               &BroadcastFilterLevel);
 
-    switch (NdisRequest->RequestType) {
-        case NdisRequestSetInformation:            
-            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
-            break;
-                
-        case NdisRequestQueryInformation:
-        case NdisRequestQueryStatistics:
-            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
-            break;
+    *PacketFilter = 0;
 
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+    if (UnicastFilterLevel == XENVIF_MAC_FILTER_ALL) {
+        ASSERT3U(MulticastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
+        ASSERT3U(BroadcastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
 
-    return ndisStatus;
+        *PacketFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+        return;
+    } else if (UnicastFilterLevel == XENVIF_MAC_FILTER_MATCHING) {
+        *PacketFilter |= NDIS_PACKET_TYPE_DIRECTED;
+    }
+
+    if (MulticastFilterLevel == XENVIF_MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+    else if (MulticastFilterLevel == XENVIF_MAC_FILTER_MATCHING)
+        *PacketFilter |= NDIS_PACKET_TYPE_MULTICAST;
+
+    if (BroadcastFilterLevel == XENVIF_MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
 }
 
-//
-// Temporarily pauses adapter.
-//
-NDIS_STATUS
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+static NDIS_STATUS
+AdapterSetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PULONG                  PacketFilter
     )
 {
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
-    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    Trace("====>\n");
+    if (*PacketFilter & ~XENNET_SUPPORTED_PACKET_FILTERS)
+        return NDIS_STATUS_INVALID_PARAMETER;
 
-    if (!Adapter->Enabled)
+    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
         goto done;
+    }
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
+        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-    AdapterMediaStateChange(Adapter);
+    if (*PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else if (*PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
+        MulticastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        MulticastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-    Adapter->Enabled = FALSE;
+    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
 done:
-    Trace("<====\n");
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               UnicastFilterLevel);
+
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               MulticastFilterLevel);
+
+    XENVIF_VIF(MacSetFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_BROADCAST,
+               BroadcastFilterLevel);
+
     return NDIS_STATUS_SUCCESS;
 }
 
-//
-// Handles PNP and Power events. NOP.
-//
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+static NDIS_STATUS
+AdapterGetOffloadEncapsulation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OFFLOAD_ENCAPSULATION Offload
     )
 {
-    UNREFERENCED_PARAMETER(NdisHandle);
+    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
 
+    if (Offload->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Offload->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto invalid_parameter;
 
-    switch (NetDevicePnPEvent->DevicePnPEvent) {
-        case NdisDevicePnPEventQueryRemoved:
-            break;
+    if (Offload->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Offload->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto invalid_parameter;
 
-        case NdisDevicePnPEventRemoved:
-            break;       
-
-        case NdisDevicePnPEventSurpriseRemoved:
-            break;
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
 
-        case NdisDevicePnPEventQueryStopped:
-            break;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    TxOptions->Value = 0;
+    TxOptions->OffloadTagManipulation = 1;
+
+    if (Adapter->Properties.lsov4 && Options.OffloadIpVersion4LargePacket)
+        TxOptions->OffloadIpVersion4LargePacket = 1;
+    if (Adapter->Properties.lsov6 && Options.OffloadIpVersion6LargePacket)
+        TxOptions->OffloadIpVersion6LargePacket = 1;
+    if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
+        TxOptions->OffloadIpVersion4HeaderChecksum = 1;
+    if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
+        TxOptions->OffloadIpVersion4TcpChecksum = 1;
+    if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
+        TxOptions->OffloadIpVersion4UdpChecksum = 1;
+    if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
+        TxOptions->OffloadIpVersion6TcpChecksum = 1;
+    if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
+        TxOptions->OffloadIpVersion6UdpChecksum = 1;
+
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
 
-        case NdisDevicePnPEventStopped:
-            break;      
-            
-        case NdisDevicePnPEventPowerProfileChanged:
-            break;      
-            
-        default:
-            break;         
-    };
+    if (Adapter->Properties.need_csum_value)
+        RxOptions->NeedChecksumValue = 1;
+    if (Adapter->Properties.lrov4)
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+    if (Adapter->Properties.lrov4)
+        RxOptions->NeedLargePacketSplit = 1;
+    if (Adapter->Properties.lrov6)
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+    if (Adapter->Properties.lrov6)
+        RxOptions->NeedLargePacketSplit = 1;
+    if (Adapter->Properties.ipv4_csum & 2)
+        RxOptions->OffloadIpVersion4HeaderChecksum = 1;
+    if (Adapter->Properties.tcpv4_csum & 2)
+        RxOptions->OffloadIpVersion4TcpChecksum = 1;
+    if (Adapter->Properties.udpv4_csum & 2)
+        RxOptions->OffloadIpVersion4UdpChecksum = 1;
+    if (Adapter->Properties.tcpv6_csum & 2)
+        RxOptions->OffloadIpVersion6TcpChecksum = 1;
+    if (Adapter->Properties.udpv6_csum & 2)
+        RxOptions->OffloadIpVersion6UdpChecksum = 1;
+
+    AdapterIndicateOffloadChanged(Adapter);
+    return NDIS_STATUS_SUCCESS;
 
-    return;
+invalid_parameter:
+    return NDIS_STATUS_INVALID_PARAMETER;
 }
 
-//
-// Reports general statistics to NDIS.
-//
-static NDIS_STATUS 
-AdapterQueryGeneralStatistics (
-    IN  PADAPTER                Adapter,
-    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
+#define NO_CHANGE(x)    ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
+#define RX_ENABLED(x)   ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||            \
+                         (x) == NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED)
+#define TX_ENABLED(x)   ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||            \
+                         (x) == NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED)
+#define CHANGE(x, y)    (((x) == (y)) ? 0 : (((x) = (y)) != (y)))
+
+static NDIS_STATUS
+AdapterGetTcpOffloadParameters(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OFFLOAD_PARAMETERS    Offload
     )
 {
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    ULONGLONG   Value;
+    XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS     TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS     RxOptions;
+    BOOLEAN                         Changed;
+
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
+
+    if (!NO_CHANGE(Offload->IPsecV1))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV1))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->TcpConnectionIPv4))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->TcpConnectionIPv6))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV2IPv4) &&
+        !(Options.OffloadIpVersion4LargePacket))
+        goto invalid_parameter;
+    if (!NO_CHANGE(Offload->LsoV2IPv6) &&
+        !(Options.OffloadIpVersion6LargePacket))
+        goto invalid_parameter;
+
+    Changed = FALSE;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+
+    if (Offload->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion4LargePacket, 1);
+    } else if (Offload->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion4LargePacket, 0);
+    }
+
+    if (Offload->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion6LargePacket, 1);
+    } else if (Offload->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= CHANGE(TxOptions->OffloadIpVersion6LargePacket, 0);
+    }
 
-    NdisZeroMemory(NdisStatisticsInfo, sizeof(NDIS_STATISTICS_INFO));
-    NdisStatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;
-    NdisStatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    NdisStatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4HeaderChecksum, TX_ENABLED(Offload->IPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4TcpChecksum, TX_ENABLED(Offload->TCPIPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion4UdpChecksum, TX_ENABLED(Offload->UDPIPv4Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion6TcpChecksum, TX_ENABLED(Offload->TCPIPv6Checksum));
+    Changed |= CHANGE(TxOptions->OffloadIpVersion6UdpChecksum, TX_ENABLED(Offload->UDPIPv6Checksum));
+
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4HeaderChecksum, RX_ENABLED(Offload->IPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4TcpChecksum, RX_ENABLED(Offload->TCPIPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion4UdpChecksum, RX_ENABLED(Offload->UDPIPv4Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion6TcpChecksum, RX_ENABLED(Offload->TCPIPv6Checksum));
+    Changed |= CHANGE(RxOptions->OffloadIpVersion6UdpChecksum, RX_ENABLED(Offload->UDPIPv6Checksum));
+
+    if (Changed)
+        AdapterIndicateOffloadChanged(Adapter);
+
+    return NDIS_STATUS_SUCCESS;
+
+invalid_parameter:
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
+
+#undef NO_CHANGE
+#undef RX_ENABLED
+#undef TX_ENABLED
+#undef CHANGE
+
+static NDIS_STATUS
+AdapterQueryGeneralStatistics(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_STATISTICS_INFO   Info
+    )
+{
+    ULONGLONG   Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    RtlZeroMemory(Info, sizeof(NDIS_STATISTICS_INFO));
+    Info->Header.Revision = NDIS_OBJECT_REVISION_1;
+    Info->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Info->Header.Size = sizeof(NDIS_STATISTICS_INFO);
 
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BACKEND_ERRORS,
                       &Value);
-
-    NdisStatisticsInfo->ifInErrors = Value;
-
+    Info->ifInErrors = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_FRONTEND_ERRORS,
                       &Value);
+    Info->ifInErrors += Value;
 
-    NdisStatisticsInfo->ifInErrors += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_PACKETS_DROPPED,
                       &Value);
+    Info->ifInDiscards = Value;
 
-    NdisStatisticsInfo->ifInDiscards = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInOctets = Value;
-
+    Info->ifHCInOctets = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInOctets += Value;
-
+    Info->ifHCInOctets += Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCInOctets += Value;
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_OCTETS,
                       &Value);
+    Info->ifHCInUcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInUcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_UNICAST_PACKETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCInUcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
-
+    Info->ifHCInUcastPkts = Value;
+    
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_OCTETS,
                       &Value);
+    Info->ifHCInMulticastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_MULTICAST_PACKETS,
                       &Value);
+    Info->ifHCInMulticastPkts = Value;
 
-    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCInBroadcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_RECEIVER_BROADCAST_PACKETS,
                       &Value);
+    Info->ifHCInBroadcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
                       &Value);
-
-    NdisStatisticsInfo->ifOutErrors = Value;
-
+    Info->ifOutErrors = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
                       &Value);
+    Info->ifOutErrors += Value;
 
-    NdisStatisticsInfo->ifOutErrors += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCOutOctets = Value;
-
+    Info->ifHCOutOctets = Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
                       &Value);
-
-    NdisStatisticsInfo->ifHCOutOctets += Value;
-
+    Info->ifHCOutOctets += Value;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCOutOctets += Value;
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
                       &Value);
+    Info->ifHCOutUcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
                       &Value);
+    Info->ifHCOutUcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
                       &Value);
+    Info->ifHCOutMulticastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
                       &Value);
+    Info->ifHCOutMulticastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
                       &Value);
+    Info->ifHCOutBroadcastOctets = Value;
 
-    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
-
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
     (VOID) XENVIF_VIF(QueryStatistic,
                       &Adapter->VifInterface,
                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
                       &Value);
+    Info->ifHCOutBroadcastPkts = Value;
 
-    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
+    Info->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
+    Info->ifOutDiscards = 0;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
-    NdisStatisticsInfo->ifOutDiscards = 0;
+    return NDIS_STATUS_SUCCESS;
+}
 
+static NDIS_STATUS
+AdapterQueryMulticastList(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN OUT PULONG           BytesNeeded
+    )
+{
+    ULONG       Count;
+    NDIS_STATUS ndisStatus;
+    NTSTATUS    status;
+
+    XENVIF_VIF(MacQueryMulticastAddresses,
+               &Adapter->VifInterface,
+               NULL,
+               &Count);
+    *BytesNeeded = Count * ETHERNET_ADDRESS_LENGTH;
+
+    ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+    if (BufferLength < *BytesNeeded) 
+        goto fail1;
+    
+    status = XENVIF_VIF(MacQueryMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Buffer,
+                        &Count);
+    ndisStatus = NDIS_STATUS_FAILURE;
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail2:
+fail1:
     return ndisStatus;
 }
 
-static VOID
-GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
+static FORCEINLINE NDIS_STATUS
+AdapterSetMulticastAddresses(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PETHERNET_ADDRESS   Address,
+    IN  ULONG               Count
+    )
 {
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
+    NTSTATUS        status;
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               &UnicastFilterLevel);
+    status = XENVIF_VIF(MacSetMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Address,
+                        Count);
+    if (!NT_SUCCESS(status))
+        return NDIS_STATUS_INVALID_DATA;
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               &MulticastFilterLevel);
+    return NDIS_STATUS_SUCCESS;
+}
 
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               &BroadcastFilterLevel);
+static NDIS_STATUS
+AdapterGetXmitOk(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONGLONG          Buffer
+    )
+{
+    ULONGLONG   Value;
 
-    *PacketFilter = 0;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                &Value);
 
-    if (UnicastFilterLevel == XENVIF_MAC_FILTER_ALL) {
-        ASSERT3U(MulticastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
-        ASSERT3U(BroadcastFilterLevel, ==, XENVIF_MAC_FILTER_ALL);
+    *Buffer = (ULONG)Value;
 
-        *PacketFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
-        return;
-    } else if (UnicastFilterLevel == XENVIF_MAC_FILTER_MATCHING) {
-        *PacketFilter |= NDIS_PACKET_TYPE_DIRECTED;
-    }
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-    if (MulticastFilterLevel == XENVIF_MAC_FILTER_ALL)
-        *PacketFilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
-    else if (MulticastFilterLevel == XENVIF_MAC_FILTER_MATCHING)
-        *PacketFilter |= NDIS_PACKET_TYPE_MULTICAST;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-    if (BroadcastFilterLevel == XENVIF_MAC_FILTER_ALL)
-        *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
+    return NDIS_STATUS_SUCCESS;
 }
 
-#define MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))
-
-//
-// Handles OID queries.
-//
-#pragma warning(push)
-#pragma warning(disable:6262)
-static NDIS_STATUS 
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+static NDIS_STATUS
+AdapterGetRcvOk(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONGLONG          Buffer
     )
 {
-    ULONG bytesAvailable = 0;
-    ULONG bytesNeeded = 0;
-    ULONG bytesWritten = 0;
-    BOOLEAN doCopy = TRUE;
-    PVOID info = NULL;
-    ULONGLONG infoData;
-    ULONG informationBufferLength;
-    PVOID informationBuffer;
-    NDIS_INTERRUPT_MODERATION_PARAMETERS intModParams;
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    NDIS_OID oid;
-
-    informationBuffer = NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
-    informationBufferLength = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
-    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
-    switch (oid) {
-        case OID_PNP_CAPABILITIES:
-            Trace("PNP_CAPABILITIES\n");
-
-            info = &Adapter->Capabilities;
-            bytesAvailable = sizeof(Adapter->Capabilities);
-            break;
-
-        case OID_PNP_QUERY_POWER:
-            Trace("QUERY_POWER\n");
-
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
-
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Trace("D0\n");
-                    break;
-
-                case NdisDeviceStateD1:
-                    Trace("D1\n");
-                    break;
-
-                case NdisDeviceStateD2:
-                    Trace("D2\n");
-                    break;
-
-                case NdisDeviceStateD3:
-                    Trace("D3\n");
-                    break;
-                }
-            }
-            break;
-
-        case OID_GEN_SUPPORTED_LIST:
-            info = &XennetSupportedOids[0];
-            bytesAvailable = sizeof(XennetSupportedOids);
-            break;
-
-        case OID_GEN_HARDWARE_STATUS:
-            infoData = NdisHardwareStatusReady;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MEDIA_SUPPORTED:
-        case OID_GEN_MEDIA_IN_USE:
-            infoData = XENNET_MEDIA_TYPE;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAXIMUM_LOOKAHEAD:
-            infoData = Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_BUFFER_SPACE:
-            XENVIF_VIF(TransmitterQueryRingSize,
-                       &Adapter->VifInterface,
-                       (PULONG)&infoData);
-            infoData *= Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_RECEIVE_BUFFER_SPACE:
-            XENVIF_VIF(TransmitterQueryRingSize,
-                       &Adapter->VifInterface,
-                       (PULONG)&infoData);
-            infoData *= Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_BLOCK_SIZE:
-        case OID_GEN_RECEIVE_BLOCK_SIZE:
-            infoData = Adapter->MaximumFrameSize;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_VENDOR_DESCRIPTION:
-            info = COMPANY_NAME_STR;
-            bytesAvailable = (ULONG)strlen(info) + 1;
-            break;
-
-        case OID_GEN_VENDOR_DRIVER_VERSION:
-            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_DRIVER_VERSION:
-            infoData = (6 << 8) | 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAC_OPTIONS:
-            infoData = XENNET_MAC_OPTIONS;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        
-        case OID_GEN_STATISTICS:
-            doCopy = FALSE;
-
-            bytesAvailable = sizeof(NDIS_STATISTICS_INFO);
-            if (informationBufferLength >= bytesAvailable) {
-                ndisStatus = AdapterQueryGeneralStatistics(Adapter, 
-                                                           informationBuffer);
-
-            }
-
-            break;
-
-        case OID_802_3_MULTICAST_LIST: {
-            ULONG Count;
-
-            doCopy = FALSE;
-
-            XENVIF_VIF(MacQueryMulticastAddresses,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &Count);
-            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
+    ULONGLONG   Value;
 
-            if (informationBufferLength >= bytesAvailable) {
-                NTSTATUS status;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_UNICAST_PACKETS,
+                &Value);
 
-                status = XENVIF_VIF(MacQueryMulticastAddresses,
-                                    &Adapter->VifInterface,
-                                    informationBuffer,
-                                    &Count);
-                if (!NT_SUCCESS(status))
-                    ndisStatus = NDIS_STATUS_FAILURE;
-            }
+    *Buffer = (ULONG)Value;
 
-            break;
-        }
-        case OID_802_3_PERMANENT_ADDRESS:
-            XENVIF_VIF(MacQueryPermanentAddress,
-                       &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
-            break;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_MULTICAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-        case OID_802_3_CURRENT_ADDRESS:
-            XENVIF_VIF(MacQueryCurrentAddress,
-                       &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
-            break;
-
-        case OID_GEN_MAXIMUM_FRAME_SIZE:
-            infoData = Adapter->MaximumFrameSize -
-                       sizeof (ETHERNET_TAGGED_HEADER);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_MAXIMUM_TOTAL_SIZE:
-            infoData = Adapter->MaximumFrameSize -
-                       sizeof (ETHERNET_TAGGED_HEADER) +
-                       sizeof (ETHERNET_UNTAGGED_HEADER);
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            infoData = Adapter->CurrentLookahead;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_VENDOR_ID:
-            infoData = 0x5853;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_LINK_SPEED: {
-            ULONG64 LinkSpeed;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BROADCAST_PACKETS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &LinkSpeed,
-                       NULL);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData = (ULONG)(LinkSpeed / 100);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MEDIA_CONNECT_STATUS:
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
-                       NULL,
-                       NULL);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        case OID_GEN_MAXIMUM_SEND_PACKETS:
-            infoData = 16;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            GetPacketFilter(Adapter, (PULONG)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_XMIT_OK: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
+static NDIS_STATUS
+AdapterGetXmitError(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONG              Buffer
+    )
+{
+    ULONGLONG   Value;
 
-            infoData = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                &Value);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
+    *Buffer = (ULONG)Value;
 
-            infoData += Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData += Value;
+static FORCEINLINE NDIS_STATUS
+AdapterGetRcvError(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PULONG              Buffer
+    )
+{
+    ULONGLONG   Value;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_RCV_OK: {
-            ULONGLONG   Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BACKEND_ERRORS,
+                &Value);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
+    *Buffer = (ULONG)Value;
 
-            infoData = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_FRONTEND_ERRORS,
+                &Value);
+    
+    *Buffer += (ULONG)Value;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-            infoData += Value;
+static FORCEINLINE NDIS_STATUS
+AdapterInterruptModeration(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_INTERRUPT_MODERATION_PARAMETERS   Params
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
+    Params->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Params->Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+    Params->Header.Size = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
 
-            infoData += Value;
+    Params->Flags = 0;
+    Params->InterruptModeration = NdisInterruptModerationNotSupported;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_XMIT_ERROR: {
-            ULONGLONG   Value;
+    return NDIS_STATUS_SUCCESS;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                       &Value);
+NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->NdisAdapterHandle;
+}
 
-            infoData = Value;
+PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return &Adapter->VifInterface;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                       &Value);
+PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->Transmitter;
+}
 
-            infoData += Value;
+PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    return Adapter->Receiver;
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_ERROR: {
-            ULONGLONG   Value;
+NDIS_STATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    NTSTATUS        status;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BACKEND_ERRORS,
-                       &Value);
+    if (Adapter->Enabled)
+        return NDIS_STATUS_SUCCESS;
 
-            infoData = Value;
+    status = XENVIF_VIF(Enable,
+                        &Adapter->VifInterface,
+                        AdapterVifCallback,
+                        Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_FRONTEND_ERRORS,
-                       &Value);
+    TransmitterEnable(Adapter->Transmitter);
+    Adapter->Enabled = TRUE;
 
-            infoData += Value;
+    return NDIS_STATUS_SUCCESS;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_NO_BUFFER:
-            infoData = 0;   // We'd need to query VIF TX drop stats from dom0
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_802_3_MAXIMUM_LIST_SIZE:
-            infoData = 32;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_IP4_OFFLOAD_STATS:
-        case OID_IP6_OFFLOAD_STATS:
-        case OID_GEN_SUPPORTED_GUIDS:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        case OID_GEN_RCV_CRC_ERROR:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_802_3_RCV_ERROR_ALIGNMENT:
-        case OID_802_3_XMIT_ONE_COLLISION:
-        case OID_802_3_XMIT_MORE_COLLISIONS:
-            infoData = 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-
-        case OID_GEN_DIRECTED_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                       &Value);
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
 
-            infoData = Value;
+BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    if (!Adapter->Enabled)
+        return FALSE;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_XMIT: {
-            ULONGLONG   Value;
+    XENVIF_VIF(Disable,
+               &Adapter->VifInterface);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
+    AdapterMediaStateChange(Adapter);
 
-            infoData = Value;
+    Adapter->Enabled = FALSE;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_XMIT: {
-            ULONGLONG   Value;
+    return TRUE;
+}
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                       &Value);
+VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER     Adapter
+    )
+{
+    NDIS_LINK_STATE         LinkState;
+    NDIS_STATUS_INDICATION  StatusIndication;
 
-            infoData = Value;
+    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
+    LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
+    LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    LinkState.Header.Size = sizeof(NDIS_LINK_STATE);
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
+    XENVIF_VIF(MacQueryState,
+               &Adapter->VifInterface,
+               &LinkState.MediaConnectState,
+               &LinkState.RcvLinkSpeed,
+               &LinkState.MediaDuplexState);
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
+    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
+        Info("LINK: STATE UNKNOWN\n");
+    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
+        Info("LINK: DOWN\n");
+    } else {
+        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
 
-            infoData = Value;
+        if (LinkState.MediaDuplexState == MediaDuplexStateHalf) 
+            Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed);
+        else if (LinkState.MediaDuplexState == MediaDuplexStateFull)
+            Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed);
+        else
+            Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed);
+    }
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_XMIT: {
-            ULONGLONG   Value;
+    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                       &Value);
+    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
+    StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION);
+
+    StatusIndication.SourceHandle = Adapter->NdisAdapterHandle;
+    StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
+    StatusIndication.StatusBuffer = &LinkState;
+    StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE);
 
-            infoData = Value;
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded;
+    ULONG           BytesRead;
+    NDIS_STATUS     ndisStatus;
+
+    Buffer = Request->DATA.SET_INFORMATION.InformationBuffer;
+    BufferLength = Request->DATA.SET_INFORMATION.InformationBufferLength;
+    BytesNeeded = BytesRead = 0;
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    switch (Request->DATA.SET_INFORMATION.Oid) {
+    case OID_PNP_SET_POWER:
+        BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+        // do nothing
+        break;
+
+    case OID_GEN_CURRENT_LOOKAHEAD:
+        BytesNeeded = sizeof(ULONG);
+        Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
+        if (BufferLength == BytesNeeded) {
+            Adapter->CurrentLookahead = *(PULONG)Buffer;
+            BytesRead = sizeof(ULONG);
+        }            
+        break;
+
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        BytesNeeded = sizeof(ULONG);
+        if (BufferLength == BytesNeeded) {
+            AdapterSetPacketFilter(Adapter,
+                                   (PULONG)Buffer);
+            BytesRead = sizeof(ULONG);
         }
-        case OID_GEN_BROADCAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
+    case OID_802_3_MULTICAST_LIST:
+        BytesNeeded = ETHERNET_ADDRESS_LENGTH;
+        if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
+            ndisStatus = AdapterSetMulticastAddresses(Adapter,
+                                                      Buffer,
+                                                      BufferLength / ETHERNET_ADDRESS_LENGTH);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = BufferLength;
+        } else {
+            ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+        }
+        break;
 
-            infoData = Value;
+    case OID_OFFLOAD_ENCAPSULATION:
+        BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetOffloadEncapsulation(Adapter,
+                                                        (PNDIS_OFFLOAD_ENCAPSULATION)Buffer);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+        }
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_TCP_OFFLOAD_PARAMETERS:
+        BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetTcpOffloadParameters(Adapter,
+                                                        (PNDIS_OFFLOAD_PARAMETERS)Buffer);
+            if (ndisStatus == NDIS_STATUS_SUCCESS)
+                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
         }
-        case OID_GEN_DIRECTED_BYTES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_OCTETS,
-                       &Value);
+    case OID_GEN_INTERRUPT_MODERATION:
+    case OID_GEN_MACHINE_NAME:
+    default:
+        ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        break;
+    }
+
+    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
+    if (ndisStatus == NDIS_STATUS_SUCCESS)
+        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
 
-            infoData = Value;
+    return ndisStatus;
+}
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+static FORCEINLINE NDIS_STATUS
+__CopyBuffer(
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN  PVOID               Source,
+    IN OUT PULONG           SourceLength
+    )
+{
+    if (BufferLength >= *SourceLength) {
+        RtlCopyMemory(Buffer, Source, *SourceLength);
+        return NDIS_STATUS_SUCCESS;
+    } else {
+        *SourceLength = BufferLength;
+        RtlCopyMemory(Buffer, Source, *SourceLength);
+        return NDIS_STATUS_BUFFER_TOO_SHORT;
+    }
+}
+
+static FORCEINLINE NDIS_STATUS
+__SetUlong(
+    IN  PVOID               Buffer,
+    IN  ULONG               BufferLength,
+    IN  ULONG               Source,
+    IN OUT PULONG           SourceLength
+    )
+{
+    if (BufferLength >= sizeof(ULONG)) {
+        *(PULONG)Buffer = Source;
+        *SourceLength = sizeof(ULONG);
+        return NDIS_STATUS_SUCCESS;
+    } else {
+        *SourceLength = 0;
+        return NDIS_STATUS_BUFFER_TOO_SHORT;
+    }
+}
+
+NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded;
+    ULONG           BytesWritten;
+    ULONG           Value32;
+    ULONGLONG       Value64;
+    NDIS_STATUS     ndisStatus;
+
+    Buffer = Request->DATA.QUERY_INFORMATION.InformationBuffer;
+    BufferLength = Request->DATA.QUERY_INFORMATION.InformationBufferLength;
+    BytesNeeded = BytesWritten = sizeof(ULONG);
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+    case OID_PNP_CAPABILITIES:
+        BytesNeeded = BytesWritten = sizeof(Adapter->Capabilities);
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  &Adapter->Capabilities,
+                                  &BytesWritten);
+        break;
+
+    case OID_PNP_QUERY_POWER:
+        BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+        // do nothing
+        break;
+
+    case OID_GEN_SUPPORTED_LIST:
+        BytesNeeded = BytesWritten = sizeof(XennetSupportedOids);
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  &XennetSupportedOids[0],
+                                  &BytesWritten);
+        break;
+
+    case OID_GEN_HARDWARE_STATUS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                NdisHardwareStatusReady,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MEDIA_SUPPORTED:
+    case OID_GEN_MEDIA_IN_USE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                XENNET_MEDIA_TYPE,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MAXIMUM_LOOKAHEAD:
+    case OID_GEN_TRANSMIT_BLOCK_SIZE:
+    case OID_GEN_RECEIVE_BLOCK_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_TRANSMIT_BUFFER_SPACE:
+    case OID_GEN_RECEIVE_BUFFER_SPACE:
+        XENVIF_VIF(TransmitterQueryRingSize,
+                    &Adapter->VifInterface,
+                    (PULONG)&Value32);
+        Value32 *= Adapter->MaximumFrameSize;
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Value32,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_DESCRIPTION:
+        BytesNeeded = BytesWritten = (ULONG)strlen(COMPANY_NAME_STR) + 1;
+        ndisStatus = __CopyBuffer(Buffer,
+                                  BufferLength,
+                                  COMPANY_NAME_STR,
+                                  &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_DRIVER_VERSION:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DRIVER_VERSION:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (6 << 8) | 0, // NDIS 6.0
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MAC_OPTIONS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                XENNET_MAC_OPTIONS,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_STATISTICS:
+        BytesNeeded = BytesWritten = sizeof(NDIS_STATISTICS_INFO);
+        if (BufferLength >= BytesNeeded)
+            ndisStatus = AdapterQueryGeneralStatistics(Adapter,
+                                                       (PNDIS_STATISTICS_INFO)Buffer);
+        break;
+
+    case OID_802_3_MULTICAST_LIST:
+        ndisStatus = AdapterQueryMulticastList(Adapter,
+                                               Buffer,
+                                               BufferLength,
+                                               &BytesNeeded);
+        BytesWritten = BytesNeeded;
+        break;
+
+    case OID_802_3_PERMANENT_ADDRESS:
+        BytesNeeded = BytesWritten = sizeof(ETHERNET_ADDRESS);
+        if (BufferLength >= BytesNeeded) {
+            XENVIF_VIF(MacQueryPermanentAddress,
+                       &Adapter->VifInterface,
+                       (PETHERNET_ADDRESS)Buffer);
         }
-        case OID_GEN_DIRECTED_FRAMES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
+    case OID_802_3_CURRENT_ADDRESS:
+        BytesNeeded = BytesWritten = sizeof(ETHERNET_ADDRESS);
+        if (BufferLength >= BytesNeeded) {
+            XENVIF_VIF(MacQueryCurrentAddress,
                        &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
+                       (PETHERNET_ADDRESS)Buffer);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_MAXIMUM_FRAME_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize - sizeof(ETHERNET_TAGGED_HEADER),
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_RCV: {
-            ULONGLONG   Value;
+    case OID_GEN_MAXIMUM_TOTAL_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->MaximumFrameSize -
+                                    sizeof(ETHERNET_TAGGED_HEADER) +
+                                    sizeof (ETHERNET_UNTAGGED_HEADER),
+                                &BytesWritten);
+        break;
 
-            XENVIF_VIF(QueryStatistic,
+    case OID_GEN_CURRENT_LOOKAHEAD:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                Adapter->CurrentLookahead,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_VENDOR_ID:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                0x5853,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_LINK_SPEED:
+        XENVIF_VIF(MacQueryState,
+                   &Adapter->VifInterface,
+                   NULL,
+                   &Value64,
+                   NULL);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)(Value64 / 100),
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MEDIA_CONNECT_STATUS:
+        if (BufferLength >= sizeof(ULONG)) {
+            XENVIF_VIF(MacQueryState,
                        &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_OCTETS,
-                       &Value);
+                       (PNET_IF_MEDIA_CONNECT_STATE)Buffer,
+                       NULL,
+                       NULL);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_MAXIMUM_SEND_PACKETS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                16,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_CURRENT_PACKET_FILTER:
+        if (BufferLength >= sizeof(ULONG)) {
+            AdapterGetPacketFilter(Adapter,
+                                   (PULONG)Buffer);
         }
-        case OID_GEN_MULTICAST_FRAMES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
+    case OID_GEN_XMIT_OK:
+        BytesNeeded = BytesWritten = sizeof(ULONGLONG);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetXmitOk(Adapter,
+                                          (PULONGLONG)Buffer);
+        }
+        break;
 
-            infoData = Value;
+    case OID_GEN_RCV_OK:
+        BytesNeeded = BytesWritten = sizeof(ULONGLONG);
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetRcvOk(Adapter,
+                                          (PULONGLONG)Buffer);
+        }
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_XMIT_ERROR:
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetXmitError(Adapter,
+                                             (PULONG)Buffer);
         }
-        case OID_GEN_BROADCAST_BYTES_RCV: {
-            ULONGLONG   Value;
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_OCTETS,
-                       &Value);
+    case OID_GEN_RCV_ERROR:
+        if (BufferLength >= BytesNeeded) {
+            ndisStatus = AdapterGetRcvError(Adapter,
+                                            (PULONG)Buffer);
+        }
+        break;
+
+    case OID_GEN_RCV_NO_BUFFER:
+    case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+    case OID_GEN_RCV_CRC_ERROR:
+    case OID_802_3_RCV_ERROR_ALIGNMENT:
+    case OID_802_3_XMIT_ONE_COLLISION:
+    case OID_802_3_XMIT_MORE_COLLISIONS:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                0,
+                                &BytesWritten);
+        break;
+
+    case OID_802_3_MAXIMUM_LIST_SIZE:
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                32,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MULTICAST_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_MULTICAST_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_BROADCAST_BYTES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_BROADCAST_FRAMES_XMIT:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_UNICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
+
+    case OID_GEN_DIRECTED_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_UNICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            infoData = Value;
+    case OID_GEN_MULTICAST_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_MULTICAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_RCV: {
-            ULONGLONG   Value;
+    case OID_GEN_MULTICAST_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_MULTICAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
+    case OID_GEN_BROADCAST_BYTES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_BROADCAST_OCTETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            infoData = Value;
+    case OID_GEN_BROADCAST_FRAMES_RCV:
+        XENVIF_VIF(QueryStatistic,
+                   &Adapter->VifInterface,
+                   XENVIF_RECEIVER_BROADCAST_PACKETS,
+                   &Value64);
+        ndisStatus = __SetUlong(Buffer,
+                                BufferLength,
+                                (ULONG)Value64,
+                                &BytesWritten);
+        break;
 
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
+    case OID_GEN_INTERRUPT_MODERATION:
+        BytesNeeded = BytesWritten = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+        if (BufferLength >= BytesWritten) {
+            ndisStatus = AdapterInterruptModeration(Adapter,
+                                                    (PNDIS_INTERRUPT_MODERATION_PARAMETERS)Buffer);
         }
-        case OID_GEN_INTERRUPT_MODERATION:
-            intModParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-            intModParams.Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
-            intModParams.Header.Size = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
-            intModParams.Flags = 0;
-            intModParams.InterruptModeration = NdisInterruptModerationNotSupported;
-            info = &intModParams;
-            bytesAvailable = sizeof(intModParams);
-            break;
+        break;
+
+    case OID_IP4_OFFLOAD_STATS:
+    case OID_IP6_OFFLOAD_STATS:
+    case OID_GEN_SUPPORTED_GUIDS:
 
         // We don't handle these since NDIS 6.0 is supposed to do this for us
-        case OID_GEN_MAC_ADDRESS:
-        case OID_GEN_MAX_LINK_SPEED:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-		// ignore these common unwanted OIDs
-		case OID_GEN_INIT_TIME_MS:
-		case OID_GEN_RESET_COUNTS:
-		case OID_GEN_MEDIA_SENSE_COUNTS:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
-
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        if (bytesAvailable <= informationBufferLength) {
-            bytesNeeded = bytesAvailable;
-            bytesWritten = bytesAvailable;
-        } else {
-            bytesNeeded = bytesAvailable;
-            bytesWritten = informationBufferLength;
-            ndisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
-        }
+    case OID_GEN_MAC_ADDRESS:
+    case OID_GEN_MAX_LINK_SPEED:
 
-        if (bytesWritten && doCopy) {
-            NdisMoveMemory(informationBuffer, info, bytesWritten);
+        // ignore these common unwanted OIDs
+	case OID_GEN_INIT_TIME_MS:
+	case OID_GEN_RESET_COUNTS:
+	case OID_GEN_MEDIA_SENSE_COUNTS:
 
-            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
-                ndisStatus = NDIS_STATUS_SUCCESS;
-        }
+    default:
+        ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        BytesNeeded = 0;
+        break;
     }
-    
-    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = bytesWritten;
-    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = bytesNeeded;
+
+    if (ndisStatus == NDIS_STATUS_SUCCESS)
+        Request->DATA.QUERY_INFORMATION.BytesWritten = BytesWritten;
+
+    Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesNeeded;
+
     return ndisStatus;
 }
-#pragma warning(pop)
 
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
+static NTSTATUS
+__QueryInterface(
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  const GUID      *Guid,
+    IN  ULONG           Version,
+    OUT PINTERFACE      Interface,
+    IN  ULONG           Size,
+    IN  BOOLEAN         Optional
     )
 {
-    UNREFERENCED_PARAMETER(MiniportAdapterContext);
-
+    KEVENT              Event;
+    IO_STATUS_BLOCK     StatusBlock;
+    PIRP                Irp;
+    PIO_STACK_LOCATION  StackLocation;
+    NTSTATUS            status;
 
-    *AddressingReset = FALSE;
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    return NDIS_STATUS_SUCCESS;
-}
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
 
-//
-// Restarts a paused adapter.
-//
-NDIS_STATUS
-AdapterRestart (
-    IN  NDIS_HANDLE                         MiniportAdapterContext,
-    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
-    )
-{
-    NTSTATUS				     status;
-    NDIS_STATUS			     ndisStatus;
-    PADAPTER				     Adapter = (PADAPTER)MiniportAdapterContext;
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
 
-    UNREFERENCED_PARAMETER(MiniportRestartParameters);
+    status = STATUS_UNSUCCESSFUL;
+    if (Irp == NULL)
+        goto fail1;
 
-    Trace("====>\n");
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
 
-    if (Adapter->Enabled) {
-        ndisStatus = NDIS_STATUS_SUCCESS;
-        goto done;
+    StackLocation->Parameters.QueryInterface.InterfaceType = Guid;
+    StackLocation->Parameters.QueryInterface.Size = (USHORT)Size;
+    StackLocation->Parameters.QueryInterface.Version = (USHORT)Version;
+    StackLocation->Parameters.QueryInterface.Interface = Interface;
+    
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    status = IoCallDriver(DeviceObject, Irp);
+    if (status == STATUS_PENDING) {
+        (VOID) KeWaitForSingleObject(&Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        status = StatusBlock.Status;
     }
 
-    status = XENVIF_VIF(Enable,
-                 &Adapter->VifInterface,
-                 AdapterVifCallback,
-                 Adapter);
-    if (NT_SUCCESS(status)) {
-        TransmitterEnable(Adapter->Transmitter);
-        Adapter->Enabled = TRUE;
-        ndisStatus = NDIS_STATUS_SUCCESS;
-    } else {
-        ndisStatus = NDIS_STATUS_FAILURE;
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_NOT_SUPPORTED && Optional)
+            goto done;
+
+        goto fail2;
     }
 
 done:
-    Trace("<====\n");
-    return ndisStatus;
-}
+    return STATUS_SUCCESS;
 
-//
-// Recycle of received net buffer lists.
-//
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+fail2:
+    Error("fail2\n");
 
-    ReceiverReturnNetBufferLists(&Adapter->Receiver,
-                                 NetBufferLists,
-                                 ReturnFlags);
+fail1:
+    Error("fail1 (%08x)\n", status);
 
-    return;
+    return status;
 }
 
-//
-// Used to send net buffer lists.
-//
-VOID 
-AdapterSendNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+#define READ_PROPERTY(field, name, defaultval, handle)  \
+    do {                                                \
+        NDIS_STATUS                     _Status;        \
+        NDIS_STRING                     _Value;         \
+        PNDIS_CONFIGURATION_PARAMETER   _Data;          \
+        RtlInitUnicodeString(&_Value, name);            \
+        NdisReadConfiguration(&_Status, &_Data, handle, \
+                        &_Value, NdisParameterInteger); \
+        if (_Status == NDIS_STATUS_SUCCESS)             \
+            field = _Data->ParameterData.IntegerData;   \
+        else                                            \
+            field = defaultval;                         \
+    } while (FALSE);
+
+static NDIS_STATUS
+AdapterGetAdvancedSettings(
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+    NDIS_CONFIGURATION_OBJECT   Config;
+    NDIS_HANDLE                 Handle;
+    NDIS_STATUS                 ndisStatus;
+
+    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
+    Config.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    Config.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    Config.Header.Size = sizeof(NDIS_CONFIGURATION_OBJECT);
+    Config.NdisHandle = Adapter->NdisAdapterHandle;
+    Config.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&Config, &Handle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
 
-    TransmitterSendNetBufferLists(Adapter->Transmitter,
-                                  NetBufferList,
-                                  PortNumber,
-                                  SendFlags);
-}
+    READ_PROPERTY(Adapter->Properties.ipv4_csum, L"*IPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.udpv4_csum, L"*UDPChecksumOffloadIPv4", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.udpv6_csum, L"*UDPChecksumOffloadIPv6", 3, Handle);
+    READ_PROPERTY(Adapter->Properties.lsov4, L"*LSOv2IPv4", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lsov6, L"*LSOv2IPv6", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lrov4, L"LROIPv4", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.lrov6, L"LROIPv6", 1, Handle);
+    READ_PROPERTY(Adapter->Properties.need_csum_value, L"NeedChecksumValue", 1, Handle);
+
+    NdisCloseConfiguration(Handle);
 
-#define XENNET_MEDIA_MAX_SPEED 1000000000ull
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
 
-#define XENNET_SUPPORTED_PACKET_FILTERS     \
-        (NDIS_PACKET_TYPE_DIRECTED |        \
-         NDIS_PACKET_TYPE_MULTICAST |       \
-         NDIS_PACKET_TYPE_ALL_MULTICAST |   \
-         NDIS_PACKET_TYPE_BROADCAST |       \
-         NDIS_PACKET_TYPE_PROMISCUOUS)
+#undef READ_PROPERTY
 
-//
-// Sets general adapter attributes. 
-//
 static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
+AdapterSetRegistrationAttributes(
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
-    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES   Attribs;
+    NDIS_STATUS                                     ndisStatus;
+
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    Attribs.MiniportAdapterContext = (NDIS_HANDLE)Adapter;
+    Attribs.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER |
+                             NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
+    Attribs.CheckForHangTimeInSeconds = 0;
+    Attribs.InterfaceType = XENNET_INTERFACE_TYPE;
 
-    NdisZeroMemory(&generalAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
-
-    generalAttributes.Header.Type = 
-                    NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 
-    generalAttributes.Header.Revision = 
-                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    return ndisStatus;
+}
 
-    generalAttributes.Header.Size = 
-                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+static NDIS_STATUS
+AdapterSetGeneralAttributes(
+    IN  PXENNET_ADAPTER Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
+    NDIS_STATUS                                 ndisStatus;
 
-    generalAttributes.MediaType = XENNET_MEDIA_TYPE;
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+    Attribs.MediaType = XENNET_MEDIA_TYPE;
 
     XENVIF_VIF(MacQueryMaximumFrameSize,
                &Adapter->VifInterface,
                (PULONG)&Adapter->MaximumFrameSize);
 
-    generalAttributes.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER);
-    generalAttributes.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
-    generalAttributes.MediaConnectState = MediaConnectStateConnected;
-    generalAttributes.MediaDuplexState = MediaDuplexStateFull;
-    generalAttributes.LookaheadSize = Adapter->MaximumFrameSize;
-    generalAttributes.PowerManagementCapabilities = &Adapter->Capabilities;
-    generalAttributes.MacOptions = XENNET_MAC_OPTIONS;
-
-    generalAttributes.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS;
-        
-    generalAttributes.MaxMulticastListSize = 32;
-    generalAttributes.MacAddressLength = ETHERNET_ADDRESS_LENGTH;
+    Attribs.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_TAGGED_HEADER);
+    Attribs.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    Attribs.MediaConnectState = MediaConnectStateConnected;
+    Attribs.MediaDuplexState = MediaDuplexStateFull;
+    Attribs.LookaheadSize = Adapter->MaximumFrameSize;
+    Attribs.PowerManagementCapabilities = &Adapter->Capabilities;
+    Attribs.MacOptions = XENNET_MAC_OPTIONS;
+    Attribs.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS;
+    Attribs.MaxMulticastListSize = 32;
+    Attribs.MacAddressLength = ETHERNET_ADDRESS_LENGTH;
 
     XENVIF_VIF(MacQueryPermanentAddress,
                &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.PermanentMacAddress);
+               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
     XENVIF_VIF(MacQueryCurrentAddress,
                &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.CurrentMacAddress);
-
-    generalAttributes.PhysicalMediumType = NdisPhysicalMedium802_3;
-    generalAttributes.RecvScaleCapabilities = NULL;
-    generalAttributes.AccessType = NET_IF_ACCESS_BROADCAST;
-    generalAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
-    generalAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
-    generalAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; 
-    generalAttributes.IfConnectorPresent = TRUE;
-
-    generalAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |
-                                            NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED |
-                                            NDIS_STATISTICS_RCV_OK_SUPPORTED |
-                                            NDIS_STATISTICS_RCV_ERROR_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED |
-                                            NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;
+               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
+
+    Attribs.PhysicalMediumType = NdisPhysicalMedium802_3;
+    Attribs.RecvScaleCapabilities = NULL;
+    Attribs.AccessType = NET_IF_ACCESS_BROADCAST;
+    Attribs.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
+    Attribs.ConnectionType = NET_IF_CONNECTION_DEDICATED;
+    Attribs.IfType = IF_TYPE_ETHERNET_CSMACD; 
+    Attribs.IfConnectorPresent = TRUE;
+    Attribs.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |
+                                  NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED |
+                                  NDIS_STATISTICS_RCV_OK_SUPPORTED |
+                                  NDIS_STATISTICS_RCV_ERROR_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED |
+                                  NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;
                       
-    generalAttributes.SupportedOidList = XennetSupportedOids;
-    generalAttributes.SupportedOidListLength = sizeof(XennetSupportedOids);
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
-
+    Attribs.SupportedOidList = XennetSupportedOids;
+    Attribs.SupportedOidListLength = sizeof(XennetSupportedOids);
+                
     ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 
     return ndisStatus;
 }
 
-#define DISPLAY_OFFLOAD(_Offload)                                   \
-        do {                                                        \
-            if ((_Offload).Checksum.IPv4Receive.IpChecksum)         \
-                Info("Checksum.IPv4Receive.IpChecksum ON\n");       \
-            else                                                    \
-                Info("Checksum.IPv4Receive.IpChecksum OFF\n");      \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Receive.TcpChecksum)        \
-                Info("Checksum.IPv4Receive.TcpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Receive.TcpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Receive.UdpChecksum)        \
-                Info("Checksum.IPv4Receive.UdpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Receive.UdpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Receive.TcpChecksum)        \
-                Info("Checksum.IPv6Receive.TcpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv6Receive.TcpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Receive.UdpChecksum)        \
-                Info("Checksum.IPv6Receive.UdpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv6Receive.UdpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.IpChecksum)        \
-                Info("Checksum.IPv4Transmit.IpChecksum ON\n");      \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.IpChecksum OFF\n");     \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.TcpChecksum)       \
-                Info("Checksum.IPv4Transmit.TcpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.TcpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv4Transmit.UdpChecksum)       \
-                Info("Checksum.IPv4Transmit.UdpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv4Transmit.UdpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Transmit.TcpChecksum)       \
-                Info("Checksum.IPv6Transmit.TcpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv6Transmit.TcpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).Checksum.IPv6Transmit.UdpChecksum)       \
-                Info("Checksum.IPv6Transmit.UdpChecksum ON\n");     \
-            else                                                    \
-                Info("Checksum.IPv6Transmit.UdpChecksum OFF\n");    \
-                                                                    \
-            if ((_Offload).LsoV2.IPv4.MaxOffLoadSize != 0)          \
-                Info("LsoV2.IPv4.MaxOffLoadSize = %u\n",            \
-                     (_Offload).LsoV2.IPv4.MaxOffLoadSize);         \
-            else                                                    \
-                Info("LsoV2.IPv4 OFF\n");                           \
-                                                                    \
-            if ((_Offload).LsoV2.IPv6.MaxOffLoadSize != 0)          \
-                Info("LsoV2.IPv6.MaxOffLoadSize = %u\n",            \
-                     (_Offload).LsoV2.IPv6.MaxOffLoadSize);         \
-            else                                                    \
-                Info("LsoV2.IPv6 OFF\n");                           \
-        } while (FALSE)
-
 static NDIS_STATUS
 AdapterSetOffloadAttributes(
-    IN  PADAPTER Adapter
+    IN  PXENNET_ADAPTER Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES offloadAttributes;
-    XENVIF_VIF_OFFLOAD_OPTIONS Options;
-    NDIS_OFFLOAD current;
-    NDIS_OFFLOAD supported;
-    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
+    XENVIF_VIF_OFFLOAD_OPTIONS                  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
+    NDIS_OFFLOAD                                Default;
+    NDIS_OFFLOAD                                Supported;
+    NDIS_STATUS                                 ndisStatus;
+
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    Adapter->Receiver.OffloadOptions.Value = 0;
-    Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+    TxOptions->Value = 0;
+    TxOptions->OffloadTagManipulation = 1;
+
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
 
     if (Adapter->Properties.need_csum_value)
-        Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+        RxOptions->NeedChecksumValue = 1;
 
     if (Adapter->Properties.lrov4) {
-        Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
 
     if (Adapter->Properties.lrov6) {
-        Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
 
-    Adapter->Transmitter->OffloadOptions.Value = 0;
-    Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
-
-    NdisZeroMemory(&offloadAttributes, sizeof(offloadAttributes));
-    NdisZeroMemory(&current, sizeof(current));
-    NdisZeroMemory(&supported, sizeof(supported));
-    
     XENVIF_VIF(ReceiverSetOffloadOptions,
                &Adapter->VifInterface,
-               Adapter->Receiver.OffloadOptions);
+               *RxOptions);
 
-    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
-    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
-    supported.Header.Size = sizeof(supported);
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               &Options);
 
-    supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
+    Supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
+    Supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
+    Supported.Header.Size = sizeof(NDIS_OFFLOAD);
 
-    supported.Checksum.IPv4Receive.IpChecksum = 1;
-    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
+    Supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv4Receive.TcpChecksum = 1;
-    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+    Supported.Checksum.IPv4Receive.IpChecksum = 1;
+    Supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
 
-    supported.Checksum.IPv4Receive.UdpChecksum = 1;
+    Supported.Checksum.IPv4Receive.TcpChecksum = 1;
+    Supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
 
-    supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Receive.UdpChecksum = 1;
 
-    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv6Receive.TcpChecksum = 1;
-    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
 
-    supported.Checksum.IPv6Receive.UdpChecksum = 1;
+    Supported.Checksum.IPv6Receive.TcpChecksum = 1;
+    Supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
 
-    XENVIF_VIF(TransmitterQueryOffloadOptions,
-               &Adapter->VifInterface,
-               &Options);
+    Supported.Checksum.IPv6Receive.UdpChecksum = 1;
 
-    supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
     if (Options.OffloadIpVersion4HeaderChecksum) {
-        supported.Checksum.IPv4Transmit.IpChecksum = 1;
-        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+        Supported.Checksum.IPv4Transmit.IpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion4TcpChecksum) {
-        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+        Supported.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion4UdpChecksum)
-        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
+        Supported.Checksum.IPv4Transmit.UdpChecksum = 1;
 
-    supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
 
-    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
 
     if (Options.OffloadIpVersion6TcpChecksum) {
-        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+        Supported.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
     }
 
     if (Options.OffloadIpVersion6UdpChecksum)
-        supported.Checksum.IPv6Transmit.UdpChecksum = 1;
+        Supported.Checksum.IPv6Transmit.UdpChecksum = 1;
 
     if (Options.OffloadIpVersion4LargePacket) {
-        ULONG Size;
-
         XENVIF_VIF(TransmitterQueryLargePacketSize,
                    &Adapter->VifInterface,
                    4,
-                   &Size);
-
-        supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        supported.LsoV2.IPv4.MaxOffLoadSize = Size;
-        supported.LsoV2.IPv4.MinSegmentCount = 2;
+                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
+        Supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv4.MinSegmentCount = 2;
     }
 
     if (Options.OffloadIpVersion6LargePacket) {
-        ULONG Size;
-
         XENVIF_VIF(TransmitterQueryLargePacketSize,
                    &Adapter->VifInterface,
                    6,
-                   &Size);
-
-        supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        supported.LsoV2.IPv6.MaxOffLoadSize = Size;
-        supported.LsoV2.IPv6.MinSegmentCount = 2;
-        supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
-        supported.LsoV2.IPv6.TcpOptionsSupported = 1;
+                   &Supported.LsoV2.IPv6.MaxOffLoadSize);
+        Supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv6.MinSegmentCount = 2;
+        Supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        Supported.LsoV2.IPv6.TcpOptionsSupported = 1;
     }
 
-    current = supported;
+    Default = Supported;
 
     if (!(Adapter->Properties.ipv4_csum & 2))
-        current.Checksum.IPv4Receive.IpChecksum = 0;
+        Default.Checksum.IPv4Receive.IpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv4_csum & 2))
-        current.Checksum.IPv4Receive.TcpChecksum = 0;
+        Default.Checksum.IPv4Receive.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv4_csum & 2))
-        current.Checksum.IPv4Receive.UdpChecksum = 0;
+        Default.Checksum.IPv4Receive.UdpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv6_csum & 2))
-        current.Checksum.IPv6Receive.TcpChecksum = 0;
+        Default.Checksum.IPv6Receive.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv6_csum & 2))
-        current.Checksum.IPv6Receive.UdpChecksum = 0;
+        Default.Checksum.IPv6Receive.UdpChecksum = 0;
 
     if (!(Adapter->Properties.ipv4_csum & 1))
-        current.Checksum.IPv4Transmit.IpChecksum = 0;
+        Default.Checksum.IPv4Transmit.IpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv4_csum & 1))
-        current.Checksum.IPv4Transmit.TcpChecksum = 0;
+        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv4_csum & 1))
-        current.Checksum.IPv4Transmit.UdpChecksum = 0;
+        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
 
     if (!(Adapter->Properties.tcpv6_csum & 1))
-        current.Checksum.IPv6Transmit.TcpChecksum = 0;
+        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
 
     if (!(Adapter->Properties.udpv6_csum & 1))
-        current.Checksum.IPv6Transmit.UdpChecksum = 0;
+        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
 
     if (!(Adapter->Properties.lsov4)) {
-        current.LsoV2.IPv4.MaxOffLoadSize = 0;
-        current.LsoV2.IPv4.MinSegmentCount = 0;
+        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv4.MinSegmentCount = 0;
     }
 
     if (!(Adapter->Properties.lsov6)) {
-        current.LsoV2.IPv6.MaxOffLoadSize = 0;
-        current.LsoV2.IPv6.MinSegmentCount = 0;
+        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv6.MinSegmentCount = 0;
     }
 
-    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = current;
-
-        DISPLAY_OFFLOAD(current);
+    if (!RtlEqualMemory(&Adapter->Offload, &Default, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = Default;
+        //DISPLAY_OFFLOAD(Default);
     }
 
-    offloadAttributes.Header.Type =
-        NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
-    offloadAttributes.Header.Revision =
-        NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
-    offloadAttributes.Header.Size = sizeof(offloadAttributes);
-    offloadAttributes.DefaultOffloadConfiguration = &current;
-    offloadAttributes.HardwareOffloadCapabilities = &supported;
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES));
+    Attribs.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
+    Attribs.Header.Revision = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
+    Attribs.Header.Size = sizeof(Attribs);
+    Attribs.DefaultOffloadConfiguration = &Default;
+    Attribs.HardwareOffloadCapabilities = &Supported;
 
-    adapterAttributes =
-        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
     ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
+                                            (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
     return ndisStatus;
 }
 
-static void
-AdapterIndicateOffloadChanged (
-    IN  PADAPTER Adapter
+NDIS_STATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE         Handle,
+    OUT PXENNET_ADAPTER     *Adapter
     )
 {
-    NDIS_STATUS_INDICATION indication;
-    NDIS_OFFLOAD offload;
-
-    NdisZeroMemory(&offload, sizeof(offload));
-    INITIALIZE_NDIS_OBJ_HEADER(offload, OFFLOAD);
-
-    offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-        offload.Checksum.IPv4Receive.IpChecksum = 1;
-        offload.Checksum.IPv4Receive.IpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-        offload.Checksum.IPv4Receive.TcpChecksum = 1;
-        offload.Checksum.IPv4Receive.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-        offload.Checksum.IPv4Receive.UdpChecksum = 1;
-    }
-
-    offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-        offload.Checksum.IPv6Receive.TcpChecksum = 1;
-        offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-        offload.Checksum.IPv6Receive.UdpChecksum = 1;
-    }
+    NDIS_STATUS             ndisStatus;
+    NTSTATUS                status;
+    PDEVICE_OBJECT          DeviceObject;
+    NDIS_SG_DMA_DESCRIPTION Dma;
 
-    XENVIF_VIF(ReceiverSetOffloadOptions,
-               &Adapter->VifInterface,
-               Adapter->Receiver.OffloadOptions);
-
-    offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-        offload.Checksum.IPv4Transmit.IpChecksum = 1;
-        offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-        offload.Checksum.IPv4Transmit.TcpChecksum = 1;
-        offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-        offload.Checksum.IPv4Transmit.UdpChecksum = 1;
-    }
-
-    offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-        offload.Checksum.IPv6Transmit.TcpChecksum = 1;
-        offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-        offload.Checksum.IPv6Transmit.UdpChecksum = 1;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-        ULONG Size;
-
-        XENVIF_VIF(TransmitterQueryLargePacketSize,
-                   &Adapter->VifInterface,
-                   4,
-                   &Size);
-
-        offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        offload.LsoV2.IPv4.MaxOffLoadSize = Size;
-        offload.LsoV2.IPv4.MinSegmentCount = 2;
-    }
-
-    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-        ULONG Size;
-
-        XENVIF_VIF(TransmitterQueryLargePacketSize,
-                   &Adapter->VifInterface,
-                   6,
-                   &Size);
-
-        offload.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-        offload.LsoV2.IPv6.MaxOffLoadSize = Size;
-        offload.LsoV2.IPv6.MinSegmentCount = 2;
-        offload.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
-        offload.LsoV2.IPv6.TcpOptionsSupported = 1;
-    }
-
-    if (!RtlEqualMemory(&Adapter->Offload, &offload, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = offload;
-
-        DISPLAY_OFFLOAD(offload);
-    }
+    *Adapter = ExAllocatePoolWithTag(NonPagedPool,
+                                     sizeof(XENNET_ADAPTER),
+                                     ADAPTER_POOL_TAG);
 
-    NdisZeroMemory(&indication, sizeof(indication));
-    INITIALIZE_NDIS_OBJ_HEADER(indication, STATUS_INDICATION);
-    indication.SourceHandle = Adapter->NdisAdapterHandle;
-    indication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
-    indication.StatusBuffer = &offload;
-    indication.StatusBufferSize = sizeof(offload);
+    ndisStatus = NDIS_STATUS_RESOURCES;
+    if (*Adapter == NULL)
+        goto fail1;
 
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
+    RtlZeroMemory(*Adapter, sizeof (XENNET_ADAPTER));
 
-}
+    NdisMGetDeviceProperty(Handle,
+                           &DeviceObject,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
 
-static NDIS_STATUS
-SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address, ULONG Count)
-{
-    NTSTATUS status;
+    status = __QueryInterface(DeviceObject,
+                              &GUID_XENVIF_VIF_INTERFACE,
+                              XENVIF_VIF_INTERFACE_VERSION_MAX,
+                              (PINTERFACE)&(*Adapter)->VifInterface,
+                              sizeof(XENVIF_VIF_INTERFACE),
+                              FALSE);
 
-    status = XENVIF_VIF(MacSetMulticastAddresses,
-                        &Adapter->VifInterface,
-                        Address,
-                        Count);
+    ndisStatus = NDIS_STATUS_FAILURE;
     if (!NT_SUCCESS(status))
-        return NDIS_STATUS_INVALID_DATA;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-static NDIS_STATUS
-SetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
-{
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
-
-    if (*PacketFilter & ~XENNET_SUPPORTED_PACKET_FILTERS)
-        return NDIS_STATUS_INVALID_PARAMETER;
+        goto fail2;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
-        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        goto done;
-    }
+    status = XENVIF_VIF(Acquire,
+                        &(*Adapter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
-        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    (*Adapter)->NdisAdapterHandle = Handle;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else if (*PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
-        MulticastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        MulticastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    ndisStatus = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail4;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
+    ndisStatus = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail5;
 
-done:
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               UnicastFilterLevel);
+    ndisStatus = AdapterGetAdvancedSettings(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail6;
+    
+    ndisStatus = AdapterSetRegistrationAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail7;
+    
+    ndisStatus = AdapterSetGeneralAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail8;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               MulticastFilterLevel);
+    ndisStatus = AdapterSetOffloadAttributes(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail9;
+
+    RtlZeroMemory(&Dma, sizeof(NDIS_SG_DMA_DESCRIPTION));
+    Dma.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
+    Dma.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
+    Dma.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);
+    Dma.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;
+    Dma.MaximumPhysicalMapping = 65536;    
+    Dma.ProcessSGListHandler = AdapterProcessSGList;
+    Dma.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
+
+    ndisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisAdapterHandle,
+                                               &Dma,
+                                               &(*Adapter)->NdisDmaHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        (*Adapter)->NdisDmaHandle = NULL;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               BroadcastFilterLevel);
+    ndisStatus = AdapterEnable(*Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail10;
 
     return NDIS_STATUS_SUCCESS;
-}
-
-//
-// Set OID handler.
-//
-static NDIS_STATUS 
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    ULONG addressCount;
-    ULONG bytesNeeded = 0;
-    ULONG bytesRead = 0;
-    PVOID informationBuffer;
-    ULONG informationBufferLength;
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    NDIS_OID oid;
-    BOOLEAN offloadChanged;
-
-    informationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
-    informationBufferLength = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
-    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
-    switch (oid) {
-        case OID_PNP_SET_POWER:
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
-
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Info("SET_POWER: D0\n");
-                    break;
-
-                case NdisDeviceStateD1:
-                    Info("SET_POWER: D1\n");
-                    break;
-
-                case NdisDeviceStateD2:
-                    Info("SET_POWER: D2\n");
-                    break;
-
-                case NdisDeviceStateD3:
-                    Info("SET_POWER: D3\n");
-                    break;
-                }
-            }
-            break;
-
-        case OID_GEN_MACHINE_NAME:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            bytesNeeded = sizeof(ULONG);
-            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
-            if (informationBufferLength == sizeof(ULONG)) {
-                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
-                bytesRead = sizeof(ULONG);
-            }
-
-            break;
-
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            bytesNeeded = sizeof(ULONG);
-            if (informationBufferLength == sizeof(ULONG)) {
-                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
-                bytesRead = sizeof(ULONG);
-            }
-
-            break;
-
-        case OID_802_3_MULTICAST_LIST:
-            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
-            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
-                addressCount = informationBufferLength / ETHERNET_ADDRESS_LENGTH;
-
-                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer, addressCount);
-                if (ndisStatus == NDIS_STATUS_SUCCESS)
-                    bytesRead = informationBufferLength;
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-
-            break;
-
-        case OID_GEN_INTERRUPT_MODERATION:
-            ndisStatus = NDIS_STATUS_INVALID_DATA;
-            break;
-
-        case OID_OFFLOAD_ENCAPSULATION: {
-            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
-
-            bytesNeeded = sizeof(*offloadEncapsulation);
-            if (informationBufferLength >= bytesNeeded) {
-                XENVIF_VIF_OFFLOAD_OPTIONS Options;
-
-                bytesRead = bytesNeeded;
-                offloadEncapsulation = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
-
-                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                XENVIF_VIF(TransmitterQueryOffloadOptions,
-                           &Adapter->VifInterface,
-                           &Options);
-                
-                Adapter->Transmitter->OffloadOptions.Value = 0;
-                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
-
-                if ((Adapter->Properties.lsov4) && (Options.OffloadIpVersion4LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
-
-                if ((Adapter->Properties.lsov6) && (Options.OffloadIpVersion6LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
-
-                if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-
-                if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-
-                Adapter->Receiver.OffloadOptions.Value = 0;
-                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
-
-                if (Adapter->Properties.need_csum_value)
-                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
-
-                if (Adapter->Properties.lrov4) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
-
-                if (Adapter->Properties.lrov6) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
-
-                if (Adapter->Properties.ipv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if (Adapter->Properties.tcpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if (Adapter->Properties.udpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-
-                if (Adapter->Properties.tcpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if (Adapter->Properties.udpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-
-                AdapterIndicateOffloadChanged(Adapter);
-            }
-            break;
-        }
-        case OID_TCP_OFFLOAD_PARAMETERS: {
-            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
-
-            bytesNeeded = sizeof(*offloadParameters);
-            if (informationBufferLength >= bytesNeeded) {
-                bytesRead = bytesNeeded;
-                offloadParameters = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
-
-#define no_change(x)  ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
-
-                if (!no_change(offloadParameters->IPsecV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                    
-                if (!no_change(offloadParameters->LsoV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->TcpConnectionIPv4))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->TcpConnectionIPv6))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-
-                if (!no_change(offloadParameters->LsoV2IPv4)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
-
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
-
-                    if (!(Options.OffloadIpVersion4LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-                if (!no_change(offloadParameters->LsoV2IPv6)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
-
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
-
-                    if (!(Options.OffloadIpVersion6LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
-
-#define rx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
-                       (x) == NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED)
-#define tx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
-                       (x) == NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED)
-
-                if (ndisStatus == NDIS_STATUS_SUCCESS) {
-                    offloadChanged = FALSE;
-
-                    if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->IPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->TCPIPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->UDPIPv4Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->TCPIPv6Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (tx_enabled(offloadParameters->UDPIPv6Checksum)) {
-                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->IPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->TCPIPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->UDPIPv4Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->TCPIPv6Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-                    if (rx_enabled(offloadParameters->UDPIPv6Checksum)) {
-                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-                            offloadChanged = TRUE;
-                        }
-                    } else {
-                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
-                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
-                            offloadChanged = TRUE;
-                        }
-                    }
-
-#undef tx_enabled
-#undef rx_enabled
-#undef no_change
-
-                    if (offloadChanged)
-                        AdapterIndicateOffloadChanged(Adapter);
-                }
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-            break;
-        }
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
-
-    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
-    }
-
-    return ndisStatus;
-}
-
-//
-// Sets miniport registration attributes.
-//
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    )
-{
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registrationAttributes;
-    NDIS_STATUS ndisStatus;
-
-
-    NdisZeroMemory(&registrationAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
-
-    registrationAttributes.Header.Type = 
-                NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
-
-    registrationAttributes.Header.Revision = 
-                NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
-
-    registrationAttributes.Header.Size = 
-                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
-
-    registrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)Adapter;
-    registrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER |
-                                            NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
-    
-    registrationAttributes.CheckForHangTimeInSeconds = 0;
-    registrationAttributes.InterfaceType = XENNET_INTERFACE_TYPE;
-
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
-
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
 
+fail10:
+    if ((*Adapter)->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
+    (*Adapter)->NdisDmaHandle = NULL;
+fail9:
+fail8:
+fail7:
+fail6:
+    ReceiverTeardown((*Adapter)->Receiver);
+    (*Adapter)->Receiver = NULL;
+fail5:
+    TransmitterTeardown((*Adapter)->Transmitter);
+    (*Adapter)->Transmitter = NULL;
+fail4:
+    (*Adapter)->NdisAdapterHandle = NULL;
+
+    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail3:
+    RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
+fail2:
+    ExFreePoolWithTag(*Adapter, ADAPTER_POOL_TAG);
+fail1:
     return ndisStatus;
 }
 
-//
-// Shuts down adapter.
-//
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER     Adapter
     )
 {
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    UNREFERENCED_PARAMETER(ShutdownAction);
-
-    if (ShutdownAction != NdisShutdownBugCheck)
-        AdapterStop(Adapter);
-
-    return;
-}
-
-//
-// Stops adapter. Waits for currently transmitted packets to complete.
-// Stops transmission of new packets.
-// Stops received packet indication to NDIS.
-//
-NDIS_STATUS
-AdapterStop (
-IN  PADAPTER    Adapter
-)
-{
-    Trace("====>\n");
+    TransmitterTeardown(Adapter->Transmitter);
+    Adapter->Transmitter = NULL;
 
-    if (!Adapter->Enabled)
-        goto done;
+    ReceiverTeardown(Adapter->Receiver);
+    Adapter->Receiver = NULL;
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    if (Adapter->NdisDmaHandle != NULL)
+        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
+    Adapter->NdisDmaHandle = NULL;
 
-    Adapter->Enabled = FALSE;
+    XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Adapter->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 
-done:
-    Trace("<====\n");
-    return NDIS_STATUS_SUCCESS;
+    ExFreePoolWithTag(Adapter, ADAPTER_POOL_TAG);
 }
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index e64e40d..6c60aad 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -29,7 +29,10 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_ADAPTER_H_
+#define _XENNET_ADAPTER_H_
+
+#include <ndis.h>
 
 #define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
 
@@ -41,6 +44,14 @@
                                          NDIS_MAC_OPTION_8021P_PRIORITY |       \
                                          NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
 
+#define XENNET_MEDIA_MAX_SPEED          1000000000ull
+
+#define XENNET_SUPPORTED_PACKET_FILTERS (NDIS_PACKET_TYPE_DIRECTED |        \
+                                         NDIS_PACKET_TYPE_MULTICAST |       \
+                                         NDIS_PACKET_TYPE_ALL_MULTICAST |   \
+                                         NDIS_PACKET_TYPE_BROADCAST |       \
+                                         NDIS_PACKET_TYPE_PROMISCUOUS)
+
 typedef struct _PROPERTIES {
     int ipv4_csum;
     int tcpv4_csum;
@@ -54,120 +65,67 @@ typedef struct _PROPERTIES {
     int lrov6;
 } PROPERTIES, *PPROPERTIES;
 
-struct _ADAPTER {
-    LIST_ENTRY              ListEntry;
-    XENVIF_VIF_INTERFACE    VifInterface;
-    BOOLEAN                 AcquiredInterfaces;
-    ULONG                   MaximumFrameSize;
-    ULONG                   CurrentLookahead;
-    NDIS_HANDLE             NdisAdapterHandle;
-    NDIS_HANDLE             NdisDmaHandle;
-    NDIS_PNP_CAPABILITIES   Capabilities;
-    PROPERTIES              Properties;
-    RECEIVER                Receiver;
-    PTRANSMITTER            Transmitter;
-    BOOLEAN                 Enabled;
-    NDIS_OFFLOAD            Offload;
-};
-
-MINIPORT_CANCEL_OID_REQUEST AdapterCancelOidRequest;
-VOID
-AdapterCancelOidRequest (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       RequestId
-    );
+typedef struct _XENNET_ADAPTER XENNET_ADAPTER, *PXENNET_ADAPTER;
 
-MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
+extern NDIS_STATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE         Handle,
+    OUT PXENNET_ADAPTER     *Adapter
     );
 
-MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    );
-
-VOID
-AdapterCleanup (
-    IN PADAPTER Adapter
-    );
-
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+extern VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_OID_REQUEST AdapterOidRequest;
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+extern NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_PAUSE AdapterPause;
-NDIS_STATUS 
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+#include <vif_interface.h>
+extern PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+#include "transmitter.h"
+extern PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RESET AdapterReset;
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
+#include "receiver.h"
+extern PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RESTART AdapterRestart;
-NDIS_STATUS 
-AdapterRestart (
-    IN  NDIS_HANDLE                         MiniportAdapterContext,
-    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+extern NDIS_STATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
+extern BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-MINIPORT_SEND_NET_BUFFER_LISTS AdapterSendNetBufferLists;
-VOID 
-AdapterSendNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+extern VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER     Adapter
     );
 
-NDIS_STATUS
-AdapterStop (
-    IN  PADAPTER    Adapter
+extern NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
     );
 
-MINIPORT_SHUTDOWN AdapterShutdown;
-
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+extern NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER     Adapter,
+    IN  PNDIS_OID_REQUEST   Request
     );
 
-extern VOID
-ReceiverReceivePackets(
-    IN  PRECEIVER   Receiver,
-    IN  PLIST_ENTRY List
-    );
+#endif // _XENNET_ADAPTER_H_
diff --git a/src/xennet/common.h b/src/xennet/common.h
deleted file mode 100644
index 4d4c04a..0000000
--- a/src/xennet/common.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-#pragma once
-
-#include "std.h"
-#include "project.h"
-#include "dbg_print.h"
-#include "assert.h"
diff --git a/src/xennet/main.c b/src/xennet/main.c
deleted file mode 100644
index e193e0e..0000000
--- a/src/xennet/main.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <version.h>
-
-#include "common.h"
-
-#pragma NDIS_INIT_FUNCTION(DriverEntry)
-
-//
-// Global miniport data.
-//
-
-static NDIS_HANDLE MiniportDriverHandle;
-
-extern MINIPORT_INITIALIZE MiniportInitialize;
-
-extern NDIS_STATUS 
-MiniportInitialize (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HANDLE                        MiniportDriverContext,
-    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
-    );
-
-MINIPORT_HALT MiniportHalt;
-
-extern VOID 
-MiniportHalt (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HALT_ACTION                   HaltAction
-    );
-
-typedef struct _XENNET_CONTEXT {
-    PDEVICE_CAPABILITIES    Capabilities;
-    PIO_COMPLETION_ROUTINE  CompletionRoutine;
-    PVOID                   CompletionContext;
-    UCHAR                   CompletionControl;
-} XENNET_CONTEXT, *PXENNET_CONTEXT;
-
-static NTSTATUS (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
-
-__drv_functionClass(IO_COMPLETION_ROUTINE)
-static NTSTATUS
-__QueryCapabilities(
-    IN  PDEVICE_OBJECT      DeviceObject,
-    IN  PIRP                Irp,
-    IN  PVOID               _Context
-    )
-{
-    PXENNET_CONTEXT         Context = _Context;
-    NTSTATUS                status;
-
-    Trace("====>\n");
-
-    Context->Capabilities->SurpriseRemovalOK = 1;
-
-    if (Context->CompletionRoutine != NULL &&
-        (Context->CompletionControl & SL_INVOKE_ON_SUCCESS))
-        status = Context->CompletionRoutine(DeviceObject, Irp, Context->CompletionContext);
-    else
-        status = STATUS_SUCCESS;
-
-    ExFreePool(Context);
-
-    Trace("<====\n");
-
-    return status;
-}
-
-NTSTATUS 
-QueryCapabilities(
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PIRP                 Irp
-    )
-{
-    PIO_STACK_LOCATION      StackLocation;
-    PXENNET_CONTEXT         Context;
-    NTSTATUS                status;
-
-    Trace("====>\n");
-
-    Trace("%p\n", DeviceObject); 
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-
-    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof (XENNET_CONTEXT), ' TEN');
-    if (Context != NULL) {
-        Context->Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities;
-        Context->CompletionRoutine = StackLocation->CompletionRoutine;
-        Context->CompletionContext = StackLocation->Context;
-        Context->CompletionControl = StackLocation->Control;
-
-        StackLocation->CompletionRoutine = __QueryCapabilities;
-        StackLocation->Context = Context;
-        StackLocation->Control = SL_INVOKE_ON_SUCCESS;
-    }
-
-    status = NdisDispatchPnp(DeviceObject, Irp);
-
-    Trace("<====\n");
-
-    return status;    
-}
-
-DRIVER_DISPATCH DispatchPnp;
-
-NTSTATUS 
-DispatchPnp(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp
-    )
-{
-    PIO_STACK_LOCATION  StackLocation;
-    UCHAR               MinorFunction;
-    NTSTATUS            status;
-
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
-    MinorFunction = StackLocation->MinorFunction;
-
-    switch (StackLocation->MinorFunction) {
-    case IRP_MN_QUERY_CAPABILITIES:
-        status = QueryCapabilities(DeviceObject, Irp);
-        break;
-
-    default:
-        status = NdisDispatchPnp(DeviceObject, Irp);
-        break;
-    }
-
-    return status;
-}
-
-DRIVER_DISPATCH DispatchFail;
-
-NTSTATUS 
-DispatchFail(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp
-    )
-{
-    NTSTATUS            status;
-
-    UNREFERENCED_PARAMETER(DeviceObject);
-
-    Trace("%p\n", Irp);
-
-    status = STATUS_UNSUCCESSFUL;
-
-    Irp->IoStatus.Status = status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return status;
-}
-
-DRIVER_INITIALIZE   DriverEntry;
-
-NTSTATUS 
-DriverEntry (
-    IN  PDRIVER_OBJECT   DriverObject,
-    IN  PUNICODE_STRING  RegistryPath
-    )
-{
-    NDIS_STATUS ndisStatus;
-    NDIS_MINIPORT_DRIVER_CHARACTERISTICS mpChars;
-    NDIS_CONFIGURATION_OBJECT ConfigurationObject;
-    NDIS_HANDLE ConfigurationHandle;
-    NDIS_STRING ParameterName;
-    PNDIS_CONFIGURATION_PARAMETER ParameterValue;
-    ULONG FailCreateClose;
-    ULONG FailDeviceControl;
-
-    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
-
-    Trace("====>\n");
-
-    if (*InitSafeBootMode > 0)
-        return NDIS_STATUS_SUCCESS;
-
-    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
-         MAJOR_VERSION,
-         MINOR_VERSION,
-         MICRO_VERSION,
-         BUILD_NUMBER,
-         DAY,
-         MONTH,
-         YEAR);
-
-    //
-    // Register miniport with NDIS.
-    //
-
-    NdisZeroMemory(&mpChars, sizeof(mpChars));
-    mpChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
-    mpChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
-    mpChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
-
-    mpChars.MajorNdisVersion = 6;
-    mpChars.MinorNdisVersion = 0;
-    mpChars.MajorDriverVersion = MAJOR_VERSION;
-    mpChars.MinorDriverVersion = MINOR_VERSION;
-
-    mpChars.CancelOidRequestHandler = AdapterCancelOidRequest;
-    mpChars.CancelSendHandler = AdapterCancelSendNetBufferLists;
-    mpChars.CheckForHangHandlerEx = AdapterCheckForHang;
-    mpChars.InitializeHandlerEx = MiniportInitialize;
-    mpChars.HaltHandlerEx = MiniportHalt;
-    mpChars.OidRequestHandler = AdapterOidRequest;    
-    mpChars.PauseHandler = AdapterPause;      
-    mpChars.DevicePnPEventNotifyHandler  = AdapterPnPEventHandler;
-    mpChars.ResetHandlerEx = AdapterReset;
-    mpChars.RestartHandler = AdapterRestart;    
-    mpChars.ReturnNetBufferListsHandler  = AdapterReturnNetBufferLists;
-    mpChars.SendNetBufferListsHandler = AdapterSendNetBufferLists;
-    mpChars.ShutdownHandlerEx = AdapterShutdown;
-    mpChars.UnloadHandler = DriverUnload;
-
-    MiniportDriverHandle = NULL;
-    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
-                                             RegistryPath,
-                                             NULL,
-                                             &mpChars,
-                                             &MiniportDriverHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        Error("Failed (0x%08X) to register miniport.\n", ndisStatus);
-        goto fail;
-    }
-
-    ConfigurationObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
-    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
-    ConfigurationObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
-    ConfigurationObject.NdisHandle = MiniportDriverHandle;
-    ConfigurationObject.Flags = 0;
-
-    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        Error("Failed (0x%08X) to open driver configuration.\n", ndisStatus);
-        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
-        goto fail;
-    }
-
-    RtlInitUnicodeString(&ParameterName, L"FailCreateClose");
-
-    NdisReadConfiguration(&ndisStatus,
-                          &ParameterValue,
-                          ConfigurationHandle,
-                          &ParameterName,
-                          NdisParameterInteger);
-    if (ndisStatus == NDIS_STATUS_SUCCESS &&
-        ParameterValue->ParameterType == NdisParameterInteger)
-        FailCreateClose = ParameterValue->ParameterData.IntegerData;
-    else
-        FailCreateClose = 0;
-
-    RtlInitUnicodeString(&ParameterName, L"FailDeviceControl");
-
-    NdisReadConfiguration(&ndisStatus,
-                          &ParameterValue,
-                          ConfigurationHandle,
-                          &ParameterName,
-                          NdisParameterInteger);
-    if (ndisStatus == NDIS_STATUS_SUCCESS &&
-        ParameterValue->ParameterType == NdisParameterInteger)
-        FailDeviceControl = ParameterValue->ParameterData.IntegerData;
-    else
-        FailDeviceControl = 0;
-
-    NdisCloseConfiguration(ConfigurationHandle);
-    ndisStatus = NDIS_STATUS_SUCCESS;
-
-    NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
-
-    if (FailCreateClose != 0) {
-#pragma prefast(suppress:28168) // No matching__drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
-    }
-
-    if (FailDeviceControl != 0) {
-#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
-        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
-    }
-
-    Trace("<====\n");
-    return ndisStatus;
-
-fail:
-    Error("fail\n");
-    return ndisStatus;
-}
-
-VOID 
-DriverUnload (
-    IN  PDRIVER_OBJECT  DriverObject
-    )
-{
-    UNREFERENCED_PARAMETER(DriverObject);
-
-    Trace("====>\n");
-
-    if (*InitSafeBootMode > 0)
-        goto done;
-
-    if (MiniportDriverHandle)
-        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
-
-    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
-         MAJOR_VERSION,
-         MINOR_VERSION,
-         MICRO_VERSION,
-         BUILD_NUMBER,
-         DAY,
-         MONTH,
-         YEAR);
-
-done:
-    Trace("<====\n");
-}
diff --git a/src/xennet/project.h b/src/xennet/project.h
deleted file mode 100644
index 981cb0e..0000000
--- a/src/xennet/project.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <util.h>
-#include <ethernet.h>
-#include <tcpip.h>
-#include <vif_interface.h>
-
-typedef struct _ADAPTER ADAPTER, *PADAPTER;
-
-DRIVER_INITIALIZE DriverEntry;
-NTSTATUS 
-DriverEntry (
-    IN  PDRIVER_OBJECT   DriverObject,
-    IN  PUNICODE_STRING  RegistryPath
-    );
-
-MINIPORT_UNLOAD DriverUnload;
-VOID 
-DriverUnload (
-    IN  PDRIVER_OBJECT  DriverObject
-    );
-
-NDIS_STATUS
-MpSetAdapterSettings(
-    IN PADAPTER Adapter
-    );
-
-NDIS_STATUS
-MpGetAdvancedSettings(
-    IN PADAPTER Adapter
-    );
-
-#include "transmitter.h"
-#include "receiver.h"
-#include "adapter.h"
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index 54bdc15..49320a5 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -29,100 +29,35 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include "receiver.h"
+#include "adapter.h"
+#include <util.h>
+#include "dbg_print.h"
+#include "assert.h"
+
+struct _XENNET_RECEIVER {
+    PXENNET_ADAPTER             Adapter;
+    NDIS_HANDLE                 NetBufferListPool;
+    PNET_BUFFER_LIST            PutList;
+    PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
+    LONG                        InNDIS;
+    LONG                        InNDISMax;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
+
+#define RECEIVER_POOL_TAG       'RteN'
+#define IN_NDIS_MAX             1024
 
-#pragma warning(disable:4711)
-
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER                   Receiver
-    )
-{
-    PADAPTER                        Adapter;
-    NDIS_STATUS                     ndisStatus = NDIS_STATUS_SUCCESS;
-    NET_BUFFER_LIST_POOL_PARAMETERS poolParameters;
-    ULONG                           Cpu;
-
-    Receiver->PutList = NULL;
-    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++)
-        Receiver->GetList[Cpu] = NULL;
-
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    NdisZeroMemory(&poolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
-    poolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
-    poolParameters.Header.Revision =
-        NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
-    poolParameters.Header.Size = sizeof(poolParameters);
-    poolParameters.ProtocolId = 0;
-    poolParameters.ContextSize = 0;
-    poolParameters.fAllocateNetBuffer = TRUE;
-    poolParameters.PoolTag = ' TEN';
-
-    Receiver->NetBufferListPool =
-        NdisAllocateNetBufferListPool(Adapter->NdisAdapterHandle,
-                                      &poolParameters);
-
-    if (!Receiver->NetBufferListPool)
-        ndisStatus = NDIS_STATUS_RESOURCES;
-
-    return ndisStatus;
-}
-
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER       Receiver
-    )
-{
-    ULONG               Cpu;
-    PNET_BUFFER_LIST    NetBufferList;
-
-    ASSERT(Receiver != NULL);
-
-    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
-        NetBufferList = Receiver->GetList[Cpu];
-        while (NetBufferList != NULL) {
-            PNET_BUFFER_LIST    Next;
-
-            Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-            NdisFreeNetBufferList(NetBufferList);
-
-            NetBufferList = Next;
-        }
-    }
-
-    NetBufferList = Receiver->PutList;
-    while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST    Next;
-
-        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-        NdisFreeNetBufferList(NetBufferList);
-
-        NetBufferList = Next;
-    }
-
-    if (Receiver->NetBufferListPool) {
-        NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
-        Receiver->NetBufferListPool = NULL;
-    }
-
-    return;
-}
-
-PNET_BUFFER_LIST
-ReceiverAllocateNetBufferList(
-    IN  PRECEIVER       Receiver,
-    IN  PMDL            Mdl,
-    IN  ULONG           Offset,
-    IN  ULONG           Length
+static PNET_BUFFER_LIST
+__ReceiverAllocateNetBufferList(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length
     )
 {
-    ULONG               Cpu;
-    PNET_BUFFER_LIST    NetBufferList;
+    ULONG                   Cpu;
+    PNET_BUFFER_LIST        NetBufferList;
 
     Cpu = KeGetCurrentProcessorNumber();
 
@@ -158,9 +93,9 @@ ReceiverAllocateNetBufferList(
     return NetBufferList;
 }        
 
-VOID
-ReceiverReleaseNetBufferList(
-    IN  PRECEIVER           Receiver,
+static VOID
+__ReceiverReleaseNetBufferList(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  BOOLEAN             Cache
     )
@@ -184,17 +119,16 @@ ReceiverReleaseNetBufferList(
 
 static FORCEINLINE ULONG
 __ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  BOOLEAN             Cache
     )
 {
-    PADAPTER                Adapter;
+    PXENVIF_VIF_INTERFACE   VifInterface;
     LIST_ENTRY              List;
     ULONG                   Count;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
+    VifInterface = AdapterGetVifInterface(Receiver->Adapter);
     InitializeListHead(&List);
 
     Count = 0;
@@ -212,7 +146,7 @@ __ReceiverReturnNetBufferLists(
 
         Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
 
-        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
+        __ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
 
         Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
 
@@ -224,51 +158,33 @@ __ReceiverReturnNetBufferLists(
 
     if (Count != 0)
         XENVIF_VIF(ReceiverReturnPackets,
-                   &Adapter->VifInterface,
+                   VifInterface,
                    &List);
 
     return Count;
 }
 
-VOID
-ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    HeadNetBufferList,
-    IN  ULONG               Flags
-    )
-{
-    ULONG                   Count;
-
-    UNREFERENCED_PARAMETER(Flags);
-
-    Count = __ReceiverReturnNetBufferLists(Receiver, HeadNetBufferList, TRUE);
-    (VOID) __InterlockedSubtract(&Receiver->InNDIS, Count);
-}
-
 static PNET_BUFFER_LIST
-ReceiverReceivePacket(
-    IN  PRECEIVER                               Receiver,
-    IN  PMDL                                    Mdl,
-    IN  ULONG                                   Offset,
-    IN  ULONG                                   Length,
-    IN  XENVIF_PACKET_CHECKSUM_FLAGS            Flags,
-    IN  USHORT                                  TagControlInformation
+__ReceiverReceivePacket(
+    IN  PXENNET_RECEIVER                Receiver,
+    IN  PMDL                            Mdl,
+    IN  ULONG                           Offset,
+    IN  ULONG                           Length,
+    IN  XENVIF_PACKET_CHECKSUM_FLAGS    Flags,
+    IN  USHORT                          TagControlInformation
     )
 {
-    PADAPTER                                    Adapter;
     PNET_BUFFER_LIST                            NetBufferList;
     NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    NetBufferList = ReceiverAllocateNetBufferList(Receiver,
-                                                  Mdl,
-                                                  Offset,
-                                                  Length);
+    NetBufferList = __ReceiverAllocateNetBufferList(Receiver,
+                                                    Mdl,
+                                                    Offset,
+                                                    Length);
     if (NetBufferList == NULL)
         goto fail1;
 
-    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
+    NetBufferList->SourceHandle = AdapterGetHandle(Receiver->Adapter);
 
     csumInfo.Value = 0;
 
@@ -300,26 +216,23 @@ ReceiverReceivePacket(
     return NetBufferList;
 
 fail2:
-    ReceiverReleaseNetBufferList(Receiver, NetBufferList, TRUE);
+    __ReceiverReleaseNetBufferList(Receiver, NetBufferList, TRUE);
 
 fail1:
     return NULL;
 }
 
 static VOID
-ReceiverPushPackets(
-    IN  PRECEIVER           Receiver,
+__ReceiverPushPackets(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               Count,
     IN  BOOLEAN             LowResources
     )
 {
-    PADAPTER                Adapter;
     ULONG                   Flags;
     LONG                    InNDIS;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
     InNDIS = Receiver->InNDIS;
 
     Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
@@ -342,7 +255,7 @@ ReceiverPushPackets(
             break;
     }
 
-    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
+    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Receiver->Adapter),
                                        NetBufferList,
                                        NDIS_DEFAULT_PORT_NUMBER,
                                        Count,
@@ -352,21 +265,121 @@ ReceiverPushPackets(
         (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
 }
 
-#define IN_NDIS_MAX 1024
+NDIS_STATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_RECEIVER    *Receiver
+    )
+{
+    NET_BUFFER_LIST_POOL_PARAMETERS Params;
+    NDIS_STATUS                     status;
+
+    *Receiver = ExAllocatePoolWithTag(NonPagedPool,
+                                      sizeof(XENNET_RECEIVER),
+                                      RECEIVER_POOL_TAG);
+
+    status = NDIS_STATUS_RESOURCES;
+    if (*Receiver == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
+    (*Receiver)->Adapter = Adapter;
+
+    RtlZeroMemory(&Params, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
+    Params.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    Params.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    Params.Header.Size = sizeof(Params);
+    Params.ProtocolId = 0;
+    Params.ContextSize = 0;
+    Params.fAllocateNetBuffer = TRUE;
+    Params.PoolTag = 'PteN';
+
+    (*Receiver)->NetBufferListPool = NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
+                                                                   &Params);
+
+    status = NDIS_STATUS_RESOURCES;
+    if ((*Receiver)->NetBufferListPool == NULL)
+        goto fail2;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail2:
+fail1:
+    return status;
+}
+
+VOID
+ReceiverTeardown(
+    IN  PXENNET_RECEIVER    Receiver
+    )
+{
+    ULONG               Cpu;
+    PNET_BUFFER_LIST    NetBufferList;
+
+    ASSERT(Receiver != NULL);
+
+    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
+        NetBufferList = Receiver->GetList[Cpu];
+        while (NetBufferList != NULL) {
+            PNET_BUFFER_LIST    Next;
+
+            Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+            NdisFreeNetBufferList(NetBufferList);
+
+            NetBufferList = Next;
+        }
+    }
+
+    NetBufferList = Receiver->PutList;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST    Next;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NdisFreeNetBufferList(NetBufferList);
+
+        NetBufferList = Next;
+    }
+
+    NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
+    Receiver->NetBufferListPool = NULL;
+
+    Receiver->Adapter = NULL;
+
+    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
+}
+
+VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  ULONG               ReturnFlags
+    )
+{
+    ULONG                   Count;
+
+    UNREFERENCED_PARAMETER(ReturnFlags);
+
+    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferList, TRUE);
+    (VOID) __InterlockedSubtract(&Receiver->InNDIS, Count);
+}
 
 VOID
 ReceiverReceivePackets(
-    IN  PRECEIVER       Receiver,
-    IN  PLIST_ENTRY     List
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PLIST_ENTRY         List
     )
 {
-    PADAPTER            Adapter;
-    PNET_BUFFER_LIST    HeadNetBufferList;
-    PNET_BUFFER_LIST    *TailNetBufferList;
-    ULONG               Count;
-    BOOLEAN             LowResources;
+    PXENVIF_VIF_INTERFACE   VifInterface;
+    PNET_BUFFER_LIST        HeadNetBufferList;
+    PNET_BUFFER_LIST        *TailNetBufferList;
+    ULONG                   Count;
+    BOOLEAN                 LowResources;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    VifInterface = AdapterGetVifInterface(Receiver->Adapter);
     LowResources = FALSE;
 
 again:
@@ -404,28 +417,28 @@ again:
 
         TagControlInformation = Info->TagControlInformation;
 
-        NetBufferList = ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
+        NetBufferList = __ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
 
         if (NetBufferList != NULL) {
             *TailNetBufferList = NetBufferList;
             TailNetBufferList = &NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
             Count++;
         } else {
-            LIST_ENTRY  List;
+            LIST_ENTRY  PacketList;
 
-            InitializeListHead(&List);
-            InsertTailList(&List, &Packet->ListEntry);
+            InitializeListHead(&PacketList);
+            InsertTailList(&PacketList, &Packet->ListEntry);
 
             XENVIF_VIF(ReceiverReturnPackets,
-                       &Adapter->VifInterface,
-                       &List);
+                       VifInterface,
+                       &PacketList);
         }
     }
 
     if (Count != 0) {
         ASSERT(HeadNetBufferList != NULL);
 
-        ReceiverPushPackets(Receiver, HeadNetBufferList, Count, LowResources);
+        __ReceiverPushPackets(Receiver, HeadNetBufferList, Count, LowResources);
     }
 
     if (!IsListEmpty(List)) {
@@ -434,3 +447,12 @@ again:
         goto again;
     }
 }
+
+PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER    Receiver
+    )
+{
+    return &Receiver->OffloadOptions;
+}
+
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
index 1a58053..fb69b96 100644
--- a/src/xennet/receiver.h
+++ b/src/xennet/receiver.h
@@ -29,49 +29,41 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_RECEIVER_H_
+#define _XENNET_RECEIVER_H_
 
-typedef struct _RECEIVER {
-    NDIS_HANDLE                 NetBufferListPool;
-    PNET_BUFFER_LIST            PutList;
-    PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
-    LONG                        InNDIS;
-    LONG                        InNDISMax;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} RECEIVER, *PRECEIVER;
+#include <ndis.h>
 
-VOID
-ReceiverDebugDump (
-    IN PRECEIVER Receiver
-    );
-
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER Receiver
-    );
+typedef struct _XENNET_RECEIVER XENNET_RECEIVER, *PXENNET_RECEIVER;
 
-VOID
-ReceiverHandleNotification (
-    IN  PRECEIVER Receiver
+#include "adapter.h"
+extern NDIS_STATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_RECEIVER    *Receiver
     );
 
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER   Receiver
+extern VOID
+ReceiverTeardown(
+    IN  PXENNET_RECEIVER    Receiver
     );
 
-VOID 
-ReceiverReturnNetBufferLists (
-    IN  PRECEIVER           Receiver,
+extern VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               ReturnFlags
     );
 
-VOID
-ReceiverWaitForPacketReturn(
-    IN  PRECEIVER   Receiver,
-    IN  BOOLEAN     Locked
+extern VOID
+ReceiverReceivePackets(
+    IN  PXENNET_RECEIVER    Receiver,
+    IN  PLIST_ENTRY         List
+    );
+
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER    Receiver
     );
 
-void ReceiverPause(PRECEIVER receiver);
-void ReceiverUnpause(PRECEIVER receiver);
+#endif // _XENNET_RECEIVER_H_
diff --git a/src/xennet/std.h b/src/xennet/std.h
deleted file mode 100644
index c72325a..0000000
--- a/src/xennet/std.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-#pragma warning(disable:4214)   // bit field types other than int
-
-#pragma warning(disable:4201)   // nameless struct/union
-#pragma warning(disable:4115)   // named type definition in parentheses
-#pragma warning(disable:4127)   // conditional expression is constant
-#pragma warning(disable:4054)   // cast of function pointer to PVOID
-#pragma warning(disable:4206)   // translation unit is empty
-
-#include <ndis.h>
-#include <ntstrsafe.h>
-
-extern PULONG InitSafeBootMode;
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 6a18a19..0c89f76 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -29,60 +29,78 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include <ndis.h>
+#include "transmitter.h"
+#include "adapter.h"
+#include <vif_interface.h>
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_TRANSMITTER {
+    PXENNET_ADAPTER             Adapter;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
+
+#define TRANSMITTER_POOL_TAG        'TteN'
 
 NDIS_STATUS
-TransmitterInitialize(
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+TransmitterInitialize (
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_TRANSMITTER *Transmitter
     )
 {
-    Transmitter->Adapter = Adapter;
-
+    *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
+                                         sizeof(XENNET_TRANSMITTER),
+                                         TRANSMITTER_POOL_TAG);
+    if (*Transmitter == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
+    (*Transmitter)->Adapter = Adapter;
+    
     return NDIS_STATUS_SUCCESS;
+
+fail1:
+    return NDIS_STATUS_FAILURE;
+}
+
+VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    Transmitter->Adapter = NULL;
+    Transmitter->OffloadOptions.Value = 0;
+
+    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
 VOID
 TransmitterEnable(
-    IN  PTRANSMITTER    Transmitter
+    IN  PXENNET_TRANSMITTER Transmitter
     )
 {
-    PADAPTER            Adapter = Transmitter->Adapter;
+    PXENVIF_VIF_INTERFACE   VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
                       (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->VifInterface,
+                      VifInterface,
                       XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 }
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER *Transmitter
-    )
-{
-    ASSERT(Transmitter != NULL);
-
-    if (*Transmitter) {
-        ExFreePool(*Transmitter);
-        *Transmitter = NULL;
-    }
-}
-
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -97,24 +115,37 @@ typedef struct _NET_BUFFER_RESERVED {
 C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
 
 static VOID
-TransmitterAbortNetBufferList(
-    IN  PTRANSMITTER        Transmitter,
-    IN  PNET_BUFFER_LIST    NetBufferList
+__TransmitterCompleteNetBufferList(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_STATUS             Status
     )
 {
     ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_NOT_ACCEPTED;
+    NET_BUFFER_LIST_STATUS(NetBufferList) = Status;
+
+    if (Status == NDIS_STATUS_SUCCESS) {
+        PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+
+        LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)
+                                &NET_BUFFER_LIST_INFO(NetBufferList,
+                                                      TcpLargeSendNetBufferListInfo);
+        if (LargeSendInfo->LsoV2Transmit.MSS != 0)
+            LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
+    }
 
-    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+    NdisMSendNetBufferListsComplete(AdapterGetHandle(Transmitter->Adapter),
                                     NetBufferList,
                                     NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
 }
 
-VOID
-TransmitterAbortPackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+
+static VOID
+__TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    IN  NDIS_STATUS                 Status
     )
 {
     while (Packet != NULL) {
@@ -135,21 +166,86 @@ TransmitterAbortPackets(
 
         ASSERT(ListReserved->Reference != 0);
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
+            __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
 
         Packet = Next;
+    }    
+}
+
+static VOID
+__TransmitterOffloadOptions(
+    IN  PNET_BUFFER_LIST            NetBufferList,
+    OUT PXENVIF_VIF_OFFLOAD_OPTIONS OffloadOptions,
+    OUT PUSHORT                     TagControlInformation,
+    OUT PUSHORT                     MaximumSegmentSize
+    )
+{
+    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+    PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO          ChecksumInfo;
+    PNDIS_NET_BUFFER_LIST_8021Q_INFO                    Ieee8021QInfo;
+
+    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                                TcpLargeSendNetBufferListInfo);
+    ChecksumInfo = (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                        TcpIpChecksumNetBufferListInfo);
+    Ieee8021QInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBufferList, 
+                                                                            Ieee8021QNetBufferListInfo);
+
+    OffloadOptions->Value = 0;
+    *TagControlInformation = 0;
+    *MaximumSegmentSize = 0;
+
+    if (ChecksumInfo->Transmit.IsIPv4) {
+        if (ChecksumInfo->Transmit.IpHeaderChecksum)
+            OffloadOptions->OffloadIpVersion4HeaderChecksum = 1;
+
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            OffloadOptions->OffloadIpVersion4TcpChecksum = 1;
+
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            OffloadOptions->OffloadIpVersion4UdpChecksum = 1;
+    }
+
+    if (ChecksumInfo->Transmit.IsIPv6) {
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            OffloadOptions->OffloadIpVersion6TcpChecksum = 1;
+
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            OffloadOptions->OffloadIpVersion6UdpChecksum = 1;
+    }
+
+    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
+        OffloadOptions->OffloadTagManipulation = 1;
+
+        ASSERT3U(Ieee8021QInfo->TagHeader.CanonicalFormatId, ==, 0);
+        ASSERT3U(Ieee8021QInfo->TagHeader.VlanId, ==, 0);
+
+        PACK_TAG_CONTROL_INFORMATION(*TagControlInformation,
+                                        Ieee8021QInfo->TagHeader.UserPriority,
+                                        Ieee8021QInfo->TagHeader.CanonicalFormatId,
+                                        Ieee8021QInfo->TagHeader.VlanId);
+    }
+
+    if (LargeSendInfo->LsoV2Transmit.MSS != 0) {
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4)
+            OffloadOptions->OffloadIpVersion4LargePacket = 1;
+
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
+            OffloadOptions->OffloadIpVersion6LargePacket = 1;
+
+        ASSERT3U(LargeSendInfo->LsoV2Transmit.MSS >> 16, ==, 0);
+        *MaximumSegmentSize = (USHORT)LargeSendInfo->LsoV2Transmit.MSS;
     }
 }
 
 VOID
 TransmitterSendNetBufferLists(
-    IN  PTRANSMITTER            Transmitter,
+    IN  PXENNET_TRANSMITTER     Transmitter,
     IN  PNET_BUFFER_LIST        NetBufferList,
     IN  NDIS_PORT_NUMBER        PortNumber,
     IN  ULONG                   SendFlags
     )
 {
-    PADAPTER                    Adapter = Transmitter->Adapter;
     PXENVIF_TRANSMITTER_PACKET  HeadPacket;
     PXENVIF_TRANSMITTER_PACKET  *TailPacket;
     KIRQL                       Irql;
@@ -167,26 +263,24 @@ TransmitterSendNetBufferLists(
     }
 
     while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST                                    ListNext;
-        PNET_BUFFER_LIST_RESERVED                           ListReserved;
-        PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
-        PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO          ChecksumInfo;
-        PNDIS_NET_BUFFER_LIST_8021Q_INFO                    Ieee8021QInfo;
-        PNET_BUFFER                                         NetBuffer;
+        PNET_BUFFER_LIST            ListNext;
+        PNET_BUFFER_LIST_RESERVED   ListReserved;
+        PNET_BUFFER                 NetBuffer;
+        XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+        USHORT                      TagControlInformation;
+        USHORT                      MaximumSegmentSize;
 
         ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
         NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
 
+        __TransmitterOffloadOptions(NetBufferList,
+                                    &OffloadOptions,
+                                    &TagControlInformation,
+                                    &MaximumSegmentSize);
+
         ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
         RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
 
-        LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                                 TcpLargeSendNetBufferListInfo);
-        ChecksumInfo = (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                         TcpIpChecksumNetBufferListInfo);
-        Ieee8021QInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBufferList, 
-                                                                                Ieee8021QNetBufferListInfo);
-
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
             PNET_BUFFER_RESERVED        Reserved;
@@ -199,50 +293,9 @@ TransmitterSendNetBufferLists(
             ListReserved->Reference++;
 
             Packet = &Reserved->Packet;
-
-            if (ChecksumInfo->Transmit.IsIPv4) {
-                if (ChecksumInfo->Transmit.IpHeaderChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
-
-                if (ChecksumInfo->Transmit.TcpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
-
-                if (ChecksumInfo->Transmit.UdpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
-            }
-
-            if (ChecksumInfo->Transmit.IsIPv6) {
-                if (ChecksumInfo->Transmit.TcpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
-
-                if (ChecksumInfo->Transmit.UdpChecksum)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
-            }
-
-            if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
-                Packet->Send.OffloadOptions.OffloadTagManipulation = 1;
-
-                ASSERT3U(Ieee8021QInfo->TagHeader.CanonicalFormatId, ==, 0);
-                ASSERT3U(Ieee8021QInfo->TagHeader.VlanId, ==, 0);
-
-                PACK_TAG_CONTROL_INFORMATION(Packet->Send.TagControlInformation,
-                                             Ieee8021QInfo->TagHeader.UserPriority,
-                                             Ieee8021QInfo->TagHeader.CanonicalFormatId,
-                                             Ieee8021QInfo->TagHeader.VlanId);
-            }
-
-            if (LargeSendInfo->LsoV2Transmit.MSS != 0) {
-                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4)
-                    Packet->Send.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-
-                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
-                    Packet->Send.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-
-                ASSERT3U(LargeSendInfo->LsoV2Transmit.MSS >> 16, ==, 0);
-                Packet->Send.MaximumSegmentSize = (USHORT)LargeSendInfo->LsoV2Transmit.MSS;
-            }
-
-            Packet->Send.OffloadOptions.Value &= Transmitter->OffloadOptions.Value;
+            Packet->Send.OffloadOptions.Value = OffloadOptions.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
+            Packet->Send.TagControlInformation = TagControlInformation;
 
             ASSERT3P(Packet->Next, ==, NULL);
             *TailPacket = Packet;
@@ -258,65 +311,29 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            &Adapter->VifInterface,
+                            AdapterGetVifInterface(Transmitter->Adapter),
                             HeadPacket);
         if (!NT_SUCCESS(status))
-            TransmitterAbortPackets(Transmitter, HeadPacket);
+            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
     }
 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
 }
 
-static VOID
-TransmitterCompleteNetBufferList(
-    IN  PTRANSMITTER                                    Transmitter,
-    IN  PNET_BUFFER_LIST                                NetBufferList
-    )
-{
-    PADAPTER                                            Adapter = Transmitter->Adapter;
-    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
-
-    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
-
-    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                             TcpLargeSendNetBufferListInfo);
-
-    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
-        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
-
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
-
-    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
-                                    NetBufferList,
-                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
-}
-
 VOID
 TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
+    IN  PXENNET_TRANSMITTER         Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
-
-        Next = Packet->Next;
-        Packet->Next = NULL;
-
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
-
-        NetBufferList = Reserved->NetBufferList;
-        ASSERT(NetBufferList != NULL);
-
-        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
-
-        ASSERT(ListReserved->Reference != 0);
-        if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
+    __TransmitterCompletePackets(Transmitter, Packet, NDIS_STATUS_SUCCESS);
+}
 
-        Packet = Next;
-    }
+PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER Transmitter
+    )
+{
+    return &Transmitter->OffloadOptions;
 }
+
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index 8dc7e8d..f63a2a0 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -29,47 +29,47 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_TRANSMITTER_H_
+#define _XENNET_TRANSMITTER_H_
 
-typedef struct _TRANSMITTER {
-    PADAPTER                    Adapter;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} TRANSMITTER, *PTRANSMITTER;
+#include <ndis.h>
 
-VOID 
-TransmitterCleanup (
-    IN OUT PTRANSMITTER* Transmitter
-    );
+typedef struct _XENNET_TRANSMITTER XENNET_TRANSMITTER, *PXENNET_TRANSMITTER;
 
-NDIS_STATUS
-TransmitterInitialize (
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+#include "adapter.h"
+extern NDIS_STATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER     Adapter,
+    OUT PXENNET_TRANSMITTER *Transmitter
     );
 
-VOID
-TransmitterEnable (
-    IN  PTRANSMITTER    Transmitter
+extern VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER Transmitter
     );
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER* Transmitter
+extern VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER Transmitter
     );
 
-VOID
+extern VOID
 TransmitterSendNetBufferLists (
-    IN  PTRANSMITTER        Transmitter,
+    IN  PXENNET_TRANSMITTER Transmitter,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  NDIS_PORT_NUMBER    PortNumber,
     IN  ULONG               SendFlags
     );
 
-VOID
+extern VOID
 TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
+    IN  PXENNET_TRANSMITTER         Transmitter,
     IN  PXENVIF_TRANSMITTER_PACKET  Packet
     );
 
-void TransmitterPause(PTRANSMITTER Transmitter);
-void TransmitterUnpause(PTRANSMITTER Transmitter);
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER Transmitter
+    );
+
+#endif // _XENNET_TRANSMITTER_H_
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index aab91d2..03ddf91 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -84,8 +84,7 @@
 	</ItemGroup>
 	<ItemGroup>
 		<ClCompile Include="../../src/xennet/adapter.c" />
-		<ClCompile Include="../../src/xennet/main.c" />
-		<ClCompile Include="../../src/xennet/miniport.c" />
+		<ClCompile Include="../../src/xennet/driver.c" />
 		<ClCompile Include="../../src/xennet/receiver.c" />
 		<ClCompile Include="../../src/xennet/transmitter.c" />
 	</ItemGroup>
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index 9401b99..60c79f7 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -115,8 +115,7 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="../../src/xennet/adapter.c" />
-    <ClCompile Include="../../src/xennet/main.c" />
-    <ClCompile Include="../../src/xennet/miniport.c" />
+    <ClCompile Include="../../src/xennet/driver.c" />
     <ClCompile Include="../../src/xennet/receiver.c" />
     <ClCompile Include="../../src/xennet/transmitter.c" />
   </ItemGroup>
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:59 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:59 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebL-00049t-6V; Thu, 18 Dec 2014 17:10:59 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebJ-000496-GJ
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:57 +0000
Received: from [193.109.254.147] by server-10.bemta-14.messagelabs.com id
	4F/0D-02696-0AA03945; Thu, 18 Dec 2014 17:10:56 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418922652!16003797!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23283 invoked from network); 18 Dec 2014 17:10:55 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877227"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:29 +0000
Message-ID: <1418921673-6008-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/6] Move interface registration to
	coinstaller
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

WHQL will fail when registry is accessed from NDIS drivers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/coinst/coinst.c          |  152 ++++++
 src/xennet/main.c            |   13 -
 src/xennet/miniport.c        |   78 +--
 src/xennet/registry.c        | 1200 ------------------------------------------
 src/xennet/registry.h        |  168 ------
 vs2012/xennet/xennet.vcxproj |    1 -
 vs2013/xennet/xennet.vcxproj |    1 -
 7 files changed, 154 insertions(+), 1459 deletions(-)
 delete mode 100644 src/xennet/registry.c
 delete mode 100644 src/xennet/registry.h

diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 532a382..265f348 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -44,6 +44,7 @@
 #include <malloc.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <vif_interface.h>
 
 #include <tcpip.h>
 #include <version.h>
@@ -2082,6 +2083,154 @@ fail1:
     return FALSE;
 }
 
+static HKEY
+OpenInterfacesKey(
+    IN  PTCHAR      ProviderName
+    )
+{
+    HRESULT     Result;
+    TCHAR       KeyName[MAX_PATH];
+    HKEY        Key;
+    HRESULT     Error;
+
+    Result = StringCbPrintf(KeyName,
+                            MAX_PATH,
+                            "%s\\%s\\Interfaces",
+                            SERVICES_KEY,
+                            ProviderName);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail1;
+    }
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         KeyName,
+                         0,
+                         KEY_ALL_ACCESS,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    return Key;
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static BOOLEAN
+RegisterInterface(
+    IN  PTCHAR      ProviderName,
+    IN  PTCHAR      InterfaceName,
+    IN  DWORD       InterfaceVersion
+    )
+{
+    HKEY            Key;
+    HKEY            InterfacesKey;
+    HRESULT         Error;
+
+    InterfacesKey = OpenInterfacesKey(ProviderName);
+    if (InterfacesKey == NULL) {
+        goto fail1;
+    }
+
+    Error = RegCreateKeyEx(InterfacesKey,
+                           "XENNET",
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &Key,
+                           NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Error = RegSetValueEx(Key,
+                          InterfaceName,
+                          0,
+                          REG_DWORD,
+                          (const BYTE *)InterfaceVersion,
+                          sizeof(DWORD));
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    RegCloseKey(Key);
+    RegCloseKey(InterfacesKey);
+    return TRUE;
+
+fail3:
+    RegCloseKey(Key);
+fail2:
+    RegCloseKey(InterfacesKey);
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+DeregisterAllInterfaces(
+    IN  PTCHAR      ProviderName
+    )
+{
+    HKEY            InterfacesKey;
+    HRESULT         Error;
+
+    InterfacesKey = OpenInterfacesKey(ProviderName);
+    if (InterfacesKey == NULL) {
+        goto fail1;
+    }
+
+    Error = RegDeleteTree(InterfacesKey,
+                          "XENNET");
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    RegCloseKey(InterfacesKey);
+    return TRUE;
+
+fail2:
+    RegCloseKey(InterfacesKey);
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
 static BOOLEAN
 RequestReboot(
     IN  HDEVINFO            DeviceInfoSet,
@@ -2185,6 +2334,8 @@ __DifInstallPostProcess(
     if (!Success)
         goto fail5;
 
+    RegisterInterface("XENVIF", "VIF", XENVIF_VIF_INTERFACE_VERSION_MAX);
+
     if (SoftwareKeyName != NULL) {
         (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
@@ -2265,6 +2416,7 @@ __DifRemovePreProcess(
 
     Log("====>");
 
+    (VOID) DeregisterAllInterfaces("XENVIF");
     (VOID) RemoveUnplugService("NICS", "XENNET");
     (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
diff --git a/src/xennet/main.c b/src/xennet/main.c
index 6622e82..e193e0e 100644
--- a/src/xennet/main.c
+++ b/src/xennet/main.c
@@ -32,7 +32,6 @@
 #include <version.h>
 
 #include "common.h"
-#include "registry.h"
 
 #pragma NDIS_INIT_FUNCTION(DriverEntry)
 
@@ -197,7 +196,6 @@ DriverEntry (
     PNDIS_CONFIGURATION_PARAMETER ParameterValue;
     ULONG FailCreateClose;
     ULONG FailDeviceControl;
-    NTSTATUS status;
 
     ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
 
@@ -215,15 +213,6 @@ DriverEntry (
          MONTH,
          YEAR);
 
-    status = RegistryInitialize(RegistryPath);
-
-    ndisStatus = (NT_SUCCESS(status)) ?
-                 NDIS_STATUS_SUCCESS :
-                 NDIS_STATUS_FAILURE;
-
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail;
-
     //
     // Register miniport with NDIS.
     //
@@ -345,8 +334,6 @@ DriverUnload (
     if (MiniportDriverHandle)
         NdisMDeregisterMiniportDriver(MiniportDriverHandle);
 
-    RegistryTeardown();
-
     Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
          MAJOR_VERSION,
          MINOR_VERSION,
diff --git a/src/xennet/miniport.c b/src/xennet/miniport.c
index a1d605f..12d332f 100644
--- a/src/xennet/miniport.c
+++ b/src/xennet/miniport.c
@@ -32,19 +32,14 @@
 #define INITGUID 1
 
 #include "common.h"
-#include "registry.h"
 
 #pragma warning( disable : 4098 )
 
 extern NTSTATUS AllocAdapter(PADAPTER *Adapter);
 
-#define SERVICES_KEY        L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"
-
 static FORCEINLINE NTSTATUS
 __QueryInterface(
     IN  PDEVICE_OBJECT  DeviceObject,
-    IN  const WCHAR     *ProviderName,
-    IN  const CHAR      *InterfaceName,
     IN  const GUID      *Guid,
     IN  ULONG           Version,
     OUT PINTERFACE      Interface,
@@ -52,9 +47,6 @@ __QueryInterface(
     IN  BOOLEAN         Optional
     )
 {
-    UNICODE_STRING      Unicode;
-    HANDLE              InterfacesKey;
-    HANDLE              SubscriberKey;
     KEVENT              Event;
     IO_STATUS_BLOCK     StatusBlock;
     PIRP                Irp;
@@ -63,40 +55,6 @@ __QueryInterface(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    Unicode.MaximumLength = (USHORT)((wcslen(SERVICES_KEY) +
-                                      1 +
-                                      wcslen(ProviderName) +
-                                      1 +
-                                      wcslen(L"Interfaces") +
-                                      1) * sizeof (WCHAR));
-
-    Unicode.Buffer = ExAllocatePoolWithTag(NonPagedPool,
-                                           Unicode.MaximumLength,
-                                           'TEN');
-
-    status = STATUS_NO_MEMORY;
-    if (Unicode.Buffer == NULL)
-        goto fail1;
-
-    status = RtlStringCbPrintfW(Unicode.Buffer,
-                                Unicode.MaximumLength,
-                                SERVICES_KEY L"\\%ws\\Interfaces",
-                                ProviderName);
-    ASSERT(NT_SUCCESS(status));
-
-    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
-
-    status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &InterfacesKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = RegistryCreateSubKey(InterfacesKey, 
-                                  "XENNET", 
-                                  REG_OPTION_NON_VOLATILE, 
-                                  &SubscriberKey);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-                   
     KeInitializeEvent(&Event, NotificationEvent, FALSE);
     RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
 
@@ -110,7 +68,7 @@ __QueryInterface(
 
     status = STATUS_UNSUCCESSFUL;
     if (Irp == NULL)
-        goto fail4;
+        goto fail1;
 
     StackLocation = IoGetNextIrpStackLocation(Irp);
     StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
@@ -136,45 +94,15 @@ __QueryInterface(
         if (status == STATUS_NOT_SUPPORTED && Optional)
             goto done;
 
-        goto fail5;
+        goto fail2;
     }
 
-    status = RegistryUpdateDwordValue(SubscriberKey,
-                                      (PCHAR)InterfaceName,
-                                      Version);
-    if (!NT_SUCCESS(status))
-        goto fail6;
-
 done:
-    RegistryCloseKey(SubscriberKey);
-
-    RegistryCloseKey(InterfacesKey);
-
-    ExFreePool(Unicode.Buffer);
-
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
-
-fail5:
-    Error("fail5\n");
-
-fail4:
-    Error("fail4\n");
-
-    RegistryCloseKey(SubscriberKey);
-
-fail3:
-    Error("fail3\n");
-
-    RegistryCloseKey(InterfacesKey);
-
 fail2:
     Error("fail2\n");
 
-    ExFreePool(Unicode.Buffer);
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -190,8 +118,6 @@ fail1:
     _Size,                                                                              \
     _Optional)                                                                          \
     __QueryInterface((_DeviceObject),                                                   \
-                     L ## #_ProviderName,                                               \
-                     #_InterfaceName,                                                   \
                      &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
                      (_Version),                                                        \
                      (_Interface),                                                      \
diff --git a/src/xennet/registry.c b/src/xennet/registry.c
deleted file mode 100644
index 5843ef5..0000000
--- a/src/xennet/registry.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <util.h>
-
-#include "registry.h"
-#include "assert.h"
-
-#define REGISTRY_POOL 'GERX'
-
-static UNICODE_STRING   RegistryPath;
-
-static FORCEINLINE PVOID
-__RegistryAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocateNonPagedPoolWithTag(Length, REGISTRY_POOL);
-}
-
-static FORCEINLINE VOID
-__RegistryFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, REGISTRY_POOL);
-}
-
-NTSTATUS
-RegistryInitialize(
-    IN PUNICODE_STRING  Path
-    )
-{
-    NTSTATUS            status;
-
-    ASSERT3P(RegistryPath.Buffer, ==, NULL);
-
-    status = RtlUpcaseUnicodeString(&RegistryPath, Path, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-VOID
-RegistryTeardown(
-    VOID
-    )
-{
-    RtlFreeUnicodeString(&RegistryPath);
-    RegistryPath.Buffer = NULL;
-    RegistryPath.MaximumLength = RegistryPath.Length = 0;
-}
-
-NTSTATUS
-RegistryOpenKey(
-    IN  HANDLE          Parent,
-    IN  PUNICODE_STRING Path,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    OBJECT_ATTRIBUTES   Attributes;
-    NTSTATUS            status;
-
-    InitializeObjectAttributes(&Attributes,
-                               Path,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Parent,
-                               NULL);
-
-    status = ZwOpenKey(Key,
-                       DesiredAccess,
-                       &Attributes);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenServiceKey(
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    return RegistryOpenKey(NULL, &RegistryPath, DesiredAccess, Key);
-}
-
-NTSTATUS
-RegistryOpenSoftwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    NTSTATUS            status;
-
-    status = IoOpenDeviceRegistryKey(DeviceObject,
-                                     PLUGPLAY_REGKEY_DRIVER,
-                                     DesiredAccess,
-                                     Key);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenHardwareKey(
-    IN  PDEVICE_OBJECT      DeviceObject,
-    IN  ACCESS_MASK         DesiredAccess,
-    OUT PHANDLE             Key
-    )
-{
-    HANDLE                  SubKey;
-    ULONG                   Length;
-    PKEY_NAME_INFORMATION   Info;
-    PWCHAR                  Cursor;
-    UNICODE_STRING          Unicode;
-    NTSTATUS                status;
-
-    status = IoOpenDeviceRegistryKey(DeviceObject,
-                                     PLUGPLAY_REGKEY_DEVICE,
-                                     KEY_READ,
-                                     &SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    Length = 0;
-    (VOID) ZwQueryKey(SubKey,
-                      KeyNameInformation,
-                      NULL,
-                      0,
-                      &Length);
-
-    status = STATUS_INVALID_PARAMETER;
-    if (Length == 0)
-        goto fail2;
-    
-    Info = __RegistryAllocate(Length + sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Info == NULL)
-        goto fail3;
-
-    status = ZwQueryKey(SubKey,
-                        KeyNameInformation,
-                        Info,
-                        Length,
-                        &Length);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    Info->Name[Info->NameLength / sizeof (WCHAR)] = '\0';
-
-    Cursor = wcsrchr(Info->Name, L'\\');
-    ASSERT(Cursor != NULL);
-
-    *Cursor = L'\0';
-    
-    RtlInitUnicodeString(&Unicode, Info->Name);
-
-    status = RegistryOpenKey(NULL, &Unicode, DesiredAccess, Key);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    __RegistryFree(Info);
-
-    RegistryCloseKey(SubKey);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Info);
-
-fail3:
-fail2:
-    RegistryCloseKey(SubKey);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         SubKey
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryOpenKey(Key, &Unicode, DesiredAccess, SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryCreateSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Options,
-    OUT PHANDLE         SubKey
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    OBJECT_ATTRIBUTES   Attributes;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    InitializeObjectAttributes(&Attributes,
-                               &Unicode,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Key,
-                               NULL);
-
-    status = ZwCreateKey(SubKey,
-                         KEY_ALL_ACCESS,
-                         &Attributes,
-                         0,
-                         NULL,
-                         Options,
-                         NULL
-                         );
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryDeleteSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    HANDLE              SubKey;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryOpenKey(Key, &Unicode, KEY_ALL_ACCESS, &SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = ZwDeleteKey(SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    ZwClose(SubKey);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    ZwClose(SubKey);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryEnumerateSubKeys(
-    IN  HANDLE              Key,
-    IN  NTSTATUS            (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID               Context
-    )
-{
-    ULONG                   Size;
-    NTSTATUS                status;
-    PKEY_FULL_INFORMATION   Full;
-    PKEY_BASIC_INFORMATION  Basic;
-    ULONG                   Index;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    Full = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Full == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        Full,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Size = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) +
-           Full->MaxNameLen;
-
-    Basic = __RegistryAllocate(Size);
-    status = STATUS_NO_MEMORY;
-    if (Basic == NULL)
-        goto fail4;
-
-    for (Index = 0; Index < Full->SubKeys; Index++) {
-        UNICODE_STRING  Unicode;
-        ANSI_STRING     Ansi;
-
-        status = ZwEnumerateKey(Key,
-                                Index,
-                                KeyBasicInformation,
-                                Basic,
-                                Size,
-                                &Size);
-        if (!NT_SUCCESS(status))
-            goto fail5;
-
-        Unicode.MaximumLength = (USHORT)Basic->NameLength;
-        Unicode.Buffer = Basic->Name;
-        Unicode.Length = (USHORT)Basic->NameLength;
-
-        Ansi.MaximumLength = (USHORT)((Basic->NameLength / sizeof (WCHAR)) + sizeof (CHAR));
-        Ansi.Buffer = __RegistryAllocate(Ansi.MaximumLength);
-
-        status = STATUS_NO_MEMORY;
-        if (Ansi.Buffer == NULL)
-            goto fail6;
-
-        status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi.Length = (USHORT)(strlen(Ansi.Buffer) * sizeof (CHAR));        
-
-        status = Callback(Context, Key, Ansi.Buffer);
-
-        __RegistryFree(Ansi.Buffer);
-        Ansi.Buffer = NULL;
-
-        if (!NT_SUCCESS(status))
-            goto fail7;
-    }
-
-    __RegistryFree(Basic);
-
-    __RegistryFree(Full);
-
-    return STATUS_SUCCESS;
-
-fail7:
-fail6:
-fail5:
-    __RegistryFree(Basic);
-
-fail4:
-fail3:
-    __RegistryFree(Full);
-    
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryEnumerateValues(
-    IN  HANDLE                      Key,
-    IN  NTSTATUS                    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID                       Context
-    )
-{
-    ULONG                           Size;
-    NTSTATUS                        status;
-    PKEY_FULL_INFORMATION           Full;
-    PKEY_VALUE_BASIC_INFORMATION    Basic;
-    ULONG                           Index;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    Full = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Full == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        Full,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
-           Full->MaxValueNameLen;
-
-    Basic = __RegistryAllocate(Size);
-    status = STATUS_NO_MEMORY;
-    if (Basic == NULL)
-        goto fail4;
-
-    for (Index = 0; Index < Full->Values; Index++) {
-        UNICODE_STRING  Unicode;
-        ANSI_STRING     Ansi;
-
-        status = ZwEnumerateValueKey(Key,
-                                     Index,
-                                     KeyValueBasicInformation,
-                                     Basic,
-                                     Size,
-                                     &Size);
-        if (!NT_SUCCESS(status))
-            goto fail5;
-
-        Unicode.MaximumLength = (USHORT)Basic->NameLength;
-        Unicode.Buffer = Basic->Name;
-        Unicode.Length = (USHORT)Basic->NameLength;
-
-        Ansi.MaximumLength = (USHORT)((Basic->NameLength / sizeof (WCHAR)) + sizeof (CHAR));
-        Ansi.Buffer = __RegistryAllocate(Ansi.MaximumLength);
-
-        status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi.Length = (USHORT)(strlen(Ansi.Buffer) * sizeof (CHAR));        
-
-        status = Callback(Context, Key, Ansi.Buffer);
-
-        __RegistryFree(Ansi.Buffer);
-
-        if (!NT_SUCCESS(status))
-            goto fail6;
-    }
-
-    __RegistryFree(Basic);
-
-    __RegistryFree(Full);
-
-    return STATUS_SUCCESS;
-
-fail6:
-fail5:
-    __RegistryFree(Basic);
-
-fail4:
-fail3:
-    __RegistryFree(Full);
-    
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryDeleteValue(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = ZwDeleteValueKey(Key, &Unicode);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQueryDwordValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    OUT PULONG                      Value
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    ULONG                           Size;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             NULL,
-                             0,
-                             &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail2;
-
-    Partial = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail3;
-
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             Partial,
-                             Size,
-                             &Size);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = STATUS_INVALID_PARAMETER;
-    if (Partial->Type != REG_DWORD ||
-        Partial->DataLength != sizeof (ULONG))
-        goto fail5;
-
-    *Value = *(PULONG)Partial->Data;            
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Partial);
-
-fail3:
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryUpdateDwordValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    IN  ULONG                       Value
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                                 sizeof (ULONG));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail2;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_DWORD;
-    Partial->DataLength = sizeof (ULONG);
-    *(PULONG)Partial->Data = Value;            
-
-    status = ZwSetValueKey(Key,
-                           &Unicode,
-                           Partial->TitleIndex,
-                           Partial->Type,
-                           Partial->Data,
-                           Partial->DataLength);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    __RegistryFree(Partial);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-
-    return status;
-}
-
-static PANSI_STRING
-RegistrySzToAnsi(
-    IN  PWCHAR      Buffer
-    )
-{
-    PANSI_STRING    Ansi;
-    ULONG           Length;
-    UNICODE_STRING  Unicode;
-    NTSTATUS        status;
-
-    Ansi = __RegistryAllocate(sizeof (ANSI_STRING) * 2);
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi == NULL)
-        goto fail1;
-
-    Length = (ULONG)wcslen(Buffer);
-    Ansi[0].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-    Ansi[0].Buffer = __RegistryAllocate(Ansi[0].MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi[0].Buffer == NULL)
-        goto fail2;
-
-    RtlInitUnicodeString(&Unicode, Buffer);
-    status = RtlUnicodeStringToAnsiString(&Ansi[0], &Unicode, FALSE);
-    ASSERT(NT_SUCCESS(status));
-
-    Ansi[0].Length = (USHORT)Length * sizeof (CHAR);
-
-    return Ansi;
-
-fail2:
-    __RegistryFree(Ansi);
-
-fail1:
-    return NULL;
-}
-
-static PANSI_STRING
-RegistryMultiSzToAnsi(
-    IN  PWCHAR      Buffer
-    )
-{
-    PANSI_STRING    Ansi;
-    LONG            Index;
-    LONG            Count;
-    NTSTATUS        status;
-
-    Index = 0;
-    Count = 0;
-    for (;;) {
-        ULONG   Length;
-
-        Length = (ULONG)wcslen(&Buffer[Index]);
-        if (Length == 0)
-            break;
-
-        Index += Length + 1;
-        Count++;
-    }
-
-    Ansi = __RegistryAllocate(sizeof (ANSI_STRING) * (Count + 1));
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi == NULL)
-        goto fail1;
-
-    for (Index = 0; Index < Count; Index++) {
-        ULONG           Length;
-        UNICODE_STRING  Unicode;
-
-        Length = (ULONG)wcslen(Buffer);
-        Ansi[Index].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-        Ansi[Index].Buffer = __RegistryAllocate(Ansi[Index].MaximumLength);
-
-        status = STATUS_NO_MEMORY;
-        if (Ansi[Index].Buffer == NULL)
-            goto fail2;
-
-        RtlInitUnicodeString(&Unicode, Buffer);
-
-        status = RtlUnicodeStringToAnsiString(&Ansi[Index], &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi[Index].Length = (USHORT)Length * sizeof (CHAR);
-        Buffer += Length + 1;
-    }
-
-    return Ansi;
-
-fail2:
-    while (--Index >= 0)
-        __RegistryFree(Ansi[Index].Buffer);
-
-    __RegistryFree(Ansi);
-
-fail1:
-    return NULL;
-}
-
-NTSTATUS
-RegistryQuerySzValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    OUT PANSI_STRING                *Array
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Value;
-    ULONG                           Size;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             NULL,
-                             0,
-                             &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail2;
-
-    Value = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Value == NULL)
-        goto fail3;
-
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             Value,
-                             Size,
-                             &Size);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    switch (Value->Type) {
-    case REG_SZ:
-        status = STATUS_NO_MEMORY;
-        *Array = RegistrySzToAnsi((PWCHAR)Value->Data);
-        break;
-
-    case REG_MULTI_SZ:
-        status = STATUS_NO_MEMORY;
-        *Array = RegistryMultiSzToAnsi((PWCHAR)Value->Data);
-        break;
-
-    default:
-        status = STATUS_INVALID_PARAMETER;
-        *Array = NULL;
-        break;
-    }
-
-    if (*Array == NULL)
-        goto fail5;
-
-    __RegistryFree(Value);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Value);
-
-fail3:
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQueryKeyName(
-    IN  HANDLE              Key,
-    OUT PANSI_STRING        *Array
-    )
-{
-    PKEY_NAME_INFORMATION   Value;
-    ULONG                   Size;
-    NTSTATUS                status;
-
-    status = ZwQueryKey(Key,
-                        KeyNameInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    // Name information is not intrinsically NULL terminated
-    Value = __RegistryAllocate(Size + sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Value == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyNameInformation,
-                        Value,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Value->Name[Value->NameLength / sizeof (WCHAR)] = L'\0';
-    *Array = RegistrySzToAnsi((PWCHAR)Value->Name);
-
-    status = STATUS_NO_MEMORY;
-    if (*Array == NULL)
-        goto fail4;
-
-    __RegistryFree(Value);
-
-    return STATUS_SUCCESS;
-
-fail4:
-fail3:
-    __RegistryFree(Value);
-
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQuerySystemStartOption(
-    IN  PCHAR                       Prefix,
-    OUT PANSI_STRING                *Value
-    )
-{
-    UNICODE_STRING                  Unicode;
-    HANDLE                          Key;
-    PANSI_STRING                    Ansi;
-    ULONG                           Length;
-    PCHAR                           Option;
-    PCHAR                           Context;
-    NTSTATUS                        status;
-
-    RtlInitUnicodeString(&Unicode, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control");
-    
-    status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &Key);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryQuerySzValue(Key, "SystemStartOptions", &Ansi);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    // SystemStartOptions is a space separated list of options.
-    // Scan it looking for the one we want.
-    Length = (ULONG)strlen(Prefix);
-
-    Option = __strtok_r(Ansi[0].Buffer, " ", &Context);
-    if (strncmp(Prefix, Option, Length) == 0)
-        goto found;
-
-    while ((Option = __strtok_r(NULL, " ", &Context)) != NULL)
-        if (strncmp(Prefix, Option, Length) == 0)
-            goto found;
-
-    status = STATUS_OBJECT_NAME_NOT_FOUND;
-    goto fail3;
-
-found:
-    *Value = __RegistryAllocate(sizeof (ANSI_STRING) * 2);
-
-    status = STATUS_NO_MEMORY;
-    if (*Value == NULL)
-        goto fail4;
-
-    Length = (ULONG)strlen(Option);
-    (*Value)[0].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-    (*Value)[0].Buffer = __RegistryAllocate((*Value)[0].MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if ((*Value)[0].Buffer == NULL)
-        goto fail5;
-
-    RtlCopyMemory((*Value)[0].Buffer, Option, Length * sizeof (CHAR));
-
-    (*Value)[0].Length = (USHORT)Length * sizeof (CHAR);
-
-    RegistryFreeSzValue(Ansi);
-
-    ZwClose(Key);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    __RegistryFree(*Value);
-
-fail4:
-fail3:
-    RegistryFreeSzValue(Ansi);
-
-fail2:
-    ZwClose(Key);
-
-fail1:
-    return status;
-}
-
-static PKEY_VALUE_PARTIAL_INFORMATION
-RegistryAnsiToSz(
-    PANSI_STRING                    Ansi
-    )
-{
-    ULONG                           Length;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    UNICODE_STRING                  Unicode;
-    NTSTATUS                        status;
-
-    Length = Ansi->Length + 1;
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                                 Length * sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail1;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_SZ;
-    Partial->DataLength = Length * sizeof (WCHAR);
-
-    Unicode.MaximumLength = (UCHAR)Partial->DataLength;
-    Unicode.Buffer = (PWCHAR)Partial->Data;
-    Unicode.Length = 0;
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, Ansi, FALSE);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    return Partial;
-
-fail2:
-    __RegistryFree(Partial);
-
-fail1:
-    return NULL;
-}
-
-static PKEY_VALUE_PARTIAL_INFORMATION
-RegistryAnsiToMultiSz(
-    PANSI_STRING                    Ansi
-    )
-{
-    ULONG                           Length;
-    ULONG                           Index;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    UNICODE_STRING                  Unicode;
-    NTSTATUS                        status;
-
-    Length = 1;
-    for (Index = 0; Ansi[Index].Buffer != NULL; Index++)
-        Length += Ansi[Index].Length + 1;
-
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                               Length * sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail1;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_MULTI_SZ;
-    Partial->DataLength = Length * sizeof (WCHAR);
-
-    Unicode.MaximumLength = (USHORT)Partial->DataLength;
-    Unicode.Buffer = (PWCHAR)Partial->Data;
-    Unicode.Length = 0;
-
-    for (Index = 0; Ansi[Index].Buffer != NULL; Index++) {
-        status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi[Index], FALSE);
-        if (!NT_SUCCESS(status))
-            goto fail2;
-
-        Length = Unicode.Length / sizeof (WCHAR);
-
-        ASSERT3U(Unicode.MaximumLength, >=, (Length + 1) * sizeof (WCHAR));
-        Unicode.MaximumLength -= (USHORT)((Length + 1) * sizeof (WCHAR));
-        Unicode.Buffer += Length + 1;
-        Unicode.Length = 0;
-    }
-    *Unicode.Buffer = L'\0';
-
-    return Partial;
-
-fail2:
-    __RegistryFree(Partial);
-
-fail1:
-    return NULL;
-}
-
-NTSTATUS
-RegistryUpdateSzValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    IN  ULONG                       Type,
-    ...
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    va_list                         Arguments;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    va_start(Arguments, Type);
-    switch (Type) {
-    case REG_SZ: {
-        PANSI_STRING    Argument;
-
-        Argument = va_arg(Arguments, PANSI_STRING);
-
-        status = STATUS_NO_MEMORY;
-        Partial = RegistryAnsiToSz(Argument);        
-        break;
-    }
-    case REG_MULTI_SZ: {
-        PANSI_STRING    Argument;
-
-        Argument = va_arg(Arguments, PANSI_STRING);
-
-        status = STATUS_NO_MEMORY;
-        Partial = RegistryAnsiToMultiSz(Argument);        
-        break;
-    }
-    default:
-        status = STATUS_INVALID_PARAMETER;
-        Partial = NULL;
-        break;
-    }
-    va_end(Arguments);
-
-    if (Partial == NULL)
-        goto fail2;
-
-    status = ZwSetValueKey(Key,
-                           &Unicode,
-                           Partial->TitleIndex,
-                           Partial->Type,
-                           Partial->Data,
-                           Partial->DataLength);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    __RegistryFree(Partial);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-VOID
-RegistryFreeSzValue(
-    IN  PANSI_STRING    Array
-    )
-{
-    ULONG               Index;
-
-    if (Array == NULL)
-        return;
-
-    for (Index = 0; Array[Index].Buffer != NULL; Index++)
-        __RegistryFree(Array[Index].Buffer);
-
-    __RegistryFree(Array);
-}
-
-VOID
-RegistryCloseKey(
-    IN  HANDLE  Key
-    )
-{
-    ZwClose(Key);
-}
diff --git a/src/xennet/registry.h b/src/xennet/registry.h
deleted file mode 100644
index 7d7dc01..0000000
--- a/src/xennet/registry.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#ifndef _XENNET_REGISTRY_H
-#define _XENNET_REGISTRY_H
-
-#include <ntddk.h>
-
-extern NTSTATUS
-RegistryInitialize(
-    IN PUNICODE_STRING  Path
-    );
-
-extern VOID
-RegistryTeardown(
-    VOID
-    );
-
-extern NTSTATUS
-RegistryOpenKey(
-    IN  HANDLE          Parent,
-    IN  PUNICODE_STRING Path,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenServiceKey(
-    IN  ACCESS_MASK DesiredAccess,
-    OUT PHANDLE     Key
-    );
-
-extern NTSTATUS
-RegistryOpenSoftwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenHardwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name,
-    IN  ACCESS_MASK DesiredAccess,
-    OUT PHANDLE     SubKey
-    );
-
-extern NTSTATUS
-RegistryCreateSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name,
-    IN  ULONG       Options,
-    OUT PHANDLE     SubKey
-    );
-
-extern NTSTATUS
-RegistryDeleteSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name
-    );
-
-extern NTSTATUS
-RegistryEnumerateSubKeys(
-    IN  HANDLE      Key,
-    IN  NTSTATUS    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID       Context
-    );
-
-extern NTSTATUS
-RegistryEnumerateValues(
-    IN  HANDLE      Key,
-    IN  NTSTATUS    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID       Context
-    );
-
-extern NTSTATUS
-RegistryDeleteValue(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name
-    );
-
-extern NTSTATUS
-RegistryQueryDwordValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    OUT PULONG          Value
-    );
-    
-extern NTSTATUS
-RegistryUpdateDwordValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Value
-    );
-    
-extern NTSTATUS
-RegistryQuerySzValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    OUT PANSI_STRING    *Array
-    );
-
-extern NTSTATUS
-RegistryQueryKeyName(
-    IN  HANDLE              Key,
-    OUT PANSI_STRING        *Array
-    );
-
-extern NTSTATUS
-RegistryQuerySystemStartOption(
-    IN  PCHAR           Name,
-    OUT PANSI_STRING    *Option
-    );
-
-extern VOID
-RegistryFreeSzValue(
-    IN  PANSI_STRING    Array
-    );
-
-extern NTSTATUS
-RegistryUpdateSzValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Type,
-    ...
-    );
-
-extern VOID
-RegistryCloseKey(
-    IN  HANDLE  Key
-    );
-
-#endif  // _XENNET_REGISTRY_H
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index db07e9b..aab91d2 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -83,7 +83,6 @@
 		<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
 	</ItemGroup>
 	<ItemGroup>
-		<ClCompile Include="../../src/xennet/registry.c" />
 		<ClCompile Include="../../src/xennet/adapter.c" />
 		<ClCompile Include="../../src/xennet/main.c" />
 		<ClCompile Include="../../src/xennet/miniport.c" />
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index 0d98f3a..9401b99 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -114,7 +114,6 @@
     <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="../../src/xennet/registry.c" />
     <ClCompile Include="../../src/xennet/adapter.c" />
     <ClCompile Include="../../src/xennet/main.c" />
     <ClCompile Include="../../src/xennet/miniport.c" />
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:10:59 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:10:59 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1ebL-00049t-6V; Thu, 18 Dec 2014 17:10:59 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1ebJ-000496-GJ
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:10:57 +0000
Received: from [193.109.254.147] by server-10.bemta-14.messagelabs.com id
	4F/0D-02696-0AA03945; Thu, 18 Dec 2014 17:10:56 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418922652!16003797!2
X-Originating-IP: [66.165.176.89]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23283 invoked from network); 18 Dec 2014 17:10:55 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:10:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="205877227"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:29 +0000
Message-ID: <1418921673-6008-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/6] Move interface registration to
	coinstaller
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

WHQL will fail when registry is accessed from NDIS drivers.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/coinst/coinst.c          |  152 ++++++
 src/xennet/main.c            |   13 -
 src/xennet/miniport.c        |   78 +--
 src/xennet/registry.c        | 1200 ------------------------------------------
 src/xennet/registry.h        |  168 ------
 vs2012/xennet/xennet.vcxproj |    1 -
 vs2013/xennet/xennet.vcxproj |    1 -
 7 files changed, 154 insertions(+), 1459 deletions(-)
 delete mode 100644 src/xennet/registry.c
 delete mode 100644 src/xennet/registry.h

diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 532a382..265f348 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -44,6 +44,7 @@
 #include <malloc.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <vif_interface.h>
 
 #include <tcpip.h>
 #include <version.h>
@@ -2082,6 +2083,154 @@ fail1:
     return FALSE;
 }
 
+static HKEY
+OpenInterfacesKey(
+    IN  PTCHAR      ProviderName
+    )
+{
+    HRESULT     Result;
+    TCHAR       KeyName[MAX_PATH];
+    HKEY        Key;
+    HRESULT     Error;
+
+    Result = StringCbPrintf(KeyName,
+                            MAX_PATH,
+                            "%s\\%s\\Interfaces",
+                            SERVICES_KEY,
+                            ProviderName);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail1;
+    }
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         KeyName,
+                         0,
+                         KEY_ALL_ACCESS,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    return Key;
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static BOOLEAN
+RegisterInterface(
+    IN  PTCHAR      ProviderName,
+    IN  PTCHAR      InterfaceName,
+    IN  DWORD       InterfaceVersion
+    )
+{
+    HKEY            Key;
+    HKEY            InterfacesKey;
+    HRESULT         Error;
+
+    InterfacesKey = OpenInterfacesKey(ProviderName);
+    if (InterfacesKey == NULL) {
+        goto fail1;
+    }
+
+    Error = RegCreateKeyEx(InterfacesKey,
+                           "XENNET",
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &Key,
+                           NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Error = RegSetValueEx(Key,
+                          InterfaceName,
+                          0,
+                          REG_DWORD,
+                          (const BYTE *)InterfaceVersion,
+                          sizeof(DWORD));
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    RegCloseKey(Key);
+    RegCloseKey(InterfacesKey);
+    return TRUE;
+
+fail3:
+    RegCloseKey(Key);
+fail2:
+    RegCloseKey(InterfacesKey);
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+DeregisterAllInterfaces(
+    IN  PTCHAR      ProviderName
+    )
+{
+    HKEY            InterfacesKey;
+    HRESULT         Error;
+
+    InterfacesKey = OpenInterfacesKey(ProviderName);
+    if (InterfacesKey == NULL) {
+        goto fail1;
+    }
+
+    Error = RegDeleteTree(InterfacesKey,
+                          "XENNET");
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    RegCloseKey(InterfacesKey);
+    return TRUE;
+
+fail2:
+    RegCloseKey(InterfacesKey);
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = __GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
 static BOOLEAN
 RequestReboot(
     IN  HDEVINFO            DeviceInfoSet,
@@ -2185,6 +2334,8 @@ __DifInstallPostProcess(
     if (!Success)
         goto fail5;
 
+    RegisterInterface("XENVIF", "VIF", XENVIF_VIF_INTERFACE_VERSION_MAX);
+
     if (SoftwareKeyName != NULL) {
         (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
@@ -2265,6 +2416,7 @@ __DifRemovePreProcess(
 
     Log("====>");
 
+    (VOID) DeregisterAllInterfaces("XENVIF");
     (VOID) RemoveUnplugService("NICS", "XENNET");
     (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
diff --git a/src/xennet/main.c b/src/xennet/main.c
index 6622e82..e193e0e 100644
--- a/src/xennet/main.c
+++ b/src/xennet/main.c
@@ -32,7 +32,6 @@
 #include <version.h>
 
 #include "common.h"
-#include "registry.h"
 
 #pragma NDIS_INIT_FUNCTION(DriverEntry)
 
@@ -197,7 +196,6 @@ DriverEntry (
     PNDIS_CONFIGURATION_PARAMETER ParameterValue;
     ULONG FailCreateClose;
     ULONG FailDeviceControl;
-    NTSTATUS status;
 
     ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
 
@@ -215,15 +213,6 @@ DriverEntry (
          MONTH,
          YEAR);
 
-    status = RegistryInitialize(RegistryPath);
-
-    ndisStatus = (NT_SUCCESS(status)) ?
-                 NDIS_STATUS_SUCCESS :
-                 NDIS_STATUS_FAILURE;
-
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail;
-
     //
     // Register miniport with NDIS.
     //
@@ -345,8 +334,6 @@ DriverUnload (
     if (MiniportDriverHandle)
         NdisMDeregisterMiniportDriver(MiniportDriverHandle);
 
-    RegistryTeardown();
-
     Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
          MAJOR_VERSION,
          MINOR_VERSION,
diff --git a/src/xennet/miniport.c b/src/xennet/miniport.c
index a1d605f..12d332f 100644
--- a/src/xennet/miniport.c
+++ b/src/xennet/miniport.c
@@ -32,19 +32,14 @@
 #define INITGUID 1
 
 #include "common.h"
-#include "registry.h"
 
 #pragma warning( disable : 4098 )
 
 extern NTSTATUS AllocAdapter(PADAPTER *Adapter);
 
-#define SERVICES_KEY        L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"
-
 static FORCEINLINE NTSTATUS
 __QueryInterface(
     IN  PDEVICE_OBJECT  DeviceObject,
-    IN  const WCHAR     *ProviderName,
-    IN  const CHAR      *InterfaceName,
     IN  const GUID      *Guid,
     IN  ULONG           Version,
     OUT PINTERFACE      Interface,
@@ -52,9 +47,6 @@ __QueryInterface(
     IN  BOOLEAN         Optional
     )
 {
-    UNICODE_STRING      Unicode;
-    HANDLE              InterfacesKey;
-    HANDLE              SubscriberKey;
     KEVENT              Event;
     IO_STATUS_BLOCK     StatusBlock;
     PIRP                Irp;
@@ -63,40 +55,6 @@ __QueryInterface(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    Unicode.MaximumLength = (USHORT)((wcslen(SERVICES_KEY) +
-                                      1 +
-                                      wcslen(ProviderName) +
-                                      1 +
-                                      wcslen(L"Interfaces") +
-                                      1) * sizeof (WCHAR));
-
-    Unicode.Buffer = ExAllocatePoolWithTag(NonPagedPool,
-                                           Unicode.MaximumLength,
-                                           'TEN');
-
-    status = STATUS_NO_MEMORY;
-    if (Unicode.Buffer == NULL)
-        goto fail1;
-
-    status = RtlStringCbPrintfW(Unicode.Buffer,
-                                Unicode.MaximumLength,
-                                SERVICES_KEY L"\\%ws\\Interfaces",
-                                ProviderName);
-    ASSERT(NT_SUCCESS(status));
-
-    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
-
-    status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &InterfacesKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = RegistryCreateSubKey(InterfacesKey, 
-                                  "XENNET", 
-                                  REG_OPTION_NON_VOLATILE, 
-                                  &SubscriberKey);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-                   
     KeInitializeEvent(&Event, NotificationEvent, FALSE);
     RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
 
@@ -110,7 +68,7 @@ __QueryInterface(
 
     status = STATUS_UNSUCCESSFUL;
     if (Irp == NULL)
-        goto fail4;
+        goto fail1;
 
     StackLocation = IoGetNextIrpStackLocation(Irp);
     StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
@@ -136,45 +94,15 @@ __QueryInterface(
         if (status == STATUS_NOT_SUPPORTED && Optional)
             goto done;
 
-        goto fail5;
+        goto fail2;
     }
 
-    status = RegistryUpdateDwordValue(SubscriberKey,
-                                      (PCHAR)InterfaceName,
-                                      Version);
-    if (!NT_SUCCESS(status))
-        goto fail6;
-
 done:
-    RegistryCloseKey(SubscriberKey);
-
-    RegistryCloseKey(InterfacesKey);
-
-    ExFreePool(Unicode.Buffer);
-
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
-
-fail5:
-    Error("fail5\n");
-
-fail4:
-    Error("fail4\n");
-
-    RegistryCloseKey(SubscriberKey);
-
-fail3:
-    Error("fail3\n");
-
-    RegistryCloseKey(InterfacesKey);
-
 fail2:
     Error("fail2\n");
 
-    ExFreePool(Unicode.Buffer);
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -190,8 +118,6 @@ fail1:
     _Size,                                                                              \
     _Optional)                                                                          \
     __QueryInterface((_DeviceObject),                                                   \
-                     L ## #_ProviderName,                                               \
-                     #_InterfaceName,                                                   \
                      &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
                      (_Version),                                                        \
                      (_Interface),                                                      \
diff --git a/src/xennet/registry.c b/src/xennet/registry.c
deleted file mode 100644
index 5843ef5..0000000
--- a/src/xennet/registry.c
+++ /dev/null
@@ -1,1200 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <util.h>
-
-#include "registry.h"
-#include "assert.h"
-
-#define REGISTRY_POOL 'GERX'
-
-static UNICODE_STRING   RegistryPath;
-
-static FORCEINLINE PVOID
-__RegistryAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocateNonPagedPoolWithTag(Length, REGISTRY_POOL);
-}
-
-static FORCEINLINE VOID
-__RegistryFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, REGISTRY_POOL);
-}
-
-NTSTATUS
-RegistryInitialize(
-    IN PUNICODE_STRING  Path
-    )
-{
-    NTSTATUS            status;
-
-    ASSERT3P(RegistryPath.Buffer, ==, NULL);
-
-    status = RtlUpcaseUnicodeString(&RegistryPath, Path, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-VOID
-RegistryTeardown(
-    VOID
-    )
-{
-    RtlFreeUnicodeString(&RegistryPath);
-    RegistryPath.Buffer = NULL;
-    RegistryPath.MaximumLength = RegistryPath.Length = 0;
-}
-
-NTSTATUS
-RegistryOpenKey(
-    IN  HANDLE          Parent,
-    IN  PUNICODE_STRING Path,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    OBJECT_ATTRIBUTES   Attributes;
-    NTSTATUS            status;
-
-    InitializeObjectAttributes(&Attributes,
-                               Path,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Parent,
-                               NULL);
-
-    status = ZwOpenKey(Key,
-                       DesiredAccess,
-                       &Attributes);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenServiceKey(
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    return RegistryOpenKey(NULL, &RegistryPath, DesiredAccess, Key);
-}
-
-NTSTATUS
-RegistryOpenSoftwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    )
-{
-    NTSTATUS            status;
-
-    status = IoOpenDeviceRegistryKey(DeviceObject,
-                                     PLUGPLAY_REGKEY_DRIVER,
-                                     DesiredAccess,
-                                     Key);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenHardwareKey(
-    IN  PDEVICE_OBJECT      DeviceObject,
-    IN  ACCESS_MASK         DesiredAccess,
-    OUT PHANDLE             Key
-    )
-{
-    HANDLE                  SubKey;
-    ULONG                   Length;
-    PKEY_NAME_INFORMATION   Info;
-    PWCHAR                  Cursor;
-    UNICODE_STRING          Unicode;
-    NTSTATUS                status;
-
-    status = IoOpenDeviceRegistryKey(DeviceObject,
-                                     PLUGPLAY_REGKEY_DEVICE,
-                                     KEY_READ,
-                                     &SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    Length = 0;
-    (VOID) ZwQueryKey(SubKey,
-                      KeyNameInformation,
-                      NULL,
-                      0,
-                      &Length);
-
-    status = STATUS_INVALID_PARAMETER;
-    if (Length == 0)
-        goto fail2;
-    
-    Info = __RegistryAllocate(Length + sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Info == NULL)
-        goto fail3;
-
-    status = ZwQueryKey(SubKey,
-                        KeyNameInformation,
-                        Info,
-                        Length,
-                        &Length);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    Info->Name[Info->NameLength / sizeof (WCHAR)] = '\0';
-
-    Cursor = wcsrchr(Info->Name, L'\\');
-    ASSERT(Cursor != NULL);
-
-    *Cursor = L'\0';
-    
-    RtlInitUnicodeString(&Unicode, Info->Name);
-
-    status = RegistryOpenKey(NULL, &Unicode, DesiredAccess, Key);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    __RegistryFree(Info);
-
-    RegistryCloseKey(SubKey);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Info);
-
-fail3:
-fail2:
-    RegistryCloseKey(SubKey);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryOpenSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         SubKey
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryOpenKey(Key, &Unicode, DesiredAccess, SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryCreateSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Options,
-    OUT PHANDLE         SubKey
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    OBJECT_ATTRIBUTES   Attributes;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    InitializeObjectAttributes(&Attributes,
-                               &Unicode,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Key,
-                               NULL);
-
-    status = ZwCreateKey(SubKey,
-                         KEY_ALL_ACCESS,
-                         &Attributes,
-                         0,
-                         NULL,
-                         Options,
-                         NULL
-                         );
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryDeleteSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    HANDLE              SubKey;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryOpenKey(Key, &Unicode, KEY_ALL_ACCESS, &SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = ZwDeleteKey(SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    ZwClose(SubKey);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    ZwClose(SubKey);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryEnumerateSubKeys(
-    IN  HANDLE              Key,
-    IN  NTSTATUS            (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID               Context
-    )
-{
-    ULONG                   Size;
-    NTSTATUS                status;
-    PKEY_FULL_INFORMATION   Full;
-    PKEY_BASIC_INFORMATION  Basic;
-    ULONG                   Index;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    Full = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Full == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        Full,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Size = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) +
-           Full->MaxNameLen;
-
-    Basic = __RegistryAllocate(Size);
-    status = STATUS_NO_MEMORY;
-    if (Basic == NULL)
-        goto fail4;
-
-    for (Index = 0; Index < Full->SubKeys; Index++) {
-        UNICODE_STRING  Unicode;
-        ANSI_STRING     Ansi;
-
-        status = ZwEnumerateKey(Key,
-                                Index,
-                                KeyBasicInformation,
-                                Basic,
-                                Size,
-                                &Size);
-        if (!NT_SUCCESS(status))
-            goto fail5;
-
-        Unicode.MaximumLength = (USHORT)Basic->NameLength;
-        Unicode.Buffer = Basic->Name;
-        Unicode.Length = (USHORT)Basic->NameLength;
-
-        Ansi.MaximumLength = (USHORT)((Basic->NameLength / sizeof (WCHAR)) + sizeof (CHAR));
-        Ansi.Buffer = __RegistryAllocate(Ansi.MaximumLength);
-
-        status = STATUS_NO_MEMORY;
-        if (Ansi.Buffer == NULL)
-            goto fail6;
-
-        status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi.Length = (USHORT)(strlen(Ansi.Buffer) * sizeof (CHAR));        
-
-        status = Callback(Context, Key, Ansi.Buffer);
-
-        __RegistryFree(Ansi.Buffer);
-        Ansi.Buffer = NULL;
-
-        if (!NT_SUCCESS(status))
-            goto fail7;
-    }
-
-    __RegistryFree(Basic);
-
-    __RegistryFree(Full);
-
-    return STATUS_SUCCESS;
-
-fail7:
-fail6:
-fail5:
-    __RegistryFree(Basic);
-
-fail4:
-fail3:
-    __RegistryFree(Full);
-    
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryEnumerateValues(
-    IN  HANDLE                      Key,
-    IN  NTSTATUS                    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID                       Context
-    )
-{
-    ULONG                           Size;
-    NTSTATUS                        status;
-    PKEY_FULL_INFORMATION           Full;
-    PKEY_VALUE_BASIC_INFORMATION    Basic;
-    ULONG                           Index;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    Full = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Full == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyFullInformation,
-                        Full,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) +
-           Full->MaxValueNameLen;
-
-    Basic = __RegistryAllocate(Size);
-    status = STATUS_NO_MEMORY;
-    if (Basic == NULL)
-        goto fail4;
-
-    for (Index = 0; Index < Full->Values; Index++) {
-        UNICODE_STRING  Unicode;
-        ANSI_STRING     Ansi;
-
-        status = ZwEnumerateValueKey(Key,
-                                     Index,
-                                     KeyValueBasicInformation,
-                                     Basic,
-                                     Size,
-                                     &Size);
-        if (!NT_SUCCESS(status))
-            goto fail5;
-
-        Unicode.MaximumLength = (USHORT)Basic->NameLength;
-        Unicode.Buffer = Basic->Name;
-        Unicode.Length = (USHORT)Basic->NameLength;
-
-        Ansi.MaximumLength = (USHORT)((Basic->NameLength / sizeof (WCHAR)) + sizeof (CHAR));
-        Ansi.Buffer = __RegistryAllocate(Ansi.MaximumLength);
-
-        status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi.Length = (USHORT)(strlen(Ansi.Buffer) * sizeof (CHAR));        
-
-        status = Callback(Context, Key, Ansi.Buffer);
-
-        __RegistryFree(Ansi.Buffer);
-
-        if (!NT_SUCCESS(status))
-            goto fail6;
-    }
-
-    __RegistryFree(Basic);
-
-    __RegistryFree(Full);
-
-    return STATUS_SUCCESS;
-
-fail6:
-fail5:
-    __RegistryFree(Basic);
-
-fail4:
-fail3:
-    __RegistryFree(Full);
-    
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryDeleteValue(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = ZwDeleteValueKey(Key, &Unicode);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQueryDwordValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    OUT PULONG                      Value
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    ULONG                           Size;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             NULL,
-                             0,
-                             &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail2;
-
-    Partial = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail3;
-
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             Partial,
-                             Size,
-                             &Size);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = STATUS_INVALID_PARAMETER;
-    if (Partial->Type != REG_DWORD ||
-        Partial->DataLength != sizeof (ULONG))
-        goto fail5;
-
-    *Value = *(PULONG)Partial->Data;            
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Partial);
-
-fail3:
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryUpdateDwordValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    IN  ULONG                       Value
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                                 sizeof (ULONG));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail2;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_DWORD;
-    Partial->DataLength = sizeof (ULONG);
-    *(PULONG)Partial->Data = Value;            
-
-    status = ZwSetValueKey(Key,
-                           &Unicode,
-                           Partial->TitleIndex,
-                           Partial->Type,
-                           Partial->Data,
-                           Partial->DataLength);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    __RegistryFree(Partial);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-
-    return status;
-}
-
-static PANSI_STRING
-RegistrySzToAnsi(
-    IN  PWCHAR      Buffer
-    )
-{
-    PANSI_STRING    Ansi;
-    ULONG           Length;
-    UNICODE_STRING  Unicode;
-    NTSTATUS        status;
-
-    Ansi = __RegistryAllocate(sizeof (ANSI_STRING) * 2);
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi == NULL)
-        goto fail1;
-
-    Length = (ULONG)wcslen(Buffer);
-    Ansi[0].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-    Ansi[0].Buffer = __RegistryAllocate(Ansi[0].MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi[0].Buffer == NULL)
-        goto fail2;
-
-    RtlInitUnicodeString(&Unicode, Buffer);
-    status = RtlUnicodeStringToAnsiString(&Ansi[0], &Unicode, FALSE);
-    ASSERT(NT_SUCCESS(status));
-
-    Ansi[0].Length = (USHORT)Length * sizeof (CHAR);
-
-    return Ansi;
-
-fail2:
-    __RegistryFree(Ansi);
-
-fail1:
-    return NULL;
-}
-
-static PANSI_STRING
-RegistryMultiSzToAnsi(
-    IN  PWCHAR      Buffer
-    )
-{
-    PANSI_STRING    Ansi;
-    LONG            Index;
-    LONG            Count;
-    NTSTATUS        status;
-
-    Index = 0;
-    Count = 0;
-    for (;;) {
-        ULONG   Length;
-
-        Length = (ULONG)wcslen(&Buffer[Index]);
-        if (Length == 0)
-            break;
-
-        Index += Length + 1;
-        Count++;
-    }
-
-    Ansi = __RegistryAllocate(sizeof (ANSI_STRING) * (Count + 1));
-
-    status = STATUS_NO_MEMORY;
-    if (Ansi == NULL)
-        goto fail1;
-
-    for (Index = 0; Index < Count; Index++) {
-        ULONG           Length;
-        UNICODE_STRING  Unicode;
-
-        Length = (ULONG)wcslen(Buffer);
-        Ansi[Index].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-        Ansi[Index].Buffer = __RegistryAllocate(Ansi[Index].MaximumLength);
-
-        status = STATUS_NO_MEMORY;
-        if (Ansi[Index].Buffer == NULL)
-            goto fail2;
-
-        RtlInitUnicodeString(&Unicode, Buffer);
-
-        status = RtlUnicodeStringToAnsiString(&Ansi[Index], &Unicode, FALSE);
-        ASSERT(NT_SUCCESS(status));
-
-        Ansi[Index].Length = (USHORT)Length * sizeof (CHAR);
-        Buffer += Length + 1;
-    }
-
-    return Ansi;
-
-fail2:
-    while (--Index >= 0)
-        __RegistryFree(Ansi[Index].Buffer);
-
-    __RegistryFree(Ansi);
-
-fail1:
-    return NULL;
-}
-
-NTSTATUS
-RegistryQuerySzValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    OUT PANSI_STRING                *Array
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    PKEY_VALUE_PARTIAL_INFORMATION  Value;
-    ULONG                           Size;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             NULL,
-                             0,
-                             &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail2;
-
-    Value = __RegistryAllocate(Size);
-
-    status = STATUS_NO_MEMORY;
-    if (Value == NULL)
-        goto fail3;
-
-    status = ZwQueryValueKey(Key,
-                             &Unicode,
-                             KeyValuePartialInformation,
-                             Value,
-                             Size,
-                             &Size);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    switch (Value->Type) {
-    case REG_SZ:
-        status = STATUS_NO_MEMORY;
-        *Array = RegistrySzToAnsi((PWCHAR)Value->Data);
-        break;
-
-    case REG_MULTI_SZ:
-        status = STATUS_NO_MEMORY;
-        *Array = RegistryMultiSzToAnsi((PWCHAR)Value->Data);
-        break;
-
-    default:
-        status = STATUS_INVALID_PARAMETER;
-        *Array = NULL;
-        break;
-    }
-
-    if (*Array == NULL)
-        goto fail5;
-
-    __RegistryFree(Value);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail5:
-fail4:
-    __RegistryFree(Value);
-
-fail3:
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQueryKeyName(
-    IN  HANDLE              Key,
-    OUT PANSI_STRING        *Array
-    )
-{
-    PKEY_NAME_INFORMATION   Value;
-    ULONG                   Size;
-    NTSTATUS                status;
-
-    status = ZwQueryKey(Key,
-                        KeyNameInformation,
-                        NULL,
-                        0,
-                        &Size);
-    if (status != STATUS_BUFFER_TOO_SMALL)
-        goto fail1;
-
-    // Name information is not intrinsically NULL terminated
-    Value = __RegistryAllocate(Size + sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Value == NULL)
-        goto fail2;
-
-    status = ZwQueryKey(Key,
-                        KeyNameInformation,
-                        Value,
-                        Size,
-                        &Size);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Value->Name[Value->NameLength / sizeof (WCHAR)] = L'\0';
-    *Array = RegistrySzToAnsi((PWCHAR)Value->Name);
-
-    status = STATUS_NO_MEMORY;
-    if (*Array == NULL)
-        goto fail4;
-
-    __RegistryFree(Value);
-
-    return STATUS_SUCCESS;
-
-fail4:
-fail3:
-    __RegistryFree(Value);
-
-fail2:
-fail1:
-    return status;
-}
-
-NTSTATUS
-RegistryQuerySystemStartOption(
-    IN  PCHAR                       Prefix,
-    OUT PANSI_STRING                *Value
-    )
-{
-    UNICODE_STRING                  Unicode;
-    HANDLE                          Key;
-    PANSI_STRING                    Ansi;
-    ULONG                           Length;
-    PCHAR                           Option;
-    PCHAR                           Context;
-    NTSTATUS                        status;
-
-    RtlInitUnicodeString(&Unicode, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control");
-    
-    status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &Key);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryQuerySzValue(Key, "SystemStartOptions", &Ansi);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    // SystemStartOptions is a space separated list of options.
-    // Scan it looking for the one we want.
-    Length = (ULONG)strlen(Prefix);
-
-    Option = __strtok_r(Ansi[0].Buffer, " ", &Context);
-    if (strncmp(Prefix, Option, Length) == 0)
-        goto found;
-
-    while ((Option = __strtok_r(NULL, " ", &Context)) != NULL)
-        if (strncmp(Prefix, Option, Length) == 0)
-            goto found;
-
-    status = STATUS_OBJECT_NAME_NOT_FOUND;
-    goto fail3;
-
-found:
-    *Value = __RegistryAllocate(sizeof (ANSI_STRING) * 2);
-
-    status = STATUS_NO_MEMORY;
-    if (*Value == NULL)
-        goto fail4;
-
-    Length = (ULONG)strlen(Option);
-    (*Value)[0].MaximumLength = (USHORT)(Length + 1) * sizeof (CHAR);
-    (*Value)[0].Buffer = __RegistryAllocate((*Value)[0].MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if ((*Value)[0].Buffer == NULL)
-        goto fail5;
-
-    RtlCopyMemory((*Value)[0].Buffer, Option, Length * sizeof (CHAR));
-
-    (*Value)[0].Length = (USHORT)Length * sizeof (CHAR);
-
-    RegistryFreeSzValue(Ansi);
-
-    ZwClose(Key);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    __RegistryFree(*Value);
-
-fail4:
-fail3:
-    RegistryFreeSzValue(Ansi);
-
-fail2:
-    ZwClose(Key);
-
-fail1:
-    return status;
-}
-
-static PKEY_VALUE_PARTIAL_INFORMATION
-RegistryAnsiToSz(
-    PANSI_STRING                    Ansi
-    )
-{
-    ULONG                           Length;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    UNICODE_STRING                  Unicode;
-    NTSTATUS                        status;
-
-    Length = Ansi->Length + 1;
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                                 Length * sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail1;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_SZ;
-    Partial->DataLength = Length * sizeof (WCHAR);
-
-    Unicode.MaximumLength = (UCHAR)Partial->DataLength;
-    Unicode.Buffer = (PWCHAR)Partial->Data;
-    Unicode.Length = 0;
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, Ansi, FALSE);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    return Partial;
-
-fail2:
-    __RegistryFree(Partial);
-
-fail1:
-    return NULL;
-}
-
-static PKEY_VALUE_PARTIAL_INFORMATION
-RegistryAnsiToMultiSz(
-    PANSI_STRING                    Ansi
-    )
-{
-    ULONG                           Length;
-    ULONG                           Index;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    UNICODE_STRING                  Unicode;
-    NTSTATUS                        status;
-
-    Length = 1;
-    for (Index = 0; Ansi[Index].Buffer != NULL; Index++)
-        Length += Ansi[Index].Length + 1;
-
-    Partial = __RegistryAllocate(FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
-                               Length * sizeof (WCHAR));
-
-    status = STATUS_NO_MEMORY;
-    if (Partial == NULL)
-        goto fail1;
-
-    Partial->TitleIndex = 0;
-    Partial->Type = REG_MULTI_SZ;
-    Partial->DataLength = Length * sizeof (WCHAR);
-
-    Unicode.MaximumLength = (USHORT)Partial->DataLength;
-    Unicode.Buffer = (PWCHAR)Partial->Data;
-    Unicode.Length = 0;
-
-    for (Index = 0; Ansi[Index].Buffer != NULL; Index++) {
-        status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi[Index], FALSE);
-        if (!NT_SUCCESS(status))
-            goto fail2;
-
-        Length = Unicode.Length / sizeof (WCHAR);
-
-        ASSERT3U(Unicode.MaximumLength, >=, (Length + 1) * sizeof (WCHAR));
-        Unicode.MaximumLength -= (USHORT)((Length + 1) * sizeof (WCHAR));
-        Unicode.Buffer += Length + 1;
-        Unicode.Length = 0;
-    }
-    *Unicode.Buffer = L'\0';
-
-    return Partial;
-
-fail2:
-    __RegistryFree(Partial);
-
-fail1:
-    return NULL;
-}
-
-NTSTATUS
-RegistryUpdateSzValue(
-    IN  HANDLE                      Key,
-    IN  PCHAR                       Name,
-    IN  ULONG                       Type,
-    ...
-    )
-{
-    ANSI_STRING                     Ansi;
-    UNICODE_STRING                  Unicode;
-    va_list                         Arguments;
-    PKEY_VALUE_PARTIAL_INFORMATION  Partial;
-    NTSTATUS                        status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-        
-    va_start(Arguments, Type);
-    switch (Type) {
-    case REG_SZ: {
-        PANSI_STRING    Argument;
-
-        Argument = va_arg(Arguments, PANSI_STRING);
-
-        status = STATUS_NO_MEMORY;
-        Partial = RegistryAnsiToSz(Argument);        
-        break;
-    }
-    case REG_MULTI_SZ: {
-        PANSI_STRING    Argument;
-
-        Argument = va_arg(Arguments, PANSI_STRING);
-
-        status = STATUS_NO_MEMORY;
-        Partial = RegistryAnsiToMultiSz(Argument);        
-        break;
-    }
-    default:
-        status = STATUS_INVALID_PARAMETER;
-        Partial = NULL;
-        break;
-    }
-    va_end(Arguments);
-
-    if (Partial == NULL)
-        goto fail2;
-
-    status = ZwSetValueKey(Key,
-                           &Unicode,
-                           Partial->TitleIndex,
-                           Partial->Type,
-                           Partial->Data,
-                           Partial->DataLength);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    __RegistryFree(Partial);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    __RegistryFree(Partial);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-VOID
-RegistryFreeSzValue(
-    IN  PANSI_STRING    Array
-    )
-{
-    ULONG               Index;
-
-    if (Array == NULL)
-        return;
-
-    for (Index = 0; Array[Index].Buffer != NULL; Index++)
-        __RegistryFree(Array[Index].Buffer);
-
-    __RegistryFree(Array);
-}
-
-VOID
-RegistryCloseKey(
-    IN  HANDLE  Key
-    )
-{
-    ZwClose(Key);
-}
diff --git a/src/xennet/registry.h b/src/xennet/registry.h
deleted file mode 100644
index 7d7dc01..0000000
--- a/src/xennet/registry.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, 
- * with or without modification, are permitted provided 
- * that the following conditions are met:
- * 
- * *   Redistributions of source code must retain the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above 
- *     copyright notice, this list of conditions and the 
- *     following disclaimer in the documentation and/or other 
- *     materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE.
- */
-
-#ifndef _XENNET_REGISTRY_H
-#define _XENNET_REGISTRY_H
-
-#include <ntddk.h>
-
-extern NTSTATUS
-RegistryInitialize(
-    IN PUNICODE_STRING  Path
-    );
-
-extern VOID
-RegistryTeardown(
-    VOID
-    );
-
-extern NTSTATUS
-RegistryOpenKey(
-    IN  HANDLE          Parent,
-    IN  PUNICODE_STRING Path,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenServiceKey(
-    IN  ACCESS_MASK DesiredAccess,
-    OUT PHANDLE     Key
-    );
-
-extern NTSTATUS
-RegistryOpenSoftwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenHardwareKey(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  ACCESS_MASK     DesiredAccess,
-    OUT PHANDLE         Key
-    );
-
-extern NTSTATUS
-RegistryOpenSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name,
-    IN  ACCESS_MASK DesiredAccess,
-    OUT PHANDLE     SubKey
-    );
-
-extern NTSTATUS
-RegistryCreateSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name,
-    IN  ULONG       Options,
-    OUT PHANDLE     SubKey
-    );
-
-extern NTSTATUS
-RegistryDeleteSubKey(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name
-    );
-
-extern NTSTATUS
-RegistryEnumerateSubKeys(
-    IN  HANDLE      Key,
-    IN  NTSTATUS    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID       Context
-    );
-
-extern NTSTATUS
-RegistryEnumerateValues(
-    IN  HANDLE      Key,
-    IN  NTSTATUS    (*Callback)(PVOID, HANDLE, PCHAR),
-    IN  PVOID       Context
-    );
-
-extern NTSTATUS
-RegistryDeleteValue(
-    IN  HANDLE      Key,
-    IN  PCHAR       Name
-    );
-
-extern NTSTATUS
-RegistryQueryDwordValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    OUT PULONG          Value
-    );
-    
-extern NTSTATUS
-RegistryUpdateDwordValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Value
-    );
-    
-extern NTSTATUS
-RegistryQuerySzValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    OUT PANSI_STRING    *Array
-    );
-
-extern NTSTATUS
-RegistryQueryKeyName(
-    IN  HANDLE              Key,
-    OUT PANSI_STRING        *Array
-    );
-
-extern NTSTATUS
-RegistryQuerySystemStartOption(
-    IN  PCHAR           Name,
-    OUT PANSI_STRING    *Option
-    );
-
-extern VOID
-RegistryFreeSzValue(
-    IN  PANSI_STRING    Array
-    );
-
-extern NTSTATUS
-RegistryUpdateSzValue(
-    IN  HANDLE          Key,
-    IN  PCHAR           Name,
-    IN  ULONG           Type,
-    ...
-    );
-
-extern VOID
-RegistryCloseKey(
-    IN  HANDLE  Key
-    );
-
-#endif  // _XENNET_REGISTRY_H
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index db07e9b..aab91d2 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -83,7 +83,6 @@
 		<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
 	</ItemGroup>
 	<ItemGroup>
-		<ClCompile Include="../../src/xennet/registry.c" />
 		<ClCompile Include="../../src/xennet/adapter.c" />
 		<ClCompile Include="../../src/xennet/main.c" />
 		<ClCompile Include="../../src/xennet/miniport.c" />
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index 0d98f3a..9401b99 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -114,7 +114,6 @@
     <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="../../src/xennet/registry.c" />
     <ClCompile Include="../../src/xennet/adapter.c" />
     <ClCompile Include="../../src/xennet/main.c" />
     <ClCompile Include="../../src/xennet/miniport.c" />
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:21:43 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:21:43 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1elj-0004Zs-2g; Thu, 18 Dec 2014 17:21:43 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1elh-0004Zn-RQ
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:21:42 +0000
Received: from [193.109.254.147] by server-11.bemta-14.messagelabs.com id
	70/3E-02696-52D03945; Thu, 18 Dec 2014 17:21:41 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418923298!16005691!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14434 invoked from network); 18 Dec 2014 17:21:40 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:21:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206356808"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:32 +0000
Message-ID: <1418921673-6008-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 5/6] Switch to VIF interface V2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  94 ++++++++-
 src/coinst/coinst.c      |   5 +-
 src/xennet.inf           |   6 +-
 src/xennet/adapter.c     |   7 +-
 src/xennet/driver.c      | 533 +++++++++++++++++++++++++++++++++++++++++++++++
 src/xennet/transmitter.c | 205 ++++++++++++------
 src/xennet/transmitter.h |   9 +-
 7 files changed, 780 insertions(+), 79 deletions(-)
 create mode 100644 src/xennet/driver.c

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..d083fd1 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -257,7 +257,7 @@ struct _XENVIF_TRANSMITTER_PACKET_V1 {
     };
 };
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET_V1, *PXENVIF_TRANSMITTER_PACKET_V1;
 
 #pragma warning(pop)
 
@@ -265,6 +265,30 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V2
+    \brief Transmit-side packet structure (v2)
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Hash value set by subscriber */
+    ULONG                                       Value;
+    /*! Packet information passed from subscriber to provider */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Packet information passed from provider to subscriber on packet return */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+    /*! Packet data MDL */
+    PMDL                                        Mdl;
+    /*! Offset into MDL to start of packet */
+    ULONG                                       Offset;
+    /*! Packet length */
+    ULONG                                       Length;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET pointer
@@ -474,16 +498,44 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+    \brief Get the packet headers into supplied buffer
+
+    \param Interface The interface header
+    \param Packet The packet to acquire headers for.
+    \param Headers The buffer to receive headers.
+    \param Info The offsets into Headers for relevant headers
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE                  Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
     \brief Queue transmit side packets at the provider
 
     \param Interface The interface header
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of _XENVIF_TRANSMITTER_PACKET_V1
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \param List List of _XENVIF_TRANSMITTER_PACKET_V2
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)(
+    IN  PINTERFACE  Interface,
+    IN  PLIST_ENTRY List
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -708,7 +760,37 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \struct _XENVIF_VIF_INTERFACE_V2
+    \brief VIF interface version 2
+    \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V2 {
+    INTERFACE                                       Interface;
+    XENVIF_VIF_ACQUIRE                              Acquire;
+    XENVIF_VIF_RELEASE                              Release;
+    XENVIF_VIF_ENABLE                               Enable;
+    XENVIF_VIF_DISABLE                              Disable;
+    XENVIF_VIF_QUERY_STATISTIC                      QueryStatistic;
+    XENVIF_VIF_RECEIVER_RETURN_PACKETS              ReceiverReturnPackets;
+    XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
+    XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
+    XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
+    XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
+    XENVIF_VIF_MAC_QUERY_STATE                      MacQueryState;
+    XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE         MacQueryMaximumFrameSize;
+    XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS          MacQueryPermanentAddress;
+    XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS            MacQueryCurrentAddress;
+    XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES        MacQueryMulticastAddresses;
+    XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
+    XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
+    XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
     \brief Macro at assist in method invocation
@@ -719,6 +801,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
 #endif  // _WINDLL
 
 #define XENVIF_VIF_INTERFACE_VERSION_MIN    1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX    1
+#define XENVIF_VIF_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENVIF_INTERFACE_H
diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 265f348..540d51d 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -45,6 +45,7 @@
 #include <stdarg.h>
 #include <assert.h>
 #include <vif_interface.h>
+#include <cache_interface.h>
 
 #include <tcpip.h>
 #include <version.h>
@@ -2165,7 +2166,7 @@ RegisterInterface(
                           InterfaceName,
                           0,
                           REG_DWORD,
-                          (const BYTE *)InterfaceVersion,
+                          (const BYTE *)&InterfaceVersion,
                           sizeof(DWORD));
     if (Error != ERROR_SUCCESS) {
         SetLastError(Error);
@@ -2335,6 +2336,7 @@ __DifInstallPostProcess(
         goto fail5;
 
     RegisterInterface("XENVIF", "VIF", XENVIF_VIF_INTERFACE_VERSION_MAX);
+    RegisterInterface("XENBUS", "CACHE", XENBUS_CACHE_INTERFACE_VERSION_MAX);
 
     if (SoftwareKeyName != NULL) {
         (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
@@ -2417,6 +2419,7 @@ __DifRemovePreProcess(
     Log("====>");
 
     (VOID) DeregisterAllInterfaces("XENVIF");
+    (VOID) DeregisterAllInterfaces("XENBUS");
     (VOID) RemoveUnplugService("NICS", "XENNET");
     (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
diff --git a/src/xennet.inf b/src/xennet.inf
index d99ffed..1adf079 100644
--- a/src/xennet.inf
+++ b/src/xennet.inf
@@ -61,9 +61,9 @@ xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll
 ; DisplayName		Section		DeviceID
 ; -----------		-------		--------
 
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XSC000&DEV_NET&REV_00000001
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0001&DEV_NET&REV_00000001
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0002&DEV_NET&REV_00000001
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XSC000&DEV_NET&REV_00000002
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0001&DEV_NET&REV_00000002
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0002&DEV_NET&REV_00000002
 
 [XenNet_Inst] 
 Characteristics=0x84
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index 2f10b35..24cf4a0 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -164,11 +164,11 @@ AdapterVifCallback(
 
     switch (Type) {
     case XENVIF_TRANSMITTER_RETURN_PACKETS: {
-        PXENVIF_TRANSMITTER_PACKET HeadPacket;
+        PLIST_ENTRY List;
 
-        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+        List = va_arg(Arguments, PLIST_ENTRY);
 
-        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+        TransmitterCompletePackets(Adapter->Transmitter, List);
         break;
     }
     case XENVIF_RECEIVER_QUEUE_PACKETS: {
@@ -964,7 +964,6 @@ AdapterEnable(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    TransmitterEnable(Adapter->Transmitter);
     Adapter->Enabled = TRUE;
 
     return NDIS_STATUS_SUCCESS;
diff --git a/src/xennet/driver.c b/src/xennet/driver.c
new file mode 100644
index 0000000..cfa5cdd
--- /dev/null
+++ b/src/xennet/driver.c
@@ -0,0 +1,533 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#define INITGUID 1
+
+#include <ndis.h>
+#include "adapter.h"
+#include <version.h>
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENNET_DRIVER {
+    NDIS_HANDLE             MiniportHandle;
+} XENNET_DRIVER;
+
+static XENNET_DRIVER Driver;
+
+extern PULONG InitSafeBootMode;
+
+MINIPORT_CANCEL_OID_REQUEST __AdapterCancelOidRequest;
+VOID
+__AdapterCancelOidRequest(
+    IN  NDIS_HANDLE     Handle,
+    IN  PVOID           Request
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Request);
+}
+
+MINIPORT_CANCEL_SEND    __AdapterCancelSendNetBufferLists;
+VOID
+__AdapterCancelSendNetBufferLists(
+    IN  NDIS_HANDLE     Handle,
+    IN  PVOID           Cancel
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Cancel);
+}
+
+MINIPORT_CHECK_FOR_HANG __AdapterCheckForHang;
+BOOLEAN
+__AdapterCheckForHang(
+    IN  NDIS_HANDLE     Handle
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    return FALSE;
+}
+
+MINIPORT_INITIALIZE __AdapterInitialize;
+NDIS_STATUS 
+__AdapterInitialize(
+    IN  NDIS_HANDLE     Handle,
+    IN  NDIS_HANDLE     DriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS  Params
+    )
+{
+    PXENNET_ADAPTER     Adapter;
+    NDIS_STATUS         ndisStatus;
+
+    UNREFERENCED_PARAMETER(DriverContext);
+    UNREFERENCED_PARAMETER(Params);
+
+    ndisStatus = AdapterInitialize(Handle, &Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
+
+    return ndisStatus;
+
+fail1:
+    Error("fail1\n");
+    return ndisStatus;
+}
+
+MINIPORT_HALT   __AdapterHalt;
+VOID 
+__AdapterHalt(
+    IN  NDIS_HANDLE     Handle,
+    IN  NDIS_HALT_ACTION    Action
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Action);
+
+    if (Adapter == NULL)
+        return;
+
+    (VOID) AdapterDisable(Adapter);
+
+    AdapterTeardown(Adapter);
+}
+
+MINIPORT_OID_REQUEST    __AdapterOidRequest;
+NDIS_STATUS
+__AdapterOidRequest(
+    IN  NDIS_HANDLE         Handle,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    NDIS_STATUS         ndisStatus;
+
+    switch (Request->RequestType) {
+        case NdisRequestSetInformation:
+            ndisStatus = AdapterSetInformation(Adapter, Request);
+            break;
+
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            ndisStatus = AdapterQueryInformation(Adapter, Request);
+            break;
+
+        default:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
+
+    return ndisStatus;
+}
+
+MINIPORT_PAUSE  __AdapterPause;
+NDIS_STATUS
+__AdapterPause(
+    IN  NDIS_HANDLE     Handle,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS Params
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Params);
+
+    if (AdapterDisable(Adapter))
+        AdapterMediaStateChange(Adapter);
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_DEVICE_PNP_EVENT_NOTIFY    __AdapterPnPEventHandler;
+VOID
+__AdapterPnPEventHandler(
+    IN  NDIS_HANDLE     Handle,
+    IN  PNET_DEVICE_PNP_EVENT   Event
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Event);
+}
+
+MINIPORT_RESET  __AdapterReset;
+NDIS_STATUS
+__AdapterReset(
+    IN  NDIS_HANDLE     Handle,
+    OUT PBOOLEAN        AddressingReset
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+
+    *AddressingReset = FALSE;
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_RESTART    __AdapterRestart;
+NDIS_STATUS
+__AdapterRestart(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   Params
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Params);
+
+    return AdapterEnable(Adapter);
+}
+
+MINIPORT_RETURN_NET_BUFFER_LISTS    __AdapterReturnNetBufferLists;
+VOID
+__AdapterReturnNetBufferLists(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    PXENNET_RECEIVER    Receiver = AdapterGetReceiver(Adapter);
+
+    ReceiverReturnNetBufferLists(Receiver,
+                                 NetBufferLists,
+                                 ReturnFlags);
+}
+
+MINIPORT_SEND_NET_BUFFER_LISTS  __AdapterSendNetBufferLists;
+VOID
+__AdapterSendNetBufferLists(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    PXENNET_TRANSMITTER Transmitter = AdapterGetTransmitter(Adapter);
+
+    TransmitterSendNetBufferLists(Transmitter,
+                                  NetBufferList,
+                                  PortNumber,
+                                  SendFlags);
+}
+
+MINIPORT_SHUTDOWN   __AdapterShutdown;
+VOID
+__AdapterShutdown(
+    IN  NDIS_HANDLE             Handle,
+    IN  NDIS_SHUTDOWN_ACTION    Action
+    )
+{
+    PXENNET_ADAPTER Adapter = (PXENNET_ADAPTER)Handle;
+
+    if (Action != NdisShutdownBugCheck)
+        AdapterDisable(Adapter);
+}
+
+typedef struct _XENNET_CONTEXT {
+    PDEVICE_CAPABILITIES    Capabilities;
+    PIO_COMPLETION_ROUTINE  CompletionRoutine;
+    PVOID                   CompletionContext;
+    UCHAR                   CompletionControl;
+} XENNET_CONTEXT, *PXENNET_CONTEXT;
+
+static NTSTATUS (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+static NTSTATUS
+__QueryCapabilities(
+    IN  PDEVICE_OBJECT      DeviceObject,
+    IN  PIRP                Irp,
+    IN  PVOID               _Context
+    )
+{
+    PXENNET_CONTEXT         Context = _Context;
+    NTSTATUS                status;
+
+    Context->Capabilities->SurpriseRemovalOK = 1;
+
+    if (Context->CompletionRoutine != NULL &&
+        (Context->CompletionControl & SL_INVOKE_ON_SUCCESS))
+        status = Context->CompletionRoutine(DeviceObject, Irp, Context->CompletionContext);
+    else
+        status = STATUS_SUCCESS;
+
+    ExFreePool(Context);
+
+    return status;
+}
+
+NTSTATUS
+QueryCapabilities(
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PIRP                 Irp
+    )
+{
+    PIO_STACK_LOCATION      StackLocation;
+    PXENNET_CONTEXT         Context;
+    NTSTATUS                status;
+
+    Trace("====>\n");
+
+    Trace("%p\n", DeviceObject);
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof (XENNET_CONTEXT), ' TEN');
+    if (Context != NULL) {
+        Context->Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities;
+        Context->CompletionRoutine = StackLocation->CompletionRoutine;
+        Context->CompletionContext = StackLocation->Context;
+        Context->CompletionControl = StackLocation->Control;
+
+        StackLocation->CompletionRoutine = __QueryCapabilities;
+        StackLocation->Context = Context;
+        StackLocation->Control = SL_INVOKE_ON_SUCCESS;
+    }
+
+    status = NdisDispatchPnp(DeviceObject, Irp);
+
+    Trace("<====\n");
+
+    return status;
+}
+
+DRIVER_DISPATCH DispatchPnp;
+
+NTSTATUS
+DispatchPnp(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    UCHAR               MinorFunction;
+    NTSTATUS            status;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    MinorFunction = StackLocation->MinorFunction;
+
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_QUERY_CAPABILITIES:
+        status = QueryCapabilities(DeviceObject, Irp);
+        break;
+
+    default:
+        status = NdisDispatchPnp(DeviceObject, Irp);
+        break;
+    }
+
+    return status;
+}
+
+DRIVER_DISPATCH DispatchFail;
+
+NTSTATUS
+DispatchFail(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+MINIPORT_UNLOAD DriverUnload;
+VOID
+DriverUnload(
+    IN  PDRIVER_OBJECT  DriverObject
+    )
+{
+    UNREFERENCED_PARAMETER(DriverObject);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        goto done;
+
+    if (Driver.MiniportHandle)
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+done:
+    Trace("<====\n");
+}
+
+DRIVER_INITIALIZE       DriverEntry;
+
+NTSTATUS
+DriverEntry (
+    IN  PDRIVER_OBJECT  DriverObject,
+    IN  PUNICODE_STRING RegistryPath
+    )
+{
+    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_DRIVER_CHARACTERISTICS mpChars;
+    NDIS_CONFIGURATION_OBJECT ConfigurationObject;
+    NDIS_HANDLE ConfigurationHandle;
+    NDIS_STRING ParameterName;
+    PNDIS_CONFIGURATION_PARAMETER ParameterValue;
+    ULONG FailCreateClose;
+    ULONG FailDeviceControl;
+
+    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        return NDIS_STATUS_SUCCESS;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    //
+    // Register miniport with NDIS.
+    //
+
+    NdisZeroMemory(&mpChars, sizeof(mpChars));
+    mpChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
+    mpChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
+    mpChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
+
+    mpChars.MajorNdisVersion = 6;
+    mpChars.MinorNdisVersion = 0;
+    mpChars.MajorDriverVersion = MAJOR_VERSION;
+    mpChars.MinorDriverVersion = MINOR_VERSION;
+
+    mpChars.CancelOidRequestHandler = __AdapterCancelOidRequest;
+    mpChars.CancelSendHandler = __AdapterCancelSendNetBufferLists;
+    mpChars.CheckForHangHandlerEx = __AdapterCheckForHang;
+    mpChars.InitializeHandlerEx = __AdapterInitialize;
+    mpChars.HaltHandlerEx = __AdapterHalt;
+    mpChars.OidRequestHandler = __AdapterOidRequest;
+    mpChars.PauseHandler = __AdapterPause;
+    mpChars.DevicePnPEventNotifyHandler  = __AdapterPnPEventHandler;
+    mpChars.ResetHandlerEx = __AdapterReset;
+    mpChars.RestartHandler = __AdapterRestart;
+    mpChars.ReturnNetBufferListsHandler = __AdapterReturnNetBufferLists;
+    mpChars.SendNetBufferListsHandler = __AdapterSendNetBufferLists;
+    mpChars.ShutdownHandlerEx = __AdapterShutdown;
+    mpChars.UnloadHandler = DriverUnload;
+
+    Driver.MiniportHandle = NULL;
+    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
+                                             RegistryPath,
+                                             NULL,
+                                             &mpChars,
+                                             &Driver.MiniportHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to register miniport.\n", ndisStatus);
+        goto fail;
+    }
+
+    ConfigurationObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.NdisHandle = Driver.MiniportHandle;
+    ConfigurationObject.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to open driver configuration.\n", ndisStatus);
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+        goto fail;
+    }
+
+    RtlInitUnicodeString(&ParameterName, L"FailCreateClose");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailCreateClose = ParameterValue->ParameterData.IntegerData;
+    else
+        FailCreateClose = 0;
+
+    RtlInitUnicodeString(&ParameterName, L"FailDeviceControl");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailDeviceControl = ParameterValue->ParameterData.IntegerData;
+    else
+        FailDeviceControl = 0;
+
+    NdisCloseConfiguration(ConfigurationHandle);
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+    if (FailCreateClose != 0) {
+#pragma prefast(suppress:28168) // No matching__drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
+    }
+
+    if (FailDeviceControl != 0) {
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
+    }
+
+    Trace("<====\n");
+    return ndisStatus;
+
+fail:
+    Error("fail\n");
+    return ndisStatus;
+}
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 0c89f76..c64591d 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -33,22 +33,72 @@
 #include "transmitter.h"
 #include "adapter.h"
 #include <vif_interface.h>
+#include <cache_interface.h>
 #include "dbg_print.h"
 #include "assert.h"
 
 struct _XENNET_TRANSMITTER {
     PXENNET_ADAPTER             Adapter;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+    PXENBUS_CACHE               PacketCache;
+    KSPIN_LOCK                  PacketLock;
 };
 
+#define XENNET_PACKET_CACHE_MIN     32
 #define TRANSMITTER_POOL_TAG        'TteN'
 
+static NTSTATUS
+__TransmitterPacketCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterPacketDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterPacketAcquireLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->PacketLock);
+}
+
+static VOID
+__TransmitterPacketReleaseLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
+}
+
 NDIS_STATUS
 TransmitterInitialize (
     IN  PXENNET_ADAPTER     Adapter,
     OUT PXENNET_TRANSMITTER *Transmitter
     )
 {
+    NTSTATUS                status;
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Adapter);
+
     *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
                                          sizeof(XENNET_TRANSMITTER),
                                          TRANSMITTER_POOL_TAG);
@@ -57,9 +107,28 @@ TransmitterInitialize (
 
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
+    KeInitializeSpinLock(&(*Transmitter)->PacketLock);
+
+    status = XENBUS_CACHE(Create,
+                          CacheInterface,
+                          "packet_cache",
+                          sizeof(XENVIF_TRANSMITTER_PACKET),
+                          XENNET_PACKET_CACHE_MIN,
+                          __TransmitterPacketCtor,
+                          __TransmitterPacketDtor,
+                          __TransmitterPacketAcquireLock,
+                          __TransmitterPacketReleaseLock,
+                          *Transmitter,
+                          &(*Transmitter)->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail2;
     
     return NDIS_STATUS_SUCCESS;
 
+fail2:
+    RtlZeroMemory(&(*Transmitter)->PacketLock, sizeof(KSPIN_LOCK));
+    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
+    *Transmitter = NULL;
 fail1:
     return NDIS_STATUS_FAILURE;
 }
@@ -69,36 +138,54 @@ TransmitterTeardown(
     IN  PXENNET_TRANSMITTER Transmitter
     )
 {
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
     Transmitter->Adapter = NULL;
     Transmitter->OffloadOptions.Value = 0;
+    RtlZeroMemory(&Transmitter->PacketLock, sizeof(KSPIN_LOCK));
+
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
 
     ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
-VOID
-TransmitterEnable(
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+__TransmitterGetPacket(
     IN  PXENNET_TRANSMITTER Transmitter
     )
 {
-    PXENVIF_VIF_INTERFACE   VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    return XENBUS_CACHE(Get,
+                        CacheInterface,
+                        Transmitter->PacketCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET));
+
+    XENBUS_CACHE(Put,
+                 CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 FALSE);
 }
 
 typedef struct _NET_BUFFER_LIST_RESERVED {
@@ -107,13 +194,6 @@ typedef struct _NET_BUFFER_LIST_RESERVED {
 
 C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved));
 
-typedef struct _NET_BUFFER_RESERVED {
-    XENVIF_TRANSMITTER_PACKET   Packet;
-    PNET_BUFFER_LIST            NetBufferList;
-} NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
-
-C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
-
 static VOID
 __TransmitterCompleteNetBufferList(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -140,26 +220,25 @@ __TransmitterCompleteNetBufferList(
                                     NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
 }
 
-
 static VOID
 __TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
-    IN  NDIS_STATUS                 Status
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List,
+    IN  NDIS_STATUS         Status
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
         PNET_BUFFER_LIST            NetBufferList;
         PNET_BUFFER_LIST_RESERVED   ListReserved;
 
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        ListEntry = RemoveHeadList(List);
+        ASSERT3P(ListEntry, !=, List);
 
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
 
-        NetBufferList = Reserved->NetBufferList;
+        NetBufferList = Packet->Cookie;
         ASSERT(NetBufferList != NULL);
 
         ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
@@ -168,7 +247,7 @@ __TransmitterCompletePackets(
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
             __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
 
-        Packet = Next;
+        __TransmitterPutPacket(Transmitter, Packet);
     }    
 }
 
@@ -246,14 +325,12 @@ TransmitterSendNetBufferLists(
     IN  ULONG                   SendFlags
     )
 {
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
+    LIST_ENTRY                  List;
     KIRQL                       Irql;
 
     UNREFERENCED_PARAMETER(PortNumber);
 
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    InitializeListHead(&List);
 
     if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
         ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
@@ -283,23 +360,35 @@ TransmitterSendNetBufferLists(
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
-            PNET_BUFFER_RESERVED        Reserved;
             PXENVIF_TRANSMITTER_PACKET  Packet;
 
-            Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
-            RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
+            Packet = __TransmitterGetPacket(Transmitter);
+            if (Packet == NULL) {
+                while (ListReserved->Reference--) {
+                    PLIST_ENTRY     ListEntry;
+
+                    ListEntry = RemoveTailList(&List);
+                    ASSERT3P(ListEntry, !=, &List);
+
+                    Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+                    
+                    __TransmitterPutPacket(Transmitter, Packet);
+                }
+                __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NDIS_STATUS_NOT_ACCEPTED);
+                break;
+            }
 
-            Reserved->NetBufferList = NetBufferList;
             ListReserved->Reference++;
 
-            Packet = &Reserved->Packet;
+            Packet->Cookie = NetBufferList;
             Packet->Send.OffloadOptions.Value = OffloadOptions.Value & Transmitter->OffloadOptions.Value;
             Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
             Packet->Send.TagControlInformation = TagControlInformation;
+            Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
+            Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
 
-            ASSERT3P(Packet->Next, ==, NULL);
-            *TailPacket = Packet;
-            TailPacket = &Packet->Next;
+            InsertTailList(&List, &Packet->ListEntry);
 
             NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
         }
@@ -307,14 +396,14 @@ TransmitterSendNetBufferLists(
         NetBufferList = ListNext;
     }
 
-    if (HeadPacket != NULL) {
+    if (!IsListEmpty(&List)) {
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
                             AdapterGetVifInterface(Transmitter->Adapter),
-                            HeadPacket);
+                            &List);
         if (!NT_SUCCESS(status))
-            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
+            __TransmitterCompletePackets(Transmitter, &List, NDIS_STATUS_NOT_ACCEPTED);
     }
 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
@@ -322,11 +411,11 @@ TransmitterSendNetBufferLists(
 
 VOID
 TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     )
 {
-    __TransmitterCompletePackets(Transmitter, Packet, NDIS_STATUS_SUCCESS);
+    __TransmitterCompletePackets(Transmitter, List, NDIS_STATUS_SUCCESS);
 }
 
 PXENVIF_VIF_OFFLOAD_OPTIONS
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index f63a2a0..0adebdc 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -49,11 +49,6 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterEnable(
-    IN  PXENNET_TRANSMITTER Transmitter
-    );
-
-extern VOID
 TransmitterSendNetBufferLists (
     IN  PXENNET_TRANSMITTER Transmitter,
     IN  PNET_BUFFER_LIST    NetBufferList,
@@ -63,8 +58,8 @@ TransmitterSendNetBufferLists (
 
 extern VOID
 TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     );
 
 extern PXENVIF_VIF_OFFLOAD_OPTIONS
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:21:43 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:21:43 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1elj-0004Zs-2g; Thu, 18 Dec 2014 17:21:43 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Y1elh-0004Zn-RQ
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:21:42 +0000
Received: from [193.109.254.147] by server-11.bemta-14.messagelabs.com id
	70/3E-02696-52D03945; Thu, 18 Dec 2014 17:21:41 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418923298!16005691!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14434 invoked from network); 18 Dec 2014 17:21:40 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:21:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,601,1413244800"; d="scan'208";a="206356808"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 16:54:32 +0000
Message-ID: <1418921673-6008-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 5/6] Switch to VIF interface V2
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  94 ++++++++-
 src/coinst/coinst.c      |   5 +-
 src/xennet.inf           |   6 +-
 src/xennet/adapter.c     |   7 +-
 src/xennet/driver.c      | 533 +++++++++++++++++++++++++++++++++++++++++++++++
 src/xennet/transmitter.c | 205 ++++++++++++------
 src/xennet/transmitter.h |   9 +-
 7 files changed, 780 insertions(+), 79 deletions(-)
 create mode 100644 src/xennet/driver.c

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..d083fd1 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -257,7 +257,7 @@ struct _XENVIF_TRANSMITTER_PACKET_V1 {
     };
 };
 
-typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET_V1, *PXENVIF_TRANSMITTER_PACKET_V1;
 
 #pragma warning(pop)
 
@@ -265,6 +265,30 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V2
+    \brief Transmit-side packet structure (v2)
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Hash value set by subscriber */
+    ULONG                                       Value;
+    /*! Packet information passed from subscriber to provider */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Packet information passed from provider to subscriber on packet return */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+    /*! Packet data MDL */
+    PMDL                                        Mdl;
+    /*! Offset into MDL to start of packet */
+    ULONG                                       Offset;
+    /*! Packet length */
+    ULONG                                       Length;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET pointer
@@ -474,16 +498,44 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
+    \brief Get the packet headers into supplied buffer
+
+    \param Interface The interface header
+    \param Packet The packet to acquire headers for.
+    \param Headers The buffer to receive headers.
+    \param Info The offsets into Headers for relevant headers
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE                  Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
+    OUT PVOID                       Headers,
+    OUT PXENVIF_PACKET_INFO         Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
     \brief Queue transmit side packets at the provider
 
     \param Interface The interface header
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of _XENVIF_TRANSMITTER_PACKET_V1
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS)(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \param List List of _XENVIF_TRANSMITTER_PACKET_V2
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2)(
+    IN  PINTERFACE  Interface,
+    IN  PLIST_ENTRY List
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -708,7 +760,37 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \struct _XENVIF_VIF_INTERFACE_V2
+    \brief VIF interface version 2
+    \ingroup interfaces
+*/
+struct _XENVIF_VIF_INTERFACE_V2 {
+    INTERFACE                                       Interface;
+    XENVIF_VIF_ACQUIRE                              Acquire;
+    XENVIF_VIF_RELEASE                              Release;
+    XENVIF_VIF_ENABLE                               Enable;
+    XENVIF_VIF_DISABLE                              Disable;
+    XENVIF_VIF_QUERY_STATISTIC                      QueryStatistic;
+    XENVIF_VIF_RECEIVER_RETURN_PACKETS              ReceiverReturnPackets;
+    XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
+    XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
+    XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
+    XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
+    XENVIF_VIF_MAC_QUERY_STATE                      MacQueryState;
+    XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE         MacQueryMaximumFrameSize;
+    XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS          MacQueryPermanentAddress;
+    XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS            MacQueryCurrentAddress;
+    XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES        MacQueryMulticastAddresses;
+    XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
+    XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
+    XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
     \brief Macro at assist in method invocation
@@ -719,6 +801,6 @@ typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTER
 #endif  // _WINDLL
 
 #define XENVIF_VIF_INTERFACE_VERSION_MIN    1
-#define XENVIF_VIF_INTERFACE_VERSION_MAX    1
+#define XENVIF_VIF_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENVIF_INTERFACE_H
diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 265f348..540d51d 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -45,6 +45,7 @@
 #include <stdarg.h>
 #include <assert.h>
 #include <vif_interface.h>
+#include <cache_interface.h>
 
 #include <tcpip.h>
 #include <version.h>
@@ -2165,7 +2166,7 @@ RegisterInterface(
                           InterfaceName,
                           0,
                           REG_DWORD,
-                          (const BYTE *)InterfaceVersion,
+                          (const BYTE *)&InterfaceVersion,
                           sizeof(DWORD));
     if (Error != ERROR_SUCCESS) {
         SetLastError(Error);
@@ -2335,6 +2336,7 @@ __DifInstallPostProcess(
         goto fail5;
 
     RegisterInterface("XENVIF", "VIF", XENVIF_VIF_INTERFACE_VERSION_MAX);
+    RegisterInterface("XENBUS", "CACHE", XENBUS_CACHE_INTERFACE_VERSION_MAX);
 
     if (SoftwareKeyName != NULL) {
         (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
@@ -2417,6 +2419,7 @@ __DifRemovePreProcess(
     Log("====>");
 
     (VOID) DeregisterAllInterfaces("XENVIF");
+    (VOID) DeregisterAllInterfaces("XENBUS");
     (VOID) RemoveUnplugService("NICS", "XENNET");
     (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
 
diff --git a/src/xennet.inf b/src/xennet.inf
index d99ffed..1adf079 100644
--- a/src/xennet.inf
+++ b/src/xennet.inf
@@ -61,9 +61,9 @@ xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll
 ; DisplayName		Section		DeviceID
 ; -----------		-------		--------
 
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XSC000&DEV_NET&REV_00000001
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0001&DEV_NET&REV_00000001
-%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0002&DEV_NET&REV_00000001
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XSC000&DEV_NET&REV_00000002
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0001&DEV_NET&REV_00000002
+%XenNetDesc%		=XenNet_Inst,	XENVIF\VEN_XS0002&DEV_NET&REV_00000002
 
 [XenNet_Inst] 
 Characteristics=0x84
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index 2f10b35..24cf4a0 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -164,11 +164,11 @@ AdapterVifCallback(
 
     switch (Type) {
     case XENVIF_TRANSMITTER_RETURN_PACKETS: {
-        PXENVIF_TRANSMITTER_PACKET HeadPacket;
+        PLIST_ENTRY List;
 
-        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+        List = va_arg(Arguments, PLIST_ENTRY);
 
-        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+        TransmitterCompletePackets(Adapter->Transmitter, List);
         break;
     }
     case XENVIF_RECEIVER_QUEUE_PACKETS: {
@@ -964,7 +964,6 @@ AdapterEnable(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    TransmitterEnable(Adapter->Transmitter);
     Adapter->Enabled = TRUE;
 
     return NDIS_STATUS_SUCCESS;
diff --git a/src/xennet/driver.c b/src/xennet/driver.c
new file mode 100644
index 0000000..cfa5cdd
--- /dev/null
+++ b/src/xennet/driver.c
@@ -0,0 +1,533 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#define INITGUID 1
+
+#include <ndis.h>
+#include "adapter.h"
+#include <version.h>
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENNET_DRIVER {
+    NDIS_HANDLE             MiniportHandle;
+} XENNET_DRIVER;
+
+static XENNET_DRIVER Driver;
+
+extern PULONG InitSafeBootMode;
+
+MINIPORT_CANCEL_OID_REQUEST __AdapterCancelOidRequest;
+VOID
+__AdapterCancelOidRequest(
+    IN  NDIS_HANDLE     Handle,
+    IN  PVOID           Request
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Request);
+}
+
+MINIPORT_CANCEL_SEND    __AdapterCancelSendNetBufferLists;
+VOID
+__AdapterCancelSendNetBufferLists(
+    IN  NDIS_HANDLE     Handle,
+    IN  PVOID           Cancel
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Cancel);
+}
+
+MINIPORT_CHECK_FOR_HANG __AdapterCheckForHang;
+BOOLEAN
+__AdapterCheckForHang(
+    IN  NDIS_HANDLE     Handle
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    return FALSE;
+}
+
+MINIPORT_INITIALIZE __AdapterInitialize;
+NDIS_STATUS 
+__AdapterInitialize(
+    IN  NDIS_HANDLE     Handle,
+    IN  NDIS_HANDLE     DriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS  Params
+    )
+{
+    PXENNET_ADAPTER     Adapter;
+    NDIS_STATUS         ndisStatus;
+
+    UNREFERENCED_PARAMETER(DriverContext);
+    UNREFERENCED_PARAMETER(Params);
+
+    ndisStatus = AdapterInitialize(Handle, &Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
+
+    return ndisStatus;
+
+fail1:
+    Error("fail1\n");
+    return ndisStatus;
+}
+
+MINIPORT_HALT   __AdapterHalt;
+VOID 
+__AdapterHalt(
+    IN  NDIS_HANDLE     Handle,
+    IN  NDIS_HALT_ACTION    Action
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Action);
+
+    if (Adapter == NULL)
+        return;
+
+    (VOID) AdapterDisable(Adapter);
+
+    AdapterTeardown(Adapter);
+}
+
+MINIPORT_OID_REQUEST    __AdapterOidRequest;
+NDIS_STATUS
+__AdapterOidRequest(
+    IN  NDIS_HANDLE         Handle,
+    IN  PNDIS_OID_REQUEST   Request
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    NDIS_STATUS         ndisStatus;
+
+    switch (Request->RequestType) {
+        case NdisRequestSetInformation:
+            ndisStatus = AdapterSetInformation(Adapter, Request);
+            break;
+
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            ndisStatus = AdapterQueryInformation(Adapter, Request);
+            break;
+
+        default:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
+
+    return ndisStatus;
+}
+
+MINIPORT_PAUSE  __AdapterPause;
+NDIS_STATUS
+__AdapterPause(
+    IN  NDIS_HANDLE     Handle,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS Params
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Params);
+
+    if (AdapterDisable(Adapter))
+        AdapterMediaStateChange(Adapter);
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_DEVICE_PNP_EVENT_NOTIFY    __AdapterPnPEventHandler;
+VOID
+__AdapterPnPEventHandler(
+    IN  NDIS_HANDLE     Handle,
+    IN  PNET_DEVICE_PNP_EVENT   Event
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+    UNREFERENCED_PARAMETER(Event);
+}
+
+MINIPORT_RESET  __AdapterReset;
+NDIS_STATUS
+__AdapterReset(
+    IN  NDIS_HANDLE     Handle,
+    OUT PBOOLEAN        AddressingReset
+    )
+{
+    UNREFERENCED_PARAMETER(Handle);
+
+    *AddressingReset = FALSE;
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_RESTART    __AdapterRestart;
+NDIS_STATUS
+__AdapterRestart(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   Params
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+
+    UNREFERENCED_PARAMETER(Params);
+
+    return AdapterEnable(Adapter);
+}
+
+MINIPORT_RETURN_NET_BUFFER_LISTS    __AdapterReturnNetBufferLists;
+VOID
+__AdapterReturnNetBufferLists(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    PXENNET_RECEIVER    Receiver = AdapterGetReceiver(Adapter);
+
+    ReceiverReturnNetBufferLists(Receiver,
+                                 NetBufferLists,
+                                 ReturnFlags);
+}
+
+MINIPORT_SEND_NET_BUFFER_LISTS  __AdapterSendNetBufferLists;
+VOID
+__AdapterSendNetBufferLists(
+    IN  NDIS_HANDLE             Handle,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    PXENNET_ADAPTER     Adapter = (PXENNET_ADAPTER)Handle;
+    PXENNET_TRANSMITTER Transmitter = AdapterGetTransmitter(Adapter);
+
+    TransmitterSendNetBufferLists(Transmitter,
+                                  NetBufferList,
+                                  PortNumber,
+                                  SendFlags);
+}
+
+MINIPORT_SHUTDOWN   __AdapterShutdown;
+VOID
+__AdapterShutdown(
+    IN  NDIS_HANDLE             Handle,
+    IN  NDIS_SHUTDOWN_ACTION    Action
+    )
+{
+    PXENNET_ADAPTER Adapter = (PXENNET_ADAPTER)Handle;
+
+    if (Action != NdisShutdownBugCheck)
+        AdapterDisable(Adapter);
+}
+
+typedef struct _XENNET_CONTEXT {
+    PDEVICE_CAPABILITIES    Capabilities;
+    PIO_COMPLETION_ROUTINE  CompletionRoutine;
+    PVOID                   CompletionContext;
+    UCHAR                   CompletionControl;
+} XENNET_CONTEXT, *PXENNET_CONTEXT;
+
+static NTSTATUS (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
+
+__drv_functionClass(IO_COMPLETION_ROUTINE)
+static NTSTATUS
+__QueryCapabilities(
+    IN  PDEVICE_OBJECT      DeviceObject,
+    IN  PIRP                Irp,
+    IN  PVOID               _Context
+    )
+{
+    PXENNET_CONTEXT         Context = _Context;
+    NTSTATUS                status;
+
+    Context->Capabilities->SurpriseRemovalOK = 1;
+
+    if (Context->CompletionRoutine != NULL &&
+        (Context->CompletionControl & SL_INVOKE_ON_SUCCESS))
+        status = Context->CompletionRoutine(DeviceObject, Irp, Context->CompletionContext);
+    else
+        status = STATUS_SUCCESS;
+
+    ExFreePool(Context);
+
+    return status;
+}
+
+NTSTATUS
+QueryCapabilities(
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PIRP                 Irp
+    )
+{
+    PIO_STACK_LOCATION      StackLocation;
+    PXENNET_CONTEXT         Context;
+    NTSTATUS                status;
+
+    Trace("====>\n");
+
+    Trace("%p\n", DeviceObject);
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof (XENNET_CONTEXT), ' TEN');
+    if (Context != NULL) {
+        Context->Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities;
+        Context->CompletionRoutine = StackLocation->CompletionRoutine;
+        Context->CompletionContext = StackLocation->Context;
+        Context->CompletionControl = StackLocation->Control;
+
+        StackLocation->CompletionRoutine = __QueryCapabilities;
+        StackLocation->Context = Context;
+        StackLocation->Control = SL_INVOKE_ON_SUCCESS;
+    }
+
+    status = NdisDispatchPnp(DeviceObject, Irp);
+
+    Trace("<====\n");
+
+    return status;
+}
+
+DRIVER_DISPATCH DispatchPnp;
+
+NTSTATUS
+DispatchPnp(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    UCHAR               MinorFunction;
+    NTSTATUS            status;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    MinorFunction = StackLocation->MinorFunction;
+
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_QUERY_CAPABILITIES:
+        status = QueryCapabilities(DeviceObject, Irp);
+        break;
+
+    default:
+        status = NdisDispatchPnp(DeviceObject, Irp);
+        break;
+    }
+
+    return status;
+}
+
+DRIVER_DISPATCH DispatchFail;
+
+NTSTATUS
+DispatchFail(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+MINIPORT_UNLOAD DriverUnload;
+VOID
+DriverUnload(
+    IN  PDRIVER_OBJECT  DriverObject
+    )
+{
+    UNREFERENCED_PARAMETER(DriverObject);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        goto done;
+
+    if (Driver.MiniportHandle)
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+done:
+    Trace("<====\n");
+}
+
+DRIVER_INITIALIZE       DriverEntry;
+
+NTSTATUS
+DriverEntry (
+    IN  PDRIVER_OBJECT  DriverObject,
+    IN  PUNICODE_STRING RegistryPath
+    )
+{
+    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_DRIVER_CHARACTERISTICS mpChars;
+    NDIS_CONFIGURATION_OBJECT ConfigurationObject;
+    NDIS_HANDLE ConfigurationHandle;
+    NDIS_STRING ParameterName;
+    PNDIS_CONFIGURATION_PARAMETER ParameterValue;
+    ULONG FailCreateClose;
+    ULONG FailDeviceControl;
+
+    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        return NDIS_STATUS_SUCCESS;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    //
+    // Register miniport with NDIS.
+    //
+
+    NdisZeroMemory(&mpChars, sizeof(mpChars));
+    mpChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
+    mpChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
+    mpChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
+
+    mpChars.MajorNdisVersion = 6;
+    mpChars.MinorNdisVersion = 0;
+    mpChars.MajorDriverVersion = MAJOR_VERSION;
+    mpChars.MinorDriverVersion = MINOR_VERSION;
+
+    mpChars.CancelOidRequestHandler = __AdapterCancelOidRequest;
+    mpChars.CancelSendHandler = __AdapterCancelSendNetBufferLists;
+    mpChars.CheckForHangHandlerEx = __AdapterCheckForHang;
+    mpChars.InitializeHandlerEx = __AdapterInitialize;
+    mpChars.HaltHandlerEx = __AdapterHalt;
+    mpChars.OidRequestHandler = __AdapterOidRequest;
+    mpChars.PauseHandler = __AdapterPause;
+    mpChars.DevicePnPEventNotifyHandler  = __AdapterPnPEventHandler;
+    mpChars.ResetHandlerEx = __AdapterReset;
+    mpChars.RestartHandler = __AdapterRestart;
+    mpChars.ReturnNetBufferListsHandler = __AdapterReturnNetBufferLists;
+    mpChars.SendNetBufferListsHandler = __AdapterSendNetBufferLists;
+    mpChars.ShutdownHandlerEx = __AdapterShutdown;
+    mpChars.UnloadHandler = DriverUnload;
+
+    Driver.MiniportHandle = NULL;
+    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
+                                             RegistryPath,
+                                             NULL,
+                                             &mpChars,
+                                             &Driver.MiniportHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to register miniport.\n", ndisStatus);
+        goto fail;
+    }
+
+    ConfigurationObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.NdisHandle = Driver.MiniportHandle;
+    ConfigurationObject.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to open driver configuration.\n", ndisStatus);
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+        goto fail;
+    }
+
+    RtlInitUnicodeString(&ParameterName, L"FailCreateClose");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailCreateClose = ParameterValue->ParameterData.IntegerData;
+    else
+        FailCreateClose = 0;
+
+    RtlInitUnicodeString(&ParameterName, L"FailDeviceControl");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailDeviceControl = ParameterValue->ParameterData.IntegerData;
+    else
+        FailDeviceControl = 0;
+
+    NdisCloseConfiguration(ConfigurationHandle);
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+    if (FailCreateClose != 0) {
+#pragma prefast(suppress:28168) // No matching__drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
+    }
+
+    if (FailDeviceControl != 0) {
+#pragma prefast(suppress:28168) // No matching __drv_dispatchType annotation
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
+    }
+
+    Trace("<====\n");
+    return ndisStatus;
+
+fail:
+    Error("fail\n");
+    return ndisStatus;
+}
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 0c89f76..c64591d 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -33,22 +33,72 @@
 #include "transmitter.h"
 #include "adapter.h"
 #include <vif_interface.h>
+#include <cache_interface.h>
 #include "dbg_print.h"
 #include "assert.h"
 
 struct _XENNET_TRANSMITTER {
     PXENNET_ADAPTER             Adapter;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+    PXENBUS_CACHE               PacketCache;
+    KSPIN_LOCK                  PacketLock;
 };
 
+#define XENNET_PACKET_CACHE_MIN     32
 #define TRANSMITTER_POOL_TAG        'TteN'
 
+static NTSTATUS
+__TransmitterPacketCtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__TransmitterPacketDtor(
+    IN  PVOID       Argument,
+    IN  PVOID       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__TransmitterPacketAcquireLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->PacketLock);
+}
+
+static VOID
+__TransmitterPacketReleaseLock(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->PacketLock);
+}
+
 NDIS_STATUS
 TransmitterInitialize (
     IN  PXENNET_ADAPTER     Adapter,
     OUT PXENNET_TRANSMITTER *Transmitter
     )
 {
+    NTSTATUS                status;
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Adapter);
+
     *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
                                          sizeof(XENNET_TRANSMITTER),
                                          TRANSMITTER_POOL_TAG);
@@ -57,9 +107,28 @@ TransmitterInitialize (
 
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
+    KeInitializeSpinLock(&(*Transmitter)->PacketLock);
+
+    status = XENBUS_CACHE(Create,
+                          CacheInterface,
+                          "packet_cache",
+                          sizeof(XENVIF_TRANSMITTER_PACKET),
+                          XENNET_PACKET_CACHE_MIN,
+                          __TransmitterPacketCtor,
+                          __TransmitterPacketDtor,
+                          __TransmitterPacketAcquireLock,
+                          __TransmitterPacketReleaseLock,
+                          *Transmitter,
+                          &(*Transmitter)->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail2;
     
     return NDIS_STATUS_SUCCESS;
 
+fail2:
+    RtlZeroMemory(&(*Transmitter)->PacketLock, sizeof(KSPIN_LOCK));
+    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
+    *Transmitter = NULL;
 fail1:
     return NDIS_STATUS_FAILURE;
 }
@@ -69,36 +138,54 @@ TransmitterTeardown(
     IN  PXENNET_TRANSMITTER Transmitter
     )
 {
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
     Transmitter->Adapter = NULL;
     Transmitter->OffloadOptions.Value = 0;
+    RtlZeroMemory(&Transmitter->PacketLock, sizeof(KSPIN_LOCK));
+
+    XENBUS_CACHE(Destroy,
+                 CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
 
     ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
-VOID
-TransmitterEnable(
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+__TransmitterGetPacket(
     IN  PXENNET_TRANSMITTER Transmitter
     )
 {
-    PXENVIF_VIF_INTERFACE   VifInterface = AdapterGetVifInterface(Transmitter->Adapter);
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      VifInterface,
-                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
-                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
-                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    return XENBUS_CACHE(Get,
+                        CacheInterface,
+                        Transmitter->PacketCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    PXENBUS_CACHE_INTERFACE CacheInterface; 
+    
+    CacheInterface = AdapterGetCacheInterface(Transmitter->Adapter);
+
+    RtlZeroMemory(Packet, sizeof(XENVIF_TRANSMITTER_PACKET));
+
+    XENBUS_CACHE(Put,
+                 CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 FALSE);
 }
 
 typedef struct _NET_BUFFER_LIST_RESERVED {
@@ -107,13 +194,6 @@ typedef struct _NET_BUFFER_LIST_RESERVED {
 
 C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved));
 
-typedef struct _NET_BUFFER_RESERVED {
-    XENVIF_TRANSMITTER_PACKET   Packet;
-    PNET_BUFFER_LIST            NetBufferList;
-} NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
-
-C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
-
 static VOID
 __TransmitterCompleteNetBufferList(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -140,26 +220,25 @@ __TransmitterCompleteNetBufferList(
                                     NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
 }
 
-
 static VOID
 __TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
-    IN  NDIS_STATUS                 Status
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List,
+    IN  NDIS_STATUS         Status
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                 ListEntry;
+        PXENVIF_TRANSMITTER_PACKET  Packet;
         PNET_BUFFER_LIST            NetBufferList;
         PNET_BUFFER_LIST_RESERVED   ListReserved;
 
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        ListEntry = RemoveHeadList(List);
+        ASSERT3P(ListEntry, !=, List);
 
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
 
-        NetBufferList = Reserved->NetBufferList;
+        NetBufferList = Packet->Cookie;
         ASSERT(NetBufferList != NULL);
 
         ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
@@ -168,7 +247,7 @@ __TransmitterCompletePackets(
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
             __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, Status);
 
-        Packet = Next;
+        __TransmitterPutPacket(Transmitter, Packet);
     }    
 }
 
@@ -246,14 +325,12 @@ TransmitterSendNetBufferLists(
     IN  ULONG                   SendFlags
     )
 {
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
+    LIST_ENTRY                  List;
     KIRQL                       Irql;
 
     UNREFERENCED_PARAMETER(PortNumber);
 
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    InitializeListHead(&List);
 
     if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
         ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
@@ -283,23 +360,35 @@ TransmitterSendNetBufferLists(
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
-            PNET_BUFFER_RESERVED        Reserved;
             PXENVIF_TRANSMITTER_PACKET  Packet;
 
-            Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
-            RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
+            Packet = __TransmitterGetPacket(Transmitter);
+            if (Packet == NULL) {
+                while (ListReserved->Reference--) {
+                    PLIST_ENTRY     ListEntry;
+
+                    ListEntry = RemoveTailList(&List);
+                    ASSERT3P(ListEntry, !=, &List);
+
+                    Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET, ListEntry);
+                    
+                    __TransmitterPutPacket(Transmitter, Packet);
+                }
+                __TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NDIS_STATUS_NOT_ACCEPTED);
+                break;
+            }
 
-            Reserved->NetBufferList = NetBufferList;
             ListReserved->Reference++;
 
-            Packet = &Reserved->Packet;
+            Packet->Cookie = NetBufferList;
             Packet->Send.OffloadOptions.Value = OffloadOptions.Value & Transmitter->OffloadOptions.Value;
             Packet->Send.MaximumSegmentSize = MaximumSegmentSize;
             Packet->Send.TagControlInformation = TagControlInformation;
+            Packet->Mdl = NET_BUFFER_CURRENT_MDL(NetBuffer);
+            Packet->Length = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            Packet->Offset = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
 
-            ASSERT3P(Packet->Next, ==, NULL);
-            *TailPacket = Packet;
-            TailPacket = &Packet->Next;
+            InsertTailList(&List, &Packet->ListEntry);
 
             NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
         }
@@ -307,14 +396,14 @@ TransmitterSendNetBufferLists(
         NetBufferList = ListNext;
     }
 
-    if (HeadPacket != NULL) {
+    if (!IsListEmpty(&List)) {
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
                             AdapterGetVifInterface(Transmitter->Adapter),
-                            HeadPacket);
+                            &List);
         if (!NT_SUCCESS(status))
-            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
+            __TransmitterCompletePackets(Transmitter, &List, NDIS_STATUS_NOT_ACCEPTED);
     }
 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
@@ -322,11 +411,11 @@ TransmitterSendNetBufferLists(
 
 VOID
 TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     )
 {
-    __TransmitterCompletePackets(Transmitter, Packet, NDIS_STATUS_SUCCESS);
+    __TransmitterCompletePackets(Transmitter, List, NDIS_STATUS_SUCCESS);
 }
 
 PXENVIF_VIF_OFFLOAD_OPTIONS
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index f63a2a0..0adebdc 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -49,11 +49,6 @@ TransmitterTeardown(
     );
 
 extern VOID
-TransmitterEnable(
-    IN  PXENNET_TRANSMITTER Transmitter
-    );
-
-extern VOID
 TransmitterSendNetBufferLists (
     IN  PXENNET_TRANSMITTER Transmitter,
     IN  PNET_BUFFER_LIST    NetBufferList,
@@ -63,8 +58,8 @@ TransmitterSendNetBufferLists (
 
 extern VOID
 TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENNET_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
     );
 
 extern PXENVIF_VIF_OFFLOAD_OPTIONS
-- 
1.9.4.msysgit.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:50:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:50:25 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1fDV-0006DR-OV; Thu, 18 Dec 2014 17:50:25 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1fDT-0006DK-Su
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:50:24 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	09/AF-09842-FD313945; Thu, 18 Dec 2014 17:50:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1418925019!16544519!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 18316 invoked from network); 18 Dec 2014 17:50:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-4.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:50:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,602,1413244800"; d="scan'208";a="206370792"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Thu, 18 Dec 2014 12:29:04 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1esq-0004Do-Ai;
	Thu, 18 Dec 2014 17:29:04 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 17:29:00 +0000
Message-ID: <1418923740-7920-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Matt Wilson <msw@linux.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Map Local APIC IDs to Processor IDs through
	the MADT
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

To use the FIFO EVTCHN ABI the frontend code needs to know the vcpu id of
the guest CPUs. This mapping is currently done by taking the the CPU local
APIC ID and dividing by 2. This currently works on most Xen installations
but Matt Wilson advises that this will not work on AWS.
This patch introduces code to map and parse the ACPI RSDP, XSDT and MADT
(APIC) tables such that the local APIC substructures present in the latter
can be used to map local APIC ID to processor ID (which is identical to
vcpu id).

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Matt Wilson <msw@linux.com>
---
 src/xen/acpi.c         | 313 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/xen/acpi.h         | 108 +++++++++++++++++
 src/xen/driver.c       |  28 +++--
 src/xen/system.c       | 117 +++++++++++++++++-
 vs2012/xen/xen.vcxproj |   1 +
 5 files changed, 555 insertions(+), 12 deletions(-)
 create mode 100644 src/xen/acpi.c
 create mode 100644 src/xen/acpi.h

diff --git a/src/xen/acpi.c b/src/xen/acpi.c
new file mode 100644
index 0000000..124dcb6
--- /dev/null
+++ b/src/xen/acpi.c
@@ -0,0 +1,313 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <util.h>
+
+#include "acpi.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define XENBUS_ACPI_TAG 'IPCA'
+
+static ACPI_RSDP    AcpiRsdp;
+static PACPI_XSDT   AcpiXsdt;
+
+static FORCEINLINE PVOID
+__AcpiAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_ACPI_TAG);
+}
+
+static FORCEINLINE VOID
+__AcpiFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_ACPI_TAG);
+}
+
+static BOOLEAN
+AcpiVerifyChecksum(
+    IN  PVOID   Table,
+    IN  ULONG   Length
+    )
+{
+    UCHAR       Sum;
+    ULONG       Index;
+
+    Sum = 0;
+    for (Index = 0; Index < Length; Index++)
+        Sum += ((PUCHAR)Table)[Index];
+
+    return (Sum == 0) ? TRUE : FALSE;
+}
+
+static NTSTATUS
+AcpiFindRsdp(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Start;
+    PHYSICAL_ADDRESS    End;
+    ULONG               Length;
+    PUCHAR              Data;
+    ULONG               Offset;
+    PACPI_RSDP          Rsdp;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (strncmp(AcpiRsdp.Signature,
+                "RSD PTR ",
+                sizeof (AcpiRsdp.Signature)) == 0)
+        goto done;
+
+    Start.QuadPart = 0xE0000;
+    End.QuadPart = 0xFFFFF;
+
+    Length = (ULONG)(End.QuadPart + 1 - Start.QuadPart);
+
+    Data = MmMapIoSpace(Start, Length, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Data == NULL)
+        goto fail1;
+
+    for (Offset = 0;
+         Offset + sizeof (ACPI_RSDP) < Length;
+         Offset += 16) {
+        Rsdp = (PACPI_RSDP)(Data + Offset);
+
+        if (strncmp(Rsdp->Signature,
+                    "RSD PTR ",
+                    sizeof (Rsdp->Signature)) == 0 &&
+            AcpiVerifyChecksum(Rsdp, sizeof (ACPI_RSDP)))
+            goto found;
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail2;
+
+found:
+    Info("0x%p\n", Start.QuadPart + Offset);
+
+    // Copy the table for reference
+    AcpiRsdp = *Rsdp;
+
+    MmUnmapIoSpace(Data, Length);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Data, Length);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+AcpiGetXsdt(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Address;
+    PACPI_XSDT          Xsdt;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (AcpiXsdt != NULL)
+        goto done;
+
+    Address.QuadPart = AcpiRsdp.XsdtAddress;
+
+    Info("0x%p\n", Address.QuadPart);
+
+    Xsdt = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Xsdt == NULL)
+        goto fail1;
+
+    if (strncmp(Xsdt->Header.Signature,
+                "XSDT",
+                sizeof (Xsdt->Header.Signature)) != 0)
+        goto fail2;
+
+    if (!AcpiVerifyChecksum(Xsdt, Xsdt->Header.Length))
+        goto fail3;
+
+    AcpiXsdt = __AcpiAllocate(Xsdt->Header.Length);
+
+    status = STATUS_NO_MEMORY;
+    if (AcpiXsdt == NULL)
+        goto fail4;
+
+    RtlCopyMemory(AcpiXsdt, Xsdt, Xsdt->Header.Length);
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    )
+{
+    ULONG               Count;
+    ULONG               Index;
+    PACPI_HEADER        Header;
+    NTSTATUS            status;
+
+    status = AcpiGetXsdt();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Count = (AcpiXsdt->Header.Length - FIELD_OFFSET(ACPI_XSDT, Entry)) /
+            sizeof (ULONG64);
+
+    for (Index = 0; Index < Count; Index++) {
+        PHYSICAL_ADDRESS    Address;
+
+        Address.QuadPart = AcpiXsdt->Entry[Index];
+
+        Header = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Header == NULL)
+            goto fail2;
+
+        if (strncmp(Header->Signature,
+                    Signature,
+                    sizeof (Header->Signature)) == 0 &&
+            AcpiVerifyChecksum(Header, Header->Length))
+            goto found;
+
+        MmUnmapIoSpace(Header, PAGE_SIZE);
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail3;
+
+found:
+    status = STATUS_BUFFER_OVERFLOW;
+    if (Buffer == NULL || Header->Length > *Length) {
+        *Length = Header->Length;
+        goto fail4;
+    }
+
+    RtlCopyMemory(Buffer, Header, Header->Length);
+
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+    return STATUS_SUCCESS;
+
+fail4:
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+fail3:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail3\n");
+
+fail2:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
+
+fail1:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiInitialize(
+    VOID
+    )
+{
+    NTSTATUS    status;
+
+    status = AcpiFindRsdp();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+AcpiTeardown(
+    VOID
+    )
+{
+    if (AcpiXsdt != NULL) {
+        __AcpiFree(AcpiXsdt);
+        AcpiXsdt = NULL;
+    }
+}
diff --git a/src/xen/acpi.h b/src/xen/acpi.h
new file mode 100644
index 0000000..334f62a
--- /dev/null
+++ b/src/xen/acpi.h
@@ -0,0 +1,108 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_ACPI_H
+#define _XEN_ACPI_H
+
+#include <ntddk.h>
+
+#pragma pack(push, 1)
+
+typedef struct _ACPI_RSDP {
+    CHAR    Signature[8];
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    UCHAR   Revision;
+    ULONG   RsdtAddress;
+    ULONG   Length;
+    ULONG64 XsdtAddress;
+    UCHAR   ExtendedChecksum;
+    UCHAR   Reserved[3];
+} ACPI_RSDP, *PACPI_RSDP;
+
+typedef struct _ACPI_HEADER {
+    CHAR    Signature[4];
+    ULONG   Length;
+    UCHAR   Revision;
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    CHAR    OemTableID[8];
+    ULONG   OemRevision;
+    CHAR    CreatorID[4];
+    ULONG   CreatorRevision;
+} ACPI_HEADER, *PACPI_HEADER;
+
+typedef struct _ACPI_XSDT {
+    ACPI_HEADER Header;
+    ULONG64     Entry[1];
+} ACPI_XSDT, *PACPI_XSDT;
+
+typedef struct _ACPI_MADT {
+    ACPI_HEADER Header;
+    ULONG       LocalAPICAddress;
+    ULONG       Flags;
+} ACPI_MADT, *PACPI_MADT;
+
+typedef struct _ACPI_MADT_HEADER {
+    UCHAR   Type;
+    UCHAR   Length;
+} ACPI_MADT_HEADER, *PACPI_MADT_HEADER;
+
+#define ACPI_MADT_TYPE_LOCAL_APIC   0x00
+
+typedef struct _ACPI_MADT_LOCAL_APIC {
+    ACPI_MADT_HEADER    Header;
+    UCHAR               ProcessorID;
+    UCHAR               ApicID;
+    ULONG               Flags;
+} ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC;
+
+#pragma pack(pop)
+
+extern NTSTATUS
+AcpiInitialize(
+    VOID
+    );
+
+extern NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    );
+
+extern VOID
+AcpiTeardown(
+    VOID
+    );
+
+#endif  // _XEN_ACPI_H
+
diff --git a/src/xen/driver.c b/src/xen/driver.c
index fce75aa..a4e91aa 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -39,6 +39,7 @@
 #include "module.h"
 #include "process.h"
 #include "system.h"
+#include "acpi.h"
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,50 +144,59 @@ DllInitialize(
          MONTH,
          YEAR);
 
-    status = SystemInitialize();
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = ProcessInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
 done:
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    ModuleTeardown();
+
 fail6:
     Error("fail6\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail5:
     Error("fail5\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail4:
     Error("fail4\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail3:
     Error("fail3\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail2:
     Error("fail2\n");
diff --git a/src/xen/system.c b/src/xen/system.c
index 1ac8123..0934ac8 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -40,23 +40,44 @@
 
 #include "registry.h"
 #include "system.h"
+#include "acpi.h"
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XEN_SYSTEM_TAG  'TSYS'
+
 typedef struct _SYSTEM_CPU {
     ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
+    UCHAR   ProcessorID;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
+    PACPI_MADT  Madt;
     SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
     PVOID       Handle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
 
+static FORCEINLINE PVOID
+__SystemAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_SYSTEM_TAG);
+}
+
+static FORCEINLINE VOID
+__SystemFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XEN_SYSTEM_TAG);
+}
+
 static FORCEINLINE const CHAR *
 __PlatformIdName(
     IN  ULONG   PlatformId
@@ -233,6 +254,77 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemGetAcpiInformation(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Length;
+    NTSTATUS        status;
+
+    status = AcpiGetTable("APIC", NULL, &Length);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        goto fail1;
+
+    Context->Madt = __SystemAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (Context->Madt == NULL)
+        goto fail2;
+
+    status = AcpiGetTable("APIC", Context->Madt, &Length);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4715)
+
+static UCHAR
+SystemApicIDToProcessorID(
+    IN  UCHAR   ApicID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    PACPI_MADT      Madt = Context->Madt;
+    ULONG           Offset;
+
+    Offset = sizeof (ACPI_MADT);
+    while (Offset < Madt->Header.Length) {
+        PACPI_MADT_HEADER       Header;
+        PACPI_MADT_LOCAL_APIC   Apic;
+
+        Header = (PACPI_MADT_HEADER)((PUCHAR)Madt + Offset);
+        Offset += Header->Length;
+
+        if (Header->Type != ACPI_MADT_TYPE_LOCAL_APIC)
+            continue;
+
+        Apic = CONTAINING_RECORD(Header, ACPI_MADT_LOCAL_APIC, Header);
+
+        if (Apic->ApicID == ApicID)
+            return Apic->ProcessorID;
+    }
+
+    BUG(__FUNCTION__);
+}
+
+#pragma warning(pop)
+
 KDEFERRED_ROUTINE   SystemCpuInformation;
 
 VOID
@@ -272,7 +364,11 @@ SystemCpuInformation(
 
     Cpu->ApicID = EBX >> 24;
 
-    Info("Local APIC ID: %02X\n", Cpu->ApicID);
+    Info("APIC ID: %02X\n", Cpu->ApicID);
+
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
     Info("<==== (%u)\n", Cpu->Index);
 
@@ -476,6 +572,10 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = SystemGetAcpiInformation();
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     SystemGetCpuInformation();
 
     status = SystemRegisterCallback(L"\\Callback\\PowerState",
@@ -483,10 +583,16 @@ SystemInitialize(
                                     NULL,
                                     &Context->Handle);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
 fail5:
     Error("fail5\n");
 
@@ -502,6 +608,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    (VOID) InterlockedDecrement(&Context->References);
+
     return status;
 }
 
@@ -516,7 +624,7 @@ SystemVirtualCpuIndex(
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
-    return Cpu->ApicID / 2;
+    return Cpu->ProcessorID;
 }
 
 VOID
@@ -531,6 +639,9 @@ SystemTeardown(
 
     RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
 
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
     (VOID) InterlockedDecrement(&Context->References);
 
     ASSERT(IsZeroMemory(Context, sizeof (SYSTEM_CONTEXT)));
diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj
index 2f4d958..9efeaf1 100644
--- a/vs2012/xen/xen.vcxproj
+++ b/vs2012/xen/xen.vcxproj
@@ -96,6 +96,7 @@
 		<ClCompile Include="..\..\src\xen\bug_check.c" />
 		<ClCompile Include="..\..\src\xen\module.c" />
 		<ClCompile Include="..\..\src\xen\process.c" />
+		<ClCompile Include="..\..\src\xen\acpi.c" />
 		<ClCompile Include="..\..\src\xen\system.c" />
 	</ItemGroup>
 	<ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Thu Dec 18 17:50:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 18 Dec 2014 17:50:25 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1fDV-0006DR-OV; Thu, 18 Dec 2014 17:50:25 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1fDT-0006DK-Su
	for win-pv-devel@lists.xenproject.org; Thu, 18 Dec 2014 17:50:24 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	09/AF-09842-FD313945; Thu, 18 Dec 2014 17:50:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1418925019!16544519!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 18316 invoked from network); 18 Dec 2014 17:50:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-4.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	18 Dec 2014 17:50:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,602,1413244800"; d="scan'208";a="206370792"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.78) with Microsoft SMTP Server id 14.3.210.2;
	Thu, 18 Dec 2014 12:29:04 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1esq-0004Do-Ai;
	Thu, 18 Dec 2014 17:29:04 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 18 Dec 2014 17:29:00 +0000
Message-ID: <1418923740-7920-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Matt Wilson <msw@linux.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Map Local APIC IDs to Processor IDs through
	the MADT
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

To use the FIFO EVTCHN ABI the frontend code needs to know the vcpu id of
the guest CPUs. This mapping is currently done by taking the the CPU local
APIC ID and dividing by 2. This currently works on most Xen installations
but Matt Wilson advises that this will not work on AWS.
This patch introduces code to map and parse the ACPI RSDP, XSDT and MADT
(APIC) tables such that the local APIC substructures present in the latter
can be used to map local APIC ID to processor ID (which is identical to
vcpu id).

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Matt Wilson <msw@linux.com>
---
 src/xen/acpi.c         | 313 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/xen/acpi.h         | 108 +++++++++++++++++
 src/xen/driver.c       |  28 +++--
 src/xen/system.c       | 117 +++++++++++++++++-
 vs2012/xen/xen.vcxproj |   1 +
 5 files changed, 555 insertions(+), 12 deletions(-)
 create mode 100644 src/xen/acpi.c
 create mode 100644 src/xen/acpi.h

diff --git a/src/xen/acpi.c b/src/xen/acpi.c
new file mode 100644
index 0000000..124dcb6
--- /dev/null
+++ b/src/xen/acpi.c
@@ -0,0 +1,313 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <util.h>
+
+#include "acpi.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define XENBUS_ACPI_TAG 'IPCA'
+
+static ACPI_RSDP    AcpiRsdp;
+static PACPI_XSDT   AcpiXsdt;
+
+static FORCEINLINE PVOID
+__AcpiAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_ACPI_TAG);
+}
+
+static FORCEINLINE VOID
+__AcpiFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_ACPI_TAG);
+}
+
+static BOOLEAN
+AcpiVerifyChecksum(
+    IN  PVOID   Table,
+    IN  ULONG   Length
+    )
+{
+    UCHAR       Sum;
+    ULONG       Index;
+
+    Sum = 0;
+    for (Index = 0; Index < Length; Index++)
+        Sum += ((PUCHAR)Table)[Index];
+
+    return (Sum == 0) ? TRUE : FALSE;
+}
+
+static NTSTATUS
+AcpiFindRsdp(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Start;
+    PHYSICAL_ADDRESS    End;
+    ULONG               Length;
+    PUCHAR              Data;
+    ULONG               Offset;
+    PACPI_RSDP          Rsdp;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (strncmp(AcpiRsdp.Signature,
+                "RSD PTR ",
+                sizeof (AcpiRsdp.Signature)) == 0)
+        goto done;
+
+    Start.QuadPart = 0xE0000;
+    End.QuadPart = 0xFFFFF;
+
+    Length = (ULONG)(End.QuadPart + 1 - Start.QuadPart);
+
+    Data = MmMapIoSpace(Start, Length, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Data == NULL)
+        goto fail1;
+
+    for (Offset = 0;
+         Offset + sizeof (ACPI_RSDP) < Length;
+         Offset += 16) {
+        Rsdp = (PACPI_RSDP)(Data + Offset);
+
+        if (strncmp(Rsdp->Signature,
+                    "RSD PTR ",
+                    sizeof (Rsdp->Signature)) == 0 &&
+            AcpiVerifyChecksum(Rsdp, sizeof (ACPI_RSDP)))
+            goto found;
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail2;
+
+found:
+    Info("0x%p\n", Start.QuadPart + Offset);
+
+    // Copy the table for reference
+    AcpiRsdp = *Rsdp;
+
+    MmUnmapIoSpace(Data, Length);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Data, Length);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+AcpiGetXsdt(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Address;
+    PACPI_XSDT          Xsdt;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (AcpiXsdt != NULL)
+        goto done;
+
+    Address.QuadPart = AcpiRsdp.XsdtAddress;
+
+    Info("0x%p\n", Address.QuadPart);
+
+    Xsdt = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Xsdt == NULL)
+        goto fail1;
+
+    if (strncmp(Xsdt->Header.Signature,
+                "XSDT",
+                sizeof (Xsdt->Header.Signature)) != 0)
+        goto fail2;
+
+    if (!AcpiVerifyChecksum(Xsdt, Xsdt->Header.Length))
+        goto fail3;
+
+    AcpiXsdt = __AcpiAllocate(Xsdt->Header.Length);
+
+    status = STATUS_NO_MEMORY;
+    if (AcpiXsdt == NULL)
+        goto fail4;
+
+    RtlCopyMemory(AcpiXsdt, Xsdt, Xsdt->Header.Length);
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    )
+{
+    ULONG               Count;
+    ULONG               Index;
+    PACPI_HEADER        Header;
+    NTSTATUS            status;
+
+    status = AcpiGetXsdt();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Count = (AcpiXsdt->Header.Length - FIELD_OFFSET(ACPI_XSDT, Entry)) /
+            sizeof (ULONG64);
+
+    for (Index = 0; Index < Count; Index++) {
+        PHYSICAL_ADDRESS    Address;
+
+        Address.QuadPart = AcpiXsdt->Entry[Index];
+
+        Header = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Header == NULL)
+            goto fail2;
+
+        if (strncmp(Header->Signature,
+                    Signature,
+                    sizeof (Header->Signature)) == 0 &&
+            AcpiVerifyChecksum(Header, Header->Length))
+            goto found;
+
+        MmUnmapIoSpace(Header, PAGE_SIZE);
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail3;
+
+found:
+    status = STATUS_BUFFER_OVERFLOW;
+    if (Buffer == NULL || Header->Length > *Length) {
+        *Length = Header->Length;
+        goto fail4;
+    }
+
+    RtlCopyMemory(Buffer, Header, Header->Length);
+
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+    return STATUS_SUCCESS;
+
+fail4:
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+fail3:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail3\n");
+
+fail2:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
+
+fail1:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiInitialize(
+    VOID
+    )
+{
+    NTSTATUS    status;
+
+    status = AcpiFindRsdp();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+AcpiTeardown(
+    VOID
+    )
+{
+    if (AcpiXsdt != NULL) {
+        __AcpiFree(AcpiXsdt);
+        AcpiXsdt = NULL;
+    }
+}
diff --git a/src/xen/acpi.h b/src/xen/acpi.h
new file mode 100644
index 0000000..334f62a
--- /dev/null
+++ b/src/xen/acpi.h
@@ -0,0 +1,108 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_ACPI_H
+#define _XEN_ACPI_H
+
+#include <ntddk.h>
+
+#pragma pack(push, 1)
+
+typedef struct _ACPI_RSDP {
+    CHAR    Signature[8];
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    UCHAR   Revision;
+    ULONG   RsdtAddress;
+    ULONG   Length;
+    ULONG64 XsdtAddress;
+    UCHAR   ExtendedChecksum;
+    UCHAR   Reserved[3];
+} ACPI_RSDP, *PACPI_RSDP;
+
+typedef struct _ACPI_HEADER {
+    CHAR    Signature[4];
+    ULONG   Length;
+    UCHAR   Revision;
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    CHAR    OemTableID[8];
+    ULONG   OemRevision;
+    CHAR    CreatorID[4];
+    ULONG   CreatorRevision;
+} ACPI_HEADER, *PACPI_HEADER;
+
+typedef struct _ACPI_XSDT {
+    ACPI_HEADER Header;
+    ULONG64     Entry[1];
+} ACPI_XSDT, *PACPI_XSDT;
+
+typedef struct _ACPI_MADT {
+    ACPI_HEADER Header;
+    ULONG       LocalAPICAddress;
+    ULONG       Flags;
+} ACPI_MADT, *PACPI_MADT;
+
+typedef struct _ACPI_MADT_HEADER {
+    UCHAR   Type;
+    UCHAR   Length;
+} ACPI_MADT_HEADER, *PACPI_MADT_HEADER;
+
+#define ACPI_MADT_TYPE_LOCAL_APIC   0x00
+
+typedef struct _ACPI_MADT_LOCAL_APIC {
+    ACPI_MADT_HEADER    Header;
+    UCHAR               ProcessorID;
+    UCHAR               ApicID;
+    ULONG               Flags;
+} ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC;
+
+#pragma pack(pop)
+
+extern NTSTATUS
+AcpiInitialize(
+    VOID
+    );
+
+extern NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    );
+
+extern VOID
+AcpiTeardown(
+    VOID
+    );
+
+#endif  // _XEN_ACPI_H
+
diff --git a/src/xen/driver.c b/src/xen/driver.c
index fce75aa..a4e91aa 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -39,6 +39,7 @@
 #include "module.h"
 #include "process.h"
 #include "system.h"
+#include "acpi.h"
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,50 +144,59 @@ DllInitialize(
          MONTH,
          YEAR);
 
-    status = SystemInitialize();
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = ProcessInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
 done:
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    ModuleTeardown();
+
 fail6:
     Error("fail6\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail5:
     Error("fail5\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail4:
     Error("fail4\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail3:
     Error("fail3\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail2:
     Error("fail2\n");
diff --git a/src/xen/system.c b/src/xen/system.c
index 1ac8123..0934ac8 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -40,23 +40,44 @@
 
 #include "registry.h"
 #include "system.h"
+#include "acpi.h"
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XEN_SYSTEM_TAG  'TSYS'
+
 typedef struct _SYSTEM_CPU {
     ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
+    UCHAR   ProcessorID;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
+    PACPI_MADT  Madt;
     SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
     PVOID       Handle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
 
+static FORCEINLINE PVOID
+__SystemAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_SYSTEM_TAG);
+}
+
+static FORCEINLINE VOID
+__SystemFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XEN_SYSTEM_TAG);
+}
+
 static FORCEINLINE const CHAR *
 __PlatformIdName(
     IN  ULONG   PlatformId
@@ -233,6 +254,77 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemGetAcpiInformation(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Length;
+    NTSTATUS        status;
+
+    status = AcpiGetTable("APIC", NULL, &Length);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        goto fail1;
+
+    Context->Madt = __SystemAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (Context->Madt == NULL)
+        goto fail2;
+
+    status = AcpiGetTable("APIC", Context->Madt, &Length);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4715)
+
+static UCHAR
+SystemApicIDToProcessorID(
+    IN  UCHAR   ApicID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    PACPI_MADT      Madt = Context->Madt;
+    ULONG           Offset;
+
+    Offset = sizeof (ACPI_MADT);
+    while (Offset < Madt->Header.Length) {
+        PACPI_MADT_HEADER       Header;
+        PACPI_MADT_LOCAL_APIC   Apic;
+
+        Header = (PACPI_MADT_HEADER)((PUCHAR)Madt + Offset);
+        Offset += Header->Length;
+
+        if (Header->Type != ACPI_MADT_TYPE_LOCAL_APIC)
+            continue;
+
+        Apic = CONTAINING_RECORD(Header, ACPI_MADT_LOCAL_APIC, Header);
+
+        if (Apic->ApicID == ApicID)
+            return Apic->ProcessorID;
+    }
+
+    BUG(__FUNCTION__);
+}
+
+#pragma warning(pop)
+
 KDEFERRED_ROUTINE   SystemCpuInformation;
 
 VOID
@@ -272,7 +364,11 @@ SystemCpuInformation(
 
     Cpu->ApicID = EBX >> 24;
 
-    Info("Local APIC ID: %02X\n", Cpu->ApicID);
+    Info("APIC ID: %02X\n", Cpu->ApicID);
+
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
     Info("<==== (%u)\n", Cpu->Index);
 
@@ -476,6 +572,10 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = SystemGetAcpiInformation();
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     SystemGetCpuInformation();
 
     status = SystemRegisterCallback(L"\\Callback\\PowerState",
@@ -483,10 +583,16 @@ SystemInitialize(
                                     NULL,
                                     &Context->Handle);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
 fail5:
     Error("fail5\n");
 
@@ -502,6 +608,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    (VOID) InterlockedDecrement(&Context->References);
+
     return status;
 }
 
@@ -516,7 +624,7 @@ SystemVirtualCpuIndex(
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
-    return Cpu->ApicID / 2;
+    return Cpu->ProcessorID;
 }
 
 VOID
@@ -531,6 +639,9 @@ SystemTeardown(
 
     RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
 
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
     (VOID) InterlockedDecrement(&Context->References);
 
     ASSERT(IsZeroMemory(Context, sizeof (SYSTEM_CONTEXT)));
diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj
index 2f4d958..9efeaf1 100644
--- a/vs2012/xen/xen.vcxproj
+++ b/vs2012/xen/xen.vcxproj
@@ -96,6 +96,7 @@
 		<ClCompile Include="..\..\src\xen\bug_check.c" />
 		<ClCompile Include="..\..\src\xen\module.c" />
 		<ClCompile Include="..\..\src\xen\process.c" />
+		<ClCompile Include="..\..\src\xen\acpi.c" />
 		<ClCompile Include="..\..\src\xen\system.c" />
 	</ItemGroup>
 	<ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 11:50:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 11:50:50 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1w54-00066k-LC; Fri, 19 Dec 2014 11:50:50 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1w53-00066e-2m
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 11:50:49 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	10/65-02702-81114945; Fri, 19 Dec 2014 11:50:48 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418989846!16165902!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14392 invoked from network); 19 Dec 2014 11:50:47 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 11:50:47 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206689329"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 06:50:45 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1w4x-000070-UZ;
	Fri, 19 Dec 2014 11:50:43 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 11:50:39 +0000
Message-ID: <1418989839-7616-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Matt Wilson <msw@linux.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2] Map Local APIC IDs to Processor IDs
	through the MADT
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

To use the FIFO EVTCHN ABI the frontend code needs to know the vcpu id of
the guest CPUs. This mapping is currently done by taking the the CPU local
APIC ID and dividing by 2. This currently works on most Xen installations
but Matt Wilson advises that this will not work on AWS.
This patch introduces code to map and parse the ACPI RSDP, XSDT and MADT
(APIC) tables such that the local APIC substructures present in the latter
can be used to map local APIC ID to processor ID (which is identical to
vcpu id).

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Matt Wilson <msw@linux.com>
---
v2:
 - Add missing line into vs2013 vcxproj

 src/xen/acpi.c         | 313 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/xen/acpi.h         | 108 +++++++++++++++++
 src/xen/driver.c       |  28 +++--
 src/xen/system.c       | 117 +++++++++++++++++-
 vs2012/xen/xen.vcxproj |   1 +
 vs2013/xen/xen.vcxproj |   1 +
 6 files changed, 556 insertions(+), 12 deletions(-)
 create mode 100644 src/xen/acpi.c
 create mode 100644 src/xen/acpi.h

diff --git a/src/xen/acpi.c b/src/xen/acpi.c
new file mode 100644
index 0000000..124dcb6
--- /dev/null
+++ b/src/xen/acpi.c
@@ -0,0 +1,313 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <util.h>
+
+#include "acpi.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define XENBUS_ACPI_TAG 'IPCA'
+
+static ACPI_RSDP    AcpiRsdp;
+static PACPI_XSDT   AcpiXsdt;
+
+static FORCEINLINE PVOID
+__AcpiAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_ACPI_TAG);
+}
+
+static FORCEINLINE VOID
+__AcpiFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_ACPI_TAG);
+}
+
+static BOOLEAN
+AcpiVerifyChecksum(
+    IN  PVOID   Table,
+    IN  ULONG   Length
+    )
+{
+    UCHAR       Sum;
+    ULONG       Index;
+
+    Sum = 0;
+    for (Index = 0; Index < Length; Index++)
+        Sum += ((PUCHAR)Table)[Index];
+
+    return (Sum == 0) ? TRUE : FALSE;
+}
+
+static NTSTATUS
+AcpiFindRsdp(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Start;
+    PHYSICAL_ADDRESS    End;
+    ULONG               Length;
+    PUCHAR              Data;
+    ULONG               Offset;
+    PACPI_RSDP          Rsdp;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (strncmp(AcpiRsdp.Signature,
+                "RSD PTR ",
+                sizeof (AcpiRsdp.Signature)) == 0)
+        goto done;
+
+    Start.QuadPart = 0xE0000;
+    End.QuadPart = 0xFFFFF;
+
+    Length = (ULONG)(End.QuadPart + 1 - Start.QuadPart);
+
+    Data = MmMapIoSpace(Start, Length, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Data == NULL)
+        goto fail1;
+
+    for (Offset = 0;
+         Offset + sizeof (ACPI_RSDP) < Length;
+         Offset += 16) {
+        Rsdp = (PACPI_RSDP)(Data + Offset);
+
+        if (strncmp(Rsdp->Signature,
+                    "RSD PTR ",
+                    sizeof (Rsdp->Signature)) == 0 &&
+            AcpiVerifyChecksum(Rsdp, sizeof (ACPI_RSDP)))
+            goto found;
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail2;
+
+found:
+    Info("0x%p\n", Start.QuadPart + Offset);
+
+    // Copy the table for reference
+    AcpiRsdp = *Rsdp;
+
+    MmUnmapIoSpace(Data, Length);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Data, Length);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+AcpiGetXsdt(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Address;
+    PACPI_XSDT          Xsdt;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (AcpiXsdt != NULL)
+        goto done;
+
+    Address.QuadPart = AcpiRsdp.XsdtAddress;
+
+    Info("0x%p\n", Address.QuadPart);
+
+    Xsdt = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Xsdt == NULL)
+        goto fail1;
+
+    if (strncmp(Xsdt->Header.Signature,
+                "XSDT",
+                sizeof (Xsdt->Header.Signature)) != 0)
+        goto fail2;
+
+    if (!AcpiVerifyChecksum(Xsdt, Xsdt->Header.Length))
+        goto fail3;
+
+    AcpiXsdt = __AcpiAllocate(Xsdt->Header.Length);
+
+    status = STATUS_NO_MEMORY;
+    if (AcpiXsdt == NULL)
+        goto fail4;
+
+    RtlCopyMemory(AcpiXsdt, Xsdt, Xsdt->Header.Length);
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    )
+{
+    ULONG               Count;
+    ULONG               Index;
+    PACPI_HEADER        Header;
+    NTSTATUS            status;
+
+    status = AcpiGetXsdt();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Count = (AcpiXsdt->Header.Length - FIELD_OFFSET(ACPI_XSDT, Entry)) /
+            sizeof (ULONG64);
+
+    for (Index = 0; Index < Count; Index++) {
+        PHYSICAL_ADDRESS    Address;
+
+        Address.QuadPart = AcpiXsdt->Entry[Index];
+
+        Header = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Header == NULL)
+            goto fail2;
+
+        if (strncmp(Header->Signature,
+                    Signature,
+                    sizeof (Header->Signature)) == 0 &&
+            AcpiVerifyChecksum(Header, Header->Length))
+            goto found;
+
+        MmUnmapIoSpace(Header, PAGE_SIZE);
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail3;
+
+found:
+    status = STATUS_BUFFER_OVERFLOW;
+    if (Buffer == NULL || Header->Length > *Length) {
+        *Length = Header->Length;
+        goto fail4;
+    }
+
+    RtlCopyMemory(Buffer, Header, Header->Length);
+
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+    return STATUS_SUCCESS;
+
+fail4:
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+fail3:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail3\n");
+
+fail2:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
+
+fail1:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiInitialize(
+    VOID
+    )
+{
+    NTSTATUS    status;
+
+    status = AcpiFindRsdp();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+AcpiTeardown(
+    VOID
+    )
+{
+    if (AcpiXsdt != NULL) {
+        __AcpiFree(AcpiXsdt);
+        AcpiXsdt = NULL;
+    }
+}
diff --git a/src/xen/acpi.h b/src/xen/acpi.h
new file mode 100644
index 0000000..334f62a
--- /dev/null
+++ b/src/xen/acpi.h
@@ -0,0 +1,108 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_ACPI_H
+#define _XEN_ACPI_H
+
+#include <ntddk.h>
+
+#pragma pack(push, 1)
+
+typedef struct _ACPI_RSDP {
+    CHAR    Signature[8];
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    UCHAR   Revision;
+    ULONG   RsdtAddress;
+    ULONG   Length;
+    ULONG64 XsdtAddress;
+    UCHAR   ExtendedChecksum;
+    UCHAR   Reserved[3];
+} ACPI_RSDP, *PACPI_RSDP;
+
+typedef struct _ACPI_HEADER {
+    CHAR    Signature[4];
+    ULONG   Length;
+    UCHAR   Revision;
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    CHAR    OemTableID[8];
+    ULONG   OemRevision;
+    CHAR    CreatorID[4];
+    ULONG   CreatorRevision;
+} ACPI_HEADER, *PACPI_HEADER;
+
+typedef struct _ACPI_XSDT {
+    ACPI_HEADER Header;
+    ULONG64     Entry[1];
+} ACPI_XSDT, *PACPI_XSDT;
+
+typedef struct _ACPI_MADT {
+    ACPI_HEADER Header;
+    ULONG       LocalAPICAddress;
+    ULONG       Flags;
+} ACPI_MADT, *PACPI_MADT;
+
+typedef struct _ACPI_MADT_HEADER {
+    UCHAR   Type;
+    UCHAR   Length;
+} ACPI_MADT_HEADER, *PACPI_MADT_HEADER;
+
+#define ACPI_MADT_TYPE_LOCAL_APIC   0x00
+
+typedef struct _ACPI_MADT_LOCAL_APIC {
+    ACPI_MADT_HEADER    Header;
+    UCHAR               ProcessorID;
+    UCHAR               ApicID;
+    ULONG               Flags;
+} ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC;
+
+#pragma pack(pop)
+
+extern NTSTATUS
+AcpiInitialize(
+    VOID
+    );
+
+extern NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    );
+
+extern VOID
+AcpiTeardown(
+    VOID
+    );
+
+#endif  // _XEN_ACPI_H
+
diff --git a/src/xen/driver.c b/src/xen/driver.c
index fce75aa..a4e91aa 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -39,6 +39,7 @@
 #include "module.h"
 #include "process.h"
 #include "system.h"
+#include "acpi.h"
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,50 +144,59 @@ DllInitialize(
          MONTH,
          YEAR);
 
-    status = SystemInitialize();
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = ProcessInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
 done:
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    ModuleTeardown();
+
 fail6:
     Error("fail6\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail5:
     Error("fail5\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail4:
     Error("fail4\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail3:
     Error("fail3\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail2:
     Error("fail2\n");
diff --git a/src/xen/system.c b/src/xen/system.c
index 1ac8123..0934ac8 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -40,23 +40,44 @@
 
 #include "registry.h"
 #include "system.h"
+#include "acpi.h"
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XEN_SYSTEM_TAG  'TSYS'
+
 typedef struct _SYSTEM_CPU {
     ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
+    UCHAR   ProcessorID;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
+    PACPI_MADT  Madt;
     SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
     PVOID       Handle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
 
+static FORCEINLINE PVOID
+__SystemAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_SYSTEM_TAG);
+}
+
+static FORCEINLINE VOID
+__SystemFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XEN_SYSTEM_TAG);
+}
+
 static FORCEINLINE const CHAR *
 __PlatformIdName(
     IN  ULONG   PlatformId
@@ -233,6 +254,77 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemGetAcpiInformation(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Length;
+    NTSTATUS        status;
+
+    status = AcpiGetTable("APIC", NULL, &Length);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        goto fail1;
+
+    Context->Madt = __SystemAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (Context->Madt == NULL)
+        goto fail2;
+
+    status = AcpiGetTable("APIC", Context->Madt, &Length);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4715)
+
+static UCHAR
+SystemApicIDToProcessorID(
+    IN  UCHAR   ApicID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    PACPI_MADT      Madt = Context->Madt;
+    ULONG           Offset;
+
+    Offset = sizeof (ACPI_MADT);
+    while (Offset < Madt->Header.Length) {
+        PACPI_MADT_HEADER       Header;
+        PACPI_MADT_LOCAL_APIC   Apic;
+
+        Header = (PACPI_MADT_HEADER)((PUCHAR)Madt + Offset);
+        Offset += Header->Length;
+
+        if (Header->Type != ACPI_MADT_TYPE_LOCAL_APIC)
+            continue;
+
+        Apic = CONTAINING_RECORD(Header, ACPI_MADT_LOCAL_APIC, Header);
+
+        if (Apic->ApicID == ApicID)
+            return Apic->ProcessorID;
+    }
+
+    BUG(__FUNCTION__);
+}
+
+#pragma warning(pop)
+
 KDEFERRED_ROUTINE   SystemCpuInformation;
 
 VOID
@@ -272,7 +364,11 @@ SystemCpuInformation(
 
     Cpu->ApicID = EBX >> 24;
 
-    Info("Local APIC ID: %02X\n", Cpu->ApicID);
+    Info("APIC ID: %02X\n", Cpu->ApicID);
+
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
     Info("<==== (%u)\n", Cpu->Index);
 
@@ -476,6 +572,10 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = SystemGetAcpiInformation();
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     SystemGetCpuInformation();
 
     status = SystemRegisterCallback(L"\\Callback\\PowerState",
@@ -483,10 +583,16 @@ SystemInitialize(
                                     NULL,
                                     &Context->Handle);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
 fail5:
     Error("fail5\n");
 
@@ -502,6 +608,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    (VOID) InterlockedDecrement(&Context->References);
+
     return status;
 }
 
@@ -516,7 +624,7 @@ SystemVirtualCpuIndex(
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
-    return Cpu->ApicID / 2;
+    return Cpu->ProcessorID;
 }
 
 VOID
@@ -531,6 +639,9 @@ SystemTeardown(
 
     RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
 
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
     (VOID) InterlockedDecrement(&Context->References);
 
     ASSERT(IsZeroMemory(Context, sizeof (SYSTEM_CONTEXT)));
diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj
index 2f4d958..9efeaf1 100644
--- a/vs2012/xen/xen.vcxproj
+++ b/vs2012/xen/xen.vcxproj
@@ -96,6 +96,7 @@
 		<ClCompile Include="..\..\src\xen\bug_check.c" />
 		<ClCompile Include="..\..\src\xen\module.c" />
 		<ClCompile Include="..\..\src\xen\process.c" />
+		<ClCompile Include="..\..\src\xen\acpi.c" />
 		<ClCompile Include="..\..\src\xen\system.c" />
 	</ItemGroup>
 	<ItemGroup>
diff --git a/vs2013/xen/xen.vcxproj b/vs2013/xen/xen.vcxproj
index 81d50ea..7a09960 100644
--- a/vs2013/xen/xen.vcxproj
+++ b/vs2013/xen/xen.vcxproj
@@ -136,6 +136,7 @@
     <ClCompile Include="..\..\src\xen\bug_check.c" />
     <ClCompile Include="..\..\src\xen\module.c" />
     <ClCompile Include="..\..\src\xen\process.c" />
+    <ClCompile Include="..\..\src\xen\acpi.c" />
     <ClCompile Include="..\..\src\xen\system.c" />
   </ItemGroup>
   <ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 11:50:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 11:50:50 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1w54-00066k-LC; Fri, 19 Dec 2014 11:50:50 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1w53-00066e-2m
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 11:50:49 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	10/65-02702-81114945; Fri, 19 Dec 2014 11:50:48 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1418989846!16165902!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14392 invoked from network); 19 Dec 2014 11:50:47 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 11:50:47 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206689329"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 06:50:45 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1w4x-000070-UZ;
	Fri, 19 Dec 2014 11:50:43 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 11:50:39 +0000
Message-ID: <1418989839-7616-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Matt Wilson <msw@linux.com>, Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2] Map Local APIC IDs to Processor IDs
	through the MADT
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

To use the FIFO EVTCHN ABI the frontend code needs to know the vcpu id of
the guest CPUs. This mapping is currently done by taking the the CPU local
APIC ID and dividing by 2. This currently works on most Xen installations
but Matt Wilson advises that this will not work on AWS.
This patch introduces code to map and parse the ACPI RSDP, XSDT and MADT
(APIC) tables such that the local APIC substructures present in the latter
can be used to map local APIC ID to processor ID (which is identical to
vcpu id).

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Matt Wilson <msw@linux.com>
---
v2:
 - Add missing line into vs2013 vcxproj

 src/xen/acpi.c         | 313 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/xen/acpi.h         | 108 +++++++++++++++++
 src/xen/driver.c       |  28 +++--
 src/xen/system.c       | 117 +++++++++++++++++-
 vs2012/xen/xen.vcxproj |   1 +
 vs2013/xen/xen.vcxproj |   1 +
 6 files changed, 556 insertions(+), 12 deletions(-)
 create mode 100644 src/xen/acpi.c
 create mode 100644 src/xen/acpi.h

diff --git a/src/xen/acpi.c b/src/xen/acpi.c
new file mode 100644
index 0000000..124dcb6
--- /dev/null
+++ b/src/xen/acpi.c
@@ -0,0 +1,313 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <stdarg.h>
+#include <xen.h>
+#include <util.h>
+
+#include "acpi.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define XENBUS_ACPI_TAG 'IPCA'
+
+static ACPI_RSDP    AcpiRsdp;
+static PACPI_XSDT   AcpiXsdt;
+
+static FORCEINLINE PVOID
+__AcpiAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_ACPI_TAG);
+}
+
+static FORCEINLINE VOID
+__AcpiFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_ACPI_TAG);
+}
+
+static BOOLEAN
+AcpiVerifyChecksum(
+    IN  PVOID   Table,
+    IN  ULONG   Length
+    )
+{
+    UCHAR       Sum;
+    ULONG       Index;
+
+    Sum = 0;
+    for (Index = 0; Index < Length; Index++)
+        Sum += ((PUCHAR)Table)[Index];
+
+    return (Sum == 0) ? TRUE : FALSE;
+}
+
+static NTSTATUS
+AcpiFindRsdp(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Start;
+    PHYSICAL_ADDRESS    End;
+    ULONG               Length;
+    PUCHAR              Data;
+    ULONG               Offset;
+    PACPI_RSDP          Rsdp;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (strncmp(AcpiRsdp.Signature,
+                "RSD PTR ",
+                sizeof (AcpiRsdp.Signature)) == 0)
+        goto done;
+
+    Start.QuadPart = 0xE0000;
+    End.QuadPart = 0xFFFFF;
+
+    Length = (ULONG)(End.QuadPart + 1 - Start.QuadPart);
+
+    Data = MmMapIoSpace(Start, Length, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Data == NULL)
+        goto fail1;
+
+    for (Offset = 0;
+         Offset + sizeof (ACPI_RSDP) < Length;
+         Offset += 16) {
+        Rsdp = (PACPI_RSDP)(Data + Offset);
+
+        if (strncmp(Rsdp->Signature,
+                    "RSD PTR ",
+                    sizeof (Rsdp->Signature)) == 0 &&
+            AcpiVerifyChecksum(Rsdp, sizeof (ACPI_RSDP)))
+            goto found;
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail2;
+
+found:
+    Info("0x%p\n", Start.QuadPart + Offset);
+
+    // Copy the table for reference
+    AcpiRsdp = *Rsdp;
+
+    MmUnmapIoSpace(Data, Length);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Data, Length);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+AcpiGetXsdt(
+    VOID
+    )
+{
+    PHYSICAL_ADDRESS    Address;
+    PACPI_XSDT          Xsdt;
+    NTSTATUS            status;
+
+    Trace("====>\n");
+
+    if (AcpiXsdt != NULL)
+        goto done;
+
+    Address.QuadPart = AcpiRsdp.XsdtAddress;
+
+    Info("0x%p\n", Address.QuadPart);
+
+    Xsdt = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Xsdt == NULL)
+        goto fail1;
+
+    if (strncmp(Xsdt->Header.Signature,
+                "XSDT",
+                sizeof (Xsdt->Header.Signature)) != 0)
+        goto fail2;
+
+    if (!AcpiVerifyChecksum(Xsdt, Xsdt->Header.Length))
+        goto fail3;
+
+    AcpiXsdt = __AcpiAllocate(Xsdt->Header.Length);
+
+    status = STATUS_NO_MEMORY;
+    if (AcpiXsdt == NULL)
+        goto fail4;
+
+    RtlCopyMemory(AcpiXsdt, Xsdt, Xsdt->Header.Length);
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Xsdt, PAGE_SIZE);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    )
+{
+    ULONG               Count;
+    ULONG               Index;
+    PACPI_HEADER        Header;
+    NTSTATUS            status;
+
+    status = AcpiGetXsdt();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Count = (AcpiXsdt->Header.Length - FIELD_OFFSET(ACPI_XSDT, Entry)) /
+            sizeof (ULONG64);
+
+    for (Index = 0; Index < Count; Index++) {
+        PHYSICAL_ADDRESS    Address;
+
+        Address.QuadPart = AcpiXsdt->Entry[Index];
+
+        Header = MmMapIoSpace(Address, PAGE_SIZE, MmCached);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Header == NULL)
+            goto fail2;
+
+        if (strncmp(Header->Signature,
+                    Signature,
+                    sizeof (Header->Signature)) == 0 &&
+            AcpiVerifyChecksum(Header, Header->Length))
+            goto found;
+
+        MmUnmapIoSpace(Header, PAGE_SIZE);
+    }
+
+    status = STATUS_UNSUCCESSFUL;
+    goto fail3;
+
+found:
+    status = STATUS_BUFFER_OVERFLOW;
+    if (Buffer == NULL || Header->Length > *Length) {
+        *Length = Header->Length;
+        goto fail4;
+    }
+
+    RtlCopyMemory(Buffer, Header, Header->Length);
+
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+    return STATUS_SUCCESS;
+
+fail4:
+    MmUnmapIoSpace(Header, PAGE_SIZE);
+
+fail3:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail3\n");
+
+fail2:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
+
+fail1:
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+AcpiInitialize(
+    VOID
+    )
+{
+    NTSTATUS    status;
+
+    status = AcpiFindRsdp();
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+AcpiTeardown(
+    VOID
+    )
+{
+    if (AcpiXsdt != NULL) {
+        __AcpiFree(AcpiXsdt);
+        AcpiXsdt = NULL;
+    }
+}
diff --git a/src/xen/acpi.h b/src/xen/acpi.h
new file mode 100644
index 0000000..334f62a
--- /dev/null
+++ b/src/xen/acpi.h
@@ -0,0 +1,108 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XEN_ACPI_H
+#define _XEN_ACPI_H
+
+#include <ntddk.h>
+
+#pragma pack(push, 1)
+
+typedef struct _ACPI_RSDP {
+    CHAR    Signature[8];
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    UCHAR   Revision;
+    ULONG   RsdtAddress;
+    ULONG   Length;
+    ULONG64 XsdtAddress;
+    UCHAR   ExtendedChecksum;
+    UCHAR   Reserved[3];
+} ACPI_RSDP, *PACPI_RSDP;
+
+typedef struct _ACPI_HEADER {
+    CHAR    Signature[4];
+    ULONG   Length;
+    UCHAR   Revision;
+    UCHAR   Checksum;
+    CHAR    OemID[6];
+    CHAR    OemTableID[8];
+    ULONG   OemRevision;
+    CHAR    CreatorID[4];
+    ULONG   CreatorRevision;
+} ACPI_HEADER, *PACPI_HEADER;
+
+typedef struct _ACPI_XSDT {
+    ACPI_HEADER Header;
+    ULONG64     Entry[1];
+} ACPI_XSDT, *PACPI_XSDT;
+
+typedef struct _ACPI_MADT {
+    ACPI_HEADER Header;
+    ULONG       LocalAPICAddress;
+    ULONG       Flags;
+} ACPI_MADT, *PACPI_MADT;
+
+typedef struct _ACPI_MADT_HEADER {
+    UCHAR   Type;
+    UCHAR   Length;
+} ACPI_MADT_HEADER, *PACPI_MADT_HEADER;
+
+#define ACPI_MADT_TYPE_LOCAL_APIC   0x00
+
+typedef struct _ACPI_MADT_LOCAL_APIC {
+    ACPI_MADT_HEADER    Header;
+    UCHAR               ProcessorID;
+    UCHAR               ApicID;
+    ULONG               Flags;
+} ACPI_MADT_LOCAL_APIC, *PACPI_MADT_LOCAL_APIC;
+
+#pragma pack(pop)
+
+extern NTSTATUS
+AcpiInitialize(
+    VOID
+    );
+
+extern NTSTATUS
+AcpiGetTable(
+    IN      const CHAR  *Signature,
+    OUT     PVOID       Buffer OPTIONAL,
+    IN OUT  PULONG      Length
+    );
+
+extern VOID
+AcpiTeardown(
+    VOID
+    );
+
+#endif  // _XEN_ACPI_H
+
diff --git a/src/xen/driver.c b/src/xen/driver.c
index fce75aa..a4e91aa 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -39,6 +39,7 @@
 #include "module.h"
 #include "process.h"
 #include "system.h"
+#include "acpi.h"
 #include "bug_check.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -143,50 +144,59 @@ DllInitialize(
          MONTH,
          YEAR);
 
-    status = SystemInitialize();
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = ProcessInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
 done:
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    ModuleTeardown();
+
 fail6:
     Error("fail6\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail5:
     Error("fail5\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail4:
     Error("fail4\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail3:
     Error("fail3\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail2:
     Error("fail2\n");
diff --git a/src/xen/system.c b/src/xen/system.c
index 1ac8123..0934ac8 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -40,23 +40,44 @@
 
 #include "registry.h"
 #include "system.h"
+#include "acpi.h"
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XEN_SYSTEM_TAG  'TSYS'
+
 typedef struct _SYSTEM_CPU {
     ULONG   Index;
     CHAR    Manufacturer[13];
     UCHAR   ApicID;
+    UCHAR   ProcessorID;
 } SYSTEM_CPU, *PSYSTEM_CPU;
 
 typedef struct _SYSTEM_CONTEXT {
     LONG        References;
+    PACPI_MADT  Madt;
     SYSTEM_CPU  Cpu[MAXIMUM_PROCESSORS];
     PVOID       Handle;
 } SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
 
 static SYSTEM_CONTEXT   SystemContext;
 
+static FORCEINLINE PVOID
+__SystemAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XEN_SYSTEM_TAG);
+}
+
+static FORCEINLINE VOID
+__SystemFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XEN_SYSTEM_TAG);
+}
+
 static FORCEINLINE const CHAR *
 __PlatformIdName(
     IN  ULONG   PlatformId
@@ -233,6 +254,77 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+SystemGetAcpiInformation(
+    VOID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    ULONG           Length;
+    NTSTATUS        status;
+
+    status = AcpiGetTable("APIC", NULL, &Length);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        goto fail1;
+
+    Context->Madt = __SystemAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (Context->Madt == NULL)
+        goto fail2;
+
+    status = AcpiGetTable("APIC", Context->Madt, &Length);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#pragma warning(push)
+#pragma warning(disable:4715)
+
+static UCHAR
+SystemApicIDToProcessorID(
+    IN  UCHAR   ApicID
+    )
+{
+    PSYSTEM_CONTEXT Context = &SystemContext;
+    PACPI_MADT      Madt = Context->Madt;
+    ULONG           Offset;
+
+    Offset = sizeof (ACPI_MADT);
+    while (Offset < Madt->Header.Length) {
+        PACPI_MADT_HEADER       Header;
+        PACPI_MADT_LOCAL_APIC   Apic;
+
+        Header = (PACPI_MADT_HEADER)((PUCHAR)Madt + Offset);
+        Offset += Header->Length;
+
+        if (Header->Type != ACPI_MADT_TYPE_LOCAL_APIC)
+            continue;
+
+        Apic = CONTAINING_RECORD(Header, ACPI_MADT_LOCAL_APIC, Header);
+
+        if (Apic->ApicID == ApicID)
+            return Apic->ProcessorID;
+    }
+
+    BUG(__FUNCTION__);
+}
+
+#pragma warning(pop)
+
 KDEFERRED_ROUTINE   SystemCpuInformation;
 
 VOID
@@ -272,7 +364,11 @@ SystemCpuInformation(
 
     Cpu->ApicID = EBX >> 24;
 
-    Info("Local APIC ID: %02X\n", Cpu->ApicID);
+    Info("APIC ID: %02X\n", Cpu->ApicID);
+
+    Cpu->ProcessorID = SystemApicIDToProcessorID(Cpu->ApicID);
+
+    Info("PROCESSOR ID: %02X\n", Cpu->ProcessorID);
 
     Info("<==== (%u)\n", Cpu->Index);
 
@@ -476,6 +572,10 @@ SystemInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = SystemGetAcpiInformation();
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
     SystemGetCpuInformation();
 
     status = SystemRegisterCallback(L"\\Callback\\PowerState",
@@ -483,10 +583,16 @@ SystemInitialize(
                                     NULL,
                                     &Context->Handle);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
 fail5:
     Error("fail5\n");
 
@@ -502,6 +608,8 @@ fail2:
 fail1:
     Error("fail1 (%08x)\n", status);
 
+    (VOID) InterlockedDecrement(&Context->References);
+
     return status;
 }
 
@@ -516,7 +624,7 @@ SystemVirtualCpuIndex(
 
     ASSERT3U(Index, <, MAXIMUM_PROCESSORS);
 
-    return Cpu->ApicID / 2;
+    return Cpu->ProcessorID;
 }
 
 VOID
@@ -531,6 +639,9 @@ SystemTeardown(
 
     RtlZeroMemory(Context->Cpu, sizeof (SYSTEM_CPU) * MAXIMUM_PROCESSORS);
 
+    __SystemFree(Context->Madt);
+    Context->Madt = NULL;
+
     (VOID) InterlockedDecrement(&Context->References);
 
     ASSERT(IsZeroMemory(Context, sizeof (SYSTEM_CONTEXT)));
diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj
index 2f4d958..9efeaf1 100644
--- a/vs2012/xen/xen.vcxproj
+++ b/vs2012/xen/xen.vcxproj
@@ -96,6 +96,7 @@
 		<ClCompile Include="..\..\src\xen\bug_check.c" />
 		<ClCompile Include="..\..\src\xen\module.c" />
 		<ClCompile Include="..\..\src\xen\process.c" />
+		<ClCompile Include="..\..\src\xen\acpi.c" />
 		<ClCompile Include="..\..\src\xen\system.c" />
 	</ItemGroup>
 	<ItemGroup>
diff --git a/vs2013/xen/xen.vcxproj b/vs2013/xen/xen.vcxproj
index 81d50ea..7a09960 100644
--- a/vs2013/xen/xen.vcxproj
+++ b/vs2013/xen/xen.vcxproj
@@ -136,6 +136,7 @@
     <ClCompile Include="..\..\src\xen\bug_check.c" />
     <ClCompile Include="..\..\src\xen\module.c" />
     <ClCompile Include="..\..\src\xen\process.c" />
+    <ClCompile Include="..\..\src\xen\acpi.c" />
     <ClCompile Include="..\..\src\xen\system.c" />
   </ItemGroup>
   <ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:17 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:17 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJ3-0006uY-39; Fri, 19 Dec 2014 12:05:17 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJ2-0006uT-Ak
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:16 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	2E/C6-09842-B7414945; Fri, 19 Dec 2014 12:05:15 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-21.messagelabs.com!1418990714!16774890!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1601 invoked from network); 19 Dec 2014 12:05:15 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206692888"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:13 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wIy-0000P1-Bs;
	Fri, 19 Dec 2014 12:05:12 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:09 +0000
Message-ID: <1418990709-9588-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Make sure version header gets re-built each
	time
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 build.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/build.py b/build.py
index 5368181..786106b 100644
--- a/build.py
+++ b/build.py
@@ -329,6 +329,8 @@ if __name__ == '__main__':
     sdv = { 'nosdv': False, None: True }
     driver = 'xenbus'
     vs = getVsVersion()
+
+    os.utime('include/version.hx', None)
     
     if 'COMPANY_NAME' not in os.environ.keys():
         os.environ['COMPANY_NAME'] = 'Xen Project'
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:17 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:17 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJ3-0006uY-39; Fri, 19 Dec 2014 12:05:17 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJ2-0006uT-Ak
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:16 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	2E/C6-09842-B7414945; Fri, 19 Dec 2014 12:05:15 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-21.messagelabs.com!1418990714!16774890!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1601 invoked from network); 19 Dec 2014 12:05:15 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-14.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206692888"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:13 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wIy-0000P1-Bs;
	Fri, 19 Dec 2014 12:05:12 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:09 +0000
Message-ID: <1418990709-9588-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH] Make sure version header gets re-built each
	time
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 build.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/build.py b/build.py
index 5368181..786106b 100644
--- a/build.py
+++ b/build.py
@@ -329,6 +329,8 @@ if __name__ == '__main__':
     sdv = { 'nosdv': False, None: True }
     driver = 'xenbus'
     vs = getVsVersion()
+
+    os.utime('include/version.hx', None)
     
     if 'COMPANY_NAME' not in os.environ.keys():
         os.environ['COMPANY_NAME'] = 'Xen Project'
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJg-0006vJ-5g; Fri, 19 Dec 2014 12:05:56 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJe-0006v8-Vv
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:55 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	23/AE-25276-2A414945; Fri, 19 Dec 2014 12:05:54 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1418990752!16755944!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20461 invoked from network); 19 Dec 2014 12:05:53 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206693179"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:52 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wJb-0000Pj-LE;
	Fri, 19 Dec 2014 12:05:51 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:49 +0000
Message-ID: <1418990749-8200-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
References: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Make sure version header gets re-built
	each time
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 build.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/build.py b/build.py
index a0053e5..8affee5 100644
--- a/build.py
+++ b/build.py
@@ -329,6 +329,8 @@ if __name__ == '__main__':
     driver = 'xenvif'
     vs = getVsVersion()
 
+    os.utime('include/version.hx', None)
+
     if 'COMPANY_NAME' not in os.environ.keys():
         os.environ['COMPANY_NAME'] = 'Xen Project'
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:56 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJg-0006vJ-5g; Fri, 19 Dec 2014 12:05:56 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJe-0006v8-Vv
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:55 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	23/AE-25276-2A414945; Fri, 19 Dec 2014 12:05:54 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1418990752!16755944!1
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20461 invoked from network); 19 Dec 2014 12:05:53 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:53 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206693179"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:52 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wJb-0000Pj-LE;
	Fri, 19 Dec 2014 12:05:51 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:49 +0000
Message-ID: <1418990749-8200-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
References: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Make sure version header gets re-built
	each time
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 build.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/build.py b/build.py
index a0053e5..8affee5 100644
--- a/build.py
+++ b/build.py
@@ -329,6 +329,8 @@ if __name__ == '__main__':
     driver = 'xenvif'
     vs = getVsVersion()
 
+    os.utime('include/version.hx', None)
+
     if 'COMPANY_NAME' not in os.environ.keys():
         os.environ['COMPANY_NAME'] = 'Xen Project'
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:57 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJh-0006vg-6t; Fri, 19 Dec 2014 12:05:57 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJf-0006vE-Vb
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:56 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	AB/CF-15461-3A414945; Fri, 19 Dec 2014 12:05:55 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1418990752!16755944!2
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20534 invoked from network); 19 Dec 2014 12:05:54 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206693180"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:52 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wJb-0000Pj-Kj;
	Fri, 19 Dec 2014 12:05:51 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:48 +0000
Message-ID: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 1/2] Squash buffer overlow error messages in
	transmit
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Occasionally packets are too fragmented to fit into the maximum number of
requests allowed by the netif protocol. In this case the packet preparation
function will fail with STATUS_BUFFER_OVERFLOW and the alternative copy-
coalesce prepation function will be called. These error messages are
therefore un-interesting (since the number of packets directly granted vs.
those that were copied is available in the statistics dump initiated by the
debug VIRQ).
This patch squashes the error messages to avoid filling logs.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/transmitter.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..29d17fa 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -787,7 +787,8 @@ __TransmitterRingGrantPayload(
 
 fail3:
 fail2:
-    Error("fail2\n");
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
 
     if (Fragment != NULL) {
         ASSERT3P(Fragment->Context, ==, Packet);
@@ -800,7 +801,8 @@ fail2:
     }
 
 fail1:
-    Error("fail1 (%08x)\n", status);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
 
     ASSERT3P(Fragment, ==, NULL);
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 12:05:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 12:05:57 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y1wJh-0006vg-6t; Fri, 19 Dec 2014 12:05:57 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y1wJf-0006vE-Vb
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 12:05:56 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	AB/CF-15461-3A414945; Fri, 19 Dec 2014 12:05:55 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1418990752!16755944!2
X-Originating-IP: [66.165.176.63]
X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: 
	VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20534 invoked from network); 19 Dec 2014 12:05:54 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 12:05:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,606,1413244800"; d="scan'208";a="206693180"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.79) with Microsoft SMTP Server id 14.3.210.2;
	Fri, 19 Dec 2014 07:05:52 -0500
Received: from fountains.uk.xensource.com ([10.80.2.29]
	helo=localhost.localdomain)	by ukmail1.uk.xensource.com with esmtp
	(Exim
	4.69)	(envelope-from <paul.durrant@citrix.com>)	id 1Y1wJb-0000Pj-Kj;
	Fri, 19 Dec 2014 12:05:51 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 19 Dec 2014 12:05:48 +0000
Message-ID: <1418990749-8200-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 1/2] Squash buffer overlow error messages in
	transmit
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

Occasionally packets are too fragmented to fit into the maximum number of
requests allowed by the netif protocol. In this case the packet preparation
function will fail with STATUS_BUFFER_OVERFLOW and the alternative copy-
coalesce prepation function will be called. These error messages are
therefore un-interesting (since the number of packets directly granted vs.
those that were copied is available in the statistics dump initiated by the
debug VIRQ).
This patch squashes the error messages to avoid filling logs.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/transmitter.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..29d17fa 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -787,7 +787,8 @@ __TransmitterRingGrantPayload(
 
 fail3:
 fail2:
-    Error("fail2\n");
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail2\n");
 
     if (Fragment != NULL) {
         ASSERT3P(Fragment->Context, ==, Packet);
@@ -800,7 +801,8 @@ fail2:
     }
 
 fail1:
-    Error("fail1 (%08x)\n", status);
+    if (status != STATUS_BUFFER_OVERFLOW)
+        Error("fail1 (%08x)\n", status);
 
     ASSERT3P(Fragment, ==, NULL);
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 17:22:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 17:22:21 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y21Ft-0004Rb-03; Fri, 19 Dec 2014 17:22:21 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y21Fr-0004RW-8h
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 17:22:19 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	E0/29-09842-ACE54945; Fri, 19 Dec 2014 17:22:18 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-21.messagelabs.com!1419009737!16808189!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23137 invoked from network); 19 Dec 2014 17:22:17 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 17:22:17 -0000
X-IronPort-AV: E=Sophos;i="5.07,607,1413244800"; d="scan'208";a="28072283"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Owen Smith <owen.smith@citrix.com>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>
Thread-Topic: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
Thread-Index: AQHQGucAkeJMX3qWREOBW29aThVWE5yXKq6A
Date: Fri, 19 Dec 2014 17:22:14 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025796736@AMSPEX01CL01.citrite.net>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
	<1418921673-6008-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1418921673-6008-2-git-send-email-owen.smith@citrix.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiB3aW4tcHYtZGV2ZWwtYm91bmNl
c0BsaXN0cy54ZW5wcm9qZWN0Lm9yZyBbbWFpbHRvOndpbi1wdi1kZXZlbC0NCj4gYm91bmNlc0Bs
aXN0cy54ZW5wcm9qZWN0Lm9yZ10gT24gQmVoYWxmIE9mIE93ZW4gU21pdGgNCj4gU2VudDogMTgg
RGVjZW1iZXIgMjAxNCAxNjo1NA0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qu
b3JnDQo+IENjOiBPd2VuIFNtaXRoDQo+IFN1YmplY3Q6IFt3aW4tcHYtZGV2ZWxdIFtQQVRDSCAx
LzZdIERvczJVbml4IGxpbmUgZW5kaW5ncw0KPiANCj4gU2lnbmVkLW9mZi1ieTogT3dlbiBTbWl0
aCA8b3dlbi5zbWl0aEBjaXRyaXguY29tPg0KDQpBY3R1YWxseSB0aGVyZSdzIG1vcmUgYnJlYWth
Z2UgdGhhbiBqdXN0IHRoaXMgZmlsZS4gSSdsbCByZXBsYWNlIHRoaXMgcGF0Y2ggd2l0aCBhIHBh
dGNoIHRvIGNsZWFuIHVwIGFsbCBicm9rZW4gZmlsZXMuDQoNCiAgUGF1bA0KDQo+IC0tLQ0KPiAg
dnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJvaiB8IDI1MiArKysrKysrKysrKysrKysrKysrKyst
LS0tLS0tLS0tLS0tLQ0KPiAtLS0tLS0tLQ0KPiAgMSBmaWxlIGNoYW5nZWQsIDEyNiBpbnNlcnRp
b25zKCspLCAxMjYgZGVsZXRpb25zKC0pDQo+IA0KPiBkaWZmIC0tZ2l0IGEvdnMyMDEzL3hlbm5l
dC94ZW5uZXQudmN4cHJvaiBiL3ZzMjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2oNCj4gaW5kZXgg
OTA4YmMyZC4uMGQ5OGYzYSAxMDA2NDQNCj4gLS0tIGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4
cHJvag0KPiArKysgYi92czIwMTMveGVubmV0L3hlbm5ldC52Y3hwcm9qDQo+IEBAIC0xLDEzMSAr
MSwxMzEgQEANCj4gLe+7vzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+
IC08UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIuMCINCj4g
eG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVpbGQvMjAw
MyI+DQo+IC0gIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4gLSAgPFBy
b3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4NCj4gLSAgICA8Q29uZmlndXJhdGlv
blR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4NCj4gLSAgICA8RHJpdmVyVHlwZT5XRE08
L0RyaXZlclR5cGU+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9Ikdsb2JhbHMiPg0KPiAtICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlzdGEgRGVi
dWc8L0NvbmZpZ3VyYXRpb24+DQo+IC0gICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQoUGxhdGZv
cm0pJyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPg0KPiAtICAgIDxEZWJ1Z2dlckZsYXZvcj5EYmdl
bmdLZXJuZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4N
Cj4gLSAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAuRGVm
YXVsdC5wcm9wcyIgLz4NCj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24i
DQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4
IFJlbGVhc2V8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9k
ZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0g
IDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENv
bmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBSZWxlYXNlfFdpbjMyJyI+DQo+
IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZv
cm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExh
YmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxh
dGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9v
bHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8
L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9u
Ig0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3Mg
VmlzdGEgRGVidWd8V2luMzInIj4NCj4gLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJu
ZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4N
Cj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0i
JyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxlYXNlfHg2
NCciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiAtICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9u
KXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIFZpc3RhDQo+IFJlbGVhc2V8V2luMzInIj4NCj4gLSAg
ICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRv
b2xzZXQ+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9
IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5X
aW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3Bl
cnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBD
b25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBSZWxl
YXNlfFdpbjMyJyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURy
aXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZp
Z3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPg0KPiAtICAgIDxQ
bGF0Zm9ybVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3Jv
dXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRp
b249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3xXaW4z
MiciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiAtICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9u
KXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcgRGVidWd8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3Jt
VG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAt
ICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0
aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgOCBEZWJ1Z3xXaW4zMiciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5l
bE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0K
PiAtICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSIn
JChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0JyI+DQo+
IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZv
cm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExh
YmVsPSJHbG9iYWxzIj4NCj4gLSAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMtNDg4Qy1C
NTEyLUM5NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+
IC0gIDxJbXBvcnQgUHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4NCj4gLSAgPEltcG9ydCBQ
cm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+DQo+IC0gIDxQ
cm9wZXJ0eUdyb3VwPg0KPiAtICAgIDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQoSW5jbHVk
ZVBhdGgpPC9JbmNsdWRlUGF0aD4NCj4gLSAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8L1J1bkNv
ZGVBbmFseXNpcz4NCj4gLSAgICA8RW5hYmxlSW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5mMmNhdD4N
Cj4gLQ0KPiA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPkNsQ29tcGlsZTtTdGFtcEluZjwvQ3Vz
dG9tQnVpbGRCZWZvcmVUYXJnZQ0KPiB0cz4NCj4gLSAgICA8SW50RGlyPi4uXCQoUHJvamVjdE5h
bWUpXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvSW50RGlyPg0KPiAtICAgIDxP
dXREaXI+Li5cJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlcPC9PdXREaXI+DQo+IC0g
IDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPEl0ZW1EZWZpbml0aW9uR3JvdXA+DQo+IC0gICAgPEN1
c3RvbUJ1aWxkU3RlcD4NCj4gK++7vzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04
Ij8+DQo+ICs8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIu
MCINCj4geG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVp
bGQvMjAwMyI+DQo+ICsgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4g
KyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4NCj4gKyAgICA8Q29uZmln
dXJhdGlvblR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4NCj4gKyAgICA8RHJpdmVyVHlw
ZT5XRE08L0RyaXZlclR5cGU+DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPFByb3BlcnR5
R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPg0KPiArICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlz
dGEgRGVidWc8L0NvbmZpZ3VyYXRpb24+DQo+ICsgICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQo
UGxhdGZvcm0pJyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPg0KPiArICAgIDxEZWJ1Z2dlckZsYXZv
cj5EYmdlbmdLZXJuZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+DQo+ICsgIDwvUHJvcGVydHlH
cm91cD4NCj4gKyAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5D
cHAuRGVmYXVsdC5wcm9wcyIgLz4NCj4gKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3Vy
YXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2lu
ZG93cyA4IFJlbGVhc2V8eDY0JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2Vy
bmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+
DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249
IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBSZWxlYXNlfFdpbjMy
JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwv
UGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24p
fCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+DQo+ICsgICAgPFBsYXRm
b3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0K
PiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dp
bmRvd3MgVmlzdGEgRGVidWd8V2luMzInIj4NCj4gKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRv
d3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+DQo+ICsgIDwvUHJvcGVydHlH
cm91cD4NCj4gKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRp
dGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxl
YXNlfHg2NCciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2
ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiArICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1
cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIFZpc3RhDQo+IFJlbGVhc2V8V2luMzInIj4N
Cj4gKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0
Zm9ybVRvb2xzZXQ+DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQ
bGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9v
bHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8
L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9u
Ig0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3Mg
NyBSZWxlYXNlfFdpbjMyJyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+
ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249Iick
KENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPg0KPiAr
ICAgIDxQbGF0Zm9ybVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3Bl
cnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBD
b25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1
Z3xXaW4zMiciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2
ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiArICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1
cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcgRGVidWd8eDY0JyI+DQo+ICsgICAgPFBs
YXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0
Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25m
aWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09
J1dpbmRvd3MgOCBEZWJ1Z3xXaW4zMiciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93
c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdy
b3VwPg0KPiArICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0
aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0
JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwv
UGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJHbG9iYWxzIj4NCj4gKyAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMt
NDg4Qy1CNTEyLUM5NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPg0KPiArICA8L1Byb3BlcnR5R3Jv
dXA+DQo+ICsgIDxJbXBvcnQgUHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4NCj4gKyAgPElt
cG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+DQo+
ICsgIDxQcm9wZXJ0eUdyb3VwPg0KPiArICAgIDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQo
SW5jbHVkZVBhdGgpPC9JbmNsdWRlUGF0aD4NCj4gKyAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8
L1J1bkNvZGVBbmFseXNpcz4NCj4gKyAgICA8RW5hYmxlSW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5m
MmNhdD4NCj4gKw0KPiA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPkNsQ29tcGlsZTtTdGFtcElu
ZjwvQ3VzdG9tQnVpbGRCZWZvcmVUYXJnZQ0KPiB0cz4NCj4gKyAgICA8SW50RGlyPi4uXCQoUHJv
amVjdE5hbWUpXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvSW50RGlyPg0KPiAr
ICAgIDxPdXREaXI+Li5cJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlcPC9PdXREaXI+
DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPEl0ZW1EZWZpbml0aW9uR3JvdXA+DQo+ICsg
ICAgPEN1c3RvbUJ1aWxkU3RlcD4NCj4gICAgICAgIDxDb21tYW5kPmVjaG8gIkJ1aWxkIEluZiIN
Cj4gICAgICAgICAgICAgICAgICBwb3dlcnNoZWxsIC1Db21tYW5kICIoR2V0LUNvbnRlbnQgLi5c
Li5cc3JjXHhlbm5ldC5pbmYpIC1yZXBsYWNlDQo+ICdATUFKT1JfVkVSU0lPTkAnLCAnJChNQUpP
Ul9WRVJTSU9OKScgLXJlcGxhY2UNCj4gJ0BNSU5PUl9WRVJTSU9OQCcsICckKE1JTk9SX1ZFUlNJ
T04pJyAtcmVwbGFjZQ0KPiAnQE1JQ1JPX1ZFUlNJT05AJywnJChNSUNST19WRVJTSU9OKScgLXJl
cGxhY2UNCj4gJ0BCVUlMRF9OVU1CRVJAJywnJChCVUlMRF9OVU1CRVIpJyAtcmVwbGFjZQ0KPiAn
QENPTVBBTllfTkFNRUAnLCckKENPTVBBTllfTkFNRSknIC1yZXBsYWNlDQo+ICdAUFJPRFVDVF9O
QU1FQCcsJyQoUFJPRFVDVF9OQU1FKScgfCBTZXQtQ29udGVudCAuLlx4ZW5uZXQuaW5mIg0KPiAg
ICAgICAgICAgICAgICAgIGVjaG8gIkJ1aWxkIHZlcnNpb24gaGVhZGVyIg0KPiAgICAgICAgICAg
ICAgICAgIHBvd2Vyc2hlbGwgLUNvbW1hbmQgIihHZXQtQ29udGVudCAuLlwuLlxpbmNsdWRlXHZl
cnNpb24uaHgpIC0NCj4gcmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFKT1JfVkVSU0lP
TiknIC1yZXBsYWNlDQo+ICdATUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9OKScgLXJl
cGxhY2UNCj4gJ0BNSUNST19WRVJTSU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNlDQo+
ICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJTERfTlVNQkVSKScgLXJlcGxhY2UNCj4gJ0BDT01QQU5Z
X05BTUVAJywnJChDT01QQU5ZX05BTUUpJyAtcmVwbGFjZQ0KPiAnQFBST0RVQ1RfTkFNRUAnLCck
KFBST0RVQ1RfTkFNRSknIC1yZXBsYWNlICdAREFZQCcsJTI0KEdldC0NCj4gRGF0ZSAtZm9ybWF0
ICUyNSUyNWQpIC1yZXBsYWNlICdATU9OVEhAJywlMjQoR2V0LURhdGUgLWZvcm1hdA0KPiAlMjUl
MjVNKSAtcmVwbGFjZSAnQFlFQVJAJywlMjQoR2V0LURhdGUgLWZvcm1hdCB5eXl5KSB8IFNldC1D
b250ZW50DQo+IC4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oIg0KPiAtICAgICAgICAgICAgPC9Db21t
YW5kPg0KPiAtICAgICAgPE91dHB1dHM+Li5ceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNp
b24uaDwvT3V0cHV0cz4NCj4gLSAgICAgIDxJbnB1dHM+Li5cLi5cc3JjXHhlbm5ldC5pbmY7Li5c
Li5caW5jbHVkZVx2ZXJzaW9uLmh4PC9JbnB1dHM+DQo+IC0gICAgPC9DdXN0b21CdWlsZFN0ZXA+
DQo+IC0gICAgPENsQ29tcGlsZT4NCj4gLQ0KPiA8UHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+X19N
T0RVTEVfXz0iWEVOTkVUIjtORElTX01JTklQT1JUX0RSSVZFDQo+IFI7TkRJUzYwX01JTklQT1JU
PTE7UE9PTF9OWF9PUFRJTj0xOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9Qcg0KPiBlcHJv
Y2Vzc29yRGVmaW5pdGlvbnM+DQo+IC0gICAgICA8V2FybmluZ0xldmVsPkVuYWJsZUFsbFdhcm5p
bmdzPC9XYXJuaW5nTGV2ZWw+DQo+IC0NCj4gPERpc2FibGVTcGVjaWZpY1dhcm5pbmdzPjQ3MTE7
NDU0ODs0ODIwOzQ2Njg7NDI1NTs2MDAxOzYwNTQ7MjgxOTY7JShEaXNhDQo+IGJsZVNwZWNpZmlj
V2FybmluZ3MpPC9EaXNhYmxlU3BlY2lmaWNXYXJuaW5ncz4NCj4gLSAgICAgIDxNdWx0aVByb2Nl
c3NvckNvbXBpbGF0aW9uPnRydWU8L011bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+DQo+IC0gICAg
ICA8RW5hYmxlUFJFZmFzdD50cnVlPC9FbmFibGVQUkVmYXN0Pg0KPiAtICAgIDwvQ2xDb21waWxl
Pg0KPiAtICAgIDxMaW5rPg0KPiAtDQo+IDxJbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5kbGVycz5m
YWxzZTwvSW1hZ2VIYXNTYWZlRXhjZXB0aW9uSGFuZGxlcnM+DQo+IC0NCj4gPEFkZGl0aW9uYWxE
ZXBlbmRlbmNpZXM+JChEREtfTElCX1BBVEgpXG5kaXMubGliOyUoQWRkaXRpb25hbERlcGVuZGUN
Cj4gbmNpZXMpPC9BZGRpdGlvbmFsRGVwZW5kZW5jaWVzPg0KPiAtICAgICAgPEVuYWJsZUNPTURB
VEZvbGRpbmc+ZmFsc2U8L0VuYWJsZUNPTURBVEZvbGRpbmc+DQo+IC0gICAgPC9MaW5rPg0KPiAt
ICAgIDxJbmY+DQo+IC0gICAgICA8U3BlY2lmeUFyY2hpdGVjdHVyZT50cnVlPC9TcGVjaWZ5QXJj
aGl0ZWN0dXJlPg0KPiAtDQo+IDxTcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbj50cnVl
PC9TcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbg0KPiA+DQo+IC0NCj4gPFRpbWVTdGFt
cD4kKE1BSk9SX1ZFUlNJT04pLiQoTUlOT1JfVkVSU0lPTikuJChNSUNST19WRVJTSU9OKS4NCj4g
JChCVUlMRF9OVU1CRVIpPC9UaW1lU3RhbXA+DQo+IC0gICAgICA8RW5hYmxlVmVyYm9zZT50cnVl
PC9FbmFibGVWZXJib3NlPg0KPiAtICAgIDwvSW5mPg0KPiAtICA8L0l0ZW1EZWZpbml0aW9uR3Jv
dXA+DQo+IC0gIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09
J1dpbjMyJyI+DQo+IC0gICAgPENsQ29tcGlsZT4NCj4gLQ0KPiA8UHJlcHJvY2Vzc29yRGVmaW5p
dGlvbnM+X19pMzg2X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXByb2Nlcw0KPiBz
b3JEZWZpbml0aW9ucz4NCj4gLSAgICA8L0NsQ29tcGlsZT4NCj4gLSAgICA8SW5mPg0KPiAtICAg
ICAgPEFyY2hpdGVjdHVyZT54ODY8L0FyY2hpdGVjdHVyZT4NCj4gLSAgICA8L0luZj4NCj4gLSAg
PC9JdGVtRGVmaW5pdGlvbkdyb3VwPg0KPiAtICA8SXRlbURlZmluaXRpb25Hcm91cCBDb25kaXRp
b249IickKFBsYXRmb3JtKSc9PSd4NjQnIj4NCj4gLSAgICA8Q2xDb21waWxlPg0KPiAtDQo+IDxQ
cmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX3g4Nl82NF9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlv
bnMpPC9QcmVwcm8NCj4gY2Vzc29yRGVmaW5pdGlvbnM+DQo+IC0gICAgPC9DbENvbXBpbGU+DQo+
IC0gICAgPEluZj4NCj4gLSAgICAgIDxBcmNoaXRlY3R1cmU+YW1kNjQ8L0FyY2hpdGVjdHVyZT4N
Cj4gLSAgICA8L0luZj4NCj4gLSAgPC9JdGVtRGVmaW5pdGlvbkdyb3VwPg0KPiAtICA8SXRlbUdy
b3VwPg0KPiAtICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRlPSIkKFRhcmdldFBhdGgpIiAvPg0K
PiAtICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRlPSIkKE91dERpcikkKFRhcmdldE5hbWUpLnBk
YiIgLz4NCj4gLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iQChJbmYtPiclKENvcHlPdXRw
dXQpJykiDQo+IENvbmRpdGlvbj0iJ0AoSW5mKSchPScnIiAvPg0KPiAtICA8L0l0ZW1Hcm91cD4N
Cj4gLSAgPEl0ZW1Hcm91cD4NCj4gLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94
ZW5uZXQvcmVnaXN0cnkuYyIgLz4NCj4gLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvYWRhcHRlci5jIiAvPg0KPiAtICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4v
c3JjL3hlbm5ldC9tYWluLmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9z
cmMveGVubmV0L21pbmlwb3J0LmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8u
Li9zcmMveGVubmV0L3JlY2VpdmVyLmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIu
Li8uLi9zcmMveGVubmV0L3RyYW5zbWl0dGVyLmMiIC8+DQo+IC0gIDwvSXRlbUdyb3VwPg0KPiAt
ICA8SXRlbUdyb3VwPg0KPiAtICAgIDxSZXNvdXJjZUNvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3Jj
XHhlbm5ldFx4ZW5uZXQucmMiIC8+DQo+IC0gIDwvSXRlbUdyb3VwPg0KPiAtICA8SXRlbUdyb3Vw
Pg0KPiAtICAgIDxJbmYgSW5jbHVkZT0iLi5ceGVubmV0LmluZiIgLz4NCj4gLSAgPC9JdGVtR3Jv
dXA+DQo+IC0gIDxJbXBvcnQgUHJvamVjdD0iJChWQ1RhcmdldHNQYXRoKVxNaWNyb3NvZnQuQ3Bw
LnRhcmdldHMiIC8+DQo+ICsgICAgICAgICAgICA8L0NvbW1hbmQ+DQo+ICsgICAgICA8T3V0cHV0
cz4uLlx4ZW5uZXQuaW5mOy4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oPC9PdXRwdXRzPg0KPiArICAg
ICAgPElucHV0cz4uLlwuLlxzcmNceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaHg8
L0lucHV0cz4NCj4gKyAgICA8L0N1c3RvbUJ1aWxkU3RlcD4NCj4gKyAgICA8Q2xDb21waWxlPg0K
PiArDQo+IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX01PRFVMRV9fPSJYRU5ORVQiO05ESVNf
TUlOSVBPUlRfRFJJVkUNCj4gUjtORElTNjBfTUlOSVBPUlQ9MTtQT09MX05YX09QVElOPTE7JShQ
cmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByDQo+IGVwcm9jZXNzb3JEZWZpbml0aW9ucz4NCj4g
KyAgICAgIDxXYXJuaW5nTGV2ZWw+RW5hYmxlQWxsV2FybmluZ3M8L1dhcm5pbmdMZXZlbD4NCj4g
Kw0KPiA8RGlzYWJsZVNwZWNpZmljV2FybmluZ3M+NDcxMTs0NTQ4OzQ4MjA7NDY2ODs0MjU1OzYw
MDE7NjA1NDsyODE5NjslKERpc2ENCj4gYmxlU3BlY2lmaWNXYXJuaW5ncyk8L0Rpc2FibGVTcGVj
aWZpY1dhcm5pbmdzPg0KPiArICAgICAgPE11bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+dHJ1ZTwv
TXVsdGlQcm9jZXNzb3JDb21waWxhdGlvbj4NCj4gKyAgICAgIDxFbmFibGVQUkVmYXN0PnRydWU8
L0VuYWJsZVBSRWZhc3Q+DQo+ICsgICAgPC9DbENvbXBpbGU+DQo+ICsgICAgPExpbms+DQo+ICsN
Cj4gPEltYWdlSGFzU2FmZUV4Y2VwdGlvbkhhbmRsZXJzPmZhbHNlPC9JbWFnZUhhc1NhZmVFeGNl
cHRpb25IYW5kbGVycz4NCj4gKw0KPiA8QWRkaXRpb25hbERlcGVuZGVuY2llcz4kKERES19MSUJf
UEFUSClcbmRpcy5saWI7JShBZGRpdGlvbmFsRGVwZW5kZQ0KPiBuY2llcyk8L0FkZGl0aW9uYWxE
ZXBlbmRlbmNpZXM+DQo+ICsgICAgICA8RW5hYmxlQ09NREFURm9sZGluZz5mYWxzZTwvRW5hYmxl
Q09NREFURm9sZGluZz4NCj4gKyAgICA8L0xpbms+DQo+ICsgICAgPEluZj4NCj4gKyAgICAgIDxT
cGVjaWZ5QXJjaGl0ZWN0dXJlPnRydWU8L1NwZWNpZnlBcmNoaXRlY3R1cmU+DQo+ICsNCj4gPFNw
ZWNpZnlEcml2ZXJWZXJEaXJlY3RpdmVWZXJzaW9uPnRydWU8L1NwZWNpZnlEcml2ZXJWZXJEaXJl
Y3RpdmVWZXJzaW9uDQo+ID4NCj4gKw0KPiA8VGltZVN0YW1wPiQoTUFKT1JfVkVSU0lPTikuJChN
SU5PUl9WRVJTSU9OKS4kKE1JQ1JPX1ZFUlNJT04pLg0KPiAkKEJVSUxEX05VTUJFUik8L1RpbWVT
dGFtcD4NCj4gKyAgICAgIDxFbmFibGVWZXJib3NlPnRydWU8L0VuYWJsZVZlcmJvc2U+DQo+ICsg
ICAgPC9JbmY+DQo+ICsgIDwvSXRlbURlZmluaXRpb25Hcm91cD4NCj4gKyAgPEl0ZW1EZWZpbml0
aW9uR3JvdXAgQ29uZGl0aW9uPSInJChQbGF0Zm9ybSknPT0nV2luMzInIj4NCj4gKyAgICA8Q2xD
b21waWxlPg0KPiArDQo+IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX2kzODZfXzslKFByZXBy
b2Nlc3NvckRlZmluaXRpb25zKTwvUHJlcHJvY2VzDQo+IHNvckRlZmluaXRpb25zPg0KPiArICAg
IDwvQ2xDb21waWxlPg0KPiArICAgIDxJbmY+DQo+ICsgICAgICA8QXJjaGl0ZWN0dXJlPng4Njwv
QXJjaGl0ZWN0dXJlPg0KPiArICAgIDwvSW5mPg0KPiArICA8L0l0ZW1EZWZpbml0aW9uR3JvdXA+
DQo+ICsgIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09J3g2
NCciPg0KPiArICAgIDxDbENvbXBpbGU+DQo+ICsNCj4gPFByZXByb2Nlc3NvckRlZmluaXRpb25z
Pl9feDg2XzY0X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXBybw0KPiBjZXNzb3JE
ZWZpbml0aW9ucz4NCj4gKyAgICA8L0NsQ29tcGlsZT4NCj4gKyAgICA8SW5mPg0KPiArICAgICAg
PEFyY2hpdGVjdHVyZT5hbWQ2NDwvQXJjaGl0ZWN0dXJlPg0KPiArICAgIDwvSW5mPg0KPiArICA8
L0l0ZW1EZWZpbml0aW9uR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAgPEZpbGVzVG9Q
YWNrYWdlIEluY2x1ZGU9IiQoVGFyZ2V0UGF0aCkiIC8+DQo+ICsgICAgPEZpbGVzVG9QYWNrYWdl
IEluY2x1ZGU9IiQoT3V0RGlyKSQoVGFyZ2V0TmFtZSkucGRiIiAvPg0KPiArICAgIDxGaWxlc1Rv
UGFja2FnZSBJbmNsdWRlPSJAKEluZi0+JyUoQ29weU91dHB1dCknKSINCj4gQ29uZGl0aW9uPSIn
QChJbmYpJyE9JyciIC8+DQo+ICsgIDwvSXRlbUdyb3VwPg0KPiArICA8SXRlbUdyb3VwPg0KPiAr
ICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9yZWdpc3RyeS5jIiAvPg0K
PiArICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9hZGFwdGVyLmMiIC8+
DQo+ICsgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVubmV0L21haW4uYyIgLz4N
Cj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvbWluaXBvcnQuYyIg
Lz4NCj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvcmVjZWl2ZXIu
YyIgLz4NCj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvdHJhbnNt
aXR0ZXIuYyIgLz4NCj4gKyAgPC9JdGVtR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAg
PFJlc291cmNlQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVubmV0XHhlbm5ldC5yYyIgLz4N
Cj4gKyAgPC9JdGVtR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAgPEluZiBJbmNsdWRl
PSIuLlx4ZW5uZXQuaW5mIiAvPg0KPiArICA8L0l0ZW1Hcm91cD4NCj4gKyAgPEltcG9ydCBQcm9q
ZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAudGFyZ2V0cyIgLz4NCj4gIDwvUHJv
amVjdD4NCj4gXCBObyBuZXdsaW5lIGF0IGVuZCBvZiBmaWxlDQo+IC0tDQo+IDEuOS40Lm1zeXNn
aXQuMQ0KPiANCj4gDQo+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fDQo+IHdpbi1wdi1kZXZlbCBtYWlsaW5nIGxpc3QNCj4gd2luLXB2LWRldmVsQGxpc3Rz
LnhlbnByb2plY3Qub3JnDQo+IGh0dHA6Ly9saXN0cy54ZW5wcm9qZWN0Lm9yZy9jZ2ktYmluL21h
aWxtYW4vbGlzdGluZm8vd2luLXB2LWRldmVsDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1kZXZl
bEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dpLWJp
bi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 17:22:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 17:22:21 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y21Ft-0004Rb-03; Fri, 19 Dec 2014 17:22:21 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y21Fr-0004RW-8h
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 17:22:19 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	E0/29-09842-ACE54945; Fri, 19 Dec 2014 17:22:18 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-21.messagelabs.com!1419009737!16808189!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23137 invoked from network); 19 Dec 2014 17:22:17 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 17:22:17 -0000
X-IronPort-AV: E=Sophos;i="5.07,607,1413244800"; d="scan'208";a="28072283"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Owen Smith <owen.smith@citrix.com>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>
Thread-Topic: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
Thread-Index: AQHQGucAkeJMX3qWREOBW29aThVWE5yXKq6A
Date: Fri, 19 Dec 2014 17:22:14 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025796736@AMSPEX01CL01.citrite.net>
References: <1418921673-6008-1-git-send-email-owen.smith@citrix.com>
	<1418921673-6008-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1418921673-6008-2-git-send-email-owen.smith@citrix.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Cc: Owen Smith <owen.smith@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 1/6] Dos2Unix line endings
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiB3aW4tcHYtZGV2ZWwtYm91bmNl
c0BsaXN0cy54ZW5wcm9qZWN0Lm9yZyBbbWFpbHRvOndpbi1wdi1kZXZlbC0NCj4gYm91bmNlc0Bs
aXN0cy54ZW5wcm9qZWN0Lm9yZ10gT24gQmVoYWxmIE9mIE93ZW4gU21pdGgNCj4gU2VudDogMTgg
RGVjZW1iZXIgMjAxNCAxNjo1NA0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qu
b3JnDQo+IENjOiBPd2VuIFNtaXRoDQo+IFN1YmplY3Q6IFt3aW4tcHYtZGV2ZWxdIFtQQVRDSCAx
LzZdIERvczJVbml4IGxpbmUgZW5kaW5ncw0KPiANCj4gU2lnbmVkLW9mZi1ieTogT3dlbiBTbWl0
aCA8b3dlbi5zbWl0aEBjaXRyaXguY29tPg0KDQpBY3R1YWxseSB0aGVyZSdzIG1vcmUgYnJlYWth
Z2UgdGhhbiBqdXN0IHRoaXMgZmlsZS4gSSdsbCByZXBsYWNlIHRoaXMgcGF0Y2ggd2l0aCBhIHBh
dGNoIHRvIGNsZWFuIHVwIGFsbCBicm9rZW4gZmlsZXMuDQoNCiAgUGF1bA0KDQo+IC0tLQ0KPiAg
dnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4cHJvaiB8IDI1MiArKysrKysrKysrKysrKysrKysrKyst
LS0tLS0tLS0tLS0tLQ0KPiAtLS0tLS0tLQ0KPiAgMSBmaWxlIGNoYW5nZWQsIDEyNiBpbnNlcnRp
b25zKCspLCAxMjYgZGVsZXRpb25zKC0pDQo+IA0KPiBkaWZmIC0tZ2l0IGEvdnMyMDEzL3hlbm5l
dC94ZW5uZXQudmN4cHJvaiBiL3ZzMjAxMy94ZW5uZXQveGVubmV0LnZjeHByb2oNCj4gaW5kZXgg
OTA4YmMyZC4uMGQ5OGYzYSAxMDA2NDQNCj4gLS0tIGEvdnMyMDEzL3hlbm5ldC94ZW5uZXQudmN4
cHJvag0KPiArKysgYi92czIwMTMveGVubmV0L3hlbm5ldC52Y3hwcm9qDQo+IEBAIC0xLDEzMSAr
MSwxMzEgQEANCj4gLe+7vzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+
IC08UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIuMCINCj4g
eG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVpbGQvMjAw
MyI+DQo+IC0gIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4gLSAgPFBy
b3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4NCj4gLSAgICA8Q29uZmlndXJhdGlv
blR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4NCj4gLSAgICA8RHJpdmVyVHlwZT5XRE08
L0RyaXZlclR5cGU+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9Ikdsb2JhbHMiPg0KPiAtICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlzdGEgRGVi
dWc8L0NvbmZpZ3VyYXRpb24+DQo+IC0gICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQoUGxhdGZv
cm0pJyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPg0KPiAtICAgIDxEZWJ1Z2dlckZsYXZvcj5EYmdl
bmdLZXJuZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4N
Cj4gLSAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAuRGVm
YXVsdC5wcm9wcyIgLz4NCj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24i
DQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyA4
IFJlbGVhc2V8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9k
ZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0g
IDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENv
bmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBSZWxlYXNlfFdpbjMyJyI+DQo+
IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZv
cm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExh
YmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxh
dGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9v
bHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8
L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9u
Ig0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3Mg
VmlzdGEgRGVidWd8V2luMzInIj4NCj4gLSAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJu
ZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4N
Cj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0i
JyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxlYXNlfHg2
NCciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiAtICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9u
KXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIFZpc3RhDQo+IFJlbGVhc2V8V2luMzInIj4NCj4gLSAg
ICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRv
b2xzZXQ+DQo+IC0gIDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPFByb3BlcnR5R3JvdXAgTGFiZWw9
IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9y
bSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5X
aW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3Bl
cnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBD
b25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBSZWxl
YXNlfFdpbjMyJyI+DQo+IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURy
aXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQ
cm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZp
Z3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPg0KPiAtICAgIDxQ
bGF0Zm9ybVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3Jv
dXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRp
b249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1Z3xXaW4z
MiciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2ZXI4LjE8
L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiAtICA8UHJvcGVydHlH
cm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1cmF0aW9u
KXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcgRGVidWd8eDY0JyI+DQo+IC0gICAgPFBsYXRmb3Jt
VG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiAt
ICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0
aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRv
d3MgOCBEZWJ1Z3xXaW4zMiciPg0KPiAtICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5l
bE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gLSAgPC9Qcm9wZXJ0eUdyb3VwPg0K
PiAtICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSIn
JChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0JyI+DQo+
IC0gICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZv
cm1Ub29sc2V0Pg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+IC0gIDxQcm9wZXJ0eUdyb3VwIExh
YmVsPSJHbG9iYWxzIj4NCj4gLSAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMtNDg4Qy1C
NTEyLUM5NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPg0KPiAtICA8L1Byb3BlcnR5R3JvdXA+DQo+
IC0gIDxJbXBvcnQgUHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4NCj4gLSAgPEltcG9ydCBQ
cm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+DQo+IC0gIDxQ
cm9wZXJ0eUdyb3VwPg0KPiAtICAgIDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQoSW5jbHVk
ZVBhdGgpPC9JbmNsdWRlUGF0aD4NCj4gLSAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8L1J1bkNv
ZGVBbmFseXNpcz4NCj4gLSAgICA8RW5hYmxlSW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5mMmNhdD4N
Cj4gLQ0KPiA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPkNsQ29tcGlsZTtTdGFtcEluZjwvQ3Vz
dG9tQnVpbGRCZWZvcmVUYXJnZQ0KPiB0cz4NCj4gLSAgICA8SW50RGlyPi4uXCQoUHJvamVjdE5h
bWUpXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvSW50RGlyPg0KPiAtICAgIDxP
dXREaXI+Li5cJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlcPC9PdXREaXI+DQo+IC0g
IDwvUHJvcGVydHlHcm91cD4NCj4gLSAgPEl0ZW1EZWZpbml0aW9uR3JvdXA+DQo+IC0gICAgPEN1
c3RvbUJ1aWxkU3RlcD4NCj4gK++7vzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04
Ij8+DQo+ICs8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIu
MCINCj4geG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVp
bGQvMjAwMyI+DQo+ICsgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4g
KyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IlByb3BlcnR5U2hlZXRzIj4NCj4gKyAgICA8Q29uZmln
dXJhdGlvblR5cGU+RHJpdmVyPC9Db25maWd1cmF0aW9uVHlwZT4NCj4gKyAgICA8RHJpdmVyVHlw
ZT5XRE08L0RyaXZlclR5cGU+DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPFByb3BlcnR5
R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPg0KPiArICAgIDxDb25maWd1cmF0aW9uPldpbmRvd3MgVmlz
dGEgRGVidWc8L0NvbmZpZ3VyYXRpb24+DQo+ICsgICAgPFBsYXRmb3JtIENvbmRpdGlvbj0iJyQo
UGxhdGZvcm0pJyA9PSAnJyI+V2luMzI8L1BsYXRmb3JtPg0KPiArICAgIDxEZWJ1Z2dlckZsYXZv
cj5EYmdlbmdLZXJuZWxEZWJ1Z2dlcjwvRGVidWdnZXJGbGF2b3I+DQo+ICsgIDwvUHJvcGVydHlH
cm91cD4NCj4gKyAgPEltcG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5D
cHAuRGVmYXVsdC5wcm9wcyIgLz4NCj4gKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3Vy
YXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2lu
ZG93cyA4IFJlbGVhc2V8eDY0JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2Vy
bmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+
DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249
IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgOCBSZWxlYXNlfFdpbjMy
JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwv
UGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24p
fCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgVmlzdGEgRGVidWd8eDY0JyI+DQo+ICsgICAgPFBsYXRm
b3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0K
PiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1
cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dp
bmRvd3MgVmlzdGEgRGVidWd8V2luMzInIj4NCj4gKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRv
d3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0Zm9ybVRvb2xzZXQ+DQo+ICsgIDwvUHJvcGVydHlH
cm91cD4NCj4gKyAgPFByb3BlcnR5R3JvdXAgTGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRp
dGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQbGF0Zm9ybSknPT0nV2luZG93cyBWaXN0YSBSZWxl
YXNlfHg2NCciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2
ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiArICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1
cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIFZpc3RhDQo+IFJlbGVhc2V8V2luMzInIj4N
Cj4gKyAgICA8UGxhdGZvcm1Ub29sc2V0PldpbmRvd3NLZXJuZWxNb2RlRHJpdmVyOC4xPC9QbGF0
Zm9ybVRvb2xzZXQ+DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPFByb3BlcnR5R3JvdXAg
TGFiZWw9IkNvbmZpZ3VyYXRpb24iDQo+IENvbmRpdGlvbj0iJyQoQ29uZmlndXJhdGlvbil8JChQ
bGF0Zm9ybSknPT0nV2luZG93cyA3IFJlbGVhc2V8eDY0JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9v
bHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8
L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9u
Ig0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3Mg
NyBSZWxlYXNlfFdpbjMyJyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVs
TW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+
ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBDb25kaXRpb249Iick
KENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3M4IERlYnVnfHg2NCciPg0KPiAr
ICAgIDxQbGF0Zm9ybVRvb2xzZXQ+djEyMDwvUGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3Bl
cnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25maWd1cmF0aW9uIg0KPiBD
b25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09J1dpbmRvd3MgNyBEZWJ1
Z3xXaW4zMiciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93c0tlcm5lbE1vZGVEcml2
ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdyb3VwPg0KPiArICA8UHJv
cGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0aW9uPSInJChDb25maWd1
cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDcgRGVidWd8eDY0JyI+DQo+ICsgICAgPFBs
YXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwvUGxhdGZvcm1Ub29sc2V0
Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJDb25m
aWd1cmF0aW9uIg0KPiBDb25kaXRpb249IickKENvbmZpZ3VyYXRpb24pfCQoUGxhdGZvcm0pJz09
J1dpbmRvd3MgOCBEZWJ1Z3xXaW4zMiciPg0KPiArICAgIDxQbGF0Zm9ybVRvb2xzZXQ+V2luZG93
c0tlcm5lbE1vZGVEcml2ZXI4LjE8L1BsYXRmb3JtVG9vbHNldD4NCj4gKyAgPC9Qcm9wZXJ0eUdy
b3VwPg0KPiArICA8UHJvcGVydHlHcm91cCBMYWJlbD0iQ29uZmlndXJhdGlvbiINCj4gQ29uZGl0
aW9uPSInJChDb25maWd1cmF0aW9uKXwkKFBsYXRmb3JtKSc9PSdXaW5kb3dzIDggRGVidWd8eDY0
JyI+DQo+ICsgICAgPFBsYXRmb3JtVG9vbHNldD5XaW5kb3dzS2VybmVsTW9kZURyaXZlcjguMTwv
UGxhdGZvcm1Ub29sc2V0Pg0KPiArICA8L1Byb3BlcnR5R3JvdXA+DQo+ICsgIDxQcm9wZXJ0eUdy
b3VwIExhYmVsPSJHbG9iYWxzIj4NCj4gKyAgICA8UHJvamVjdEd1aWQ+ezk3RDk5NDJCLTVFQTMt
NDg4Qy1CNTEyLUM5NkU1RDA3N0Y4RX08L1Byb2plY3RHdWlkPg0KPiArICA8L1Byb3BlcnR5R3Jv
dXA+DQo+ICsgIDxJbXBvcnQgUHJvamVjdD0iLi5cdGFyZ2V0cy5wcm9wcyIgLz4NCj4gKyAgPElt
cG9ydCBQcm9qZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAucHJvcHMiIC8+DQo+
ICsgIDxQcm9wZXJ0eUdyb3VwPg0KPiArICAgIDxJbmNsdWRlUGF0aD4uLlwuLlxpbmNsdWRlOyQo
SW5jbHVkZVBhdGgpPC9JbmNsdWRlUGF0aD4NCj4gKyAgICA8UnVuQ29kZUFuYWx5c2lzPnRydWU8
L1J1bkNvZGVBbmFseXNpcz4NCj4gKyAgICA8RW5hYmxlSW5mMmNhdD5mYWxzZTwvRW5hYmxlSW5m
MmNhdD4NCj4gKw0KPiA8Q3VzdG9tQnVpbGRCZWZvcmVUYXJnZXRzPkNsQ29tcGlsZTtTdGFtcElu
ZjwvQ3VzdG9tQnVpbGRCZWZvcmVUYXJnZQ0KPiB0cz4NCj4gKyAgICA8SW50RGlyPi4uXCQoUHJv
amVjdE5hbWUpXCQoQ29uZmlndXJhdGlvbk5hbWUpXCQoUGxhdGZvcm0pXDwvSW50RGlyPg0KPiAr
ICAgIDxPdXREaXI+Li5cJChDb25maWd1cmF0aW9uTmFtZSlcJChQbGF0Zm9ybSlcPC9PdXREaXI+
DQo+ICsgIDwvUHJvcGVydHlHcm91cD4NCj4gKyAgPEl0ZW1EZWZpbml0aW9uR3JvdXA+DQo+ICsg
ICAgPEN1c3RvbUJ1aWxkU3RlcD4NCj4gICAgICAgIDxDb21tYW5kPmVjaG8gIkJ1aWxkIEluZiIN
Cj4gICAgICAgICAgICAgICAgICBwb3dlcnNoZWxsIC1Db21tYW5kICIoR2V0LUNvbnRlbnQgLi5c
Li5cc3JjXHhlbm5ldC5pbmYpIC1yZXBsYWNlDQo+ICdATUFKT1JfVkVSU0lPTkAnLCAnJChNQUpP
Ul9WRVJTSU9OKScgLXJlcGxhY2UNCj4gJ0BNSU5PUl9WRVJTSU9OQCcsICckKE1JTk9SX1ZFUlNJ
T04pJyAtcmVwbGFjZQ0KPiAnQE1JQ1JPX1ZFUlNJT05AJywnJChNSUNST19WRVJTSU9OKScgLXJl
cGxhY2UNCj4gJ0BCVUlMRF9OVU1CRVJAJywnJChCVUlMRF9OVU1CRVIpJyAtcmVwbGFjZQ0KPiAn
QENPTVBBTllfTkFNRUAnLCckKENPTVBBTllfTkFNRSknIC1yZXBsYWNlDQo+ICdAUFJPRFVDVF9O
QU1FQCcsJyQoUFJPRFVDVF9OQU1FKScgfCBTZXQtQ29udGVudCAuLlx4ZW5uZXQuaW5mIg0KPiAg
ICAgICAgICAgICAgICAgIGVjaG8gIkJ1aWxkIHZlcnNpb24gaGVhZGVyIg0KPiAgICAgICAgICAg
ICAgICAgIHBvd2Vyc2hlbGwgLUNvbW1hbmQgIihHZXQtQ29udGVudCAuLlwuLlxpbmNsdWRlXHZl
cnNpb24uaHgpIC0NCj4gcmVwbGFjZSAnQE1BSk9SX1ZFUlNJT05AJywgJyQoTUFKT1JfVkVSU0lP
TiknIC1yZXBsYWNlDQo+ICdATUlOT1JfVkVSU0lPTkAnLCAnJChNSU5PUl9WRVJTSU9OKScgLXJl
cGxhY2UNCj4gJ0BNSUNST19WRVJTSU9OQCcsJyQoTUlDUk9fVkVSU0lPTiknIC1yZXBsYWNlDQo+
ICdAQlVJTERfTlVNQkVSQCcsJyQoQlVJTERfTlVNQkVSKScgLXJlcGxhY2UNCj4gJ0BDT01QQU5Z
X05BTUVAJywnJChDT01QQU5ZX05BTUUpJyAtcmVwbGFjZQ0KPiAnQFBST0RVQ1RfTkFNRUAnLCck
KFBST0RVQ1RfTkFNRSknIC1yZXBsYWNlICdAREFZQCcsJTI0KEdldC0NCj4gRGF0ZSAtZm9ybWF0
ICUyNSUyNWQpIC1yZXBsYWNlICdATU9OVEhAJywlMjQoR2V0LURhdGUgLWZvcm1hdA0KPiAlMjUl
MjVNKSAtcmVwbGFjZSAnQFlFQVJAJywlMjQoR2V0LURhdGUgLWZvcm1hdCB5eXl5KSB8IFNldC1D
b250ZW50DQo+IC4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oIg0KPiAtICAgICAgICAgICAgPC9Db21t
YW5kPg0KPiAtICAgICAgPE91dHB1dHM+Li5ceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNp
b24uaDwvT3V0cHV0cz4NCj4gLSAgICAgIDxJbnB1dHM+Li5cLi5cc3JjXHhlbm5ldC5pbmY7Li5c
Li5caW5jbHVkZVx2ZXJzaW9uLmh4PC9JbnB1dHM+DQo+IC0gICAgPC9DdXN0b21CdWlsZFN0ZXA+
DQo+IC0gICAgPENsQ29tcGlsZT4NCj4gLQ0KPiA8UHJlcHJvY2Vzc29yRGVmaW5pdGlvbnM+X19N
T0RVTEVfXz0iWEVOTkVUIjtORElTX01JTklQT1JUX0RSSVZFDQo+IFI7TkRJUzYwX01JTklQT1JU
PTE7UE9PTF9OWF9PUFRJTj0xOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlvbnMpPC9Qcg0KPiBlcHJv
Y2Vzc29yRGVmaW5pdGlvbnM+DQo+IC0gICAgICA8V2FybmluZ0xldmVsPkVuYWJsZUFsbFdhcm5p
bmdzPC9XYXJuaW5nTGV2ZWw+DQo+IC0NCj4gPERpc2FibGVTcGVjaWZpY1dhcm5pbmdzPjQ3MTE7
NDU0ODs0ODIwOzQ2Njg7NDI1NTs2MDAxOzYwNTQ7MjgxOTY7JShEaXNhDQo+IGJsZVNwZWNpZmlj
V2FybmluZ3MpPC9EaXNhYmxlU3BlY2lmaWNXYXJuaW5ncz4NCj4gLSAgICAgIDxNdWx0aVByb2Nl
c3NvckNvbXBpbGF0aW9uPnRydWU8L011bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+DQo+IC0gICAg
ICA8RW5hYmxlUFJFZmFzdD50cnVlPC9FbmFibGVQUkVmYXN0Pg0KPiAtICAgIDwvQ2xDb21waWxl
Pg0KPiAtICAgIDxMaW5rPg0KPiAtDQo+IDxJbWFnZUhhc1NhZmVFeGNlcHRpb25IYW5kbGVycz5m
YWxzZTwvSW1hZ2VIYXNTYWZlRXhjZXB0aW9uSGFuZGxlcnM+DQo+IC0NCj4gPEFkZGl0aW9uYWxE
ZXBlbmRlbmNpZXM+JChEREtfTElCX1BBVEgpXG5kaXMubGliOyUoQWRkaXRpb25hbERlcGVuZGUN
Cj4gbmNpZXMpPC9BZGRpdGlvbmFsRGVwZW5kZW5jaWVzPg0KPiAtICAgICAgPEVuYWJsZUNPTURB
VEZvbGRpbmc+ZmFsc2U8L0VuYWJsZUNPTURBVEZvbGRpbmc+DQo+IC0gICAgPC9MaW5rPg0KPiAt
ICAgIDxJbmY+DQo+IC0gICAgICA8U3BlY2lmeUFyY2hpdGVjdHVyZT50cnVlPC9TcGVjaWZ5QXJj
aGl0ZWN0dXJlPg0KPiAtDQo+IDxTcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbj50cnVl
PC9TcGVjaWZ5RHJpdmVyVmVyRGlyZWN0aXZlVmVyc2lvbg0KPiA+DQo+IC0NCj4gPFRpbWVTdGFt
cD4kKE1BSk9SX1ZFUlNJT04pLiQoTUlOT1JfVkVSU0lPTikuJChNSUNST19WRVJTSU9OKS4NCj4g
JChCVUlMRF9OVU1CRVIpPC9UaW1lU3RhbXA+DQo+IC0gICAgICA8RW5hYmxlVmVyYm9zZT50cnVl
PC9FbmFibGVWZXJib3NlPg0KPiAtICAgIDwvSW5mPg0KPiAtICA8L0l0ZW1EZWZpbml0aW9uR3Jv
dXA+DQo+IC0gIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09
J1dpbjMyJyI+DQo+IC0gICAgPENsQ29tcGlsZT4NCj4gLQ0KPiA8UHJlcHJvY2Vzc29yRGVmaW5p
dGlvbnM+X19pMzg2X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXByb2Nlcw0KPiBz
b3JEZWZpbml0aW9ucz4NCj4gLSAgICA8L0NsQ29tcGlsZT4NCj4gLSAgICA8SW5mPg0KPiAtICAg
ICAgPEFyY2hpdGVjdHVyZT54ODY8L0FyY2hpdGVjdHVyZT4NCj4gLSAgICA8L0luZj4NCj4gLSAg
PC9JdGVtRGVmaW5pdGlvbkdyb3VwPg0KPiAtICA8SXRlbURlZmluaXRpb25Hcm91cCBDb25kaXRp
b249IickKFBsYXRmb3JtKSc9PSd4NjQnIj4NCj4gLSAgICA8Q2xDb21waWxlPg0KPiAtDQo+IDxQ
cmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX3g4Nl82NF9fOyUoUHJlcHJvY2Vzc29yRGVmaW5pdGlv
bnMpPC9QcmVwcm8NCj4gY2Vzc29yRGVmaW5pdGlvbnM+DQo+IC0gICAgPC9DbENvbXBpbGU+DQo+
IC0gICAgPEluZj4NCj4gLSAgICAgIDxBcmNoaXRlY3R1cmU+YW1kNjQ8L0FyY2hpdGVjdHVyZT4N
Cj4gLSAgICA8L0luZj4NCj4gLSAgPC9JdGVtRGVmaW5pdGlvbkdyb3VwPg0KPiAtICA8SXRlbUdy
b3VwPg0KPiAtICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRlPSIkKFRhcmdldFBhdGgpIiAvPg0K
PiAtICAgIDxGaWxlc1RvUGFja2FnZSBJbmNsdWRlPSIkKE91dERpcikkKFRhcmdldE5hbWUpLnBk
YiIgLz4NCj4gLSAgICA8RmlsZXNUb1BhY2thZ2UgSW5jbHVkZT0iQChJbmYtPiclKENvcHlPdXRw
dXQpJykiDQo+IENvbmRpdGlvbj0iJ0AoSW5mKSchPScnIiAvPg0KPiAtICA8L0l0ZW1Hcm91cD4N
Cj4gLSAgPEl0ZW1Hcm91cD4NCj4gLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94
ZW5uZXQvcmVnaXN0cnkuYyIgLz4NCj4gLSAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3Ny
Yy94ZW5uZXQvYWRhcHRlci5jIiAvPg0KPiAtICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4v
c3JjL3hlbm5ldC9tYWluLmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9z
cmMveGVubmV0L21pbmlwb3J0LmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8u
Li9zcmMveGVubmV0L3JlY2VpdmVyLmMiIC8+DQo+IC0gICAgPENsQ29tcGlsZSBJbmNsdWRlPSIu
Li8uLi9zcmMveGVubmV0L3RyYW5zbWl0dGVyLmMiIC8+DQo+IC0gIDwvSXRlbUdyb3VwPg0KPiAt
ICA8SXRlbUdyb3VwPg0KPiAtICAgIDxSZXNvdXJjZUNvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3Jj
XHhlbm5ldFx4ZW5uZXQucmMiIC8+DQo+IC0gIDwvSXRlbUdyb3VwPg0KPiAtICA8SXRlbUdyb3Vw
Pg0KPiAtICAgIDxJbmYgSW5jbHVkZT0iLi5ceGVubmV0LmluZiIgLz4NCj4gLSAgPC9JdGVtR3Jv
dXA+DQo+IC0gIDxJbXBvcnQgUHJvamVjdD0iJChWQ1RhcmdldHNQYXRoKVxNaWNyb3NvZnQuQ3Bw
LnRhcmdldHMiIC8+DQo+ICsgICAgICAgICAgICA8L0NvbW1hbmQ+DQo+ICsgICAgICA8T3V0cHV0
cz4uLlx4ZW5uZXQuaW5mOy4uXC4uXGluY2x1ZGVcdmVyc2lvbi5oPC9PdXRwdXRzPg0KPiArICAg
ICAgPElucHV0cz4uLlwuLlxzcmNceGVubmV0LmluZjsuLlwuLlxpbmNsdWRlXHZlcnNpb24uaHg8
L0lucHV0cz4NCj4gKyAgICA8L0N1c3RvbUJ1aWxkU3RlcD4NCj4gKyAgICA8Q2xDb21waWxlPg0K
PiArDQo+IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX01PRFVMRV9fPSJYRU5ORVQiO05ESVNf
TUlOSVBPUlRfRFJJVkUNCj4gUjtORElTNjBfTUlOSVBPUlQ9MTtQT09MX05YX09QVElOPTE7JShQ
cmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByDQo+IGVwcm9jZXNzb3JEZWZpbml0aW9ucz4NCj4g
KyAgICAgIDxXYXJuaW5nTGV2ZWw+RW5hYmxlQWxsV2FybmluZ3M8L1dhcm5pbmdMZXZlbD4NCj4g
Kw0KPiA8RGlzYWJsZVNwZWNpZmljV2FybmluZ3M+NDcxMTs0NTQ4OzQ4MjA7NDY2ODs0MjU1OzYw
MDE7NjA1NDsyODE5NjslKERpc2ENCj4gYmxlU3BlY2lmaWNXYXJuaW5ncyk8L0Rpc2FibGVTcGVj
aWZpY1dhcm5pbmdzPg0KPiArICAgICAgPE11bHRpUHJvY2Vzc29yQ29tcGlsYXRpb24+dHJ1ZTwv
TXVsdGlQcm9jZXNzb3JDb21waWxhdGlvbj4NCj4gKyAgICAgIDxFbmFibGVQUkVmYXN0PnRydWU8
L0VuYWJsZVBSRWZhc3Q+DQo+ICsgICAgPC9DbENvbXBpbGU+DQo+ICsgICAgPExpbms+DQo+ICsN
Cj4gPEltYWdlSGFzU2FmZUV4Y2VwdGlvbkhhbmRsZXJzPmZhbHNlPC9JbWFnZUhhc1NhZmVFeGNl
cHRpb25IYW5kbGVycz4NCj4gKw0KPiA8QWRkaXRpb25hbERlcGVuZGVuY2llcz4kKERES19MSUJf
UEFUSClcbmRpcy5saWI7JShBZGRpdGlvbmFsRGVwZW5kZQ0KPiBuY2llcyk8L0FkZGl0aW9uYWxE
ZXBlbmRlbmNpZXM+DQo+ICsgICAgICA8RW5hYmxlQ09NREFURm9sZGluZz5mYWxzZTwvRW5hYmxl
Q09NREFURm9sZGluZz4NCj4gKyAgICA8L0xpbms+DQo+ICsgICAgPEluZj4NCj4gKyAgICAgIDxT
cGVjaWZ5QXJjaGl0ZWN0dXJlPnRydWU8L1NwZWNpZnlBcmNoaXRlY3R1cmU+DQo+ICsNCj4gPFNw
ZWNpZnlEcml2ZXJWZXJEaXJlY3RpdmVWZXJzaW9uPnRydWU8L1NwZWNpZnlEcml2ZXJWZXJEaXJl
Y3RpdmVWZXJzaW9uDQo+ID4NCj4gKw0KPiA8VGltZVN0YW1wPiQoTUFKT1JfVkVSU0lPTikuJChN
SU5PUl9WRVJTSU9OKS4kKE1JQ1JPX1ZFUlNJT04pLg0KPiAkKEJVSUxEX05VTUJFUik8L1RpbWVT
dGFtcD4NCj4gKyAgICAgIDxFbmFibGVWZXJib3NlPnRydWU8L0VuYWJsZVZlcmJvc2U+DQo+ICsg
ICAgPC9JbmY+DQo+ICsgIDwvSXRlbURlZmluaXRpb25Hcm91cD4NCj4gKyAgPEl0ZW1EZWZpbml0
aW9uR3JvdXAgQ29uZGl0aW9uPSInJChQbGF0Zm9ybSknPT0nV2luMzInIj4NCj4gKyAgICA8Q2xD
b21waWxlPg0KPiArDQo+IDxQcmVwcm9jZXNzb3JEZWZpbml0aW9ucz5fX2kzODZfXzslKFByZXBy
b2Nlc3NvckRlZmluaXRpb25zKTwvUHJlcHJvY2VzDQo+IHNvckRlZmluaXRpb25zPg0KPiArICAg
IDwvQ2xDb21waWxlPg0KPiArICAgIDxJbmY+DQo+ICsgICAgICA8QXJjaGl0ZWN0dXJlPng4Njwv
QXJjaGl0ZWN0dXJlPg0KPiArICAgIDwvSW5mPg0KPiArICA8L0l0ZW1EZWZpbml0aW9uR3JvdXA+
DQo+ICsgIDxJdGVtRGVmaW5pdGlvbkdyb3VwIENvbmRpdGlvbj0iJyQoUGxhdGZvcm0pJz09J3g2
NCciPg0KPiArICAgIDxDbENvbXBpbGU+DQo+ICsNCj4gPFByZXByb2Nlc3NvckRlZmluaXRpb25z
Pl9feDg2XzY0X187JShQcmVwcm9jZXNzb3JEZWZpbml0aW9ucyk8L1ByZXBybw0KPiBjZXNzb3JE
ZWZpbml0aW9ucz4NCj4gKyAgICA8L0NsQ29tcGlsZT4NCj4gKyAgICA8SW5mPg0KPiArICAgICAg
PEFyY2hpdGVjdHVyZT5hbWQ2NDwvQXJjaGl0ZWN0dXJlPg0KPiArICAgIDwvSW5mPg0KPiArICA8
L0l0ZW1EZWZpbml0aW9uR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAgPEZpbGVzVG9Q
YWNrYWdlIEluY2x1ZGU9IiQoVGFyZ2V0UGF0aCkiIC8+DQo+ICsgICAgPEZpbGVzVG9QYWNrYWdl
IEluY2x1ZGU9IiQoT3V0RGlyKSQoVGFyZ2V0TmFtZSkucGRiIiAvPg0KPiArICAgIDxGaWxlc1Rv
UGFja2FnZSBJbmNsdWRlPSJAKEluZi0+JyUoQ29weU91dHB1dCknKSINCj4gQ29uZGl0aW9uPSIn
QChJbmYpJyE9JyciIC8+DQo+ICsgIDwvSXRlbUdyb3VwPg0KPiArICA8SXRlbUdyb3VwPg0KPiAr
ICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9yZWdpc3RyeS5jIiAvPg0K
PiArICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi4vLi4vc3JjL3hlbm5ldC9hZGFwdGVyLmMiIC8+
DQo+ICsgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLi8uLi9zcmMveGVubmV0L21haW4uYyIgLz4N
Cj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvbWluaXBvcnQuYyIg
Lz4NCj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvcmVjZWl2ZXIu
YyIgLz4NCj4gKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uLy4uL3NyYy94ZW5uZXQvdHJhbnNt
aXR0ZXIuYyIgLz4NCj4gKyAgPC9JdGVtR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAg
PFJlc291cmNlQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVubmV0XHhlbm5ldC5yYyIgLz4N
Cj4gKyAgPC9JdGVtR3JvdXA+DQo+ICsgIDxJdGVtR3JvdXA+DQo+ICsgICAgPEluZiBJbmNsdWRl
PSIuLlx4ZW5uZXQuaW5mIiAvPg0KPiArICA8L0l0ZW1Hcm91cD4NCj4gKyAgPEltcG9ydCBQcm9q
ZWN0PSIkKFZDVGFyZ2V0c1BhdGgpXE1pY3Jvc29mdC5DcHAudGFyZ2V0cyIgLz4NCj4gIDwvUHJv
amVjdD4NCj4gXCBObyBuZXdsaW5lIGF0IGVuZCBvZiBmaWxlDQo+IC0tDQo+IDEuOS40Lm1zeXNn
aXQuMQ0KPiANCj4gDQo+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fDQo+IHdpbi1wdi1kZXZlbCBtYWlsaW5nIGxpc3QNCj4gd2luLXB2LWRldmVsQGxpc3Rz
LnhlbnByb2plY3Qub3JnDQo+IGh0dHA6Ly9saXN0cy54ZW5wcm9qZWN0Lm9yZy9jZ2ktYmluL21h
aWxtYW4vbGlzdGluZm8vd2luLXB2LWRldmVsDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1kZXZl
bEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dpLWJp
bi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 17:58:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 17:58:07 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y21oV-0005eu-CO; Fri, 19 Dec 2014 17:58:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y21oU-0005em-KF
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 17:58:06 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	C9/40-27623-D2764945; Fri, 19 Dec 2014 17:58:05 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1419011885!14722650!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 444 invoked from network); 19 Dec 2014 17:58:05 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 17:58:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,607,1413244800"; d="scan'208";a="28072771"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: Development builds now available!
Thread-Index: AdAbtQCyj0nPUnTFSQ2bRpo1ZwrEoQ==
Date: Fri, 19 Dec 2014 17:58:03 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02579685D@AMSPEX01CL01.citrite.net>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Subject: [win-pv-devel] Development builds now available!
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

All,

  Just in time for the holidays, I'm pleased to announce that development builds of the Windows PV drivers are available via the xenproject.org website. There is a link in the downloads panel of the Windows PV drivers project front-page(http://xenproject.org/developers/teams/windows-pv-drivers.html) or you can access them via the downloads page at http://xenproject.org/downloads/windows-pv-drivers.html.

  Happy holidays!

    Paul

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

From win-pv-devel-bounces@lists.xenproject.org Fri Dec 19 17:58:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 19 Dec 2014 17:58:07 +0000
Received: from localhost ([127.0.0.1] helo=lists.xen.org)
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <win-pv-devel-bounces@lists.xenproject.org>)
	id 1Y21oV-0005eu-CO; Fri, 19 Dec 2014 17:58:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <Paul.Durrant@citrix.com>) id 1Y21oU-0005em-KF
	for win-pv-devel@lists.xenproject.org; Fri, 19 Dec 2014 17:58:06 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	C9/40-27623-D2764945; Fri, 19 Dec 2014 17:58:05 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1419011885!14722650!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=received_headers: No 
	Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 444 invoked from network); 19 Dec 2014 17:58:05 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	19 Dec 2014 17:58:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,607,1413244800"; d="scan'208";a="28072771"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: Development builds now available!
Thread-Index: AdAbtQCyj0nPUnTFSQ2bRpo1ZwrEoQ==
Date: Fri, 19 Dec 2014 17:58:03 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02579685D@AMSPEX01CL01.citrite.net>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
MIME-Version: 1.0
X-DLP: AMS1
Subject: [win-pv-devel] Development builds now available!
X-BeenThere: win-pv-devel@lists.xenproject.org
X-Mailman-Version: 2.1.13
Precedence: list
List-Id: Developer list for the Windows PV Drivers subproject
	<win-pv-devel.lists.xenproject.org>
List-Unsubscribe: <http://lists.xenproject.org/cgi-bin/mailman/options/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=unsubscribe>
List-Post: <mailto:win-pv-devel@lists.xenproject.org>
List-Help: <mailto:win-pv-devel-request@lists.xenproject.org?subject=help>
List-Subscribe: <http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel>,
	<mailto:win-pv-devel-request@lists.xenproject.org?subject=subscribe>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

All,

  Just in time for the holidays, I'm pleased to announce that development builds of the Windows PV drivers are available via the xenproject.org website. There is a link in the downloads panel of the Windows PV drivers project front-page(http://xenproject.org/developers/teams/windows-pv-drivers.html) or you can access them via the downloads page at http://xenproject.org/downloads/windows-pv-drivers.html.

  Happy holidays!

    Paul

_______________________________________________
win-pv-devel mailing list
win-pv-devel@lists.xenproject.org
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

