From win-pv-devel-bounces@lists.xenproject.org Thu Nov 06 14:24:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:44 +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 1XmNzQ-0001Ws-Fl; Thu, 06 Nov 2014 14:24:44 +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 1XmNzP-0001WZ-Q5
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:43 +0000
Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id
	5E/1B-14214-AA48B545; Thu, 06 Nov 2014 14:24:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 2515 invoked from network); 6 Nov 2014 14:24:41 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:41 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771845"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-50;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:11 +0000
Message-ID: <1415283861-26028-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 0/10] Use FIFO event channel ABI when
	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

This series adds code to make use of the FIFO event channel ABI which
was added in Xen 4.4.

Patch #1 is a simple whitespace fix

Patch #2 fixes a bug that I noticed while adding other code

Patch #3 is an efficiency fix

Patch #4 separates some conflated use of the shared info page

Patch #5 introduces a hash table for event channel lookup, which is
needed since the upper limit on port number when using the fifo ABI
is significantly higher

Patch #6 simplifies some code

Patch #7 separates the event channel ABI from the core code

Patch #8 fixes a type mis-definition that I noticed (without affecting
compatibility in any way)

Patch #9 updates to Xen 4.4 headers so that the hypercalls necessary
to use the FIFO ABI are available

Patch #10 adds the new ABI code

 include/evtchn_interface.h      |   6 +-
 include/shared_info_interface.h |  46 ++-
 include/xen.h                   |  49 ++-
 include/xen/arch-x86/xen.h      |   9 +
 include/xen/event_channel.h     |  91 ++++++
 include/xen/hvm/hvm_op.h        | 195 ++++++++---
 include/xen/hvm/params.h        |  48 ++-
 include/xen/io/xs_wire.h        |  16 +-
 include/xen/memory.h            | 130 +++++++-
 include/xen/sched.h             |   7 +-
 include/xen/trace.h             |  25 +-
 include/xen/xen-compat.h        |   2 +-
 include/xen/xen.h               |  16 +-
 src/xen/event_channel.c         | 128 ++++++++
 src/xen/system.c                |  20 +-
 src/xenbus/evtchn.c             | 393 ++++++++++++++--------
 src/xenbus/evtchn_2l.c          | 293 +++++++++++++++++
 src/xenbus/evtchn_2l.h          |  59 ++++
 src/xenbus/evtchn_abi.h         | 109 +++++++
 src/xenbus/evtchn_fifo.c        | 702 ++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_fifo.h        |  59 ++++
 src/xenbus/hash_table.c         | 367 +++++++++++++++++++++
 src/xenbus/hash_table.h         |  70 ++++
 src/xenbus/shared_info.c        | 203 ++++++++----
 src/xenbus/store.c              |  11 +-
 vs2012/xenbus/xenbus.vcxproj    |   3 +
 vs2013/xenbus/xenbus.vcxproj    |   5 +-
 27 files changed, 2770 insertions(+), 292 deletions(-)



_______________________________________________
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001Xg-Kq; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wq-TL
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:45 +0000
Received: from [85.158.139.211] by server-6.bemta-5.messagelabs.com id
	1E/0D-26652-CA48B545; Thu, 06 Nov 2014 14:24:44 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4873 invoked from network); 6 Nov 2014 14:24:43 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771855"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-BY;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:20 +0000
Message-ID: <1415283861-26028-10-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 08/10] Fix type mis-definition in EVTCHN
	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: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 3a48915..5898e08 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -191,7 +191,7 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
     XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
     XENBUS_EVTCHN_SEND      EvtchnSend;
-    XENBUS_EVTCHN_SEND      EvtchnTrigger;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
     XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
-- 
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001XI-Hx; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wa-4I
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:44 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	87/CB-23865-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15913 invoked from network); 6 Nov 2014 14:24:42 -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;
	6 Nov 2014 14:24:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771847"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-5h;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:12 +0000
Message-ID: <1415283861-26028-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 01/10] Whitespace fix
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/evtchn.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index ee5243a..d2743bd 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -720,8 +720,8 @@ EvtchnDebugCallback(
                      "EVENT CHANNELS:\n");
 
         for (ListEntry = Context->List.Flink;
-                ListEntry != &Context->List;
-                ListEntry = ListEntry->Flink) {
+             ListEntry != &Context->List;
+             ListEntry = ListEntry->Flink) {
             PXENBUS_EVTCHN_CHANNEL  Channel;
             PCHAR                   Name;
             ULONG_PTR               Offset;
-- 
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001XN-Is; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wb-7n
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:44 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	F4/29-19763-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 3946 invoked from network); 6 Nov 2014 14:24:42 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771848"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-7V;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:13 +0000
Message-ID: <1415283861-26028-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 02/10] Fix bug in EVTCHN interrupt enabling
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 code in EvtchnOpen attempts to enable interrupts on demand when new
channels are added to a list. However there is a bug in the logic that
means interrupts will not be enabled until the second channel is opened.
This patch fixes the bug.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index d2743bd..9ba2e84 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -359,13 +359,13 @@ EvtchnOpen(
     Context->Channel[LocalPort] = Channel;
     Channel->Active = TRUE;
 
+    InsertTailList(&Context->List, &Channel->ListEntry);
+
     if (!IsListEmpty(&Context->List) && !Context->Enabled) {
         EvtchnInterruptEnable(Context);
         Context->Enabled = TRUE;
     }
 
-    InsertTailList(&Context->List, &Channel->ListEntry);
-
     __EvtchnReleaseInterruptLock(Context, DISPATCH_LEVEL);
 
     KeLowerIrql(Irql);
-- 
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001XN-Is; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wb-7n
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:44 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	F4/29-19763-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 3946 invoked from network); 6 Nov 2014 14:24:42 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771848"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-7V;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:13 +0000
Message-ID: <1415283861-26028-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 02/10] Fix bug in EVTCHN interrupt enabling
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 code in EvtchnOpen attempts to enable interrupts on demand when new
channels are added to a list. However there is a bug in the logic that
means interrupts will not be enabled until the second channel is opened.
This patch fixes the bug.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index d2743bd..9ba2e84 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -359,13 +359,13 @@ EvtchnOpen(
     Context->Channel[LocalPort] = Channel;
     Channel->Active = TRUE;
 
+    InsertTailList(&Context->List, &Channel->ListEntry);
+
     if (!IsListEmpty(&Context->List) && !Context->Enabled) {
         EvtchnInterruptEnable(Context);
         Context->Enabled = TRUE;
     }
 
-    InsertTailList(&Context->List, &Channel->ListEntry);
-
     __EvtchnReleaseInterruptLock(Context, DISPATCH_LEVEL);
 
     KeLowerIrql(Irql);
-- 
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001XI-Hx; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wa-4I
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:44 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	87/CB-23865-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15913 invoked from network); 6 Nov 2014 14:24:42 -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;
	6 Nov 2014 14:24:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771847"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-5h;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:12 +0000
Message-ID: <1415283861-26028-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 01/10] Whitespace fix
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/evtchn.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index ee5243a..d2743bd 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -720,8 +720,8 @@ EvtchnDebugCallback(
                      "EVENT CHANNELS:\n");
 
         for (ListEntry = Context->List.Flink;
-                ListEntry != &Context->List;
-                ListEntry = ListEntry->Flink) {
+             ListEntry != &Context->List;
+             ListEntry = ListEntry->Flink) {
             PXENBUS_EVTCHN_CHANNEL  Channel;
             PCHAR                   Name;
             ULONG_PTR               Offset;
-- 
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 Nov 06 14:24:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:44 +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 1XmNzQ-0001Ws-Fl; Thu, 06 Nov 2014 14:24:44 +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 1XmNzP-0001WZ-Q5
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:43 +0000
Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id
	5E/1B-14214-AA48B545; Thu, 06 Nov 2014 14:24:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 2515 invoked from network); 6 Nov 2014 14:24:41 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:41 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771845"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-50;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:11 +0000
Message-ID: <1415283861-26028-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 0/10] Use FIFO event channel ABI when
	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

This series adds code to make use of the FIFO event channel ABI which
was added in Xen 4.4.

Patch #1 is a simple whitespace fix

Patch #2 fixes a bug that I noticed while adding other code

Patch #3 is an efficiency fix

Patch #4 separates some conflated use of the shared info page

Patch #5 introduces a hash table for event channel lookup, which is
needed since the upper limit on port number when using the fifo ABI
is significantly higher

Patch #6 simplifies some code

Patch #7 separates the event channel ABI from the core code

Patch #8 fixes a type mis-definition that I noticed (without affecting
compatibility in any way)

Patch #9 updates to Xen 4.4 headers so that the hypercalls necessary
to use the FIFO ABI are available

Patch #10 adds the new ABI code

 include/evtchn_interface.h      |   6 +-
 include/shared_info_interface.h |  46 ++-
 include/xen.h                   |  49 ++-
 include/xen/arch-x86/xen.h      |   9 +
 include/xen/event_channel.h     |  91 ++++++
 include/xen/hvm/hvm_op.h        | 195 ++++++++---
 include/xen/hvm/params.h        |  48 ++-
 include/xen/io/xs_wire.h        |  16 +-
 include/xen/memory.h            | 130 +++++++-
 include/xen/sched.h             |   7 +-
 include/xen/trace.h             |  25 +-
 include/xen/xen-compat.h        |   2 +-
 include/xen/xen.h               |  16 +-
 src/xen/event_channel.c         | 128 ++++++++
 src/xen/system.c                |  20 +-
 src/xenbus/evtchn.c             | 393 ++++++++++++++--------
 src/xenbus/evtchn_2l.c          | 293 +++++++++++++++++
 src/xenbus/evtchn_2l.h          |  59 ++++
 src/xenbus/evtchn_abi.h         | 109 +++++++
 src/xenbus/evtchn_fifo.c        | 702 ++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_fifo.h        |  59 ++++
 src/xenbus/hash_table.c         | 367 +++++++++++++++++++++
 src/xenbus/hash_table.h         |  70 ++++
 src/xenbus/shared_info.c        | 203 ++++++++----
 src/xenbus/store.c              |  11 +-
 vs2012/xenbus/xenbus.vcxproj    |   3 +
 vs2013/xenbus/xenbus.vcxproj    |   5 +-
 27 files changed, 2770 insertions(+), 292 deletions(-)



_______________________________________________
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 Nov 06 14:24:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:45 +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 1XmNzR-0001Xg-Kq; Thu, 06 Nov 2014 14:24:45 +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 1XmNzQ-0001Wq-TL
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:45 +0000
Received: from [85.158.139.211] by server-6.bemta-5.messagelabs.com id
	1E/0D-26652-CA48B545; Thu, 06 Nov 2014 14:24:44 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4873 invoked from network); 6 Nov 2014 14:24:43 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771855"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-BY;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:20 +0000
Message-ID: <1415283861-26028-10-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 08/10] Fix type mis-definition in EVTCHN
	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: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 3a48915..5898e08 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -191,7 +191,7 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
     XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
     XENBUS_EVTCHN_SEND      EvtchnSend;
-    XENBUS_EVTCHN_SEND      EvtchnTrigger;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
     XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
-- 
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 Nov 06 14:24:46 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:46 +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 1XmNzS-0001YX-MF; Thu, 06 Nov 2014 14:24:46 +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 1XmNzR-0001Wr-0D
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:45 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	0D/CB-23865-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15988 invoked from network); 6 Nov 2014 14:24:43 -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;
	6 Nov 2014 14:24:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771851"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-81;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:14 +0000
Message-ID: <1415283861-26028-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 03/10] Use InterlockedBitTestAnd[Set|Reset]
	in SHARED_INFO
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

Rather then using InterlockedCompareAndExchange to set and clear bits
in the SHARED_INFO event channel masks, use
InterlockedBitTestAnd[Set|Reset] as these will resolve to instrinsics
when available.

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

diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 9a6af3a..41c99cf 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -74,21 +74,12 @@ SharedInfoSetBit(
     IN  ULONG               Bit
     )
 {
-    ULONG_PTR               Old;
-    ULONG_PTR               New;
-
     ASSERT3U(Bit, <, sizeof (ULONG_PTR) * 8);
 
     KeMemoryBarrier();
 
-    do {
-        Old = *Mask;
-        New = Old | ((ULONG_PTR)1 << Bit);
-    } while (InterlockedCompareExchangePointer((PVOID *)Mask, (PVOID)New, (PVOID)Old) != (PVOID)Old);
-
-    KeMemoryBarrier();
-
-    return (Old & ((ULONG_PTR)1 << Bit)) ? FALSE : TRUE;    // return TRUE if we set the bit
+    // return TRUE if we set the bit
+    return (InterlockedBitTestAndSet((LONG *)Mask, Bit) == 0) ? TRUE : FALSE;
 }
 
 static BOOLEAN
@@ -97,21 +88,12 @@ SharedInfoClearBit(
     IN  ULONG               Bit
     )
 {
-    ULONG_PTR               Old;
-    ULONG_PTR               New;
-
     ASSERT3U(Bit, <, sizeof (ULONG_PTR) * 8);
 
     KeMemoryBarrier();
 
-    do {
-        Old = *Mask;
-        New = Old & ~((ULONG_PTR)1 << Bit);
-    } while (InterlockedCompareExchangePointer((PVOID *)Mask, (PVOID)New, (PVOID)Old) != (PVOID)Old);
-
-    KeMemoryBarrier();
-
-    return (Old & ((ULONG_PTR)1 << Bit)) ? TRUE : FALSE;    // return TRUE if we cleared the bit
+    // return TRUE if we cleared the bit
+    return (InterlockedBitTestAndReset((LONG *)Mask, Bit) != 0) ? TRUE : FALSE;
 }
 
 static BOOLEAN
-- 
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 Nov 06 14:24:46 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:46 +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 1XmNzS-0001YX-MF; Thu, 06 Nov 2014 14:24:46 +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 1XmNzR-0001Wr-0D
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:45 +0000
Received: from [85.158.137.68] by server-4.bemta-3.messagelabs.com id
	0D/CB-23865-BA48B545; Thu, 06 Nov 2014 14:24:43 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15988 invoked from network); 6 Nov 2014 14:24:43 -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;
	6 Nov 2014 14:24:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771851"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-81;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:14 +0000
Message-ID: <1415283861-26028-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 03/10] Use InterlockedBitTestAnd[Set|Reset]
	in SHARED_INFO
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

Rather then using InterlockedCompareAndExchange to set and clear bits
in the SHARED_INFO event channel masks, use
InterlockedBitTestAnd[Set|Reset] as these will resolve to instrinsics
when available.

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

diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 9a6af3a..41c99cf 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -74,21 +74,12 @@ SharedInfoSetBit(
     IN  ULONG               Bit
     )
 {
-    ULONG_PTR               Old;
-    ULONG_PTR               New;
-
     ASSERT3U(Bit, <, sizeof (ULONG_PTR) * 8);
 
     KeMemoryBarrier();
 
-    do {
-        Old = *Mask;
-        New = Old | ((ULONG_PTR)1 << Bit);
-    } while (InterlockedCompareExchangePointer((PVOID *)Mask, (PVOID)New, (PVOID)Old) != (PVOID)Old);
-
-    KeMemoryBarrier();
-
-    return (Old & ((ULONG_PTR)1 << Bit)) ? FALSE : TRUE;    // return TRUE if we set the bit
+    // return TRUE if we set the bit
+    return (InterlockedBitTestAndSet((LONG *)Mask, Bit) == 0) ? TRUE : FALSE;
 }
 
 static BOOLEAN
@@ -97,21 +88,12 @@ SharedInfoClearBit(
     IN  ULONG               Bit
     )
 {
-    ULONG_PTR               Old;
-    ULONG_PTR               New;
-
     ASSERT3U(Bit, <, sizeof (ULONG_PTR) * 8);
 
     KeMemoryBarrier();
 
-    do {
-        Old = *Mask;
-        New = Old & ~((ULONG_PTR)1 << Bit);
-    } while (InterlockedCompareExchangePointer((PVOID *)Mask, (PVOID)New, (PVOID)Old) != (PVOID)Old);
-
-    KeMemoryBarrier();
-
-    return (Old & ((ULONG_PTR)1 << Bit)) ? TRUE : FALSE;    // return TRUE if we cleared the bit
+    // return TRUE if we cleared the bit
+    return (InterlockedBitTestAndReset((LONG *)Mask, Bit) != 0) ? TRUE : FALSE;
 }
 
 static BOOLEAN
-- 
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 Nov 06 14:24:47 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:47 +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 1XmNzT-0001Z4-OM; Thu, 06 Nov 2014 14:24:47 +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 1XmNzS-0001Xt-5y
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:46 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	0F/E3-07724-DA48B545; Thu, 06 Nov 2014 14:24:45 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16202 invoked from network); 6 Nov 2014 14:24:44 -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;
	6 Nov 2014 14:24:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771857"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-AJ;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:18 +0000
Message-ID: <1415283861-26028-8-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 06/10] Make auto-masking a generic event
	channel property
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

Keeping the Mask boolean in the per-type event channel parameters makes the
code needlessly complex in several places. Just make it a generic property.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn.c | 97 +++++++++++------------------------------------------
 1 file changed, 20 insertions(+), 77 deletions(-)

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 338a90f..5a0822d 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -40,19 +40,13 @@
 #include "dbg_print.h"
 #include "assert.h"
 
-typedef struct _XENBUS_EVTCHN_FIXED_PARAMETERS {
-    BOOLEAN Mask;
-} XENBUS_EVTCHN_FIXED_PARAMETERS, *PXENBUS_EVTCHN_FIXED_PARAMETERS;
-
 typedef struct _XENBUS_EVTCHN_UNBOUND_PARAMETERS {
     USHORT  RemoteDomain;
-    BOOLEAN Mask;
 } XENBUS_EVTCHN_UNBOUND_PARAMETERS, *PXENBUS_EVTCHN_UNBOUND_PARAMETERS;
 
 typedef struct _XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS {
     USHORT  RemoteDomain;
     ULONG   RemotePort;
-    BOOLEAN Mask;
 } XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS, *PXENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS;
 
 typedef struct _XENBUS_EVTCHN_VIRQ_PARAMETERS {
@@ -64,7 +58,6 @@ typedef struct _XENBUS_EVTCHN_VIRQ_PARAMETERS {
 
 typedef struct _XENBUS_EVTCHN_PARAMETERS {
     union {
-        XENBUS_EVTCHN_FIXED_PARAMETERS         Fixed;
         XENBUS_EVTCHN_UNBOUND_PARAMETERS       Unbound;
         XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS  InterDomain;
         XENBUS_EVTCHN_VIRQ_PARAMETERS          Virq;
@@ -84,6 +77,7 @@ struct _XENBUS_EVTCHN_CHANNEL {
     BOOLEAN                     Active; // Must be tested at >= DISPATCH_LEVEL
     XENBUS_EVTCHN_TYPE          Type;
     XENBUS_EVTCHN_PARAMETERS    Parameters;
+    BOOLEAN                     Mask;
     ULONG                       LocalPort;
 };
 
@@ -183,8 +177,7 @@ EvtchnOpenFixed(
     LocalPort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
 
-    Channel->Parameters.Fixed.Mask = Mask;
-
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -209,8 +202,8 @@ EvtchnOpenUnbound(
         goto fail1;
 
     Channel->Parameters.Unbound.RemoteDomain = RemoteDomain;
-    Channel->Parameters.Unbound.Mask = Mask;
 
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -243,8 +236,8 @@ EvtchnOpenInterDomain(
 
     Channel->Parameters.InterDomain.RemoteDomain = RemoteDomain;
     Channel->Parameters.InterDomain.RemotePort = RemotePort;
-    Channel->Parameters.InterDomain.Mask = Mask;
 
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -426,35 +419,10 @@ EvtchnUnmask(
                                      &Context->SharedInfoInterface,
                                      Channel->LocalPort);
 
-        if (Pending) {
-            BOOLEAN Mask = FALSE;
-
-            switch (Channel->Type) {
-            case XENBUS_EVTCHN_TYPE_FIXED:
-                Mask = Channel->Parameters.Fixed.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_UNBOUND:
-                Mask = Channel->Parameters.Unbound.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
-                Mask = Channel->Parameters.InterDomain.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_VIRQ:
-                break;
-
-            default:
-                ASSERT(FALSE);
-                break;
-            }
-
-            if (Mask)
-                XENBUS_SHARED_INFO(EvtchnMask,
-                                   &Context->SharedInfoInterface,
-                                   Channel->LocalPort);
-        }
+        if (Pending && Channel->Mask)
+            XENBUS_SHARED_INFO(EvtchnMask,
+                               &Context->SharedInfoInterface,
+                               Channel->LocalPort);
     }
 
     if (!InCallback)
@@ -620,7 +588,6 @@ EvtchnPollCallback(
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Argument;
     PXENBUS_EVTCHN_CHANNEL  Channel;
-    BOOLEAN                 Mask;
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
@@ -639,30 +606,7 @@ EvtchnPollCallback(
         goto done;
     }
 
-    Mask = FALSE;
-
-    switch (Channel->Type) {
-    case XENBUS_EVTCHN_TYPE_FIXED:
-        Mask = Channel->Parameters.Fixed.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_UNBOUND:
-        Mask = Channel->Parameters.Unbound.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
-        Mask = Channel->Parameters.InterDomain.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_VIRQ:
-        break;
-
-    default:
-        ASSERT(FALSE);
-        break;
-    }
-
-    if (Mask)
+    if (Channel->Mask)
         XENBUS_SHARED_INFO(EvtchnMask,
                            &Context->SharedInfoInterface,
                            LocalPort);
@@ -759,43 +703,42 @@ EvtchnDebugCallback(
             if (Name != NULL) {
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "- (%04x) BY %s + %p [%s]\n",
+                             "- (%04x) BY %s + %p %s%s\n",
                              Channel->LocalPort,
                              Name,
                              (PVOID)Offset,
-                             (Channel->Active) ? "TRUE" : "FALSE");
+                             (Channel->Mask) ? "AUTO-MASK " : "",
+                             (Channel->Active) ? "ACTIVE" : "");
             } else {
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "- (%04x) BY %p [%s]\n",
+                             "- (%04x) BY %p %s%s\n",
                              Channel->LocalPort,
                              (PVOID)Channel->Caller,
-                             (Channel->Active) ? "TRUE" : "FALSE");
+                             (Channel->Mask) ? "AUTO-MASK " : "",
+                             (Channel->Active) ? "ACTIVE" : "");
             }
 
             switch (Channel->Type) {
             case XENBUS_EVTCHN_TYPE_FIXED:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "FIXED: Mask = %s\n",
-                             (Channel->Parameters.Fixed.Mask) ? "TRUE" : "FALSE");
+                             "FIXED\n");
                 break;
 
             case XENBUS_EVTCHN_TYPE_UNBOUND:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "UNBOUND: RemoteDomain = %u Mask = %s\n",
-                             Channel->Parameters.Unbound.RemoteDomain,
-                             (Channel->Parameters.Unbound.Mask) ? "TRUE" : "FALSE");
+                             "UNBOUND: RemoteDomain = %u\n",
+                             Channel->Parameters.Unbound.RemoteDomain);
                 break;
 
             case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "INTER_DOMAIN: RemoteDomain = %u RemotePort = %u Mask = %s\n",
+                             "INTER_DOMAIN: RemoteDomain = %u RemotePort = %u\n",
                              Channel->Parameters.InterDomain.RemoteDomain,
-                             Channel->Parameters.InterDomain.RemotePort,
-                             (Channel->Parameters.InterDomain.Mask) ? "TRUE" : "FALSE");
+                             Channel->Parameters.InterDomain.RemotePort);
                 break;
 
             case XENBUS_EVTCHN_TYPE_VIRQ:
-- 
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 Nov 06 14:24:47 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:47 +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 1XmNzT-0001Z4-OM; Thu, 06 Nov 2014 14:24:47 +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 1XmNzS-0001Xt-5y
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:46 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	0F/E3-07724-DA48B545; Thu, 06 Nov 2014 14:24:45 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16202 invoked from network); 6 Nov 2014 14:24:44 -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;
	6 Nov 2014 14:24:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771857"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-AJ;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:18 +0000
Message-ID: <1415283861-26028-8-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 06/10] Make auto-masking a generic event
	channel property
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

Keeping the Mask boolean in the per-type event channel parameters makes the
code needlessly complex in several places. Just make it a generic property.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn.c | 97 +++++++++++------------------------------------------
 1 file changed, 20 insertions(+), 77 deletions(-)

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 338a90f..5a0822d 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -40,19 +40,13 @@
 #include "dbg_print.h"
 #include "assert.h"
 
-typedef struct _XENBUS_EVTCHN_FIXED_PARAMETERS {
-    BOOLEAN Mask;
-} XENBUS_EVTCHN_FIXED_PARAMETERS, *PXENBUS_EVTCHN_FIXED_PARAMETERS;
-
 typedef struct _XENBUS_EVTCHN_UNBOUND_PARAMETERS {
     USHORT  RemoteDomain;
-    BOOLEAN Mask;
 } XENBUS_EVTCHN_UNBOUND_PARAMETERS, *PXENBUS_EVTCHN_UNBOUND_PARAMETERS;
 
 typedef struct _XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS {
     USHORT  RemoteDomain;
     ULONG   RemotePort;
-    BOOLEAN Mask;
 } XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS, *PXENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS;
 
 typedef struct _XENBUS_EVTCHN_VIRQ_PARAMETERS {
@@ -64,7 +58,6 @@ typedef struct _XENBUS_EVTCHN_VIRQ_PARAMETERS {
 
 typedef struct _XENBUS_EVTCHN_PARAMETERS {
     union {
-        XENBUS_EVTCHN_FIXED_PARAMETERS         Fixed;
         XENBUS_EVTCHN_UNBOUND_PARAMETERS       Unbound;
         XENBUS_EVTCHN_INTER_DOMAIN_PARAMETERS  InterDomain;
         XENBUS_EVTCHN_VIRQ_PARAMETERS          Virq;
@@ -84,6 +77,7 @@ struct _XENBUS_EVTCHN_CHANNEL {
     BOOLEAN                     Active; // Must be tested at >= DISPATCH_LEVEL
     XENBUS_EVTCHN_TYPE          Type;
     XENBUS_EVTCHN_PARAMETERS    Parameters;
+    BOOLEAN                     Mask;
     ULONG                       LocalPort;
 };
 
@@ -183,8 +177,7 @@ EvtchnOpenFixed(
     LocalPort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
 
-    Channel->Parameters.Fixed.Mask = Mask;
-
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -209,8 +202,8 @@ EvtchnOpenUnbound(
         goto fail1;
 
     Channel->Parameters.Unbound.RemoteDomain = RemoteDomain;
-    Channel->Parameters.Unbound.Mask = Mask;
 
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -243,8 +236,8 @@ EvtchnOpenInterDomain(
 
     Channel->Parameters.InterDomain.RemoteDomain = RemoteDomain;
     Channel->Parameters.InterDomain.RemotePort = RemotePort;
-    Channel->Parameters.InterDomain.Mask = Mask;
 
+    Channel->Mask = Mask;
     Channel->LocalPort = LocalPort;
 
     return STATUS_SUCCESS;
@@ -426,35 +419,10 @@ EvtchnUnmask(
                                      &Context->SharedInfoInterface,
                                      Channel->LocalPort);
 
-        if (Pending) {
-            BOOLEAN Mask = FALSE;
-
-            switch (Channel->Type) {
-            case XENBUS_EVTCHN_TYPE_FIXED:
-                Mask = Channel->Parameters.Fixed.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_UNBOUND:
-                Mask = Channel->Parameters.Unbound.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
-                Mask = Channel->Parameters.InterDomain.Mask;
-                break;
-
-            case XENBUS_EVTCHN_TYPE_VIRQ:
-                break;
-
-            default:
-                ASSERT(FALSE);
-                break;
-            }
-
-            if (Mask)
-                XENBUS_SHARED_INFO(EvtchnMask,
-                                   &Context->SharedInfoInterface,
-                                   Channel->LocalPort);
-        }
+        if (Pending && Channel->Mask)
+            XENBUS_SHARED_INFO(EvtchnMask,
+                               &Context->SharedInfoInterface,
+                               Channel->LocalPort);
     }
 
     if (!InCallback)
@@ -620,7 +588,6 @@ EvtchnPollCallback(
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Argument;
     PXENBUS_EVTCHN_CHANNEL  Channel;
-    BOOLEAN                 Mask;
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
@@ -639,30 +606,7 @@ EvtchnPollCallback(
         goto done;
     }
 
-    Mask = FALSE;
-
-    switch (Channel->Type) {
-    case XENBUS_EVTCHN_TYPE_FIXED:
-        Mask = Channel->Parameters.Fixed.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_UNBOUND:
-        Mask = Channel->Parameters.Unbound.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
-        Mask = Channel->Parameters.InterDomain.Mask;
-        break;
-
-    case XENBUS_EVTCHN_TYPE_VIRQ:
-        break;
-
-    default:
-        ASSERT(FALSE);
-        break;
-    }
-
-    if (Mask)
+    if (Channel->Mask)
         XENBUS_SHARED_INFO(EvtchnMask,
                            &Context->SharedInfoInterface,
                            LocalPort);
@@ -759,43 +703,42 @@ EvtchnDebugCallback(
             if (Name != NULL) {
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "- (%04x) BY %s + %p [%s]\n",
+                             "- (%04x) BY %s + %p %s%s\n",
                              Channel->LocalPort,
                              Name,
                              (PVOID)Offset,
-                             (Channel->Active) ? "TRUE" : "FALSE");
+                             (Channel->Mask) ? "AUTO-MASK " : "",
+                             (Channel->Active) ? "ACTIVE" : "");
             } else {
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "- (%04x) BY %p [%s]\n",
+                             "- (%04x) BY %p %s%s\n",
                              Channel->LocalPort,
                              (PVOID)Channel->Caller,
-                             (Channel->Active) ? "TRUE" : "FALSE");
+                             (Channel->Mask) ? "AUTO-MASK " : "",
+                             (Channel->Active) ? "ACTIVE" : "");
             }
 
             switch (Channel->Type) {
             case XENBUS_EVTCHN_TYPE_FIXED:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "FIXED: Mask = %s\n",
-                             (Channel->Parameters.Fixed.Mask) ? "TRUE" : "FALSE");
+                             "FIXED\n");
                 break;
 
             case XENBUS_EVTCHN_TYPE_UNBOUND:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "UNBOUND: RemoteDomain = %u Mask = %s\n",
-                             Channel->Parameters.Unbound.RemoteDomain,
-                             (Channel->Parameters.Unbound.Mask) ? "TRUE" : "FALSE");
+                             "UNBOUND: RemoteDomain = %u\n",
+                             Channel->Parameters.Unbound.RemoteDomain);
                 break;
 
             case XENBUS_EVTCHN_TYPE_INTER_DOMAIN:
                 XENBUS_DEBUG(Printf,
                              &Context->DebugInterface,
-                             "INTER_DOMAIN: RemoteDomain = %u RemotePort = %u Mask = %s\n",
+                             "INTER_DOMAIN: RemoteDomain = %u RemotePort = %u\n",
                              Channel->Parameters.InterDomain.RemoteDomain,
-                             Channel->Parameters.InterDomain.RemotePort,
-                             (Channel->Parameters.InterDomain.Mask) ? "TRUE" : "FALSE");
+                             Channel->Parameters.InterDomain.RemotePort);
                 break;
 
             case XENBUS_EVTCHN_TYPE_VIRQ:
-- 
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 Nov 06 14:24:47 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:47 +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 1XmNzT-0001ZB-PV; Thu, 06 Nov 2014 14:24:47 +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 1XmNzS-0001YO-OS
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:46 +0000
Received: from [85.158.137.68] by server-17.bemta-3.messagelabs.com id
	F0/FB-11608-DA48B545; Thu, 06 Nov 2014 14:24:45 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-31.messagelabs.com!1415283882!10878952!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8929 invoked from network); 6 Nov 2014 14:24:44 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-7.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771859"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-8Z;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:15 +0000
Message-ID: <1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 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

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(-)

diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
index 2e402a8..0d36ac8 100644
--- a/include/shared_info_interface.h
+++ b/include/shared_info_interface.h
@@ -63,11 +63,34 @@ typedef VOID
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENBUS_SHARED_INFO_UPCALL_PENDING
+    \brief Private method for EVTCHN inerface
+*/
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_UPCALL_PENDING)(
+    IN  PINTERFACE  Interface,
+    IN  ULONG       Cpu
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVENT)(
+    IN  PVOID   Argument,
+    IN  ULONG   Port
+    );
+
 /*! \typedef XENBUS_SHARED_INFO_EVTCHN_POLL
     \brief Private method for EVTCHN inerface
 */  
 typedef BOOLEAN
 (*XENBUS_SHARED_INFO_EVTCHN_POLL)(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVTCHN_POLL_V1)(
     IN  PINTERFACE  Interface,
     IN  BOOLEAN     (*Function)(PVOID, ULONG),
     IN  PVOID       Argument
@@ -123,6 +146,22 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     INTERFACE                           Interface;
     XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
     XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_EVTCHN_POLL_V1   SharedInfoEvtchnPollVersion1;
+    XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
+    XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
+    XENBUS_SHARED_INFO_EVTCHN_UNMASK    SharedInfoEvtchnUnmask;
+    XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
+};
+
+/*! \struct _XENBUS_SHARED_INFO_INTERFACE_V2
+    \brief SHARED_INFO interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_SHARED_INFO_INTERFACE_V2 {
+    INTERFACE                           Interface;
+    XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
+    XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_UPCALL_PENDING   SharedInfoUpcallPending;
     XENBUS_SHARED_INFO_EVTCHN_POLL      SharedInfoEvtchnPoll;
     XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
     XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
@@ -130,7 +169,7 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
 };
 
-typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
+typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
 
 /*! \def XENBUS_SHARED_INFO
     \brief Macro at assist in method invocation
@@ -141,6 +180,6 @@ typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, *P
 #endif  // _WINDLL
 
 #define XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN    1
-#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    1
+#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENBUS_SHARED_INFO_H
diff --git a/include/xen.h b/include/xen.h
index 4a202fc..674676c 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -257,4 +257,12 @@ LogPrintf(
     ...
     );
 
+// SYSTEM
+
+XEN_API
+ULONG
+SystemVirtualCpuIndex(
+    IN  ULONG   Index
+    );
+
 #endif  // _XEN_H
diff --git a/src/xen/system.c b/src/xen/system.c
index a9d88c1..1ac8123 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#define XEN_API __declspec(dllexport)
+
 #include <ntddk.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
@@ -447,7 +449,7 @@ SystemPowerStateCallback(
     }
 }
 
-extern NTSTATUS
+NTSTATUS
 SystemInitialize(
     VOID
     )
@@ -503,7 +505,21 @@ fail1:
     return status;
 }
 
-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;
+}
+
+VOID
 SystemTeardown(
     VOID
     )
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 9ba2e84..35ad44a 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -665,10 +665,20 @@ EvtchnInterrupt(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return XENBUS_SHARED_INFO(EvtchnPoll,
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              EvtchnPollCallback,
-                              Context);
+                              0))
+        DoneSomething |= XENBUS_SHARED_INFO(EvtchnPoll,
+                                            &Context->SharedInfoInterface,
+                                            0,
+                                            EvtchnPollCallback,
+                                            Context);
+
+    return DoneSomething;
 }
 
 static VOID
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 41c99cf..0afc218 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -44,6 +44,7 @@ struct _XENBUS_SHARED_INFO_CONTEXT {
     LONG                        References;
     PHYSICAL_ADDRESS            Address;
     shared_info_t               *Shared;
+    ULONG                       Port;
     XENBUS_SUSPEND_INTERFACE    SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
@@ -128,7 +129,7 @@ SharedInfoTestBit(
 }
 
 static VOID
-SharedInfoMaskAll(
+SharedInfoEvtchnMaskAll(
     IN  PXENBUS_SHARED_INFO_CONTEXT Context
     )
 {
@@ -149,70 +150,105 @@ SharedInfoMaskAll(
 }
 
 static BOOLEAN
-SharedInfoEvtchnPoll(
+SharedInfoUpcallPending(
     IN  PINTERFACE              Interface,
-    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
-    IN  PVOID                   Argument OPTIONAL
+    IN  ULONG                   Cpu
     )
 {
     PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
-    shared_info_t               *Shared;
-    static ULONG                Port;
-    BOOLEAN                     DoneSomething;
+    shared_info_t               *Shared = Context->Shared;
+    int                         vcpu_id = SystemVirtualCpuIndex(Cpu);
+    UCHAR                       Pending;
 
-    Shared = Context->Shared;
+    KeMemoryBarrier();
 
-    DoneSomething = FALSE;
+    Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[vcpu_id].evtchn_upcall_pending, 0);
 
-    for (;;) {
-        UCHAR       Pending;
-        ULONG_PTR   SelectorMask;
+    return (Pending != 0) ? TRUE : FALSE;
+}
 
-        KeMemoryBarrier();
+static BOOLEAN
+SharedInfoEvtchnPoll(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument OPTIONAL
+    )
+{
+    PXENBUS_SHARED_INFO_CONTEXT     Context = Interface->Context;
+    shared_info_t                   *Shared = Context->Shared;
+    int                             vcpu_id = SystemVirtualCpuIndex(Cpu);
+    ULONG                           Port;
+    ULONG_PTR                       SelectorMask;
+    BOOLEAN                         DoneSomething;
 
-        Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[0].evtchn_upcall_pending, 0);
-        if (Pending == 0)
-            break;
+    DoneSomething = FALSE;
 
-        SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[0].evtchn_pending_sel, (PVOID)0);
+    KeMemoryBarrier();
 
-        KeMemoryBarrier();
+    SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[vcpu_id].evtchn_pending_sel, (PVOID)0);
+
+    KeMemoryBarrier();
 
-        while (SelectorMask != 0) {
-            ULONG   SelectorBit;
-            ULONG   PortBit;
+    Port = Context->Port;
 
-            SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-            PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+    while (SelectorMask != 0) {
+        ULONG   SelectorBit;
+        ULONG   PortBit;
 
-            if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
-                ULONG_PTR   PortMask;
 
-                PortMask = Shared->evtchn_pending[SelectorBit];
-                PortMask &= ~Shared->evtchn_mask[SelectorBit];
+        SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+        PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
+            ULONG_PTR   PortMask;
 
-                while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
-                    if (SharedInfoTestBit(&PortMask, PortBit)) {
-                        DoneSomething |= Function(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
+            PortMask = Shared->evtchn_pending[SelectorBit];
+            PortMask &= ~Shared->evtchn_mask[SelectorBit];
 
-                        (VOID) SharedInfoClearBitUnlocked(&PortMask, PortBit);
-                    }
+            while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
+                if (SharedInfoTestBit(&PortMask, PortBit)) {
+                    DoneSomething |= Event(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
 
-                    PortBit++;
+                    PortMask &= ~((ULONG_PTR)1 << PortBit);
                 }
 
-                // Are we done with this selector?
-                if (PortMask == 0)
-                    (VOID) SharedInfoClearBitUnlocked(&SelectorMask, SelectorBit);
+                PortBit++;
             }
 
-            Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-
-            if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
-                Port = 0;
+            // Are we done with this selector?
+            if (PortMask == 0)
+                SelectorMask &= ~((ULONG_PTR)1 << SelectorBit);
         }
+
+        Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
+            Port = 0;
     }
 
+    Context->Port = Port;
+
+    return DoneSomething;
+}
+
+static BOOLEAN
+SharedInfoEvtchnPollVersion1(
+    IN  PINTERFACE              Interface,
+    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
+    IN  PVOID                   Argument OPTIONAL
+    )
+{
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (SharedInfoUpcallPending(Interface, 0))
+        DoneSomething |= SharedInfoEvtchnPoll(Interface,
+                                              0,
+                                              Function,
+                                              Argument);
+
     return DoneSomething;
 }
 
@@ -404,7 +440,7 @@ SharedInfoSuspendCallbackEarly(
     PXENBUS_SHARED_INFO_CONTEXT Context = Argument;
 
     SharedInfoMap(Context);
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 }
 
 static VOID
@@ -423,17 +459,30 @@ SharedInfoDebugCallback(
 
     if (!Crashing) {
         shared_info_t   *Shared;
+        LONG            Cpu;
         ULONG           Selector;
 
         Shared = Context->Shared;
 
         KeMemoryBarrier();
 
-        XENBUS_DEBUG(Printf,
-                     &Context->DebugInterface,
-                     "CPU: PENDING: %s SELECTOR MASK: %p\n",
-                     Shared->vcpu_info[0].evtchn_upcall_pending ? "TRUE" : "FALSE",
-                     (PVOID)Shared->vcpu_info[0].evtchn_pending_sel);
+        for (Cpu = 0; Cpu < KeNumberProcessors; Cpu++) {
+            int vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: PENDING: %s\n",
+                         Cpu,
+                         Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
+                         "TRUE" :
+                         "FALSE");
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: SELECTOR MASK: %p\n",
+                         Cpu,
+                         (PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
+        }
 
         for (Selector = 0; Selector < XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT; Selector += 4) {
             XENBUS_DEBUG(Printf,
@@ -490,7 +539,7 @@ SharedInfoAcquire(
     if (Context->Shared == NULL)
         goto fail2;
 
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
@@ -583,6 +632,8 @@ SharedInfoRelease (
 
     Trace("====>\n");
 
+    Context->Port = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
@@ -615,6 +666,18 @@ static struct _XENBUS_SHARED_INFO_INTERFACE_V1 SharedInfoInterfaceVersion1 = {
     { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V1), 1, NULL, NULL, NULL },
     SharedInfoAcquire,
     SharedInfoRelease,
+    SharedInfoEvtchnPollVersion1,
+    SharedInfoEvtchnAck,
+    SharedInfoEvtchnMask,
+    SharedInfoEvtchnUnmask,
+    SharedInfoGetTime
+};
+
+static struct _XENBUS_SHARED_INFO_INTERFACE_V2 SharedInfoInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2), 2, NULL, NULL, NULL },
+    SharedInfoAcquire,
+    SharedInfoRelease,
+    SharedInfoUpcallPending,
     SharedInfoEvtchnPoll,
     SharedInfoEvtchnAck,
     SharedInfoEvtchnMask,
@@ -696,6 +759,23 @@ SharedInfoGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_SHARED_INFO_INTERFACE_V2 *SharedInfoInterface;
+
+        SharedInfoInterface = (struct _XENBUS_SHARED_INFO_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2))
+            break;
+
+        *SharedInfoInterface = SharedInfoInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
-- 
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 Nov 06 14:24:47 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:47 +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 1XmNzT-0001ZB-PV; Thu, 06 Nov 2014 14:24:47 +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 1XmNzS-0001YO-OS
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:46 +0000
Received: from [85.158.137.68] by server-17.bemta-3.messagelabs.com id
	F0/FB-11608-DA48B545; Thu, 06 Nov 2014 14:24:45 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-31.messagelabs.com!1415283882!10878952!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8929 invoked from network); 6 Nov 2014 14:24:44 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-7.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771859"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-8Z;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:15 +0000
Message-ID: <1415283861-26028-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 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

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(-)

diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
index 2e402a8..0d36ac8 100644
--- a/include/shared_info_interface.h
+++ b/include/shared_info_interface.h
@@ -63,11 +63,34 @@ typedef VOID
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENBUS_SHARED_INFO_UPCALL_PENDING
+    \brief Private method for EVTCHN inerface
+*/
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_UPCALL_PENDING)(
+    IN  PINTERFACE  Interface,
+    IN  ULONG       Cpu
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVENT)(
+    IN  PVOID   Argument,
+    IN  ULONG   Port
+    );
+
 /*! \typedef XENBUS_SHARED_INFO_EVTCHN_POLL
     \brief Private method for EVTCHN inerface
 */  
 typedef BOOLEAN
 (*XENBUS_SHARED_INFO_EVTCHN_POLL)(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument
+    );
+
+typedef BOOLEAN
+(*XENBUS_SHARED_INFO_EVTCHN_POLL_V1)(
     IN  PINTERFACE  Interface,
     IN  BOOLEAN     (*Function)(PVOID, ULONG),
     IN  PVOID       Argument
@@ -123,6 +146,22 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     INTERFACE                           Interface;
     XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
     XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_EVTCHN_POLL_V1   SharedInfoEvtchnPollVersion1;
+    XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
+    XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
+    XENBUS_SHARED_INFO_EVTCHN_UNMASK    SharedInfoEvtchnUnmask;
+    XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
+};
+
+/*! \struct _XENBUS_SHARED_INFO_INTERFACE_V2
+    \brief SHARED_INFO interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_SHARED_INFO_INTERFACE_V2 {
+    INTERFACE                           Interface;
+    XENBUS_SHARED_INFO_ACQUIRE          SharedInfoAcquire;
+    XENBUS_SHARED_INFO_RELEASE          SharedInfoRelease;
+    XENBUS_SHARED_INFO_UPCALL_PENDING   SharedInfoUpcallPending;
     XENBUS_SHARED_INFO_EVTCHN_POLL      SharedInfoEvtchnPoll;
     XENBUS_SHARED_INFO_EVTCHN_ACK       SharedInfoEvtchnAck;
     XENBUS_SHARED_INFO_EVTCHN_MASK      SharedInfoEvtchnMask;
@@ -130,7 +169,7 @@ struct _XENBUS_SHARED_INFO_INTERFACE_V1 {
     XENBUS_SHARED_INFO_GET_TIME         SharedInfoGetTime;
 };
 
-typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
+typedef struct _XENBUS_SHARED_INFO_INTERFACE_V2 XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
 
 /*! \def XENBUS_SHARED_INFO
     \brief Macro at assist in method invocation
@@ -141,6 +180,6 @@ typedef struct _XENBUS_SHARED_INFO_INTERFACE_V1 XENBUS_SHARED_INFO_INTERFACE, *P
 #endif  // _WINDLL
 
 #define XENBUS_SHARED_INFO_INTERFACE_VERSION_MIN    1
-#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    1
+#define XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX    2
 
 #endif  // _XENBUS_SHARED_INFO_H
diff --git a/include/xen.h b/include/xen.h
index 4a202fc..674676c 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -257,4 +257,12 @@ LogPrintf(
     ...
     );
 
+// SYSTEM
+
+XEN_API
+ULONG
+SystemVirtualCpuIndex(
+    IN  ULONG   Index
+    );
+
 #endif  // _XEN_H
diff --git a/src/xen/system.c b/src/xen/system.c
index a9d88c1..1ac8123 100644
--- a/src/xen/system.c
+++ b/src/xen/system.c
@@ -29,6 +29,8 @@
  * SUCH DAMAGE.
  */
 
+#define XEN_API __declspec(dllexport)
+
 #include <ntddk.h>
 #include <ntstrsafe.h>
 #include <stdlib.h>
@@ -447,7 +449,7 @@ SystemPowerStateCallback(
     }
 }
 
-extern NTSTATUS
+NTSTATUS
 SystemInitialize(
     VOID
     )
@@ -503,7 +505,21 @@ fail1:
     return status;
 }
 
-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;
+}
+
+VOID
 SystemTeardown(
     VOID
     )
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 9ba2e84..35ad44a 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -665,10 +665,20 @@ EvtchnInterrupt(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return XENBUS_SHARED_INFO(EvtchnPoll,
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              EvtchnPollCallback,
-                              Context);
+                              0))
+        DoneSomething |= XENBUS_SHARED_INFO(EvtchnPoll,
+                                            &Context->SharedInfoInterface,
+                                            0,
+                                            EvtchnPollCallback,
+                                            Context);
+
+    return DoneSomething;
 }
 
 static VOID
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 41c99cf..0afc218 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -44,6 +44,7 @@ struct _XENBUS_SHARED_INFO_CONTEXT {
     LONG                        References;
     PHYSICAL_ADDRESS            Address;
     shared_info_t               *Shared;
+    ULONG                       Port;
     XENBUS_SUSPEND_INTERFACE    SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
@@ -128,7 +129,7 @@ SharedInfoTestBit(
 }
 
 static VOID
-SharedInfoMaskAll(
+SharedInfoEvtchnMaskAll(
     IN  PXENBUS_SHARED_INFO_CONTEXT Context
     )
 {
@@ -149,70 +150,105 @@ SharedInfoMaskAll(
 }
 
 static BOOLEAN
-SharedInfoEvtchnPoll(
+SharedInfoUpcallPending(
     IN  PINTERFACE              Interface,
-    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
-    IN  PVOID                   Argument OPTIONAL
+    IN  ULONG                   Cpu
     )
 {
     PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
-    shared_info_t               *Shared;
-    static ULONG                Port;
-    BOOLEAN                     DoneSomething;
+    shared_info_t               *Shared = Context->Shared;
+    int                         vcpu_id = SystemVirtualCpuIndex(Cpu);
+    UCHAR                       Pending;
 
-    Shared = Context->Shared;
+    KeMemoryBarrier();
 
-    DoneSomething = FALSE;
+    Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[vcpu_id].evtchn_upcall_pending, 0);
 
-    for (;;) {
-        UCHAR       Pending;
-        ULONG_PTR   SelectorMask;
+    return (Pending != 0) ? TRUE : FALSE;
+}
 
-        KeMemoryBarrier();
+static BOOLEAN
+SharedInfoEvtchnPoll(
+    IN  PINTERFACE                  Interface,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_SHARED_INFO_EVENT    Event,
+    IN  PVOID                       Argument OPTIONAL
+    )
+{
+    PXENBUS_SHARED_INFO_CONTEXT     Context = Interface->Context;
+    shared_info_t                   *Shared = Context->Shared;
+    int                             vcpu_id = SystemVirtualCpuIndex(Cpu);
+    ULONG                           Port;
+    ULONG_PTR                       SelectorMask;
+    BOOLEAN                         DoneSomething;
 
-        Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[0].evtchn_upcall_pending, 0);
-        if (Pending == 0)
-            break;
+    DoneSomething = FALSE;
 
-        SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[0].evtchn_pending_sel, (PVOID)0);
+    KeMemoryBarrier();
 
-        KeMemoryBarrier();
+    SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[vcpu_id].evtchn_pending_sel, (PVOID)0);
+
+    KeMemoryBarrier();
 
-        while (SelectorMask != 0) {
-            ULONG   SelectorBit;
-            ULONG   PortBit;
+    Port = Context->Port;
 
-            SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-            PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+    while (SelectorMask != 0) {
+        ULONG   SelectorBit;
+        ULONG   PortBit;
 
-            if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
-                ULONG_PTR   PortMask;
 
-                PortMask = Shared->evtchn_pending[SelectorBit];
-                PortMask &= ~Shared->evtchn_mask[SelectorBit];
+        SelectorBit = Port / XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+        PortBit = Port % XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (SharedInfoTestBit(&SelectorMask, SelectorBit)) {
+            ULONG_PTR   PortMask;
 
-                while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
-                    if (SharedInfoTestBit(&PortMask, PortBit)) {
-                        DoneSomething |= Function(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
+            PortMask = Shared->evtchn_pending[SelectorBit];
+            PortMask &= ~Shared->evtchn_mask[SelectorBit];
 
-                        (VOID) SharedInfoClearBitUnlocked(&PortMask, PortBit);
-                    }
+            while (PortMask != 0 && PortBit < XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) {
+                if (SharedInfoTestBit(&PortMask, PortBit)) {
+                    DoneSomething |= Event(Argument, (SelectorBit * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR) + PortBit);
 
-                    PortBit++;
+                    PortMask &= ~((ULONG_PTR)1 << PortBit);
                 }
 
-                // Are we done with this selector?
-                if (PortMask == 0)
-                    (VOID) SharedInfoClearBitUnlocked(&SelectorMask, SelectorBit);
+                PortBit++;
             }
 
-            Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
-
-            if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
-                Port = 0;
+            // Are we done with this selector?
+            if (PortMask == 0)
+                SelectorMask &= ~((ULONG_PTR)1 << SelectorBit);
         }
+
+        Port = (SelectorBit + 1) * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR;
+
+        if (Port >= XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR)
+            Port = 0;
     }
 
+    Context->Port = Port;
+
+    return DoneSomething;
+}
+
+static BOOLEAN
+SharedInfoEvtchnPollVersion1(
+    IN  PINTERFACE              Interface,
+    IN  BOOLEAN                 (*Function)(PVOID, ULONG),
+    IN  PVOID                   Argument OPTIONAL
+    )
+{
+    BOOLEAN                     DoneSomething;
+
+    DoneSomething = FALSE;
+
+    while (SharedInfoUpcallPending(Interface, 0))
+        DoneSomething |= SharedInfoEvtchnPoll(Interface,
+                                              0,
+                                              Function,
+                                              Argument);
+
     return DoneSomething;
 }
 
@@ -404,7 +440,7 @@ SharedInfoSuspendCallbackEarly(
     PXENBUS_SHARED_INFO_CONTEXT Context = Argument;
 
     SharedInfoMap(Context);
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 }
 
 static VOID
@@ -423,17 +459,30 @@ SharedInfoDebugCallback(
 
     if (!Crashing) {
         shared_info_t   *Shared;
+        LONG            Cpu;
         ULONG           Selector;
 
         Shared = Context->Shared;
 
         KeMemoryBarrier();
 
-        XENBUS_DEBUG(Printf,
-                     &Context->DebugInterface,
-                     "CPU: PENDING: %s SELECTOR MASK: %p\n",
-                     Shared->vcpu_info[0].evtchn_upcall_pending ? "TRUE" : "FALSE",
-                     (PVOID)Shared->vcpu_info[0].evtchn_pending_sel);
+        for (Cpu = 0; Cpu < KeNumberProcessors; Cpu++) {
+            int vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: PENDING: %s\n",
+                         Cpu,
+                         Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
+                         "TRUE" :
+                         "FALSE");
+
+            XENBUS_DEBUG(Printf,
+                         &Context->DebugInterface,
+                         "CPU %u: SELECTOR MASK: %p\n",
+                         Cpu,
+                         (PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
+        }
 
         for (Selector = 0; Selector < XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT; Selector += 4) {
             XENBUS_DEBUG(Printf,
@@ -490,7 +539,7 @@ SharedInfoAcquire(
     if (Context->Shared == NULL)
         goto fail2;
 
-    SharedInfoMaskAll(Context);
+    SharedInfoEvtchnMaskAll(Context);
 
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
@@ -583,6 +632,8 @@ SharedInfoRelease (
 
     Trace("====>\n");
 
+    Context->Port = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
@@ -615,6 +666,18 @@ static struct _XENBUS_SHARED_INFO_INTERFACE_V1 SharedInfoInterfaceVersion1 = {
     { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V1), 1, NULL, NULL, NULL },
     SharedInfoAcquire,
     SharedInfoRelease,
+    SharedInfoEvtchnPollVersion1,
+    SharedInfoEvtchnAck,
+    SharedInfoEvtchnMask,
+    SharedInfoEvtchnUnmask,
+    SharedInfoGetTime
+};
+
+static struct _XENBUS_SHARED_INFO_INTERFACE_V2 SharedInfoInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2), 2, NULL, NULL, NULL },
+    SharedInfoAcquire,
+    SharedInfoRelease,
+    SharedInfoUpcallPending,
     SharedInfoEvtchnPoll,
     SharedInfoEvtchnAck,
     SharedInfoEvtchnMask,
@@ -696,6 +759,23 @@ SharedInfoGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_SHARED_INFO_INTERFACE_V2 *SharedInfoInterface;
+
+        SharedInfoInterface = (struct _XENBUS_SHARED_INFO_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_SHARED_INFO_INTERFACE_V2))
+            break;
+
+        *SharedInfoInterface = SharedInfoInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
-- 
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 Nov 06 14:24:48 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:48 +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 1XmNzU-0001Zw-RQ; Thu, 06 Nov 2014 14:24:48 +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 1XmNzT-0001Ys-CP
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:47 +0000
Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id
	9E/F4-26858-EA48B545; Thu, 06 Nov 2014 14:24:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16386 invoked from network); 6 Nov 2014 14:24:45 -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;
	6 Nov 2014 14:24:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771862"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-9m;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:17 +0000
Message-ID: <1415283861-26028-7-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 30675
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 05/10] Use a hash table for event channel
	lookup
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

UmF0aGVyIHRoYW4gdXNpbmcgYSBsYXJnZSBhcnJheSBmb3IgbWFwcGluZyBwb3J0IHZhbHVlcyB0
byBjaGFubmVsCnN0cnVjdHVyZXMsIHVzZSBhIGhhc2ggdGFibGUuIFRoaXMgbWVhbnMgd2Ugbm8g
bG9uZ2VyIG5lZWQgdG8gY29kZSBhCmhhcmQgcG9ydCBudW1iZXIgbGltaXQgaW50byB0aGUgRVZU
Q0hOIGltcGxlbWVudGF0aW9uLgoKQmVjYXVzZSB0aGUgaGFzaCB0YWJsZSBpbXBsZW1lbnRhdGlv
biBtYW5hZ2VzIGl0cyBvd24gbG9ja2luZywgd2UgYWxzbyBubwpsb25nZXIgbmVlZCB0byBtYWtl
IHN1Y2ggbGliZXJhbCB1c2Ugb2YgdGhlIGludGVycnVwdCBsb2NrIGluIHRoZSBFVlRDSE4KaW1w
bGVtZW50YXRpb24gYW5kIGNhbiB1c2UgdGhlIHNwaW5sb2NrIGluc3RlYWQuCgpTaWduZWQtb2Zm
LWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGluY2x1ZGUv
ZXZ0Y2huX2ludGVyZmFjZS5oICAgICAgfCAgIDQgKy0KIGluY2x1ZGUvc2hhcmVkX2luZm9faW50
ZXJmYWNlLmggfCAgIDMgLQogc3JjL3hlbmJ1cy9ldnRjaG4uYyAgICAgICAgICAgICB8ICA4OSAr
KysrKystLS0tCiBzcmMveGVuYnVzL2hhc2hfdGFibGUuYyAgICAgICAgIHwgMzY3ICsrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNyYy94ZW5idXMvaGFzaF90YWJsZS5o
ICAgICAgICAgfCAgNzAgKysrKysrKysKIHNyYy94ZW5idXMvc2hhcmVkX2luZm8uYyAgICAgICAg
fCAgIDMgKwogdnMyMDEyL3hlbmJ1cy94ZW5idXMudmN4cHJvaiAgICB8ICAgMSArCiB2czIwMTMv
eGVuYnVzL3hlbmJ1cy52Y3hwcm9qICAgIHwgICAzICstCiA4IGZpbGVzIGNoYW5nZWQsIDUwNCBp
bnNlcnRpb25zKCspLCAzNiBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBzcmMveGVu
YnVzL2hhc2hfdGFibGUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IHNyYy94ZW5idXMvaGFzaF90YWJs
ZS5oCgpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9ldnRjaG5faW50ZXJmYWNlLmggYi9pbmNsdWRlL2V2
dGNobl9pbnRlcmZhY2UuaAppbmRleCA5OTFkNjEwLi4zYTQ4OTE1IDEwMDY0NAotLS0gYS9pbmNs
dWRlL2V2dGNobl9pbnRlcmZhY2UuaAorKysgYi9pbmNsdWRlL2V2dGNobl9pbnRlcmZhY2UuaApA
QCAtMTE3LDE0ICsxMTcsMTQgQEAgdHlwZWRlZiBQWEVOQlVTX0VWVENITl9DSEFOTkVMCiAKICAg
ICBccGFyYW0gSW50ZXJmYWNlIFRoZSBpbnRlcmZhY2UgaGVhZGVyCiAgICAgXHBhcmFtIENoYW5u
ZWwgVGhlIGNoYW5uZWwgaGFuZGxlCi0gICAgXHBhcmFtIExvY2tlZCBTZXQgdG8gVFJVRSBpZiB0
aGlzIG1ldGhvZCBpcyBpbnZva2VkIGluIGNvbnRleHQgb2YgdGhlIGNoYW5uZWwgY2FsbGJhY2sK
KyAgICBccGFyYW0gSW5DYWxsYmFjayBTZXQgdG8gVFJVRSBpZiB0aGlzIG1ldGhvZCBpcyBpbnZv
a2VkIGluIGNvbnRleHQgb2YgdGhlIGNoYW5uZWwgY2FsbGJhY2sKICAgICBccmV0dXJuIFRSVUUg
aWYgdGhlcmUgd2FzIGFuIGV2ZW50IHBlbmRpbmcgYXQgdGhlIHBvaW50IG9mIHVubWFzaywgRkFM
U0Ugb3RoZXJ3aXNlCiAqLwogdHlwZWRlZiBCT09MRUFOCiAoKlhFTkJVU19FVlRDSE5fVU5NQVNL
KSgKICAgICBJTiAgUElOVEVSRkFDRSAgICAgICAgICAgICAgSW50ZXJmYWNlLAogICAgIElOICBQ
WEVOQlVTX0VWVENITl9DSEFOTkVMICBDaGFubmVsLAotICAgIElOICBCT09MRUFOICAgICAgICAg
ICAgICAgICBMb2NrZWQKKyAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgSW5DYWxsYmFj
awogICAgICk7CiAKIC8qISBcdHlwZWRlZiBYRU5CVVNfRVZUQ0hOX1NFTkQKZGlmZiAtLWdpdCBh
L2luY2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmggYi9pbmNsdWRlL3NoYXJlZF9pbmZvX2lu
dGVyZmFjZS5oCmluZGV4IDBkMzZhYzguLjBlNWEwZDcgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvc2hh
cmVkX2luZm9faW50ZXJmYWNlLmgKKysrIGIvaW5jbHVkZS9zaGFyZWRfaW5mb19pbnRlcmZhY2Uu
aApAQCAtNDAsOSArNDAsNiBAQAogCiAjaWZuZGVmIF9XSU5ETEwKIAotI2RlZmluZSBYRU5CVVNf
U0hBUkVEX0lORk9fRVZUQ0hOX1BFUl9TRUxFQ1RPUiAgICAgKHNpemVvZiAoVUxPTkdfUFRSKSAq
IDgpCi0jZGVmaW5lIFhFTkJVU19TSEFSRURfSU5GT19FVlRDSE5fU0VMRUNUT1JfQ09VTlQgICAo
UlRMX0ZJRUxEX1NJWkUoc2hhcmVkX2luZm9fdCwgZXZ0Y2huX3BlbmRpbmcpIC8gc2l6ZW9mIChV
TE9OR19QVFIpKQotCiAvKiEgXHR5cGVkZWYgWEVOQlVTX1NIQVJFRF9JTkZPX0FDUVVJUkUKICAg
ICBcYnJpZWYgQWNxdWlyZSBhIHJlZmVyZW5jZSB0byB0aGUgU0hBUkVEX0lORk8gaW50ZXJmYWNl
CiAKZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZXZ0Y2huLmMgYi9zcmMveGVuYnVzL2V2dGNobi5j
CmluZGV4IDM1YWQ0NGEuLjMzOGE5MGYgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZXZ0Y2huLmMK
KysrIGIvc3JjL3hlbmJ1cy9ldnRjaG4uYwpAQCAtMzYsNiArMzYsNyBAQAogCiAjaW5jbHVkZSAi
ZXZ0Y2huLmgiCiAjaW5jbHVkZSAiZmRvLmgiCisjaW5jbHVkZSAiaGFzaF90YWJsZS5oIgogI2lu
Y2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgogCkBAIC05Nyw3ICs5OCw3
IEBAIHN0cnVjdCBfWEVOQlVTX0VWVENITl9DT05URVhUIHsKICAgICBYRU5CVVNfREVCVUdfSU5U
RVJGQUNFICAgICAgICAgIERlYnVnSW50ZXJmYWNlOwogICAgIFBYRU5CVVNfREVCVUdfQ0FMTEJB
Q0sgICAgICAgICAgRGVidWdDYWxsYmFjazsKICAgICBYRU5CVVNfU0hBUkVEX0lORk9fSU5URVJG
QUNFICAgIFNoYXJlZEluZm9JbnRlcmZhY2U7Ci0gICAgUFhFTkJVU19FVlRDSE5fQ0hBTk5FTCAg
ICAgICAgICBDaGFubmVsW1hFTkJVU19TSEFSRURfSU5GT19FVlRDSE5fU0VMRUNUT1JfQ09VTlQg
KiBYRU5CVVNfU0hBUkVEX0lORk9fRVZUQ0hOX1BFUl9TRUxFQ1RPUl07CisgICAgUFhFTkJVU19I
QVNIX1RBQkxFICAgICAgICAgICAgICBUYWJsZTsKICAgICBMSVNUX0VOVFJZICAgICAgICAgICAg
ICAgICAgICAgIExpc3Q7CiB9OwogCkBAIC0zNTEsMTQgKzM1MiwxNiBAQCBFdnRjaG5PcGVuKAog
CiAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OwogCi0gICAgQVNTRVJUM1UoTG9j
YWxQb3J0LCA8LCBzaXplb2YgKENvbnRleHQtPkNoYW5uZWwpIC8gc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsWzBdKSk7Ci0KLSAgICAoVk9JRCkgX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhD
b250ZXh0KTsKKyAgICBzdGF0dXMgPSBIYXNoVGFibGVBZGQoQ29udGV4dC0+VGFibGUsCisgICAg
ICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwKKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgKFVMT05HX1BUUilDaGFubmVsKTsKKyAgICBpZiAoIU5UX1NVQ0NFU1Moc3RhdHVzKSkKKyAg
ICAgICAgZ290byBmYWlsMzsKIAotICAgIEFTU0VSVDNQKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQ
b3J0XSwgPT0sIE5VTEwpOwotICAgIENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSA9IENoYW5u
ZWw7CiAgICAgQ2hhbm5lbC0+QWN0aXZlID0gVFJVRTsKIAorICAgIEtlQWNxdWlyZVNwaW5Mb2Nr
QXREcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7CisKICAgICBJbnNlcnRUYWlsTGlzdCgmQ29udGV4
dC0+TGlzdCwgJkNoYW5uZWwtPkxpc3RFbnRyeSk7CiAKICAgICBpZiAoIUlzTGlzdEVtcHR5KCZD
b250ZXh0LT5MaXN0KSAmJiAhQ29udGV4dC0+RW5hYmxlZCkgewpAQCAtMzY2LDEyICszNjksMTgg
QEAgRXZ0Y2huT3BlbigKICAgICAgICAgQ29udGV4dC0+RW5hYmxlZCA9IFRSVUU7CiAgICAgfQog
Ci0gICAgX19FdnRjaG5SZWxlYXNlSW50ZXJydXB0TG9jayhDb250ZXh0LCBESVNQQVRDSF9MRVZF
TCk7CisgICAgS2VSZWxlYXNlU3BpbkxvY2tGcm9tRHBjTGV2ZWwoJkNvbnRleHQtPkxvY2spOwog
CiAgICAgS2VMb3dlcklycWwoSXJxbCk7CiAKICAgICByZXR1cm4gQ2hhbm5lbDsKIAorZmFpbDM6
CisgICAgRXJyb3IoImZhaWwzXG4iKTsKKworICAgIENoYW5uZWwtPkxvY2FsUG9ydCA9IDA7Cisg
ICAgUnRsWmVyb01lbW9yeSgmQ2hhbm5lbC0+UGFyYW1ldGVycywgc2l6ZW9mIChYRU5CVVNfRVZU
Q0hOX1BBUkFNRVRFUlMpKTsKKwogZmFpbDI6CiAgICAgRXJyb3IoImZhaWwyXG4iKTsKIApAQCAt
Mzk4LDcgKzQwNyw3IEBAIHN0YXRpYyBCT09MRUFOCiBFdnRjaG5Vbm1hc2soCiAgICAgSU4gIFBJ
TlRFUkZBQ0UgICAgICAgICAgICAgIEludGVyZmFjZSwKICAgICBJTiAgUFhFTkJVU19FVlRDSE5f
Q0hBTk5FTCAgQ2hhbm5lbCwKLSAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTG9ja2Vk
CisgICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAgICAgIEluQ2FsbGJhY2sKICAgICApCiB7CiAg
ICAgUFhFTkJVU19FVlRDSE5fQ09OVEVYVCAgICAgIENvbnRleHQgPSBJbnRlcmZhY2UtPkNvbnRl
eHQ7CkBAIC00MDcsOCArNDE2LDEwIEBAIEV2dGNoblVubWFzaygKIAogICAgIEFTU0VSVDNVKENo
YW5uZWwtPk1hZ2ljLCA9PSwgWEVOQlVTX0VWVENITl9DSEFOTkVMX01BR0lDKTsKIAotICAgIGlm
ICghTG9ja2VkKQotICAgICAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhD
b250ZXh0KTsKKyAgICBpZiAoIUluQ2FsbGJhY2spCisgICAgICAgIEtlUmFpc2VJcnFsKERJU1BB
VENIX0xFVkVMLCAmSXJxbCk7IC8vIFByZXZlbnQgc3VzcGVuZAorCisgICAgQVNTRVJUM1UoS2VH
ZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFUQ0hfTEVWRUwpOwogCiAgICAgaWYgKENoYW5uZWwt
PkFjdGl2ZSkgewogICAgICAgICBQZW5kaW5nID0gWEVOQlVTX1NIQVJFRF9JTkZPKEV2dGNoblVu
bWFzaywKQEAgLTQ0Niw4ICs0NTcsOCBAQCBFdnRjaG5Vbm1hc2soCiAgICAgICAgIH0KICAgICB9
CiAKLSAgICBpZiAoIUxvY2tlZCkKLSAgICAgICAgX19FdnRjaG5SZWxlYXNlSW50ZXJydXB0TG9j
ayhDb250ZXh0LCBJcnFsKTsKKyAgICBpZiAoIUluQ2FsbGJhY2spCisgICAgICAgIEtlTG93ZXJJ
cnFsKElycWwpOwogCiAgICAgcmV0dXJuIFBlbmRpbmc7CiB9CkBAIC01MTMsNiArNTI0LDggQEAg
RXZ0Y2huVHJpZ2dlcigKIAogICAgIElycWwgPSBfX0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2Nr
KENvbnRleHQpOwogCisgICAgQVNTRVJUM1UoS2VHZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFU
Q0hfTEVWRUwpOworCiAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgewogICAgICAgICBEb25lU29t
ZXRoaW5nID0gRXZ0Y2huQ2FsbGJhY2soQ29udGV4dCwgQ2hhbm5lbCk7CiAgICAgfSBlbHNlIHsK
QEAgLTUzNiw3ICs1NDksOSBAQCBFdnRjaG5DbG9zZSgKIAogICAgIEFTU0VSVDNVKENoYW5uZWwt
Pk1hZ2ljLCA9PSwgWEVOQlVTX0VWVENITl9DSEFOTkVMX01BR0lDKTsKIAotICAgIElycWwgPSBf
X0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2NrKENvbnRleHQpOworICAgIEtlUmFpc2VJcnFsKERJ
U1BBVENIX0xFVkVMLCAmSXJxbCk7IC8vIFByZXZlbnQgc3VzcGVuZAorCisgICAgS2VBY3F1aXJl
U3BpbkxvY2tBdERwY0xldmVsKCZDb250ZXh0LT5Mb2NrKTsKIAogICAgIFJlbW92ZUVudHJ5TGlz
dCgmQ2hhbm5lbC0+TGlzdEVudHJ5KTsKIApAQCAtNTQ1LDEyICs1NjAsMTMgQEAgRXZ0Y2huQ2xv
c2UoCiAgICAgICAgIENvbnRleHQtPkVuYWJsZWQgPSBGQUxTRTsKICAgICB9CiAKKyAgICBLZVJl
bGVhc2VTcGluTG9ja0Zyb21EcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7CisKICAgICBSdGxaZXJv
TWVtb3J5KCZDaGFubmVsLT5MaXN0RW50cnksIHNpemVvZiAoTElTVF9FTlRSWSkpOwogCiAgICAg
aWYgKENoYW5uZWwtPkFjdGl2ZSkgewotICAgICAgICBVTE9ORyAgIExvY2FsUG9ydCA9IENoYW5u
ZWwtPkxvY2FsUG9ydDsKLQotICAgICAgICBBU1NFUlQzVShMb2NhbFBvcnQsIDwsIHNpemVvZiAo
Q29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtPkNoYW5uZWxbMF0pKTsKKyAgICAg
ICAgVUxPTkcgICAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OworICAgICAgICBO
VFNUQVRVUyAgICBzdGF0dXM7CiAKICAgICAgICAgQ2hhbm5lbC0+QWN0aXZlID0gRkFMU0U7CiAK
QEAgLTU2MSwxMiArNTc3LDEwIEBAIEV2dGNobkNsb3NlKAogICAgICAgICBpZiAoQ2hhbm5lbC0+
VHlwZSAhPSBYRU5CVVNfRVZUQ0hOX1RZUEVfRklYRUQpCiAgICAgICAgICAgICAoVk9JRCkgRXZl
bnRDaGFubmVsQ2xvc2UoTG9jYWxQb3J0KTsKIAotICAgICAgICBBU1NFUlQoQ29udGV4dC0+Q2hh
bm5lbFtMb2NhbFBvcnRdICE9IE5VTEwpOwotICAgICAgICBDb250ZXh0LT5DaGFubmVsW0xvY2Fs
UG9ydF0gPSBOVUxMOworICAgICAgICBzdGF0dXMgPSBIYXNoVGFibGVSZW1vdmUoQ29udGV4dC0+
VGFibGUsIExvY2FsUG9ydCk7CisgICAgICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykpOwog
ICAgIH0KIAotICAgIF9fRXZ0Y2huUmVsZWFzZUludGVycnVwdExvY2soQ29udGV4dCwgSXJxbCk7
Ci0KICAgICBDaGFubmVsLT5Mb2NhbFBvcnQgPSAwOwogICAgIFJ0bFplcm9NZW1vcnkoJkNoYW5u
ZWwtPlBhcmFtZXRlcnMsIHNpemVvZiAoWEVOQlVTX0VWVENITl9QQVJBTUVURVJTKSk7CiAKQEAg
LTU4MCw2ICs1OTQsOCBAQCBFdnRjaG5DbG9zZSgKIAogICAgIEFTU0VSVChJc1plcm9NZW1vcnko
Q2hhbm5lbCwgc2l6ZW9mIChYRU5CVVNfRVZUQ0hOX0NIQU5ORUwpKSk7CiAgICAgX19FdnRjaG5G
cmVlKENoYW5uZWwpOworCisgICAgS2VMb3dlcklycWwoSXJxbCk7CiB9CiAKIHN0YXRpYyBVTE9O
RwpAQCAtNjA2LDEyICs2MjIsMTMgQEAgRXZ0Y2huUG9sbENhbGxiYWNrKAogICAgIFBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwgIENoYW5uZWw7CiAgICAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTWFz
azsKICAgICBCT09MRUFOICAgICAgICAgICAgICAgICBEb25lU29tZXRoaW5nOworICAgIE5UU1RB
VFVTICAgICAgICAgICAgICAgIHN0YXR1czsKIAotICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwg
c2l6ZW9mIChDb250ZXh0LT5DaGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbFswXSkp
OwotCi0gICAgQ2hhbm5lbCA9IENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XTsKLQotICAgIGlm
IChDaGFubmVsID09IE5VTEwpIHsKKyAgICBzdGF0dXMgPSBIYXNoVGFibGVMb29rdXAoQ29udGV4
dC0+VGFibGUsCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwKKyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgKFBVTE9OR19QVFIpJkNoYW5uZWwpOworICAgIAorICAg
IGlmICghTlRfU1VDQ0VTUyhzdGF0dXMpKSB7CiAgICAgICAgIFdhcm5pbmcoIlslZF06IElOVkFM
SUQgUE9SVFxuIiwgTG9jYWxQb3J0KTsKIAogICAgICAgICBYRU5CVVNfU0hBUkVEX0lORk8oRXZ0
Y2huTWFzaywKQEAgLTY5NywxNCArNzE0LDEzIEBAIEV2dGNoblN1c3BlbmRDYWxsYmFja0Vhcmx5
KAogICAgICAgICBDaGFubmVsID0gQ09OVEFJTklOR19SRUNPUkQoTGlzdEVudHJ5LCBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwsIExpc3RFbnRyeSk7CiAKICAgICAgICAgaWYgKENoYW5uZWwtPkFjdGl2
ZSkgewotICAgICAgICAgICAgVUxPTkcgICBMb2NhbFBvcnQgPSBDaGFubmVsLT5Mb2NhbFBvcnQ7
Ci0KLSAgICAgICAgICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwgc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbFswXSkpOworICAgICAgICAgICAgVUxP
TkcgICAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OworICAgICAgICAgICAgTlRT
VEFUVVMgICAgc3RhdHVzOwogCiAgICAgICAgICAgICBDaGFubmVsLT5BY3RpdmUgPSBGQUxTRTsK
IAotICAgICAgICAgICAgQVNTRVJUKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSAhPSBOVUxM
KTsKLSAgICAgICAgICAgIENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSA9IE5VTEw7CisgICAg
ICAgICAgICBzdGF0dXMgPSBIYXNoVGFibGVSZW1vdmUoQ29udGV4dC0+VGFibGUsIExvY2FsUG9y
dCk7CisgICAgICAgICAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsKICAgICAgICAgfQog
ICAgIH0KIApAQCAtOTU4LDYgKzk3NCwxMCBAQCBFdnRjaG5Jbml0aWFsaXplKAogICAgIGlmICgq
Q29udGV4dCA9PSBOVUxMKQogICAgICAgICBnb3RvIGZhaWwxOwogCisgICAgc3RhdHVzID0gSGFz
aFRhYmxlQ3JlYXRlKCYoKkNvbnRleHQpLT5UYWJsZSk7CisgICAgaWYgKCFOVF9TVUNDRVNTKHN0
YXR1cykpCisgICAgICAgIGdvdG8gZmFpbDI7CisKICAgICBzdGF0dXMgPSBTdXNwZW5kR2V0SW50
ZXJmYWNlKEZkb0dldFN1c3BlbmRDb250ZXh0KEZkbyksCiAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICBYRU5CVVNfU1VTUEVORF9JTlRFUkZBQ0VfVkVSU0lPTl9NQVgsCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAoUElOVEVSRkFDRSkmKCpDb250ZXh0KS0+U3VzcGVu
ZEludGVyZmFjZSwKQEAgLTk4OCw2ICsxMDA4LDEyIEBAIEV2dGNobkluaXRpYWxpemUoCiAKICAg
ICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CiAKK2ZhaWwyOgorICAgIEVycm9yKCJmYWlsMlxuIik7
CisKKyAgICBBU1NFUlQoSXNaZXJvTWVtb3J5KENvbnRleHQsIHNpemVvZiAoWEVOQlVTX0VWVENI
Tl9DT05URVhUKSkpOworICAgIF9fRXZ0Y2huRnJlZShDb250ZXh0KTsKKwogZmFpbDE6CiAgICAg
RXJyb3IoImZhaWwxICglMDh4KVxuIiwgc3RhdHVzKTsKIApAQCAtMTA1Myw2ICsxMDc5LDkgQEAg
RXZ0Y2huVGVhcmRvd24oCiAgICAgUnRsWmVyb01lbW9yeSgmQ29udGV4dC0+U3VzcGVuZEludGVy
ZmFjZSwKICAgICAgICAgICAgICAgICAgIHNpemVvZiAoWEVOQlVTX1NVU1BFTkRfSU5URVJGQUNF
KSk7CiAKKyAgICBIYXNoVGFibGVEZXN0cm95KENvbnRleHQtPlRhYmxlKTsKKyAgICBDb250ZXh0
LT5UYWJsZSA9IE5VTEw7CisKICAgICBBU1NFUlQoSXNaZXJvTWVtb3J5KENvbnRleHQsIHNpemVv
ZiAoWEVOQlVTX0VWVENITl9DT05URVhUKSkpOwogICAgIF9fRXZ0Y2huRnJlZShDb250ZXh0KTsK
IApkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMgYi9zcmMveGVuYnVzL2hhc2hf
dGFibGUuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5iOGUyN2Q4Ci0tLSAv
ZGV2L251bGwKKysrIGIvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMKQEAgLTAsMCArMSwzNjcgQEAK
Ky8qIENvcHlyaWdodCAoYykgQ2l0cml4IFN5c3RlbXMgSW5jLgorICogQWxsIHJpZ2h0cyByZXNl
cnZlZC4KKyAqIAorICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFy
eSBmb3JtcywgCisgKiB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVk
IHByb3ZpZGVkIAorICogdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKKyAq
IAorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUg
YWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMg
YW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1lci4KKyAqICogICBSZWRpc3RyaWJ1
dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIAorICogICAgIGNv
cHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgCisgKiAgICAg
Zm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIAor
ICogICAgIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCisgKiAKKyAq
IFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCAK
KyAqIENPTlRSSUJVVE9SUyAiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJB
TlRJRVMsIAorICogSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdB
UlJBTlRJRVMgT0YgCisgKiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElD
VUxBUiBQVVJQT1NFIEFSRSAKKyAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBD
T1BZUklHSFQgSE9MREVSIE9SIAorICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJ
UkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIAorICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBD
T05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgCisgKiBCVVQgTk9UIExJTUlURUQgVE8s
IFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgCisgKiBTRVJWSUNFUzsgTE9TUyBP
RiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIAorICogSU5URVJSVVBUSU9OKSBI
T1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIAorICogV0hFVEhF
UiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIAorICog
TkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVT
RSAKKyAqIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJ
VFkgT0YgCisgKiBTVUNIIERBTUFHRS4KKyAqLworCisjaW5jbHVkZSA8bnRkZGsuaD4KKyNpbmNs
dWRlIDxzdGRhcmcuaD4KKyNpbmNsdWRlIDx4ZW4uaD4KKyNpbmNsdWRlIDx1dGlsLmg+CisKKyNp
bmNsdWRlICJoYXNoX3RhYmxlLmgiCisjaW5jbHVkZSAiZGJnX3ByaW50LmgiCisjaW5jbHVkZSAi
YXNzZXJ0LmgiCisKK3R5cGVkZWYgc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRV9OT0RFIHsKKyAg
ICBMSVNUX0VOVFJZICBMaXN0RW50cnk7CisgICAgVUxPTkdfUFRSICAgS2V5OworICAgIFVMT05H
X1BUUiAgIFZhbHVlOworfSBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLCAqUFhFTkJVU19IQVNIX1RB
QkxFX05PREU7CisKK3R5cGVkZWYgc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRV9CVUNLRVQgewor
ICAgIExPTkcgICAgICAgIExvY2s7CisgICAgTElTVF9FTlRSWSAgTGlzdDsKK30gWEVOQlVTX0hB
U0hfVEFCTEVfQlVDS0VULCAqUFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVDsKKworI2RlZmluZSBY
RU5CVVNfSEFTSF9UQUJMRV9OUl9CVUNLRVRTIFwKKyAgICAoMSA8PCAoc2l6ZW9mIChVQ0hBUikg
KiA4KSkKKworc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRSB7CisgICAgWEVOQlVTX0hBU0hfVEFC
TEVfQlVDS0VUICAgIEJ1Y2tldFtYRU5CVVNfSEFTSF9UQUJMRV9OUl9CVUNLRVRTXTsKK307CisK
KyNkZWZpbmUgWEVOQlVTX0hBU0hfVEFCTEVfVEFHICAgJ0hTQUgnCisKK3N0YXRpYyBGT1JDRUlO
TElORSBQVk9JRAorX19IYXNoVGFibGVBbGxvY2F0ZSgKKyAgICBJTiAgVUxPTkcgICBMZW5ndGgK
KyAgICApCit7CisgICAgcmV0dXJuIF9fQWxsb2NhdGVQb29sV2l0aFRhZyhOb25QYWdlZFBvb2ws
IExlbmd0aCwgWEVOQlVTX0hBU0hfVEFCTEVfVEFHKTsKK30KKworc3RhdGljIEZPUkNFSU5MSU5F
IFZPSUQKK19fSGFzaFRhYmxlRnJlZSgKKyAgICBJTiAgUFZPSUQgICBCdWZmZXIKKyAgICApCit7
CisgICAgRXhGcmVlUG9vbFdpdGhUYWcoQnVmZmVyLCBYRU5CVVNfSEFTSF9UQUJMRV9UQUcpOwor
fQorCitzdGF0aWMgVUxPTkcKK0hhc2hUYWJsZUhhc2goCisgICAgSU4gIFVMT05HX1BUUiAgIEtl
eQorICAgICkKK3sKKyAgICBQVUNIQVIgICAgICAgICAgQXJyYXkgPSAoUFVDSEFSKSZLZXk7Cisg
ICAgVUxPTkcgICAgICAgICAgIEFjY3VtdWxhdG9yOworICAgIFVMT05HICAgICAgICAgICBJbmRl
eDsKKworICAgIEFjY3VtdWxhdG9yID0gMDsKKworICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8
IHNpemVvZiAoVUxPTkdfUFRSKTsgSW5kZXgrKykgeworICAgICAgICBVTE9ORyAgIE92ZXJmbG93
OworCisgICAgICAgIEFjY3VtdWxhdG9yID0gKEFjY3VtdWxhdG9yIDw8IDQpICsgQXJyYXlbSW5k
ZXhdOworCisgICAgICAgIE92ZXJmbG93ID0gQWNjdW11bGF0b3IgJiAweDAwMDAwZjAwOworICAg
ICAgICBpZiAoT3ZlcmZsb3cgIT0gMCkgeworICAgICAgICAgICAgQWNjdW11bGF0b3IgXj0gT3Zl
cmZsb3cgPj4gODsKKyAgICAgICAgICAgIEFjY3VtdWxhdG9yIF49IE92ZXJmbG93OworICAgICAg
ICB9CisgICAgfQorCisgICAgQVNTRVJUM1UoQWNjdW11bGF0b3IsIDwsIFhFTkJVU19IQVNIX1RB
QkxFX05SX0JVQ0tFVFMpOworCisgICAgcmV0dXJuIEFjY3VtdWxhdG9yOworfQorCitzdGF0aWMK
K19JUlFMX3JlcXVpcmVzX21heF8oSElHSF9MRVZFTCkKK19JUlFMX3NhdmVzXworX0lSUUxfcmFp
c2VzXyhISUdIX0xFVkVMKQorS0lSUUwKK19fSGFzaFRhYmxlQnVja2V0TG9jaygKKyAgICBJTiAg
UFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCwKKyAgICBJTiAgQk9PTEVBTiAgICAg
ICAgICAgICAgICAgICAgIFdyaXRlcgorICAgICkKK3sKKyAgICBLSVJRTCAgICAgICAgICAgICAg
ICAgICAgICAgICAgIElycWw7CisKKyAgICBLZVJhaXNlSXJxbChISUdIX0xFVkVMLCAmSXJxbCk7
CisKKyAgICBmb3IgKDs7KSB7CisgICAgICAgIExPTkcgICAgTG9jazsKKyAgICAgICAgTE9ORyAg
ICBSZWFkZXJzOworICAgICAgICBMT05HICAgIFdyaXRlcnM7CisgICAgICAgIExPTkcgICAgT2xk
OworICAgICAgICBMT05HICAgIE5ldzsKKworICAgICAgICBLZU1lbW9yeUJhcnJpZXIoKTsKKwor
ICAgICAgICBMb2NrID0gQnVja2V0LT5Mb2NrOworICAgICAgICBSZWFkZXJzID0gTG9jayA+PiAx
OworICAgICAgICBXcml0ZXJzID0gTG9jayAmIDE7CisKKyAgICAgICAgLy8gVGhlcmUgbXVzdCBi
ZSBubyBleGlzdGluZyB3cml0ZXIKKyAgICAgICAgT2xkID0gUmVhZGVycyA8PCAxOworCisgICAg
ICAgIGlmIChXcml0ZXIpIAorICAgICAgICAgICAgV3JpdGVycysrOworICAgICAgICBlbHNlCisg
ICAgICAgICAgICBSZWFkZXJzKys7CisKKyAgICAgICAgTmV3ID0gKFJlYWRlcnMgPDwgMSkgfCAo
V3JpdGVycyAmIDEpOworCisgICAgICAgIGlmIChJbnRlcmxvY2tlZENvbXBhcmVFeGNoYW5nZSgm
QnVja2V0LT5Mb2NrLCBOZXcsIE9sZCkgIT0gT2xkKQorICAgICAgICAgICAgY29udGludWU7CisK
KyAgICAgICAgLy8KKyAgICAgICAgLy8gV2UgYXJlIGRvbmUgaWYgd2UncmUgbm90IGEgd3JpdGVy
LCBvciB0aGVyZSBhcmUgbm8gcmVhZGVycworICAgICAgICAvLyBsZWZ0LgorICAgICAgICAvLwor
ICAgICAgICBpZiAoIVdyaXRlciB8fCBSZWFkZXJzID09IDApCisgICAgICAgICAgICBicmVhazsK
KyAgICB9CisKKyAgICByZXR1cm4gSXJxbDsKK30KKworI2RlZmluZSBIYXNoVGFibGVCdWNrZXRM
b2NrKF9CdWNrZXQsIF9Xcml0ZXIsIF9JcnFsKSAgICAgICAgICAgIFwKKyAgICBkbyB7ICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCisgICAg
ICAgICooX0lycWwpID0gX19IYXNoVGFibGVCdWNrZXRMb2NrKChfQnVja2V0KSwgKF9Xcml0ZXIp
KTsgXAorICAgIH0gd2hpbGUgKEZBTFNFKQorCitzdGF0aWMKK19fZHJ2X3JlcXVpcmVzSVJRTChI
SUdIX0xFVkVMKQorVk9JRAorSGFzaFRhYmxlQnVja2V0VW5sb2NrKAorICAgIElOICBQWEVOQlVT
X0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0LAorICAgIElOICBCT09MRUFOICAgICAgICAgICAg
ICAgICAgICAgV3JpdGVyLAorICAgIElOICBfX2Rydl9yZXN0b3Jlc0lSUUwgS0lSUUwgICAgSXJx
bAorICAgICkKK3sKKyAgICBmb3IgKDs7KSB7CisgICAgICAgIExPTkcgICAgTG9jazsKKyAgICAg
ICAgTE9ORyAgICBSZWFkZXJzOworICAgICAgICBMT05HICAgIFdyaXRlcnM7CisgICAgICAgIExP
TkcgICAgT2xkOworICAgICAgICBMT05HICAgIE5ldzsKKworICAgICAgICBLZU1lbW9yeUJhcnJp
ZXIoKTsKKworICAgICAgICBMb2NrID0gQnVja2V0LT5Mb2NrOworICAgICAgICBSZWFkZXJzID0g
TG9jayA+PiAxOworICAgICAgICBXcml0ZXJzID0gTG9jayAmIDE7CisKKyAgICAgICAgT2xkID0g
KFJlYWRlcnMgPDwgMSkgfCAoV3JpdGVycyAmIDEpOworCisgICAgICAgIGlmIChXcml0ZXIpIHsK
KyAgICAgICAgICAgIEFTU0VSVChXcml0ZXJzICE9IDApOworICAgICAgICAgICAgLS1Xcml0ZXJz
OworICAgICAgICB9IGVsc2UgeworICAgICAgICAgICAgLS1SZWFkZXJzOworICAgICAgICB9CisK
KyAgICAgICAgTmV3ID0gKFJlYWRlcnMgPDwgMSkgfCAoV3JpdGVycyAmIDEpOworCisgICAgICAg
IGlmIChJbnRlcmxvY2tlZENvbXBhcmVFeGNoYW5nZSgmQnVja2V0LT5Mb2NrLCBOZXcsIE9sZCkg
PT0gT2xkKQorICAgICAgICAgICAgYnJlYWs7CisgICAgfQorCisgICAgS2VMb3dlcklycWwoSXJx
bCk7Cit9CisKK05UU1RBVFVTCitIYXNoVGFibGVBZGQoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9U
QUJMRSAgICAgIFRhYmxlLAorICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBLZXksCisg
ICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgICAgIFZhbHVlCisgICAgKQoreworICAgIFBYRU5C
VVNfSEFTSF9UQUJMRV9OT0RFICAgICBOb2RlOworICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9CVUNL
RVQgICBCdWNrZXQ7CisgICAgS0lSUUwgICAgICAgICAgICAgICAgICAgICAgIElycWw7CisgICAg
TlRTVEFUVVMgICAgICAgICAgICAgICAgICAgIHN0YXR1czsKKworICAgIE5vZGUgPSBfX0hhc2hU
YWJsZUFsbG9jYXRlKHNpemVvZiAoWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSkpOworCisgICAgc3Rh
dHVzID0gU1RBVFVTX05PX01FTU9SWTsKKyAgICBpZiAoTm9kZSA9PSBOVUxMKQorICAgICAgICBn
b3RvIGZhaWwxOworCisgICAgTm9kZS0+S2V5ID0gS2V5OworICAgIE5vZGUtPlZhbHVlID0gVmFs
dWU7CisKKyAgICBCdWNrZXQgPSAmVGFibGUtPkJ1Y2tldFtIYXNoVGFibGVIYXNoKEtleSldOwor
ICAgIAorICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0LCBUUlVFLCAmSXJxbCk7CisgICAg
SW5zZXJ0VGFpbExpc3QoJkJ1Y2tldC0+TGlzdCwgJk5vZGUtPkxpc3RFbnRyeSk7CisgICAgSGFz
aFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJxbCk7CisKKyAgICByZXR1cm4gU1RB
VFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWlsMSAoJTA4eClcbiIsIHN0YXR1
cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNUQVRVUworSGFzaFRhYmxlUmVtb3Zl
KAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICBUYWJsZSwKKyAgICBJTiAgVUxPTkdf
UFRSICAgICAgICAgICAgICAgS2V5CisgICAgKQoreworICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9C
VUNLRVQgICBCdWNrZXQ7CisgICAgUExJU1RfRU5UUlkgICAgICAgICAgICAgICAgIExpc3RFbnRy
eTsKKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsKKyAgICBLSVJRTCAgICAg
ICAgICAgICAgICAgICAgICAgSXJxbDsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgICAgICAgICAg
c3RhdHVzOworCisgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkp
XTsKKyAgICAKKyAgICBIYXNoVGFibGVCdWNrZXRMb2NrKEJ1Y2tldCwgVFJVRSwgJklycWwpOwor
CisgICAgTGlzdEVudHJ5ID0gQnVja2V0LT5MaXN0LkZsaW5rOworICAgIHdoaWxlIChMaXN0RW50
cnkgIT0gJkJ1Y2tldC0+TGlzdCkgeworICAgICAgICBOb2RlID0gQ09OVEFJTklOR19SRUNPUkQo
TGlzdEVudHJ5LCBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLCBMaXN0RW50cnkpOworCisgICAgICAg
IGlmIChOb2RlLT5LZXkgPT0gS2V5KQorICAgICAgICAgICAgZ290byBmb3VuZDsKKyAgICB9CisK
KyAgICBIYXNoVGFibGVCdWNrZXRVbmxvY2soQnVja2V0LCBUUlVFLCBJcnFsKTsKKworICAgIHN0
YXR1cyA9IFNUQVRVU19PQkpFQ1RfTkFNRV9OT1RfRk9VTkQ7CisgICAgZ290byBmYWlsMTsKKwor
Zm91bmQ6CisgICAgUmVtb3ZlRW50cnlMaXN0KExpc3RFbnRyeSk7CisgICAgX19IYXNoVGFibGVG
cmVlKE5vZGUpOworCisgICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJx
bCk7CisKKyAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJm
YWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNU
QVRVUworSGFzaFRhYmxlTG9va3VwKAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICBU
YWJsZSwKKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAgICAgICAgS2V5LAorICAgIE9VVCBQVUxP
TkdfUFRSICAgICAgICAgICAgICBWYWx1ZQorICAgICkKK3sKKyAgICBQWEVOQlVTX0hBU0hfVEFC
TEVfQlVDS0VUICAgQnVja2V0OworICAgIFBMSVNUX0VOVFJZICAgICAgICAgICAgICAgICBMaXN0
RW50cnk7CisgICAgUFhFTkJVU19IQVNIX1RBQkxFX05PREUgICAgIE5vZGU7CisgICAgS0lSUUwg
ICAgICAgICAgICAgICAgICAgICAgIElycWw7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIEJ1Y2tldCA9ICZUYWJsZS0+QnVja2V0W0hhc2hUYWJsZUhhc2go
S2V5KV07CisgICAgCisgICAgSGFzaFRhYmxlQnVja2V0TG9jayhCdWNrZXQsIEZBTFNFLCAmSXJx
bCk7CisKKyAgICBMaXN0RW50cnkgPSBCdWNrZXQtPkxpc3QuRmxpbms7CisgICAgd2hpbGUgKExp
c3RFbnRyeSAhPSAmQnVja2V0LT5MaXN0KSB7CisgICAgICAgIE5vZGUgPSBDT05UQUlOSU5HX1JF
Q09SRChMaXN0RW50cnksIFhFTkJVU19IQVNIX1RBQkxFX05PREUsIExpc3RFbnRyeSk7CisKKyAg
ICAgICAgaWYgKE5vZGUtPktleSA9PSBLZXkpCisgICAgICAgICAgICBnb3RvIGZvdW5kOworICAg
IH0KKworICAgIEhhc2hUYWJsZUJ1Y2tldFVubG9jayhCdWNrZXQsIEZBTFNFLCBJcnFsKTsKKwor
ICAgIHN0YXR1cyA9IFNUQVRVU19PQkpFQ1RfTkFNRV9OT1RfRk9VTkQ7CisgICAgZ290byBmYWls
MTsKKworZm91bmQ6CisgICAgKlZhbHVlID0gTm9kZS0+VmFsdWU7CisKKyAgICBIYXNoVGFibGVC
dWNrZXRVbmxvY2soQnVja2V0LCBGQUxTRSwgSXJxbCk7CisKKyAgICByZXR1cm4gU1RBVFVTX1NV
Q0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7CisK
KyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNUQVRVUworSGFzaFRhYmxlQ3JlYXRlKAorICAg
IE9VVCBQWEVOQlVTX0hBU0hfVEFCTEUgICpUYWJsZQorICAgICkKK3sKKyAgICBVTE9ORyAgICAg
ICAgICAgICAgICAgICBJbmRleDsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgICAgICBzdGF0dXM7
CisKKyAgICAqVGFibGUgPSBfX0hhc2hUYWJsZUFsbG9jYXRlKHNpemVvZiAoWEVOQlVTX0hBU0hf
VEFCTEUpKTsKKworICAgIHN0YXR1cyA9IFNUQVRVU19OT19NRU1PUlk7CisgICAgaWYgKCpUYWJs
ZSA9PSBOVUxMKQorICAgICAgICBnb3RvIGZhaWwxOworCisgICAgZm9yIChJbmRleCA9IDA7IElu
ZGV4IDwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUzsgSW5kZXgrKykgeworICAgICAgICBQ
WEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0ID0gJigqVGFibGUpLT5CdWNrZXRbSW5k
ZXhdOworCisgICAgICAgIEluaXRpYWxpemVMaXN0SGVhZCgmQnVja2V0LT5MaXN0KTsKKyAgICB9
CisKKyAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWls
MSAoJTA4eClcbiIsIHN0YXR1cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitWT0lECitI
YXNoVGFibGVEZXN0cm95KAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxlCisgICAg
KQoreworICAgIFVMT05HICAgICAgICAgICAgICAgICAgIEluZGV4OworCisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUzsgSW5kZXgrKykgewor
ICAgICAgICBQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0ID0gJlRhYmxlLT5CdWNr
ZXRbSW5kZXhdOworCisgICAgICAgIEFTU0VSVChJc0xpc3RFbXB0eSgmQnVja2V0LT5MaXN0KSk7
CisgICAgICAgIFJ0bFplcm9NZW1vcnkoJkJ1Y2tldC0+TGlzdCwgc2l6ZW9mIChMSVNUX0VOVFJZ
KSk7CisgICAgfQorCisgICAgQVNTRVJUKElzWmVyb01lbW9yeShUYWJsZSwgc2l6ZW9mIChYRU5C
VVNfSEFTSF9UQUJMRSkpKTsKKyAgICBfX0hhc2hUYWJsZUZyZWUoVGFibGUpOworfQorCmRpZmYg
LS1naXQgYS9zcmMveGVuYnVzL2hhc2hfdGFibGUuaCBiL3NyYy94ZW5idXMvaGFzaF90YWJsZS5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmNlMGM5MDYKLS0tIC9kZXYvbnVs
bAorKysgYi9zcmMveGVuYnVzL2hhc2hfdGFibGUuaApAQCAtMCwwICsxLDcwIEBACisvKiBDb3B5
cmlnaHQgKGMpIENpdHJpeCBTeXN0ZW1zIEluYy4KKyAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuCisg
KiAKKyAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMs
IAorICogd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRl
ZCAKKyAqIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CisgKiAKKyAqICog
ICBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIAor
ICogICAgIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUg
CisgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIuCisgKiAqICAgUmVkaXN0cmlidXRpb25zIGlu
IGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5cmlnaHQg
bm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZvbGxvd2lu
ZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciAKKyAqICAgICBt
YXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgorICogCisgKiBUSElTIFNP
RlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgCisgKiBDT05U
UklCVVRPUlMgIkFTIElTIiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCAK
KyAqIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVT
IE9GIAorICogTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVS
UE9TRSBBUkUgCisgKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hU
IEhPTERFUiBPUiAKKyAqIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElO
RElSRUNULCBJTkNJREVOVEFMLCAKKyAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVO
VElBTCBEQU1BR0VTIChJTkNMVURJTkcsIAorICogQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJF
TUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIAorICogU0VSVklDRVM7IExPU1MgT0YgVVNFLCBE
QVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyAKKyAqIElOVEVSUlVQVElPTikgSE9XRVZFUiBD
QVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCAKKyAqIFdIRVRIRVIgSU4gQ09O
VFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyAKKyAqIE5FR0xJR0VO
Q0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgCisgKiBP
RiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIAor
ICogU1VDSCBEQU1BR0UuCisgKi8KKworI2lmbmRlZiBfWEVOQlVTX0hBU0hfVEFCTEVfSAorI2Rl
ZmluZSBfWEVOQlVTX0hBU0hfVEFCTEVfSAorCisjaW5jbHVkZSA8bnRkZGsuaD4KKwordHlwZWRl
ZiBzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFIFhFTkJVU19IQVNIX1RBQkxFLCAqUFhFTkJVU19I
QVNIX1RBQkxFOyAKKworZXh0ZXJuIE5UU1RBVFVTCitIYXNoVGFibGVBZGQoCisgICAgSU4gIFBY
RU5CVVNfSEFTSF9UQUJMRSAgVGFibGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5
LAorICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIFZhbHVlCisgICAgKTsKKworZXh0ZXJuIE5U
U1RBVFVTCitIYXNoVGFibGVSZW1vdmUoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5CisgICAgKTsKKworZXh0ZXJuIE5U
U1RBVFVTCitIYXNoVGFibGVMb29rdXAoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5LAorICAgIE9VVCBQVUxPTkdfUFRS
ICAgICAgICAgIFZhbHVlCisgICAgKTsKKworZXh0ZXJuIE5UU1RBVFVTCitIYXNoVGFibGVDcmVh
dGUoCisgICAgT1VUIFBYRU5CVVNfSEFTSF9UQUJMRSAgKlRhYmxlCisgICAgKTsKKworZXh0ZXJu
IFZPSUQKK0hhc2hUYWJsZURlc3Ryb3koCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUKKyAgICApOworCisjZW5kaWYgIC8vIF9YRU5CVVNfSEFTSF9UQUJMRV9ICisKZGlmZiAtLWdp
dCBhL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYyBiL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYwpp
bmRleCAwYWZjMjE4Li42N2JlMjBjIDEwMDY0NAotLS0gYS9zcmMveGVuYnVzL3NoYXJlZF9pbmZv
LmMKKysrIGIvc3JjL3hlbmJ1cy9zaGFyZWRfaW5mby5jCkBAIC0zOCw2ICszOCw5IEBACiAjaW5j
bHVkZSAiZGJnX3ByaW50LmgiCiAjaW5jbHVkZSAiYXNzZXJ0LmgiCiAKKyNkZWZpbmUgWEVOQlVT
X1NIQVJFRF9JTkZPX0VWVENITl9QRVJfU0VMRUNUT1IgICAgIChzaXplb2YgKFVMT05HX1BUUikg
KiA4KQorI2RlZmluZSBYRU5CVVNfU0hBUkVEX0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UICAg
KFJUTF9GSUVMRF9TSVpFKHNoYXJlZF9pbmZvX3QsIGV2dGNobl9wZW5kaW5nKSAvIHNpemVvZiAo
VUxPTkdfUFRSKSkKKwogc3RydWN0IF9YRU5CVVNfU0hBUkVEX0lORk9fQ09OVEVYVCB7CiAgICAg
UFhFTkJVU19GRE8gICAgICAgICAgICAgICAgIEZkbzsKICAgICBLU1BJTl9MT0NLICAgICAgICAg
ICAgICAgICAgTG9jazsKZGlmZiAtLWdpdCBhL3ZzMjAxMi94ZW5idXMveGVuYnVzLnZjeHByb2og
Yi92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qCmluZGV4IGMzMDc3NGUuLmE2NDhiY2UgMTAw
NjQ0Ci0tLSBhL3ZzMjAxMi94ZW5idXMveGVuYnVzLnZjeHByb2oKKysrIGIvdnMyMDEyL3hlbmJ1
cy94ZW5idXMudmN4cHJvagpAQCAtOTksNiArOTksNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5idXNccmFuZ2Vfc2V0LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0i
Li5cLi5cc3JjXHhlbmJ1c1xiYWxsb29uLmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5c
Li5cc3JjXHhlbmJ1c1xjYWNoZS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNy
Y1x4ZW5idXNcaGFzaF90YWJsZS5jIiAvPgogCTwvSXRlbUdyb3VwPgogCTxJdGVtR3JvdXA+CiAJ
CTxSZXNvdXJjZUNvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlbmJ1c1x4ZW5idXMucmMiIC8+
CmRpZmYgLS1naXQgYS92czIwMTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qIGIvdnMyMDEzL3hlbmJ1
cy94ZW5idXMudmN4cHJvagppbmRleCA1ODhiMGM1Li4yYzM0ZWQxIDEwMDY0NAotLS0gYS92czIw
MTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qCisrKyBiL3ZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHBy
b2oKQEAgLTEsNCArMSw0IEBACi3vu788P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJ1dGYt
OCI/PgorPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KIDxQcm9qZWN0IERl
ZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIxMi4wIiB4bWxucz0iaHR0cDovL3Nj
aGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWlsZC8yMDAzIj4KICAgPEltcG9ydCBQ
cm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgogICA8UHJvcGVydHlHcm91cCBMYWJlbD0iR2xv
YmFscyI+CkBAIC0xMzksNiArMTM5LDcgQEAKICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4u
XHNyY1x4ZW5idXNccmFuZ2Vfc2V0LmMiIC8+CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuYnVzXGJhbGxvb24uYyIgLz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4u
XHNyY1x4ZW5idXNcY2FjaGUuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNy
Y1x4ZW5idXNcaGFzaF90YWJsZS5jIiAvPgogICA8L0l0ZW1Hcm91cD4KICAgPEl0ZW1Hcm91cD4K
ICAgICA8UmVzb3VyY2VDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNceGVuYnVzLnJj
IiAvPgotLSAKMi4xLjEKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1kZXZlbEBsaXN0cy54ZW5w
cm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dpLWJpbi9tYWlsbWFuL2xp
c3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 06 14:24:48 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:48 +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 1XmNzU-0001Zw-RQ; Thu, 06 Nov 2014 14:24:48 +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 1XmNzT-0001Ys-CP
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:47 +0000
Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id
	9E/F4-26858-EA48B545; Thu, 06 Nov 2014 14:24:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415283880!10925263!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16386 invoked from network); 6 Nov 2014 14:24:45 -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;
	6 Nov 2014 14:24:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771862"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-9m;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:17 +0000
Message-ID: <1415283861-26028-7-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 30675
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 05/10] Use a hash table for event channel
	lookup
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

UmF0aGVyIHRoYW4gdXNpbmcgYSBsYXJnZSBhcnJheSBmb3IgbWFwcGluZyBwb3J0IHZhbHVlcyB0
byBjaGFubmVsCnN0cnVjdHVyZXMsIHVzZSBhIGhhc2ggdGFibGUuIFRoaXMgbWVhbnMgd2Ugbm8g
bG9uZ2VyIG5lZWQgdG8gY29kZSBhCmhhcmQgcG9ydCBudW1iZXIgbGltaXQgaW50byB0aGUgRVZU
Q0hOIGltcGxlbWVudGF0aW9uLgoKQmVjYXVzZSB0aGUgaGFzaCB0YWJsZSBpbXBsZW1lbnRhdGlv
biBtYW5hZ2VzIGl0cyBvd24gbG9ja2luZywgd2UgYWxzbyBubwpsb25nZXIgbmVlZCB0byBtYWtl
IHN1Y2ggbGliZXJhbCB1c2Ugb2YgdGhlIGludGVycnVwdCBsb2NrIGluIHRoZSBFVlRDSE4KaW1w
bGVtZW50YXRpb24gYW5kIGNhbiB1c2UgdGhlIHNwaW5sb2NrIGluc3RlYWQuCgpTaWduZWQtb2Zm
LWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGluY2x1ZGUv
ZXZ0Y2huX2ludGVyZmFjZS5oICAgICAgfCAgIDQgKy0KIGluY2x1ZGUvc2hhcmVkX2luZm9faW50
ZXJmYWNlLmggfCAgIDMgLQogc3JjL3hlbmJ1cy9ldnRjaG4uYyAgICAgICAgICAgICB8ICA4OSAr
KysrKystLS0tCiBzcmMveGVuYnVzL2hhc2hfdGFibGUuYyAgICAgICAgIHwgMzY3ICsrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNyYy94ZW5idXMvaGFzaF90YWJsZS5o
ICAgICAgICAgfCAgNzAgKysrKysrKysKIHNyYy94ZW5idXMvc2hhcmVkX2luZm8uYyAgICAgICAg
fCAgIDMgKwogdnMyMDEyL3hlbmJ1cy94ZW5idXMudmN4cHJvaiAgICB8ICAgMSArCiB2czIwMTMv
eGVuYnVzL3hlbmJ1cy52Y3hwcm9qICAgIHwgICAzICstCiA4IGZpbGVzIGNoYW5nZWQsIDUwNCBp
bnNlcnRpb25zKCspLCAzNiBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBzcmMveGVu
YnVzL2hhc2hfdGFibGUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IHNyYy94ZW5idXMvaGFzaF90YWJs
ZS5oCgpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9ldnRjaG5faW50ZXJmYWNlLmggYi9pbmNsdWRlL2V2
dGNobl9pbnRlcmZhY2UuaAppbmRleCA5OTFkNjEwLi4zYTQ4OTE1IDEwMDY0NAotLS0gYS9pbmNs
dWRlL2V2dGNobl9pbnRlcmZhY2UuaAorKysgYi9pbmNsdWRlL2V2dGNobl9pbnRlcmZhY2UuaApA
QCAtMTE3LDE0ICsxMTcsMTQgQEAgdHlwZWRlZiBQWEVOQlVTX0VWVENITl9DSEFOTkVMCiAKICAg
ICBccGFyYW0gSW50ZXJmYWNlIFRoZSBpbnRlcmZhY2UgaGVhZGVyCiAgICAgXHBhcmFtIENoYW5u
ZWwgVGhlIGNoYW5uZWwgaGFuZGxlCi0gICAgXHBhcmFtIExvY2tlZCBTZXQgdG8gVFJVRSBpZiB0
aGlzIG1ldGhvZCBpcyBpbnZva2VkIGluIGNvbnRleHQgb2YgdGhlIGNoYW5uZWwgY2FsbGJhY2sK
KyAgICBccGFyYW0gSW5DYWxsYmFjayBTZXQgdG8gVFJVRSBpZiB0aGlzIG1ldGhvZCBpcyBpbnZv
a2VkIGluIGNvbnRleHQgb2YgdGhlIGNoYW5uZWwgY2FsbGJhY2sKICAgICBccmV0dXJuIFRSVUUg
aWYgdGhlcmUgd2FzIGFuIGV2ZW50IHBlbmRpbmcgYXQgdGhlIHBvaW50IG9mIHVubWFzaywgRkFM
U0Ugb3RoZXJ3aXNlCiAqLwogdHlwZWRlZiBCT09MRUFOCiAoKlhFTkJVU19FVlRDSE5fVU5NQVNL
KSgKICAgICBJTiAgUElOVEVSRkFDRSAgICAgICAgICAgICAgSW50ZXJmYWNlLAogICAgIElOICBQ
WEVOQlVTX0VWVENITl9DSEFOTkVMICBDaGFubmVsLAotICAgIElOICBCT09MRUFOICAgICAgICAg
ICAgICAgICBMb2NrZWQKKyAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgSW5DYWxsYmFj
awogICAgICk7CiAKIC8qISBcdHlwZWRlZiBYRU5CVVNfRVZUQ0hOX1NFTkQKZGlmZiAtLWdpdCBh
L2luY2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmggYi9pbmNsdWRlL3NoYXJlZF9pbmZvX2lu
dGVyZmFjZS5oCmluZGV4IDBkMzZhYzguLjBlNWEwZDcgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvc2hh
cmVkX2luZm9faW50ZXJmYWNlLmgKKysrIGIvaW5jbHVkZS9zaGFyZWRfaW5mb19pbnRlcmZhY2Uu
aApAQCAtNDAsOSArNDAsNiBAQAogCiAjaWZuZGVmIF9XSU5ETEwKIAotI2RlZmluZSBYRU5CVVNf
U0hBUkVEX0lORk9fRVZUQ0hOX1BFUl9TRUxFQ1RPUiAgICAgKHNpemVvZiAoVUxPTkdfUFRSKSAq
IDgpCi0jZGVmaW5lIFhFTkJVU19TSEFSRURfSU5GT19FVlRDSE5fU0VMRUNUT1JfQ09VTlQgICAo
UlRMX0ZJRUxEX1NJWkUoc2hhcmVkX2luZm9fdCwgZXZ0Y2huX3BlbmRpbmcpIC8gc2l6ZW9mIChV
TE9OR19QVFIpKQotCiAvKiEgXHR5cGVkZWYgWEVOQlVTX1NIQVJFRF9JTkZPX0FDUVVJUkUKICAg
ICBcYnJpZWYgQWNxdWlyZSBhIHJlZmVyZW5jZSB0byB0aGUgU0hBUkVEX0lORk8gaW50ZXJmYWNl
CiAKZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZXZ0Y2huLmMgYi9zcmMveGVuYnVzL2V2dGNobi5j
CmluZGV4IDM1YWQ0NGEuLjMzOGE5MGYgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZXZ0Y2huLmMK
KysrIGIvc3JjL3hlbmJ1cy9ldnRjaG4uYwpAQCAtMzYsNiArMzYsNyBAQAogCiAjaW5jbHVkZSAi
ZXZ0Y2huLmgiCiAjaW5jbHVkZSAiZmRvLmgiCisjaW5jbHVkZSAiaGFzaF90YWJsZS5oIgogI2lu
Y2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgogCkBAIC05Nyw3ICs5OCw3
IEBAIHN0cnVjdCBfWEVOQlVTX0VWVENITl9DT05URVhUIHsKICAgICBYRU5CVVNfREVCVUdfSU5U
RVJGQUNFICAgICAgICAgIERlYnVnSW50ZXJmYWNlOwogICAgIFBYRU5CVVNfREVCVUdfQ0FMTEJB
Q0sgICAgICAgICAgRGVidWdDYWxsYmFjazsKICAgICBYRU5CVVNfU0hBUkVEX0lORk9fSU5URVJG
QUNFICAgIFNoYXJlZEluZm9JbnRlcmZhY2U7Ci0gICAgUFhFTkJVU19FVlRDSE5fQ0hBTk5FTCAg
ICAgICAgICBDaGFubmVsW1hFTkJVU19TSEFSRURfSU5GT19FVlRDSE5fU0VMRUNUT1JfQ09VTlQg
KiBYRU5CVVNfU0hBUkVEX0lORk9fRVZUQ0hOX1BFUl9TRUxFQ1RPUl07CisgICAgUFhFTkJVU19I
QVNIX1RBQkxFICAgICAgICAgICAgICBUYWJsZTsKICAgICBMSVNUX0VOVFJZICAgICAgICAgICAg
ICAgICAgICAgIExpc3Q7CiB9OwogCkBAIC0zNTEsMTQgKzM1MiwxNiBAQCBFdnRjaG5PcGVuKAog
CiAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OwogCi0gICAgQVNTRVJUM1UoTG9j
YWxQb3J0LCA8LCBzaXplb2YgKENvbnRleHQtPkNoYW5uZWwpIC8gc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsWzBdKSk7Ci0KLSAgICAoVk9JRCkgX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhD
b250ZXh0KTsKKyAgICBzdGF0dXMgPSBIYXNoVGFibGVBZGQoQ29udGV4dC0+VGFibGUsCisgICAg
ICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwKKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgKFVMT05HX1BUUilDaGFubmVsKTsKKyAgICBpZiAoIU5UX1NVQ0NFU1Moc3RhdHVzKSkKKyAg
ICAgICAgZ290byBmYWlsMzsKIAotICAgIEFTU0VSVDNQKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQ
b3J0XSwgPT0sIE5VTEwpOwotICAgIENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSA9IENoYW5u
ZWw7CiAgICAgQ2hhbm5lbC0+QWN0aXZlID0gVFJVRTsKIAorICAgIEtlQWNxdWlyZVNwaW5Mb2Nr
QXREcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7CisKICAgICBJbnNlcnRUYWlsTGlzdCgmQ29udGV4
dC0+TGlzdCwgJkNoYW5uZWwtPkxpc3RFbnRyeSk7CiAKICAgICBpZiAoIUlzTGlzdEVtcHR5KCZD
b250ZXh0LT5MaXN0KSAmJiAhQ29udGV4dC0+RW5hYmxlZCkgewpAQCAtMzY2LDEyICszNjksMTgg
QEAgRXZ0Y2huT3BlbigKICAgICAgICAgQ29udGV4dC0+RW5hYmxlZCA9IFRSVUU7CiAgICAgfQog
Ci0gICAgX19FdnRjaG5SZWxlYXNlSW50ZXJydXB0TG9jayhDb250ZXh0LCBESVNQQVRDSF9MRVZF
TCk7CisgICAgS2VSZWxlYXNlU3BpbkxvY2tGcm9tRHBjTGV2ZWwoJkNvbnRleHQtPkxvY2spOwog
CiAgICAgS2VMb3dlcklycWwoSXJxbCk7CiAKICAgICByZXR1cm4gQ2hhbm5lbDsKIAorZmFpbDM6
CisgICAgRXJyb3IoImZhaWwzXG4iKTsKKworICAgIENoYW5uZWwtPkxvY2FsUG9ydCA9IDA7Cisg
ICAgUnRsWmVyb01lbW9yeSgmQ2hhbm5lbC0+UGFyYW1ldGVycywgc2l6ZW9mIChYRU5CVVNfRVZU
Q0hOX1BBUkFNRVRFUlMpKTsKKwogZmFpbDI6CiAgICAgRXJyb3IoImZhaWwyXG4iKTsKIApAQCAt
Mzk4LDcgKzQwNyw3IEBAIHN0YXRpYyBCT09MRUFOCiBFdnRjaG5Vbm1hc2soCiAgICAgSU4gIFBJ
TlRFUkZBQ0UgICAgICAgICAgICAgIEludGVyZmFjZSwKICAgICBJTiAgUFhFTkJVU19FVlRDSE5f
Q0hBTk5FTCAgQ2hhbm5lbCwKLSAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTG9ja2Vk
CisgICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAgICAgIEluQ2FsbGJhY2sKICAgICApCiB7CiAg
ICAgUFhFTkJVU19FVlRDSE5fQ09OVEVYVCAgICAgIENvbnRleHQgPSBJbnRlcmZhY2UtPkNvbnRl
eHQ7CkBAIC00MDcsOCArNDE2LDEwIEBAIEV2dGNoblVubWFzaygKIAogICAgIEFTU0VSVDNVKENo
YW5uZWwtPk1hZ2ljLCA9PSwgWEVOQlVTX0VWVENITl9DSEFOTkVMX01BR0lDKTsKIAotICAgIGlm
ICghTG9ja2VkKQotICAgICAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhD
b250ZXh0KTsKKyAgICBpZiAoIUluQ2FsbGJhY2spCisgICAgICAgIEtlUmFpc2VJcnFsKERJU1BB
VENIX0xFVkVMLCAmSXJxbCk7IC8vIFByZXZlbnQgc3VzcGVuZAorCisgICAgQVNTRVJUM1UoS2VH
ZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFUQ0hfTEVWRUwpOwogCiAgICAgaWYgKENoYW5uZWwt
PkFjdGl2ZSkgewogICAgICAgICBQZW5kaW5nID0gWEVOQlVTX1NIQVJFRF9JTkZPKEV2dGNoblVu
bWFzaywKQEAgLTQ0Niw4ICs0NTcsOCBAQCBFdnRjaG5Vbm1hc2soCiAgICAgICAgIH0KICAgICB9
CiAKLSAgICBpZiAoIUxvY2tlZCkKLSAgICAgICAgX19FdnRjaG5SZWxlYXNlSW50ZXJydXB0TG9j
ayhDb250ZXh0LCBJcnFsKTsKKyAgICBpZiAoIUluQ2FsbGJhY2spCisgICAgICAgIEtlTG93ZXJJ
cnFsKElycWwpOwogCiAgICAgcmV0dXJuIFBlbmRpbmc7CiB9CkBAIC01MTMsNiArNTI0LDggQEAg
RXZ0Y2huVHJpZ2dlcigKIAogICAgIElycWwgPSBfX0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2Nr
KENvbnRleHQpOwogCisgICAgQVNTRVJUM1UoS2VHZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFU
Q0hfTEVWRUwpOworCiAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgewogICAgICAgICBEb25lU29t
ZXRoaW5nID0gRXZ0Y2huQ2FsbGJhY2soQ29udGV4dCwgQ2hhbm5lbCk7CiAgICAgfSBlbHNlIHsK
QEAgLTUzNiw3ICs1NDksOSBAQCBFdnRjaG5DbG9zZSgKIAogICAgIEFTU0VSVDNVKENoYW5uZWwt
Pk1hZ2ljLCA9PSwgWEVOQlVTX0VWVENITl9DSEFOTkVMX01BR0lDKTsKIAotICAgIElycWwgPSBf
X0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2NrKENvbnRleHQpOworICAgIEtlUmFpc2VJcnFsKERJ
U1BBVENIX0xFVkVMLCAmSXJxbCk7IC8vIFByZXZlbnQgc3VzcGVuZAorCisgICAgS2VBY3F1aXJl
U3BpbkxvY2tBdERwY0xldmVsKCZDb250ZXh0LT5Mb2NrKTsKIAogICAgIFJlbW92ZUVudHJ5TGlz
dCgmQ2hhbm5lbC0+TGlzdEVudHJ5KTsKIApAQCAtNTQ1LDEyICs1NjAsMTMgQEAgRXZ0Y2huQ2xv
c2UoCiAgICAgICAgIENvbnRleHQtPkVuYWJsZWQgPSBGQUxTRTsKICAgICB9CiAKKyAgICBLZVJl
bGVhc2VTcGluTG9ja0Zyb21EcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7CisKICAgICBSdGxaZXJv
TWVtb3J5KCZDaGFubmVsLT5MaXN0RW50cnksIHNpemVvZiAoTElTVF9FTlRSWSkpOwogCiAgICAg
aWYgKENoYW5uZWwtPkFjdGl2ZSkgewotICAgICAgICBVTE9ORyAgIExvY2FsUG9ydCA9IENoYW5u
ZWwtPkxvY2FsUG9ydDsKLQotICAgICAgICBBU1NFUlQzVShMb2NhbFBvcnQsIDwsIHNpemVvZiAo
Q29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtPkNoYW5uZWxbMF0pKTsKKyAgICAg
ICAgVUxPTkcgICAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OworICAgICAgICBO
VFNUQVRVUyAgICBzdGF0dXM7CiAKICAgICAgICAgQ2hhbm5lbC0+QWN0aXZlID0gRkFMU0U7CiAK
QEAgLTU2MSwxMiArNTc3LDEwIEBAIEV2dGNobkNsb3NlKAogICAgICAgICBpZiAoQ2hhbm5lbC0+
VHlwZSAhPSBYRU5CVVNfRVZUQ0hOX1RZUEVfRklYRUQpCiAgICAgICAgICAgICAoVk9JRCkgRXZl
bnRDaGFubmVsQ2xvc2UoTG9jYWxQb3J0KTsKIAotICAgICAgICBBU1NFUlQoQ29udGV4dC0+Q2hh
bm5lbFtMb2NhbFBvcnRdICE9IE5VTEwpOwotICAgICAgICBDb250ZXh0LT5DaGFubmVsW0xvY2Fs
UG9ydF0gPSBOVUxMOworICAgICAgICBzdGF0dXMgPSBIYXNoVGFibGVSZW1vdmUoQ29udGV4dC0+
VGFibGUsIExvY2FsUG9ydCk7CisgICAgICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykpOwog
ICAgIH0KIAotICAgIF9fRXZ0Y2huUmVsZWFzZUludGVycnVwdExvY2soQ29udGV4dCwgSXJxbCk7
Ci0KICAgICBDaGFubmVsLT5Mb2NhbFBvcnQgPSAwOwogICAgIFJ0bFplcm9NZW1vcnkoJkNoYW5u
ZWwtPlBhcmFtZXRlcnMsIHNpemVvZiAoWEVOQlVTX0VWVENITl9QQVJBTUVURVJTKSk7CiAKQEAg
LTU4MCw2ICs1OTQsOCBAQCBFdnRjaG5DbG9zZSgKIAogICAgIEFTU0VSVChJc1plcm9NZW1vcnko
Q2hhbm5lbCwgc2l6ZW9mIChYRU5CVVNfRVZUQ0hOX0NIQU5ORUwpKSk7CiAgICAgX19FdnRjaG5G
cmVlKENoYW5uZWwpOworCisgICAgS2VMb3dlcklycWwoSXJxbCk7CiB9CiAKIHN0YXRpYyBVTE9O
RwpAQCAtNjA2LDEyICs2MjIsMTMgQEAgRXZ0Y2huUG9sbENhbGxiYWNrKAogICAgIFBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwgIENoYW5uZWw7CiAgICAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTWFz
azsKICAgICBCT09MRUFOICAgICAgICAgICAgICAgICBEb25lU29tZXRoaW5nOworICAgIE5UU1RB
VFVTICAgICAgICAgICAgICAgIHN0YXR1czsKIAotICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwg
c2l6ZW9mIChDb250ZXh0LT5DaGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbFswXSkp
OwotCi0gICAgQ2hhbm5lbCA9IENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XTsKLQotICAgIGlm
IChDaGFubmVsID09IE5VTEwpIHsKKyAgICBzdGF0dXMgPSBIYXNoVGFibGVMb29rdXAoQ29udGV4
dC0+VGFibGUsCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwKKyAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgKFBVTE9OR19QVFIpJkNoYW5uZWwpOworICAgIAorICAg
IGlmICghTlRfU1VDQ0VTUyhzdGF0dXMpKSB7CiAgICAgICAgIFdhcm5pbmcoIlslZF06IElOVkFM
SUQgUE9SVFxuIiwgTG9jYWxQb3J0KTsKIAogICAgICAgICBYRU5CVVNfU0hBUkVEX0lORk8oRXZ0
Y2huTWFzaywKQEAgLTY5NywxNCArNzE0LDEzIEBAIEV2dGNoblN1c3BlbmRDYWxsYmFja0Vhcmx5
KAogICAgICAgICBDaGFubmVsID0gQ09OVEFJTklOR19SRUNPUkQoTGlzdEVudHJ5LCBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwsIExpc3RFbnRyeSk7CiAKICAgICAgICAgaWYgKENoYW5uZWwtPkFjdGl2
ZSkgewotICAgICAgICAgICAgVUxPTkcgICBMb2NhbFBvcnQgPSBDaGFubmVsLT5Mb2NhbFBvcnQ7
Ci0KLSAgICAgICAgICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwgc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbFswXSkpOworICAgICAgICAgICAgVUxP
TkcgICAgICAgTG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0OworICAgICAgICAgICAgTlRT
VEFUVVMgICAgc3RhdHVzOwogCiAgICAgICAgICAgICBDaGFubmVsLT5BY3RpdmUgPSBGQUxTRTsK
IAotICAgICAgICAgICAgQVNTRVJUKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSAhPSBOVUxM
KTsKLSAgICAgICAgICAgIENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSA9IE5VTEw7CisgICAg
ICAgICAgICBzdGF0dXMgPSBIYXNoVGFibGVSZW1vdmUoQ29udGV4dC0+VGFibGUsIExvY2FsUG9y
dCk7CisgICAgICAgICAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsKICAgICAgICAgfQog
ICAgIH0KIApAQCAtOTU4LDYgKzk3NCwxMCBAQCBFdnRjaG5Jbml0aWFsaXplKAogICAgIGlmICgq
Q29udGV4dCA9PSBOVUxMKQogICAgICAgICBnb3RvIGZhaWwxOwogCisgICAgc3RhdHVzID0gSGFz
aFRhYmxlQ3JlYXRlKCYoKkNvbnRleHQpLT5UYWJsZSk7CisgICAgaWYgKCFOVF9TVUNDRVNTKHN0
YXR1cykpCisgICAgICAgIGdvdG8gZmFpbDI7CisKICAgICBzdGF0dXMgPSBTdXNwZW5kR2V0SW50
ZXJmYWNlKEZkb0dldFN1c3BlbmRDb250ZXh0KEZkbyksCiAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICBYRU5CVVNfU1VTUEVORF9JTlRFUkZBQ0VfVkVSU0lPTl9NQVgsCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAoUElOVEVSRkFDRSkmKCpDb250ZXh0KS0+U3VzcGVu
ZEludGVyZmFjZSwKQEAgLTk4OCw2ICsxMDA4LDEyIEBAIEV2dGNobkluaXRpYWxpemUoCiAKICAg
ICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CiAKK2ZhaWwyOgorICAgIEVycm9yKCJmYWlsMlxuIik7
CisKKyAgICBBU1NFUlQoSXNaZXJvTWVtb3J5KENvbnRleHQsIHNpemVvZiAoWEVOQlVTX0VWVENI
Tl9DT05URVhUKSkpOworICAgIF9fRXZ0Y2huRnJlZShDb250ZXh0KTsKKwogZmFpbDE6CiAgICAg
RXJyb3IoImZhaWwxICglMDh4KVxuIiwgc3RhdHVzKTsKIApAQCAtMTA1Myw2ICsxMDc5LDkgQEAg
RXZ0Y2huVGVhcmRvd24oCiAgICAgUnRsWmVyb01lbW9yeSgmQ29udGV4dC0+U3VzcGVuZEludGVy
ZmFjZSwKICAgICAgICAgICAgICAgICAgIHNpemVvZiAoWEVOQlVTX1NVU1BFTkRfSU5URVJGQUNF
KSk7CiAKKyAgICBIYXNoVGFibGVEZXN0cm95KENvbnRleHQtPlRhYmxlKTsKKyAgICBDb250ZXh0
LT5UYWJsZSA9IE5VTEw7CisKICAgICBBU1NFUlQoSXNaZXJvTWVtb3J5KENvbnRleHQsIHNpemVv
ZiAoWEVOQlVTX0VWVENITl9DT05URVhUKSkpOwogICAgIF9fRXZ0Y2huRnJlZShDb250ZXh0KTsK
IApkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMgYi9zcmMveGVuYnVzL2hhc2hf
dGFibGUuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5iOGUyN2Q4Ci0tLSAv
ZGV2L251bGwKKysrIGIvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMKQEAgLTAsMCArMSwzNjcgQEAK
Ky8qIENvcHlyaWdodCAoYykgQ2l0cml4IFN5c3RlbXMgSW5jLgorICogQWxsIHJpZ2h0cyByZXNl
cnZlZC4KKyAqIAorICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFy
eSBmb3JtcywgCisgKiB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVk
IHByb3ZpZGVkIAorICogdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKKyAq
IAorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUg
YWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMg
YW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1lci4KKyAqICogICBSZWRpc3RyaWJ1
dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIAorICogICAgIGNv
cHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgCisgKiAgICAg
Zm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIAor
ICogICAgIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCisgKiAKKyAq
IFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCAK
KyAqIENPTlRSSUJVVE9SUyAiQVMgSVMiIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJB
TlRJRVMsIAorICogSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEIFdB
UlJBTlRJRVMgT0YgCisgKiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElD
VUxBUiBQVVJQT1NFIEFSRSAKKyAqIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBD
T1BZUklHSFQgSE9MREVSIE9SIAorICogQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJ
UkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIAorICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBD
T05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgCisgKiBCVVQgTk9UIExJTUlURUQgVE8s
IFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IgCisgKiBTRVJWSUNFUzsgTE9TUyBP
RiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIAorICogSU5URVJSVVBUSU9OKSBI
T1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIAorICogV0hFVEhF
UiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIAorICog
TkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVT
RSAKKyAqIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJ
VFkgT0YgCisgKiBTVUNIIERBTUFHRS4KKyAqLworCisjaW5jbHVkZSA8bnRkZGsuaD4KKyNpbmNs
dWRlIDxzdGRhcmcuaD4KKyNpbmNsdWRlIDx4ZW4uaD4KKyNpbmNsdWRlIDx1dGlsLmg+CisKKyNp
bmNsdWRlICJoYXNoX3RhYmxlLmgiCisjaW5jbHVkZSAiZGJnX3ByaW50LmgiCisjaW5jbHVkZSAi
YXNzZXJ0LmgiCisKK3R5cGVkZWYgc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRV9OT0RFIHsKKyAg
ICBMSVNUX0VOVFJZICBMaXN0RW50cnk7CisgICAgVUxPTkdfUFRSICAgS2V5OworICAgIFVMT05H
X1BUUiAgIFZhbHVlOworfSBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLCAqUFhFTkJVU19IQVNIX1RB
QkxFX05PREU7CisKK3R5cGVkZWYgc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRV9CVUNLRVQgewor
ICAgIExPTkcgICAgICAgIExvY2s7CisgICAgTElTVF9FTlRSWSAgTGlzdDsKK30gWEVOQlVTX0hB
U0hfVEFCTEVfQlVDS0VULCAqUFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVDsKKworI2RlZmluZSBY
RU5CVVNfSEFTSF9UQUJMRV9OUl9CVUNLRVRTIFwKKyAgICAoMSA8PCAoc2l6ZW9mIChVQ0hBUikg
KiA4KSkKKworc3RydWN0IF9YRU5CVVNfSEFTSF9UQUJMRSB7CisgICAgWEVOQlVTX0hBU0hfVEFC
TEVfQlVDS0VUICAgIEJ1Y2tldFtYRU5CVVNfSEFTSF9UQUJMRV9OUl9CVUNLRVRTXTsKK307CisK
KyNkZWZpbmUgWEVOQlVTX0hBU0hfVEFCTEVfVEFHICAgJ0hTQUgnCisKK3N0YXRpYyBGT1JDRUlO
TElORSBQVk9JRAorX19IYXNoVGFibGVBbGxvY2F0ZSgKKyAgICBJTiAgVUxPTkcgICBMZW5ndGgK
KyAgICApCit7CisgICAgcmV0dXJuIF9fQWxsb2NhdGVQb29sV2l0aFRhZyhOb25QYWdlZFBvb2ws
IExlbmd0aCwgWEVOQlVTX0hBU0hfVEFCTEVfVEFHKTsKK30KKworc3RhdGljIEZPUkNFSU5MSU5F
IFZPSUQKK19fSGFzaFRhYmxlRnJlZSgKKyAgICBJTiAgUFZPSUQgICBCdWZmZXIKKyAgICApCit7
CisgICAgRXhGcmVlUG9vbFdpdGhUYWcoQnVmZmVyLCBYRU5CVVNfSEFTSF9UQUJMRV9UQUcpOwor
fQorCitzdGF0aWMgVUxPTkcKK0hhc2hUYWJsZUhhc2goCisgICAgSU4gIFVMT05HX1BUUiAgIEtl
eQorICAgICkKK3sKKyAgICBQVUNIQVIgICAgICAgICAgQXJyYXkgPSAoUFVDSEFSKSZLZXk7Cisg
ICAgVUxPTkcgICAgICAgICAgIEFjY3VtdWxhdG9yOworICAgIFVMT05HICAgICAgICAgICBJbmRl
eDsKKworICAgIEFjY3VtdWxhdG9yID0gMDsKKworICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8
IHNpemVvZiAoVUxPTkdfUFRSKTsgSW5kZXgrKykgeworICAgICAgICBVTE9ORyAgIE92ZXJmbG93
OworCisgICAgICAgIEFjY3VtdWxhdG9yID0gKEFjY3VtdWxhdG9yIDw8IDQpICsgQXJyYXlbSW5k
ZXhdOworCisgICAgICAgIE92ZXJmbG93ID0gQWNjdW11bGF0b3IgJiAweDAwMDAwZjAwOworICAg
ICAgICBpZiAoT3ZlcmZsb3cgIT0gMCkgeworICAgICAgICAgICAgQWNjdW11bGF0b3IgXj0gT3Zl
cmZsb3cgPj4gODsKKyAgICAgICAgICAgIEFjY3VtdWxhdG9yIF49IE92ZXJmbG93OworICAgICAg
ICB9CisgICAgfQorCisgICAgQVNTRVJUM1UoQWNjdW11bGF0b3IsIDwsIFhFTkJVU19IQVNIX1RB
QkxFX05SX0JVQ0tFVFMpOworCisgICAgcmV0dXJuIEFjY3VtdWxhdG9yOworfQorCitzdGF0aWMK
K19JUlFMX3JlcXVpcmVzX21heF8oSElHSF9MRVZFTCkKK19JUlFMX3NhdmVzXworX0lSUUxfcmFp
c2VzXyhISUdIX0xFVkVMKQorS0lSUUwKK19fSGFzaFRhYmxlQnVja2V0TG9jaygKKyAgICBJTiAg
UFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCwKKyAgICBJTiAgQk9PTEVBTiAgICAg
ICAgICAgICAgICAgICAgIFdyaXRlcgorICAgICkKK3sKKyAgICBLSVJRTCAgICAgICAgICAgICAg
ICAgICAgICAgICAgIElycWw7CisKKyAgICBLZVJhaXNlSXJxbChISUdIX0xFVkVMLCAmSXJxbCk7
CisKKyAgICBmb3IgKDs7KSB7CisgICAgICAgIExPTkcgICAgTG9jazsKKyAgICAgICAgTE9ORyAg
ICBSZWFkZXJzOworICAgICAgICBMT05HICAgIFdyaXRlcnM7CisgICAgICAgIExPTkcgICAgT2xk
OworICAgICAgICBMT05HICAgIE5ldzsKKworICAgICAgICBLZU1lbW9yeUJhcnJpZXIoKTsKKwor
ICAgICAgICBMb2NrID0gQnVja2V0LT5Mb2NrOworICAgICAgICBSZWFkZXJzID0gTG9jayA+PiAx
OworICAgICAgICBXcml0ZXJzID0gTG9jayAmIDE7CisKKyAgICAgICAgLy8gVGhlcmUgbXVzdCBi
ZSBubyBleGlzdGluZyB3cml0ZXIKKyAgICAgICAgT2xkID0gUmVhZGVycyA8PCAxOworCisgICAg
ICAgIGlmIChXcml0ZXIpIAorICAgICAgICAgICAgV3JpdGVycysrOworICAgICAgICBlbHNlCisg
ICAgICAgICAgICBSZWFkZXJzKys7CisKKyAgICAgICAgTmV3ID0gKFJlYWRlcnMgPDwgMSkgfCAo
V3JpdGVycyAmIDEpOworCisgICAgICAgIGlmIChJbnRlcmxvY2tlZENvbXBhcmVFeGNoYW5nZSgm
QnVja2V0LT5Mb2NrLCBOZXcsIE9sZCkgIT0gT2xkKQorICAgICAgICAgICAgY29udGludWU7CisK
KyAgICAgICAgLy8KKyAgICAgICAgLy8gV2UgYXJlIGRvbmUgaWYgd2UncmUgbm90IGEgd3JpdGVy
LCBvciB0aGVyZSBhcmUgbm8gcmVhZGVycworICAgICAgICAvLyBsZWZ0LgorICAgICAgICAvLwor
ICAgICAgICBpZiAoIVdyaXRlciB8fCBSZWFkZXJzID09IDApCisgICAgICAgICAgICBicmVhazsK
KyAgICB9CisKKyAgICByZXR1cm4gSXJxbDsKK30KKworI2RlZmluZSBIYXNoVGFibGVCdWNrZXRM
b2NrKF9CdWNrZXQsIF9Xcml0ZXIsIF9JcnFsKSAgICAgICAgICAgIFwKKyAgICBkbyB7ICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCisgICAg
ICAgICooX0lycWwpID0gX19IYXNoVGFibGVCdWNrZXRMb2NrKChfQnVja2V0KSwgKF9Xcml0ZXIp
KTsgXAorICAgIH0gd2hpbGUgKEZBTFNFKQorCitzdGF0aWMKK19fZHJ2X3JlcXVpcmVzSVJRTChI
SUdIX0xFVkVMKQorVk9JRAorSGFzaFRhYmxlQnVja2V0VW5sb2NrKAorICAgIElOICBQWEVOQlVT
X0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0LAorICAgIElOICBCT09MRUFOICAgICAgICAgICAg
ICAgICAgICAgV3JpdGVyLAorICAgIElOICBfX2Rydl9yZXN0b3Jlc0lSUUwgS0lSUUwgICAgSXJx
bAorICAgICkKK3sKKyAgICBmb3IgKDs7KSB7CisgICAgICAgIExPTkcgICAgTG9jazsKKyAgICAg
ICAgTE9ORyAgICBSZWFkZXJzOworICAgICAgICBMT05HICAgIFdyaXRlcnM7CisgICAgICAgIExP
TkcgICAgT2xkOworICAgICAgICBMT05HICAgIE5ldzsKKworICAgICAgICBLZU1lbW9yeUJhcnJp
ZXIoKTsKKworICAgICAgICBMb2NrID0gQnVja2V0LT5Mb2NrOworICAgICAgICBSZWFkZXJzID0g
TG9jayA+PiAxOworICAgICAgICBXcml0ZXJzID0gTG9jayAmIDE7CisKKyAgICAgICAgT2xkID0g
KFJlYWRlcnMgPDwgMSkgfCAoV3JpdGVycyAmIDEpOworCisgICAgICAgIGlmIChXcml0ZXIpIHsK
KyAgICAgICAgICAgIEFTU0VSVChXcml0ZXJzICE9IDApOworICAgICAgICAgICAgLS1Xcml0ZXJz
OworICAgICAgICB9IGVsc2UgeworICAgICAgICAgICAgLS1SZWFkZXJzOworICAgICAgICB9CisK
KyAgICAgICAgTmV3ID0gKFJlYWRlcnMgPDwgMSkgfCAoV3JpdGVycyAmIDEpOworCisgICAgICAg
IGlmIChJbnRlcmxvY2tlZENvbXBhcmVFeGNoYW5nZSgmQnVja2V0LT5Mb2NrLCBOZXcsIE9sZCkg
PT0gT2xkKQorICAgICAgICAgICAgYnJlYWs7CisgICAgfQorCisgICAgS2VMb3dlcklycWwoSXJx
bCk7Cit9CisKK05UU1RBVFVTCitIYXNoVGFibGVBZGQoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9U
QUJMRSAgICAgIFRhYmxlLAorICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBLZXksCisg
ICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgICAgIFZhbHVlCisgICAgKQoreworICAgIFBYRU5C
VVNfSEFTSF9UQUJMRV9OT0RFICAgICBOb2RlOworICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9CVUNL
RVQgICBCdWNrZXQ7CisgICAgS0lSUUwgICAgICAgICAgICAgICAgICAgICAgIElycWw7CisgICAg
TlRTVEFUVVMgICAgICAgICAgICAgICAgICAgIHN0YXR1czsKKworICAgIE5vZGUgPSBfX0hhc2hU
YWJsZUFsbG9jYXRlKHNpemVvZiAoWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSkpOworCisgICAgc3Rh
dHVzID0gU1RBVFVTX05PX01FTU9SWTsKKyAgICBpZiAoTm9kZSA9PSBOVUxMKQorICAgICAgICBn
b3RvIGZhaWwxOworCisgICAgTm9kZS0+S2V5ID0gS2V5OworICAgIE5vZGUtPlZhbHVlID0gVmFs
dWU7CisKKyAgICBCdWNrZXQgPSAmVGFibGUtPkJ1Y2tldFtIYXNoVGFibGVIYXNoKEtleSldOwor
ICAgIAorICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0LCBUUlVFLCAmSXJxbCk7CisgICAg
SW5zZXJ0VGFpbExpc3QoJkJ1Y2tldC0+TGlzdCwgJk5vZGUtPkxpc3RFbnRyeSk7CisgICAgSGFz
aFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJxbCk7CisKKyAgICByZXR1cm4gU1RB
VFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWlsMSAoJTA4eClcbiIsIHN0YXR1
cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNUQVRVUworSGFzaFRhYmxlUmVtb3Zl
KAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICBUYWJsZSwKKyAgICBJTiAgVUxPTkdf
UFRSICAgICAgICAgICAgICAgS2V5CisgICAgKQoreworICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9C
VUNLRVQgICBCdWNrZXQ7CisgICAgUExJU1RfRU5UUlkgICAgICAgICAgICAgICAgIExpc3RFbnRy
eTsKKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsKKyAgICBLSVJRTCAgICAg
ICAgICAgICAgICAgICAgICAgSXJxbDsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgICAgICAgICAg
c3RhdHVzOworCisgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkp
XTsKKyAgICAKKyAgICBIYXNoVGFibGVCdWNrZXRMb2NrKEJ1Y2tldCwgVFJVRSwgJklycWwpOwor
CisgICAgTGlzdEVudHJ5ID0gQnVja2V0LT5MaXN0LkZsaW5rOworICAgIHdoaWxlIChMaXN0RW50
cnkgIT0gJkJ1Y2tldC0+TGlzdCkgeworICAgICAgICBOb2RlID0gQ09OVEFJTklOR19SRUNPUkQo
TGlzdEVudHJ5LCBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLCBMaXN0RW50cnkpOworCisgICAgICAg
IGlmIChOb2RlLT5LZXkgPT0gS2V5KQorICAgICAgICAgICAgZ290byBmb3VuZDsKKyAgICB9CisK
KyAgICBIYXNoVGFibGVCdWNrZXRVbmxvY2soQnVja2V0LCBUUlVFLCBJcnFsKTsKKworICAgIHN0
YXR1cyA9IFNUQVRVU19PQkpFQ1RfTkFNRV9OT1RfRk9VTkQ7CisgICAgZ290byBmYWlsMTsKKwor
Zm91bmQ6CisgICAgUmVtb3ZlRW50cnlMaXN0KExpc3RFbnRyeSk7CisgICAgX19IYXNoVGFibGVG
cmVlKE5vZGUpOworCisgICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJx
bCk7CisKKyAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJm
YWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNU
QVRVUworSGFzaFRhYmxlTG9va3VwKAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICBU
YWJsZSwKKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAgICAgICAgS2V5LAorICAgIE9VVCBQVUxP
TkdfUFRSICAgICAgICAgICAgICBWYWx1ZQorICAgICkKK3sKKyAgICBQWEVOQlVTX0hBU0hfVEFC
TEVfQlVDS0VUICAgQnVja2V0OworICAgIFBMSVNUX0VOVFJZICAgICAgICAgICAgICAgICBMaXN0
RW50cnk7CisgICAgUFhFTkJVU19IQVNIX1RBQkxFX05PREUgICAgIE5vZGU7CisgICAgS0lSUUwg
ICAgICAgICAgICAgICAgICAgICAgIElycWw7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIEJ1Y2tldCA9ICZUYWJsZS0+QnVja2V0W0hhc2hUYWJsZUhhc2go
S2V5KV07CisgICAgCisgICAgSGFzaFRhYmxlQnVja2V0TG9jayhCdWNrZXQsIEZBTFNFLCAmSXJx
bCk7CisKKyAgICBMaXN0RW50cnkgPSBCdWNrZXQtPkxpc3QuRmxpbms7CisgICAgd2hpbGUgKExp
c3RFbnRyeSAhPSAmQnVja2V0LT5MaXN0KSB7CisgICAgICAgIE5vZGUgPSBDT05UQUlOSU5HX1JF
Q09SRChMaXN0RW50cnksIFhFTkJVU19IQVNIX1RBQkxFX05PREUsIExpc3RFbnRyeSk7CisKKyAg
ICAgICAgaWYgKE5vZGUtPktleSA9PSBLZXkpCisgICAgICAgICAgICBnb3RvIGZvdW5kOworICAg
IH0KKworICAgIEhhc2hUYWJsZUJ1Y2tldFVubG9jayhCdWNrZXQsIEZBTFNFLCBJcnFsKTsKKwor
ICAgIHN0YXR1cyA9IFNUQVRVU19PQkpFQ1RfTkFNRV9OT1RfRk9VTkQ7CisgICAgZ290byBmYWls
MTsKKworZm91bmQ6CisgICAgKlZhbHVlID0gTm9kZS0+VmFsdWU7CisKKyAgICBIYXNoVGFibGVC
dWNrZXRVbmxvY2soQnVja2V0LCBGQUxTRSwgSXJxbCk7CisKKyAgICByZXR1cm4gU1RBVFVTX1NV
Q0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7CisK
KyAgICByZXR1cm4gc3RhdHVzOworfQorCitOVFNUQVRVUworSGFzaFRhYmxlQ3JlYXRlKAorICAg
IE9VVCBQWEVOQlVTX0hBU0hfVEFCTEUgICpUYWJsZQorICAgICkKK3sKKyAgICBVTE9ORyAgICAg
ICAgICAgICAgICAgICBJbmRleDsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgICAgICBzdGF0dXM7
CisKKyAgICAqVGFibGUgPSBfX0hhc2hUYWJsZUFsbG9jYXRlKHNpemVvZiAoWEVOQlVTX0hBU0hf
VEFCTEUpKTsKKworICAgIHN0YXR1cyA9IFNUQVRVU19OT19NRU1PUlk7CisgICAgaWYgKCpUYWJs
ZSA9PSBOVUxMKQorICAgICAgICBnb3RvIGZhaWwxOworCisgICAgZm9yIChJbmRleCA9IDA7IElu
ZGV4IDwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUzsgSW5kZXgrKykgeworICAgICAgICBQ
WEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0ID0gJigqVGFibGUpLT5CdWNrZXRbSW5k
ZXhdOworCisgICAgICAgIEluaXRpYWxpemVMaXN0SGVhZCgmQnVja2V0LT5MaXN0KTsKKyAgICB9
CisKKyAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CisKK2ZhaWwxOgorICAgIEVycm9yKCJmYWls
MSAoJTA4eClcbiIsIHN0YXR1cyk7CisKKyAgICByZXR1cm4gc3RhdHVzOworfQorCitWT0lECitI
YXNoVGFibGVEZXN0cm95KAorICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxlCisgICAg
KQoreworICAgIFVMT05HICAgICAgICAgICAgICAgICAgIEluZGV4OworCisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUzsgSW5kZXgrKykgewor
ICAgICAgICBQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0ID0gJlRhYmxlLT5CdWNr
ZXRbSW5kZXhdOworCisgICAgICAgIEFTU0VSVChJc0xpc3RFbXB0eSgmQnVja2V0LT5MaXN0KSk7
CisgICAgICAgIFJ0bFplcm9NZW1vcnkoJkJ1Y2tldC0+TGlzdCwgc2l6ZW9mIChMSVNUX0VOVFJZ
KSk7CisgICAgfQorCisgICAgQVNTRVJUKElzWmVyb01lbW9yeShUYWJsZSwgc2l6ZW9mIChYRU5C
VVNfSEFTSF9UQUJMRSkpKTsKKyAgICBfX0hhc2hUYWJsZUZyZWUoVGFibGUpOworfQorCmRpZmYg
LS1naXQgYS9zcmMveGVuYnVzL2hhc2hfdGFibGUuaCBiL3NyYy94ZW5idXMvaGFzaF90YWJsZS5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmNlMGM5MDYKLS0tIC9kZXYvbnVs
bAorKysgYi9zcmMveGVuYnVzL2hhc2hfdGFibGUuaApAQCAtMCwwICsxLDcwIEBACisvKiBDb3B5
cmlnaHQgKGMpIENpdHJpeCBTeXN0ZW1zIEluYy4KKyAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuCisg
KiAKKyAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMs
IAorICogd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRl
ZCAKKyAqIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6CisgKiAKKyAqICog
ICBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIAor
ICogICAgIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUg
CisgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIuCisgKiAqICAgUmVkaXN0cmlidXRpb25zIGlu
IGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5cmlnaHQg
bm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZvbGxvd2lu
ZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciAKKyAqICAgICBt
YXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLgorICogCisgKiBUSElTIFNP
RlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgCisgKiBDT05U
UklCVVRPUlMgIkFTIElTIiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCAK
KyAqIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVT
IE9GIAorICogTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVS
UE9TRSBBUkUgCisgKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hU
IEhPTERFUiBPUiAKKyAqIENPTlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElO
RElSRUNULCBJTkNJREVOVEFMLCAKKyAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVO
VElBTCBEQU1BR0VTIChJTkNMVURJTkcsIAorICogQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJF
TUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIAorICogU0VSVklDRVM7IExPU1MgT0YgVVNFLCBE
QVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyAKKyAqIElOVEVSUlVQVElPTikgSE9XRVZFUiBD
QVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCAKKyAqIFdIRVRIRVIgSU4gQ09O
VFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyAKKyAqIE5FR0xJR0VO
Q0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgCisgKiBP
RiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIAor
ICogU1VDSCBEQU1BR0UuCisgKi8KKworI2lmbmRlZiBfWEVOQlVTX0hBU0hfVEFCTEVfSAorI2Rl
ZmluZSBfWEVOQlVTX0hBU0hfVEFCTEVfSAorCisjaW5jbHVkZSA8bnRkZGsuaD4KKwordHlwZWRl
ZiBzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFIFhFTkJVU19IQVNIX1RBQkxFLCAqUFhFTkJVU19I
QVNIX1RBQkxFOyAKKworZXh0ZXJuIE5UU1RBVFVTCitIYXNoVGFibGVBZGQoCisgICAgSU4gIFBY
RU5CVVNfSEFTSF9UQUJMRSAgVGFibGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5
LAorICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIFZhbHVlCisgICAgKTsKKworZXh0ZXJuIE5U
U1RBVFVTCitIYXNoVGFibGVSZW1vdmUoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5CisgICAgKTsKKworZXh0ZXJuIE5U
U1RBVFVTCitIYXNoVGFibGVMb29rdXAoCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUsCisgICAgSU4gIFVMT05HX1BUUiAgICAgICAgICAgS2V5LAorICAgIE9VVCBQVUxPTkdfUFRS
ICAgICAgICAgIFZhbHVlCisgICAgKTsKKworZXh0ZXJuIE5UU1RBVFVTCitIYXNoVGFibGVDcmVh
dGUoCisgICAgT1VUIFBYRU5CVVNfSEFTSF9UQUJMRSAgKlRhYmxlCisgICAgKTsKKworZXh0ZXJu
IFZPSUQKK0hhc2hUYWJsZURlc3Ryb3koCisgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgVGFi
bGUKKyAgICApOworCisjZW5kaWYgIC8vIF9YRU5CVVNfSEFTSF9UQUJMRV9ICisKZGlmZiAtLWdp
dCBhL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYyBiL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYwpp
bmRleCAwYWZjMjE4Li42N2JlMjBjIDEwMDY0NAotLS0gYS9zcmMveGVuYnVzL3NoYXJlZF9pbmZv
LmMKKysrIGIvc3JjL3hlbmJ1cy9zaGFyZWRfaW5mby5jCkBAIC0zOCw2ICszOCw5IEBACiAjaW5j
bHVkZSAiZGJnX3ByaW50LmgiCiAjaW5jbHVkZSAiYXNzZXJ0LmgiCiAKKyNkZWZpbmUgWEVOQlVT
X1NIQVJFRF9JTkZPX0VWVENITl9QRVJfU0VMRUNUT1IgICAgIChzaXplb2YgKFVMT05HX1BUUikg
KiA4KQorI2RlZmluZSBYRU5CVVNfU0hBUkVEX0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UICAg
KFJUTF9GSUVMRF9TSVpFKHNoYXJlZF9pbmZvX3QsIGV2dGNobl9wZW5kaW5nKSAvIHNpemVvZiAo
VUxPTkdfUFRSKSkKKwogc3RydWN0IF9YRU5CVVNfU0hBUkVEX0lORk9fQ09OVEVYVCB7CiAgICAg
UFhFTkJVU19GRE8gICAgICAgICAgICAgICAgIEZkbzsKICAgICBLU1BJTl9MT0NLICAgICAgICAg
ICAgICAgICAgTG9jazsKZGlmZiAtLWdpdCBhL3ZzMjAxMi94ZW5idXMveGVuYnVzLnZjeHByb2og
Yi92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qCmluZGV4IGMzMDc3NGUuLmE2NDhiY2UgMTAw
NjQ0Ci0tLSBhL3ZzMjAxMi94ZW5idXMveGVuYnVzLnZjeHByb2oKKysrIGIvdnMyMDEyL3hlbmJ1
cy94ZW5idXMudmN4cHJvagpAQCAtOTksNiArOTksNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5idXNccmFuZ2Vfc2V0LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0i
Li5cLi5cc3JjXHhlbmJ1c1xiYWxsb29uLmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5c
Li5cc3JjXHhlbmJ1c1xjYWNoZS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNy
Y1x4ZW5idXNcaGFzaF90YWJsZS5jIiAvPgogCTwvSXRlbUdyb3VwPgogCTxJdGVtR3JvdXA+CiAJ
CTxSZXNvdXJjZUNvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlbmJ1c1x4ZW5idXMucmMiIC8+
CmRpZmYgLS1naXQgYS92czIwMTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qIGIvdnMyMDEzL3hlbmJ1
cy94ZW5idXMudmN4cHJvagppbmRleCA1ODhiMGM1Li4yYzM0ZWQxIDEwMDY0NAotLS0gYS92czIw
MTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qCisrKyBiL3ZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHBy
b2oKQEAgLTEsNCArMSw0IEBACi3vu788P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJ1dGYt
OCI/PgorPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KIDxQcm9qZWN0IERl
ZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIxMi4wIiB4bWxucz0iaHR0cDovL3Nj
aGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWlsZC8yMDAzIj4KICAgPEltcG9ydCBQ
cm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgogICA8UHJvcGVydHlHcm91cCBMYWJlbD0iR2xv
YmFscyI+CkBAIC0xMzksNiArMTM5LDcgQEAKICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4u
XHNyY1x4ZW5idXNccmFuZ2Vfc2V0LmMiIC8+CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuYnVzXGJhbGxvb24uYyIgLz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4u
XHNyY1x4ZW5idXNcY2FjaGUuYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNy
Y1x4ZW5idXNcaGFzaF90YWJsZS5jIiAvPgogICA8L0l0ZW1Hcm91cD4KICAgPEl0ZW1Hcm91cD4K
ICAgICA8UmVzb3VyY2VDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNceGVuYnVzLnJj
IiAvPgotLSAKMi4xLjEKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1kZXZlbEBsaXN0cy54ZW5w
cm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dpLWJpbi9tYWlsbWFuL2xp
c3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 06 14:24:48 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:48 +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 1XmNzU-0001aC-T6; Thu, 06 Nov 2014 14:24:48 +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 1XmNzT-0001Yy-Q7
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:48 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	7B/44-22819-EA48B545; Thu, 06 Nov 2014 14:24:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6737 invoked from network); 6 Nov 2014 14:24:45 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771860"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-9B;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:16 +0000
Message-ID: <1415283861-26028-6-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 05/10] Use a hash table for event channel
	lookup
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

Rather than using a large array for mapping port values to channel
structures, use a hash table. This means we no longer need to code a
hard port number limit into the EVTCHN implementation.

Because the hash table implementation manages its own locking, we also no
longer need to make such liberal use of the interrupt lock in the EVTCHN
implementation and can use the spinlock instead.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h      |   4 +-
 include/shared_info_interface.h |   3 -
 src/xenbus/evtchn.c             |  89 ++++++----
 src/xenbus/hash_table.c         | 367 ++++++++++++++++++++++++++++++++++++++++
 src/xenbus/hash_table.h         |  70 ++++++++
 src/xenbus/shared_info.c        |   3 +
 vs2012/xenbus/xenbus.vcxproj    |   1 +
 vs2013/xenbus/xenbus.vcxproj    |   3 +-
 8 files changed, 504 insertions(+), 36 deletions(-)
 create mode 100644 src/xenbus/hash_table.c
 create mode 100644 src/xenbus/hash_table.h

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 991d610..3a48915 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -117,14 +117,14 @@ typedef PXENBUS_EVTCHN_CHANNEL
 
     \param Interface The interface header
     \param Channel The channel handle
-    \param Locked Set to TRUE if this method is invoked in context of the channel callback
+    \param InCallback Set to TRUE if this method is invoked in context of the channel callback
     \return TRUE if there was an event pending at the point of unmask, FALSE otherwise
 */
 typedef BOOLEAN
 (*XENBUS_EVTCHN_UNMASK)(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     );
 
 /*! \typedef XENBUS_EVTCHN_SEND
diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
index 0d36ac8..0e5a0d7 100644
--- a/include/shared_info_interface.h
+++ b/include/shared_info_interface.h
@@ -40,9 +40,6 @@
 
 #ifndef _WINDLL
 
-#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR     (sizeof (ULONG_PTR) * 8)
-#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT   (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR))
-
 /*! \typedef XENBUS_SHARED_INFO_ACQUIRE
     \brief Acquire a reference to the SHARED_INFO interface
 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 35ad44a..338a90f 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -36,6 +36,7 @@
 
 #include "evtchn.h"
 #include "fdo.h"
+#include "hash_table.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -97,7 +98,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     XENBUS_DEBUG_INTERFACE          DebugInterface;
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
-    PXENBUS_EVTCHN_CHANNEL          Channel[XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR];
+    PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
 
@@ -351,14 +352,16 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
-    ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
-
-    (VOID) __EvtchnAcquireInterruptLock(Context);
+    status = HashTableAdd(Context->Table,
+                          LocalPort,
+                          (ULONG_PTR)Channel);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    ASSERT3P(Context->Channel[LocalPort], ==, NULL);
-    Context->Channel[LocalPort] = Channel;
     Channel->Active = TRUE;
 
+    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
+
     InsertTailList(&Context->List, &Channel->ListEntry);
 
     if (!IsListEmpty(&Context->List) && !Context->Enabled) {
@@ -366,12 +369,18 @@ EvtchnOpen(
         Context->Enabled = TRUE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, DISPATCH_LEVEL);
+    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
 
     KeLowerIrql(Irql);
 
     return Channel;
 
+fail3:
+    Error("fail3\n");
+
+    Channel->LocalPort = 0;
+    RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
+
 fail2:
     Error("fail2\n");
 
@@ -398,7 +407,7 @@ static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     )
 {
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
@@ -407,8 +416,10 @@ EvtchnUnmask(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    if (!Locked)
-        Irql = __EvtchnAcquireInterruptLock(Context);
+    if (!InCallback)
+        KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
     if (Channel->Active) {
         Pending = XENBUS_SHARED_INFO(EvtchnUnmask,
@@ -446,8 +457,8 @@ EvtchnUnmask(
         }
     }
 
-    if (!Locked)
-        __EvtchnReleaseInterruptLock(Context, Irql);
+    if (!InCallback)
+        KeLowerIrql(Irql);
 
     return Pending;
 }
@@ -513,6 +524,8 @@ EvtchnTrigger(
 
     Irql = __EvtchnAcquireInterruptLock(Context);
 
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+
     if (Channel->Active) {
         DoneSomething = EvtchnCallback(Context, Channel);
     } else {
@@ -536,7 +549,9 @@ EvtchnClose(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+
+    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
 
     RemoveEntryList(&Channel->ListEntry);
 
@@ -545,12 +560,13 @@ EvtchnClose(
         Context->Enabled = FALSE;
     }
 
+    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
+
     RtlZeroMemory(&Channel->ListEntry, sizeof (LIST_ENTRY));
 
     if (Channel->Active) {
-        ULONG   LocalPort = Channel->LocalPort;
-
-        ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
+        ULONG       LocalPort = Channel->LocalPort;
+        NTSTATUS    status;
 
         Channel->Active = FALSE;
 
@@ -561,12 +577,10 @@ EvtchnClose(
         if (Channel->Type != XENBUS_EVTCHN_TYPE_FIXED)
             (VOID) EventChannelClose(LocalPort);
 
-        ASSERT(Context->Channel[LocalPort] != NULL);
-        Context->Channel[LocalPort] = NULL;
+        status = HashTableRemove(Context->Table, LocalPort);
+        ASSERT(NT_SUCCESS(status));
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
-
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -580,6 +594,8 @@ EvtchnClose(
 
     ASSERT(IsZeroMemory(Channel, sizeof (XENBUS_EVTCHN_CHANNEL)));
     __EvtchnFree(Channel);
+
+    KeLowerIrql(Irql);
 }
 
 static ULONG
@@ -606,12 +622,13 @@ EvtchnPollCallback(
     PXENBUS_EVTCHN_CHANNEL  Channel;
     BOOLEAN                 Mask;
     BOOLEAN                 DoneSomething;
+    NTSTATUS                status;
 
-    ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
-
-    Channel = Context->Channel[LocalPort];
-
-    if (Channel == NULL) {
+    status = HashTableLookup(Context->Table,
+                             LocalPort,
+                             (PULONG_PTR)&Channel);
+    
+    if (!NT_SUCCESS(status)) {
         Warning("[%d]: INVALID PORT\n", LocalPort);
 
         XENBUS_SHARED_INFO(EvtchnMask,
@@ -697,14 +714,13 @@ EvtchnSuspendCallbackEarly(
         Channel = CONTAINING_RECORD(ListEntry, XENBUS_EVTCHN_CHANNEL, ListEntry);
 
         if (Channel->Active) {
-            ULONG   LocalPort = Channel->LocalPort;
-
-            ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
+            ULONG       LocalPort = Channel->LocalPort;
+            NTSTATUS    status;
 
             Channel->Active = FALSE;
 
-            ASSERT(Context->Channel[LocalPort] != NULL);
-            Context->Channel[LocalPort] = NULL;
+            status = HashTableRemove(Context->Table, LocalPort);
+            ASSERT(NT_SUCCESS(status));
         }
     }
 
@@ -958,6 +974,10 @@ EvtchnInitialize(
     if (*Context == NULL)
         goto fail1;
 
+    status = HashTableCreate(&(*Context)->Table);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -988,6 +1008,12 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
+    __EvtchnFree(Context);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1053,6 +1079,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    HashTableDestroy(Context->Table);
+    Context->Table = NULL;
+
     ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
     __EvtchnFree(Context);
 
diff --git a/src/xenbus/hash_table.c b/src/xenbus/hash_table.c
new file mode 100644
index 0000000..b8e27d8
--- /dev/null
+++ b/src/xenbus/hash_table.c
@@ -0,0 +1,367 @@
+/* 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 "hash_table.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENBUS_HASH_TABLE_NODE {
+    LIST_ENTRY  ListEntry;
+    ULONG_PTR   Key;
+    ULONG_PTR   Value;
+} XENBUS_HASH_TABLE_NODE, *PXENBUS_HASH_TABLE_NODE;
+
+typedef struct _XENBUS_HASH_TABLE_BUCKET {
+    LONG        Lock;
+    LIST_ENTRY  List;
+} XENBUS_HASH_TABLE_BUCKET, *PXENBUS_HASH_TABLE_BUCKET;
+
+#define XENBUS_HASH_TABLE_NR_BUCKETS \
+    (1 << (sizeof (UCHAR) * 8))
+
+struct _XENBUS_HASH_TABLE {
+    XENBUS_HASH_TABLE_BUCKET    Bucket[XENBUS_HASH_TABLE_NR_BUCKETS];
+};
+
+#define XENBUS_HASH_TABLE_TAG   'HSAH'
+
+static FORCEINLINE PVOID
+__HashTableAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_HASH_TABLE_TAG);
+}
+
+static FORCEINLINE VOID
+__HashTableFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_HASH_TABLE_TAG);
+}
+
+static ULONG
+HashTableHash(
+    IN  ULONG_PTR   Key
+    )
+{
+    PUCHAR          Array = (PUCHAR)&Key;
+    ULONG           Accumulator;
+    ULONG           Index;
+
+    Accumulator = 0;
+
+    for (Index = 0; Index < sizeof (ULONG_PTR); Index++) {
+        ULONG   Overflow;
+
+        Accumulator = (Accumulator << 4) + Array[Index];
+
+        Overflow = Accumulator & 0x00000f00;
+        if (Overflow != 0) {
+            Accumulator ^= Overflow >> 8;
+            Accumulator ^= Overflow;
+        }
+    }
+
+    ASSERT3U(Accumulator, <, XENBUS_HASH_TABLE_NR_BUCKETS);
+
+    return Accumulator;
+}
+
+static
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+__HashTableBucketLock(
+    IN  PXENBUS_HASH_TABLE_BUCKET   Bucket,
+    IN  BOOLEAN                     Writer
+    )
+{
+    KIRQL                           Irql;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    for (;;) {
+        LONG    Lock;
+        LONG    Readers;
+        LONG    Writers;
+        LONG    Old;
+        LONG    New;
+
+        KeMemoryBarrier();
+
+        Lock = Bucket->Lock;
+        Readers = Lock >> 1;
+        Writers = Lock & 1;
+
+        // There must be no existing writer
+        Old = Readers << 1;
+
+        if (Writer) 
+            Writers++;
+        else
+            Readers++;
+
+        New = (Readers << 1) | (Writers & 1);
+
+        if (InterlockedCompareExchange(&Bucket->Lock, New, Old) != Old)
+            continue;
+
+        //
+        // We are done if we're not a writer, or there are no readers
+        // left.
+        //
+        if (!Writer || Readers == 0)
+            break;
+    }
+
+    return Irql;
+}
+
+#define HashTableBucketLock(_Bucket, _Writer, _Irql)            \
+    do {                                                        \
+        *(_Irql) = __HashTableBucketLock((_Bucket), (_Writer)); \
+    } while (FALSE)
+
+static
+__drv_requiresIRQL(HIGH_LEVEL)
+VOID
+HashTableBucketUnlock(
+    IN  PXENBUS_HASH_TABLE_BUCKET   Bucket,
+    IN  BOOLEAN                     Writer,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    for (;;) {
+        LONG    Lock;
+        LONG    Readers;
+        LONG    Writers;
+        LONG    Old;
+        LONG    New;
+
+        KeMemoryBarrier();
+
+        Lock = Bucket->Lock;
+        Readers = Lock >> 1;
+        Writers = Lock & 1;
+
+        Old = (Readers << 1) | (Writers & 1);
+
+        if (Writer) {
+            ASSERT(Writers != 0);
+            --Writers;
+        } else {
+            --Readers;
+        }
+
+        New = (Readers << 1) | (Writers & 1);
+
+        if (InterlockedCompareExchange(&Bucket->Lock, New, Old) == Old)
+            break;
+    }
+
+    KeLowerIrql(Irql);
+}
+
+NTSTATUS
+HashTableAdd(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key,
+    IN  ULONG_PTR               Value
+    )
+{
+    PXENBUS_HASH_TABLE_NODE     Node;
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Node = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE_NODE));
+
+    status = STATUS_NO_MEMORY;
+    if (Node == NULL)
+        goto fail1;
+
+    Node->Key = Key;
+    Node->Value = Value;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, TRUE, &Irql);
+    InsertTailList(&Bucket->List, &Node->ListEntry);
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableRemove(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key
+    )
+{
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    PLIST_ENTRY                 ListEntry;
+    PXENBUS_HASH_TABLE_NODE     Node;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, TRUE, &Irql);
+
+    ListEntry = Bucket->List.Flink;
+    while (ListEntry != &Bucket->List) {
+        Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry);
+
+        if (Node->Key == Key)
+            goto found;
+    }
+
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    RemoveEntryList(ListEntry);
+    __HashTableFree(Node);
+
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableLookup(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key,
+    OUT PULONG_PTR              Value
+    )
+{
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    PLIST_ENTRY                 ListEntry;
+    PXENBUS_HASH_TABLE_NODE     Node;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, FALSE, &Irql);
+
+    ListEntry = Bucket->List.Flink;
+    while (ListEntry != &Bucket->List) {
+        Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry);
+
+        if (Node->Key == Key)
+            goto found;
+    }
+
+    HashTableBucketUnlock(Bucket, FALSE, Irql);
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    *Value = Node->Value;
+
+    HashTableBucketUnlock(Bucket, FALSE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableCreate(
+    OUT PXENBUS_HASH_TABLE  *Table
+    )
+{
+    ULONG                   Index;
+    NTSTATUS                status;
+
+    *Table = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE));
+
+    status = STATUS_NO_MEMORY;
+    if (*Table == NULL)
+        goto fail1;
+
+    for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) {
+        PXENBUS_HASH_TABLE_BUCKET   Bucket = &(*Table)->Bucket[Index];
+
+        InitializeListHead(&Bucket->List);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+HashTableDestroy(
+    IN  PXENBUS_HASH_TABLE  Table
+    )
+{
+    ULONG                   Index;
+
+    for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) {
+        PXENBUS_HASH_TABLE_BUCKET   Bucket = &Table->Bucket[Index];
+
+        ASSERT(IsListEmpty(&Bucket->List));
+        RtlZeroMemory(&Bucket->List, sizeof (LIST_ENTRY));
+    }
+
+    ASSERT(IsZeroMemory(Table, sizeof (XENBUS_HASH_TABLE)));
+    __HashTableFree(Table);
+}
+
diff --git a/src/xenbus/hash_table.h b/src/xenbus/hash_table.h
new file mode 100644
index 0000000..ce0c906
--- /dev/null
+++ b/src/xenbus/hash_table.h
@@ -0,0 +1,70 @@
+/* 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 _XENBUS_HASH_TABLE_H
+#define _XENBUS_HASH_TABLE_H
+
+#include <ntddk.h>
+
+typedef struct _XENBUS_HASH_TABLE XENBUS_HASH_TABLE, *PXENBUS_HASH_TABLE; 
+
+extern NTSTATUS
+HashTableAdd(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key,
+    IN  ULONG_PTR           Value
+    );
+
+extern NTSTATUS
+HashTableRemove(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key
+    );
+
+extern NTSTATUS
+HashTableLookup(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key,
+    OUT PULONG_PTR          Value
+    );
+
+extern NTSTATUS
+HashTableCreate(
+    OUT PXENBUS_HASH_TABLE  *Table
+    );
+
+extern VOID
+HashTableDestroy(
+    IN  PXENBUS_HASH_TABLE  Table
+    );
+
+#endif  // _XENBUS_HASH_TABLE_H
+
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 0afc218..67be20c 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -38,6 +38,9 @@
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR     (sizeof (ULONG_PTR) * 8)
+#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT   (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR))
+
 struct _XENBUS_SHARED_INFO_CONTEXT {
     PXENBUS_FDO                 Fdo;
     KSPIN_LOCK                  Lock;
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index c30774e..a648bce 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -99,6 +99,7 @@
 		<ClCompile Include="..\..\src\xenbus\range_set.c" />
 		<ClCompile Include="..\..\src\xenbus\balloon.c" />
 		<ClCompile Include="..\..\src\xenbus\cache.c" />
+		<ClCompile Include="..\..\src\xenbus\hash_table.c" />
 	</ItemGroup>
 	<ItemGroup>
 		<ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 588b0c5..2c34ed1 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -139,6 +139,7 @@
     <ClCompile Include="..\..\src\xenbus\range_set.c" />
     <ClCompile Include="..\..\src\xenbus\balloon.c" />
     <ClCompile Include="..\..\src\xenbus\cache.c" />
+    <ClCompile Include="..\..\src\xenbus\hash_table.c" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
-- 
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 Nov 06 14:24:48 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24:48 +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 1XmNzU-0001aC-T6; Thu, 06 Nov 2014 14:24:48 +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 1XmNzT-0001Yy-Q7
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:48 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	7B/44-22819-EA48B545; Thu, 06 Nov 2014 14:24:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415283879!10918010!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6737 invoked from network); 6 Nov 2014 14:24:45 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771860"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-9B;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:16 +0000
Message-ID: <1415283861-26028-6-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 05/10] Use a hash table for event channel
	lookup
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

Rather than using a large array for mapping port values to channel
structures, use a hash table. This means we no longer need to code a
hard port number limit into the EVTCHN implementation.

Because the hash table implementation manages its own locking, we also no
longer need to make such liberal use of the interrupt lock in the EVTCHN
implementation and can use the spinlock instead.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h      |   4 +-
 include/shared_info_interface.h |   3 -
 src/xenbus/evtchn.c             |  89 ++++++----
 src/xenbus/hash_table.c         | 367 ++++++++++++++++++++++++++++++++++++++++
 src/xenbus/hash_table.h         |  70 ++++++++
 src/xenbus/shared_info.c        |   3 +
 vs2012/xenbus/xenbus.vcxproj    |   1 +
 vs2013/xenbus/xenbus.vcxproj    |   3 +-
 8 files changed, 504 insertions(+), 36 deletions(-)
 create mode 100644 src/xenbus/hash_table.c
 create mode 100644 src/xenbus/hash_table.h

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 991d610..3a48915 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -117,14 +117,14 @@ typedef PXENBUS_EVTCHN_CHANNEL
 
     \param Interface The interface header
     \param Channel The channel handle
-    \param Locked Set to TRUE if this method is invoked in context of the channel callback
+    \param InCallback Set to TRUE if this method is invoked in context of the channel callback
     \return TRUE if there was an event pending at the point of unmask, FALSE otherwise
 */
 typedef BOOLEAN
 (*XENBUS_EVTCHN_UNMASK)(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     );
 
 /*! \typedef XENBUS_EVTCHN_SEND
diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
index 0d36ac8..0e5a0d7 100644
--- a/include/shared_info_interface.h
+++ b/include/shared_info_interface.h
@@ -40,9 +40,6 @@
 
 #ifndef _WINDLL
 
-#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR     (sizeof (ULONG_PTR) * 8)
-#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT   (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR))
-
 /*! \typedef XENBUS_SHARED_INFO_ACQUIRE
     \brief Acquire a reference to the SHARED_INFO interface
 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 35ad44a..338a90f 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -36,6 +36,7 @@
 
 #include "evtchn.h"
 #include "fdo.h"
+#include "hash_table.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -97,7 +98,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     XENBUS_DEBUG_INTERFACE          DebugInterface;
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
-    PXENBUS_EVTCHN_CHANNEL          Channel[XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT * XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR];
+    PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
 
@@ -351,14 +352,16 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
-    ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
-
-    (VOID) __EvtchnAcquireInterruptLock(Context);
+    status = HashTableAdd(Context->Table,
+                          LocalPort,
+                          (ULONG_PTR)Channel);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    ASSERT3P(Context->Channel[LocalPort], ==, NULL);
-    Context->Channel[LocalPort] = Channel;
     Channel->Active = TRUE;
 
+    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
+
     InsertTailList(&Context->List, &Channel->ListEntry);
 
     if (!IsListEmpty(&Context->List) && !Context->Enabled) {
@@ -366,12 +369,18 @@ EvtchnOpen(
         Context->Enabled = TRUE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, DISPATCH_LEVEL);
+    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
 
     KeLowerIrql(Irql);
 
     return Channel;
 
+fail3:
+    Error("fail3\n");
+
+    Channel->LocalPort = 0;
+    RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
+
 fail2:
     Error("fail2\n");
 
@@ -398,7 +407,7 @@ static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     )
 {
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
@@ -407,8 +416,10 @@ EvtchnUnmask(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    if (!Locked)
-        Irql = __EvtchnAcquireInterruptLock(Context);
+    if (!InCallback)
+        KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
     if (Channel->Active) {
         Pending = XENBUS_SHARED_INFO(EvtchnUnmask,
@@ -446,8 +457,8 @@ EvtchnUnmask(
         }
     }
 
-    if (!Locked)
-        __EvtchnReleaseInterruptLock(Context, Irql);
+    if (!InCallback)
+        KeLowerIrql(Irql);
 
     return Pending;
 }
@@ -513,6 +524,8 @@ EvtchnTrigger(
 
     Irql = __EvtchnAcquireInterruptLock(Context);
 
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+
     if (Channel->Active) {
         DoneSomething = EvtchnCallback(Context, Channel);
     } else {
@@ -536,7 +549,9 @@ EvtchnClose(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+
+    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
 
     RemoveEntryList(&Channel->ListEntry);
 
@@ -545,12 +560,13 @@ EvtchnClose(
         Context->Enabled = FALSE;
     }
 
+    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
+
     RtlZeroMemory(&Channel->ListEntry, sizeof (LIST_ENTRY));
 
     if (Channel->Active) {
-        ULONG   LocalPort = Channel->LocalPort;
-
-        ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
+        ULONG       LocalPort = Channel->LocalPort;
+        NTSTATUS    status;
 
         Channel->Active = FALSE;
 
@@ -561,12 +577,10 @@ EvtchnClose(
         if (Channel->Type != XENBUS_EVTCHN_TYPE_FIXED)
             (VOID) EventChannelClose(LocalPort);
 
-        ASSERT(Context->Channel[LocalPort] != NULL);
-        Context->Channel[LocalPort] = NULL;
+        status = HashTableRemove(Context->Table, LocalPort);
+        ASSERT(NT_SUCCESS(status));
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
-
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -580,6 +594,8 @@ EvtchnClose(
 
     ASSERT(IsZeroMemory(Channel, sizeof (XENBUS_EVTCHN_CHANNEL)));
     __EvtchnFree(Channel);
+
+    KeLowerIrql(Irql);
 }
 
 static ULONG
@@ -606,12 +622,13 @@ EvtchnPollCallback(
     PXENBUS_EVTCHN_CHANNEL  Channel;
     BOOLEAN                 Mask;
     BOOLEAN                 DoneSomething;
+    NTSTATUS                status;
 
-    ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
-
-    Channel = Context->Channel[LocalPort];
-
-    if (Channel == NULL) {
+    status = HashTableLookup(Context->Table,
+                             LocalPort,
+                             (PULONG_PTR)&Channel);
+    
+    if (!NT_SUCCESS(status)) {
         Warning("[%d]: INVALID PORT\n", LocalPort);
 
         XENBUS_SHARED_INFO(EvtchnMask,
@@ -697,14 +714,13 @@ EvtchnSuspendCallbackEarly(
         Channel = CONTAINING_RECORD(ListEntry, XENBUS_EVTCHN_CHANNEL, ListEntry);
 
         if (Channel->Active) {
-            ULONG   LocalPort = Channel->LocalPort;
-
-            ASSERT3U(LocalPort, <, sizeof (Context->Channel) / sizeof (Context->Channel[0]));
+            ULONG       LocalPort = Channel->LocalPort;
+            NTSTATUS    status;
 
             Channel->Active = FALSE;
 
-            ASSERT(Context->Channel[LocalPort] != NULL);
-            Context->Channel[LocalPort] = NULL;
+            status = HashTableRemove(Context->Table, LocalPort);
+            ASSERT(NT_SUCCESS(status));
         }
     }
 
@@ -958,6 +974,10 @@ EvtchnInitialize(
     if (*Context == NULL)
         goto fail1;
 
+    status = HashTableCreate(&(*Context)->Table);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -988,6 +1008,12 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
+    __EvtchnFree(Context);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1053,6 +1079,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    HashTableDestroy(Context->Table);
+    Context->Table = NULL;
+
     ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
     __EvtchnFree(Context);
 
diff --git a/src/xenbus/hash_table.c b/src/xenbus/hash_table.c
new file mode 100644
index 0000000..b8e27d8
--- /dev/null
+++ b/src/xenbus/hash_table.c
@@ -0,0 +1,367 @@
+/* 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 "hash_table.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENBUS_HASH_TABLE_NODE {
+    LIST_ENTRY  ListEntry;
+    ULONG_PTR   Key;
+    ULONG_PTR   Value;
+} XENBUS_HASH_TABLE_NODE, *PXENBUS_HASH_TABLE_NODE;
+
+typedef struct _XENBUS_HASH_TABLE_BUCKET {
+    LONG        Lock;
+    LIST_ENTRY  List;
+} XENBUS_HASH_TABLE_BUCKET, *PXENBUS_HASH_TABLE_BUCKET;
+
+#define XENBUS_HASH_TABLE_NR_BUCKETS \
+    (1 << (sizeof (UCHAR) * 8))
+
+struct _XENBUS_HASH_TABLE {
+    XENBUS_HASH_TABLE_BUCKET    Bucket[XENBUS_HASH_TABLE_NR_BUCKETS];
+};
+
+#define XENBUS_HASH_TABLE_TAG   'HSAH'
+
+static FORCEINLINE PVOID
+__HashTableAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_HASH_TABLE_TAG);
+}
+
+static FORCEINLINE VOID
+__HashTableFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_HASH_TABLE_TAG);
+}
+
+static ULONG
+HashTableHash(
+    IN  ULONG_PTR   Key
+    )
+{
+    PUCHAR          Array = (PUCHAR)&Key;
+    ULONG           Accumulator;
+    ULONG           Index;
+
+    Accumulator = 0;
+
+    for (Index = 0; Index < sizeof (ULONG_PTR); Index++) {
+        ULONG   Overflow;
+
+        Accumulator = (Accumulator << 4) + Array[Index];
+
+        Overflow = Accumulator & 0x00000f00;
+        if (Overflow != 0) {
+            Accumulator ^= Overflow >> 8;
+            Accumulator ^= Overflow;
+        }
+    }
+
+    ASSERT3U(Accumulator, <, XENBUS_HASH_TABLE_NR_BUCKETS);
+
+    return Accumulator;
+}
+
+static
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+__HashTableBucketLock(
+    IN  PXENBUS_HASH_TABLE_BUCKET   Bucket,
+    IN  BOOLEAN                     Writer
+    )
+{
+    KIRQL                           Irql;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    for (;;) {
+        LONG    Lock;
+        LONG    Readers;
+        LONG    Writers;
+        LONG    Old;
+        LONG    New;
+
+        KeMemoryBarrier();
+
+        Lock = Bucket->Lock;
+        Readers = Lock >> 1;
+        Writers = Lock & 1;
+
+        // There must be no existing writer
+        Old = Readers << 1;
+
+        if (Writer) 
+            Writers++;
+        else
+            Readers++;
+
+        New = (Readers << 1) | (Writers & 1);
+
+        if (InterlockedCompareExchange(&Bucket->Lock, New, Old) != Old)
+            continue;
+
+        //
+        // We are done if we're not a writer, or there are no readers
+        // left.
+        //
+        if (!Writer || Readers == 0)
+            break;
+    }
+
+    return Irql;
+}
+
+#define HashTableBucketLock(_Bucket, _Writer, _Irql)            \
+    do {                                                        \
+        *(_Irql) = __HashTableBucketLock((_Bucket), (_Writer)); \
+    } while (FALSE)
+
+static
+__drv_requiresIRQL(HIGH_LEVEL)
+VOID
+HashTableBucketUnlock(
+    IN  PXENBUS_HASH_TABLE_BUCKET   Bucket,
+    IN  BOOLEAN                     Writer,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    for (;;) {
+        LONG    Lock;
+        LONG    Readers;
+        LONG    Writers;
+        LONG    Old;
+        LONG    New;
+
+        KeMemoryBarrier();
+
+        Lock = Bucket->Lock;
+        Readers = Lock >> 1;
+        Writers = Lock & 1;
+
+        Old = (Readers << 1) | (Writers & 1);
+
+        if (Writer) {
+            ASSERT(Writers != 0);
+            --Writers;
+        } else {
+            --Readers;
+        }
+
+        New = (Readers << 1) | (Writers & 1);
+
+        if (InterlockedCompareExchange(&Bucket->Lock, New, Old) == Old)
+            break;
+    }
+
+    KeLowerIrql(Irql);
+}
+
+NTSTATUS
+HashTableAdd(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key,
+    IN  ULONG_PTR               Value
+    )
+{
+    PXENBUS_HASH_TABLE_NODE     Node;
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Node = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE_NODE));
+
+    status = STATUS_NO_MEMORY;
+    if (Node == NULL)
+        goto fail1;
+
+    Node->Key = Key;
+    Node->Value = Value;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, TRUE, &Irql);
+    InsertTailList(&Bucket->List, &Node->ListEntry);
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableRemove(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key
+    )
+{
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    PLIST_ENTRY                 ListEntry;
+    PXENBUS_HASH_TABLE_NODE     Node;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, TRUE, &Irql);
+
+    ListEntry = Bucket->List.Flink;
+    while (ListEntry != &Bucket->List) {
+        Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry);
+
+        if (Node->Key == Key)
+            goto found;
+    }
+
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    RemoveEntryList(ListEntry);
+    __HashTableFree(Node);
+
+    HashTableBucketUnlock(Bucket, TRUE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableLookup(
+    IN  PXENBUS_HASH_TABLE      Table,
+    IN  ULONG_PTR               Key,
+    OUT PULONG_PTR              Value
+    )
+{
+    PXENBUS_HASH_TABLE_BUCKET   Bucket;
+    PLIST_ENTRY                 ListEntry;
+    PXENBUS_HASH_TABLE_NODE     Node;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    Bucket = &Table->Bucket[HashTableHash(Key)];
+    
+    HashTableBucketLock(Bucket, FALSE, &Irql);
+
+    ListEntry = Bucket->List.Flink;
+    while (ListEntry != &Bucket->List) {
+        Node = CONTAINING_RECORD(ListEntry, XENBUS_HASH_TABLE_NODE, ListEntry);
+
+        if (Node->Key == Key)
+            goto found;
+    }
+
+    HashTableBucketUnlock(Bucket, FALSE, Irql);
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    *Value = Node->Value;
+
+    HashTableBucketUnlock(Bucket, FALSE, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+HashTableCreate(
+    OUT PXENBUS_HASH_TABLE  *Table
+    )
+{
+    ULONG                   Index;
+    NTSTATUS                status;
+
+    *Table = __HashTableAllocate(sizeof (XENBUS_HASH_TABLE));
+
+    status = STATUS_NO_MEMORY;
+    if (*Table == NULL)
+        goto fail1;
+
+    for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) {
+        PXENBUS_HASH_TABLE_BUCKET   Bucket = &(*Table)->Bucket[Index];
+
+        InitializeListHead(&Bucket->List);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+HashTableDestroy(
+    IN  PXENBUS_HASH_TABLE  Table
+    )
+{
+    ULONG                   Index;
+
+    for (Index = 0; Index < XENBUS_HASH_TABLE_NR_BUCKETS; Index++) {
+        PXENBUS_HASH_TABLE_BUCKET   Bucket = &Table->Bucket[Index];
+
+        ASSERT(IsListEmpty(&Bucket->List));
+        RtlZeroMemory(&Bucket->List, sizeof (LIST_ENTRY));
+    }
+
+    ASSERT(IsZeroMemory(Table, sizeof (XENBUS_HASH_TABLE)));
+    __HashTableFree(Table);
+}
+
diff --git a/src/xenbus/hash_table.h b/src/xenbus/hash_table.h
new file mode 100644
index 0000000..ce0c906
--- /dev/null
+++ b/src/xenbus/hash_table.h
@@ -0,0 +1,70 @@
+/* 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 _XENBUS_HASH_TABLE_H
+#define _XENBUS_HASH_TABLE_H
+
+#include <ntddk.h>
+
+typedef struct _XENBUS_HASH_TABLE XENBUS_HASH_TABLE, *PXENBUS_HASH_TABLE; 
+
+extern NTSTATUS
+HashTableAdd(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key,
+    IN  ULONG_PTR           Value
+    );
+
+extern NTSTATUS
+HashTableRemove(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key
+    );
+
+extern NTSTATUS
+HashTableLookup(
+    IN  PXENBUS_HASH_TABLE  Table,
+    IN  ULONG_PTR           Key,
+    OUT PULONG_PTR          Value
+    );
+
+extern NTSTATUS
+HashTableCreate(
+    OUT PXENBUS_HASH_TABLE  *Table
+    );
+
+extern VOID
+HashTableDestroy(
+    IN  PXENBUS_HASH_TABLE  Table
+    );
+
+#endif  // _XENBUS_HASH_TABLE_H
+
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 0afc218..67be20c 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -38,6 +38,9 @@
 #include "dbg_print.h"
 #include "assert.h"
 
+#define XENBUS_SHARED_INFO_EVTCHN_PER_SELECTOR     (sizeof (ULONG_PTR) * 8)
+#define XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT   (RTL_FIELD_SIZE(shared_info_t, evtchn_pending) / sizeof (ULONG_PTR))
+
 struct _XENBUS_SHARED_INFO_CONTEXT {
     PXENBUS_FDO                 Fdo;
     KSPIN_LOCK                  Lock;
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index c30774e..a648bce 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -99,6 +99,7 @@
 		<ClCompile Include="..\..\src\xenbus\range_set.c" />
 		<ClCompile Include="..\..\src\xenbus\balloon.c" />
 		<ClCompile Include="..\..\src\xenbus\cache.c" />
+		<ClCompile Include="..\..\src\xenbus\hash_table.c" />
 	</ItemGroup>
 	<ItemGroup>
 		<ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 588b0c5..2c34ed1 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -139,6 +139,7 @@
     <ClCompile Include="..\..\src\xenbus\range_set.c" />
     <ClCompile Include="..\..\src\xenbus\balloon.c" />
     <ClCompile Include="..\..\src\xenbus\cache.c" />
+    <ClCompile Include="..\..\src\xenbus\hash_table.c" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" />
-- 
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 Nov 06 14:24:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24: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 1XmNzV-0001ai-W5; Thu, 06 Nov 2014 14:24:49 +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 1XmNzU-0001Yx-50
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:48 +0000
Received: from [85.158.137.68] by server-10.bemta-3.messagelabs.com id
	18/AC-24859-FA48B545; Thu, 06 Nov 2014 14:24:47 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-31.messagelabs.com!1415283882!10878952!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9080 invoked from network); 6 Nov 2014 14:24:46 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-7.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:46 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771863"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-Ap;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:19 +0000
Message-ID: <1415283861-26028-9-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 07/10] Separate event channel ABI from core
	evtchn interface code
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 event channel ABI now known as two-level is implemented using the
domain shared info. Use of the SHARED_INFO interface is therefore baked
into the EVTCHN interface.
Xen has recently acquired a new event channel ABI called fifo, which
improves on both scalability and performance as compared to two-level.
Hence this patch separates the ABI code from the core EVTCHN interface
code so that a subsequent patch can add support for the fifo ABI on
capable versions of Xen.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn.c          | 180 +++++++++++++++++++++-----
 src/xenbus/evtchn_2l.c       | 293 +++++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_2l.h       |  59 +++++++++
 src/xenbus/evtchn_abi.h      | 109 ++++++++++++++++
 vs2012/xenbus/xenbus.vcxproj |   1 +
 vs2013/xenbus/xenbus.vcxproj |   1 +
 6 files changed, 609 insertions(+), 34 deletions(-)
 create mode 100644 src/xenbus/evtchn_2l.c
 create mode 100644 src/xenbus/evtchn_2l.h
 create mode 100644 src/xenbus/evtchn_abi.h

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 5a0822d..f13667e 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -35,6 +35,7 @@
 #include <util.h>
 
 #include "evtchn.h"
+#include "evtchn_2l.h"
 #include "fdo.h"
 #include "hash_table.h"
 #include "dbg_print.h"
@@ -89,9 +90,12 @@ struct _XENBUS_EVTCHN_CONTEXT {
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
+    PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
     XENBUS_DEBUG_INTERFACE          DebugInterface;
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
+    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
+    XENBUS_EVTCHN_ABI               EvtchnAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
@@ -345,11 +349,17 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    status = XENBUS_EVTCHN_ABI(PortEnable,
+                               &Context->EvtchnAbi,
+                               LocalPort);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = HashTableAdd(Context->Table,
                           LocalPort,
                           (ULONG_PTR)Channel);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     Channel->Active = TRUE;
 
@@ -368,6 +378,13 @@ EvtchnOpen(
 
     return Channel;
 
+fail4:
+    Error("fail4\n");
+
+    XENBUS_EVTCHN_ABI(PortDisable,
+                      &Context->EvtchnAbi,
+                      LocalPort);
+
 fail3:
     Error("fail3\n");
 
@@ -415,14 +432,14 @@ EvtchnUnmask(
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
     if (Channel->Active) {
-        Pending = XENBUS_SHARED_INFO(EvtchnUnmask,
-                                     &Context->SharedInfoInterface,
-                                     Channel->LocalPort);
+        Pending = XENBUS_EVTCHN_ABI(PortUnmask,
+                                    &Context->EvtchnAbi,
+                                    Channel->LocalPort);
 
         if (Pending && Channel->Mask)
-            XENBUS_SHARED_INFO(EvtchnMask,
-                               &Context->SharedInfoInterface,
-                               Channel->LocalPort);
+            XENBUS_EVTCHN_ABI(PortMask,
+                              &Context->EvtchnAbi,
+                              Channel->LocalPort);
     }
 
     if (!InCallback)
@@ -538,9 +555,9 @@ EvtchnClose(
 
         Channel->Active = FALSE;
 
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
         if (Channel->Type != XENBUS_EVTCHN_TYPE_FIXED)
             (VOID) EventChannelClose(LocalPort);
@@ -598,22 +615,22 @@ EvtchnPollCallback(
     if (!NT_SUCCESS(status)) {
         Warning("[%d]: INVALID PORT\n", LocalPort);
 
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
         DoneSomething = FALSE;
         goto done;
     }
 
     if (Channel->Mask)
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
-    XENBUS_SHARED_INFO(EvtchnAck,
-                       &Context->SharedInfoInterface,
-                       LocalPort);
+    XENBUS_EVTCHN_ABI(PortAck,
+                      &Context->EvtchnAbi,
+                      LocalPort);
 
     DoneSomething = EvtchnCallback(Context, Channel);
 
@@ -633,15 +650,47 @@ EvtchnInterrupt(
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
                               0))
-        DoneSomething |= XENBUS_SHARED_INFO(EvtchnPoll,
-                                            &Context->SharedInfoInterface,
-                                            0,
-                                            EvtchnPollCallback,
-                                            Context);
+        DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
+                                           &Context->EvtchnAbi,
+                                           0,
+                                           EvtchnPollCallback,
+                                           Context);
 
     return DoneSomething;
 }
 
+static NTSTATUS
+EvtchnAbiAcquire(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    )
+{
+    NTSTATUS                    status;
+
+    EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
+                         &Context->EvtchnAbi);
+
+    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static VOID
+EvtchnAbiRelease(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    )
+{
+    XENBUS_EVTCHN_ABI(Release, &Context->EvtchnAbi);
+
+    RtlZeroMemory(&Context->EvtchnAbi, sizeof (XENBUS_EVTCHN_ABI));
+}
+
 static VOID
 EvtchnSuspendCallbackEarly(
     IN  PVOID               Argument
@@ -667,6 +716,20 @@ EvtchnSuspendCallbackEarly(
             ASSERT(NT_SUCCESS(status));
         }
     }
+}
+
+static VOID
+EvtchnSuspendCallbackLate(
+    IN  PVOID               Argument
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    NTSTATUS                status;
+
+    EvtchnAbiRelease(Context);
+
+    status = EvtchnAbiAcquire(Context);
+    ASSERT(NT_SUCCESS(status));
 
     if (Context->Enabled)
         EvtchnInterruptEnable(Context);
@@ -772,6 +835,8 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
+    Context->Vector = FdoGetInterruptVector(Fdo);
+
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -785,10 +850,19 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = XENBUS_DEBUG(Acquire, &Context->DebugInterface);
+    status = XENBUS_SUSPEND(Register,
+                            &Context->SuspendInterface,
+                            SUSPEND_CALLBACK_LATE,
+                            EvtchnSuspendCallbackLate,
+                            Context,
+                            &Context->SuspendCallbackLate);
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_DEBUG(Acquire, &Context->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = XENBUS_DEBUG(Register,
                           &Context->DebugInterface,
                           __MODULE__ "|EVTCHN",
@@ -796,13 +870,15 @@ EvtchnAcquire(
                           Context,
                           &Context->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     status = XENBUS_SHARED_INFO(Acquire, &Context->SharedInfoInterface);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
+    status = EvtchnAbiAcquire(Context);
+    if (!NT_SUCCESS(status))
+        goto fail7;
 
     Trace("<====\n");
 
@@ -811,18 +887,31 @@ done:
 
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+fail6:
+    Error("fail6\n");
 
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
     Context->DebugCallback = NULL;
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_DEBUG(Release, &Context->DebugInterface);
+
 fail4:
     Error("fail4\n");
 
-    XENBUS_DEBUG(Release, &Context->DebugInterface);
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
 
 fail3:
     Error("fail3\n");
@@ -837,6 +926,8 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
+    Context->Vector = 0;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -865,7 +956,7 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    Context->Vector = 0;
+    EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
 
@@ -878,11 +969,18 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Deregister,
                    &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
                    Context->SuspendCallbackEarly);
     Context->SuspendCallbackEarly = NULL;
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
+    Context->Vector = 0;
+
     Trace("<====\n");
 
 done:
@@ -921,6 +1019,11 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = EvtchnTwoLevelInitialize(Fdo,
+                                      &(*Context)->EvtchnTwoLevelContext);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -951,11 +1054,17 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
+    HashTableDestroy((*Context)->Table);
+    (*Context)->Table = NULL;
+
 fail2:
     Error("fail2\n");
 
-    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
-    __EvtchnFree(Context);
+    ASSERT(IsZeroMemory(*Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
+    __EvtchnFree(*Context);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -1022,6 +1131,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
+    Context->EvtchnTwoLevelContext = NULL;
+
     HashTableDestroy(Context->Table);
     Context->Table = NULL;
 
diff --git a/src/xenbus/evtchn_2l.c b/src/xenbus/evtchn_2l.c
new file mode 100644
index 0000000..0f839ee
--- /dev/null
+++ b/src/xenbus/evtchn_2l.c
@@ -0,0 +1,293 @@
+/* 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 "evtchn_2l.h"
+#include "shared_info.h"
+#include "fdo.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENBUS_EVTCHN_TWO_LEVEL_CONTEXT {
+    PXENBUS_FDO                     Fdo;
+    KSPIN_LOCK                      Lock;
+    LONG                            References;
+    XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
+} XENBUS_EVTCHN_TWO_LEVEL_CONTEXT, *PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT;
+
+#define XENBUS_EVTCHN_TWO_LEVEL_TAG  'L2'
+
+static FORCEINLINE PVOID
+__EvtchnTwoLevelAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_EVTCHN_TWO_LEVEL_TAG);
+}
+
+static FORCEINLINE VOID
+__EvtchnTwoLevelFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_TWO_LEVEL_TAG);
+}
+
+static BOOLEAN
+EvtchnTwoLevelPoll(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT         Event,
+    IN  PVOID                           Argument
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    return XENBUS_SHARED_INFO(EvtchnPoll,
+                              &Context->SharedInfoInterface,
+                              Cpu,
+                              Event,
+                              Argument);
+}
+
+static NTSTATUS
+EvtchnTwoLevelPortEnable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    UNREFERENCED_PARAMETER(_Context);
+    UNREFERENCED_PARAMETER(Port);
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+EvtchnTwoLevelPortDisable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnMask,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static VOID
+EvtchnTwoLevelPortAck(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnAck,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static VOID
+EvtchnTwoLevelPortMask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnMask,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static BOOLEAN
+EvtchnTwoLevelPortUnmask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    return XENBUS_SHARED_INFO(EvtchnUnmask,
+                              &Context->SharedInfoInterface,
+                              Port);
+}
+
+static NTSTATUS
+EvtchnTwoLevelAcquire(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+    KIRQL                               Irql;
+    NTSTATUS                            status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    status = XENBUS_SHARED_INFO(Acquire, &Context->SharedInfoInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+    --Context->References;
+    ASSERT3U(Context->References, ==, 0);
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+VOID
+EvtchnTwoLevelRelease(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+    KIRQL                               Irql;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static XENBUS_EVTCHN_ABI EvtchnAbiTwoLevel = {
+    NULL,
+    EvtchnTwoLevelAcquire,
+    EvtchnTwoLevelRelease,
+    EvtchnTwoLevelPoll,
+    EvtchnTwoLevelPortEnable,
+    EvtchnTwoLevelPortDisable,
+    EvtchnTwoLevelPortAck,
+    EvtchnTwoLevelPortMask,
+    EvtchnTwoLevelPortUnmask
+};
+
+NTSTATUS
+EvtchnTwoLevelInitialize(
+    IN  PXENBUS_FDO                     Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context;
+    NTSTATUS                            status;
+
+    Trace("====>\n");
+
+    Context = __EvtchnTwoLevelAllocate(sizeof (XENBUS_EVTCHN_TWO_LEVEL_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (Context == NULL)
+        goto fail1;
+
+    status = SharedInfoGetInterface(FdoGetSharedInfoContext(Fdo),
+                                    XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX,
+                                    (PINTERFACE)&Context->SharedInfoInterface,
+                                    sizeof (Context->SharedInfoInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT(Context->SharedInfoInterface.Interface.Context != NULL);
+
+    KeInitializeSpinLock(&Context->Lock);
+
+    Context->Fdo = Fdo;
+
+    *_Context = (PVOID)Context;
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+EvtchnTwoLevelGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    OUT PXENBUS_EVTCHN_ABI              Abi)
+{
+    *Abi = EvtchnAbiTwoLevel;
+
+    Abi->Context = (PVOID)_Context;
+}
+
+VOID
+EvtchnTwoLevelTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    Trace("====>\n");
+
+    Context->Fdo = NULL;
+
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    RtlZeroMemory(&Context->SharedInfoInterface,
+                  sizeof (XENBUS_SHARED_INFO_INTERFACE));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_TWO_LEVEL_CONTEXT)));
+    __EvtchnTwoLevelFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenbus/evtchn_2l.h b/src/xenbus/evtchn_2l.h
new file mode 100644
index 0000000..c69c555
--- /dev/null
+++ b/src/xenbus/evtchn_2l.h
@@ -0,0 +1,59 @@
+/* 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 _XENBUS_EVTCHN_2L_H
+#define _XENBUS_EVTCHN_2L_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+#include "evtchn_abi.h"
+#include "fdo.h"
+
+extern NTSTATUS
+EvtchnTwoLevelInitialize(
+    IN  PXENBUS_FDO                 Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
+    );
+
+extern VOID
+EvtchnTwoLevelGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    OUT PXENBUS_EVTCHN_ABI          Abi
+    );
+
+extern VOID
+EvtchnTwoLevelTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+#endif  // _XENBUS_EVTCHN_H
+
diff --git a/src/xenbus/evtchn_abi.h b/src/xenbus/evtchn_abi.h
new file mode 100644
index 0000000..237ce7d
--- /dev/null
+++ b/src/xenbus/evtchn_abi.h
@@ -0,0 +1,109 @@
+/* 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 WARRAN4TIES, 
+ * 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 _XENBUS_EVTCHN_ABI_H
+#define _XENBUS_EVTCHN_ABI_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+typedef PVOID *PXENBUS_EVTCHN_ABI_CONTEXT;
+
+typedef NTSTATUS
+(*XENBUS_EVTCHN_ABI_ACQUIRE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_RELEASE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_EVENT)(
+    IN  PVOID   Argument,
+    IN  ULONG   Port
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_POLL)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    );
+
+typedef NTSTATUS
+(*XENBUS_EVTCHN_ABI_PORT_ENABLE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_DISABLE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_ACK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_MASK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_PORT_UNMASK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef struct _XENBUS_EVTCHN_ABI {
+    PXENBUS_EVTCHN_ABI_CONTEXT      Context;
+    XENBUS_EVTCHN_ABI_ACQUIRE       EvtchnAbiAcquire;
+    XENBUS_EVTCHN_ABI_RELEASE       EvtchnAbiRelease;
+    XENBUS_EVTCHN_ABI_POLL          EvtchnAbiPoll;
+    XENBUS_EVTCHN_ABI_PORT_ENABLE   EvtchnAbiPortEnable;
+    XENBUS_EVTCHN_ABI_PORT_DISABLE  EvtchnAbiPortDisable;
+    XENBUS_EVTCHN_ABI_PORT_ACK      EvtchnAbiPortAck;
+    XENBUS_EVTCHN_ABI_PORT_MASK     EvtchnAbiPortMask;
+    XENBUS_EVTCHN_ABI_PORT_UNMASK   EvtchnAbiPortUnmask;
+} XENBUS_EVTCHN_ABI, *PXENBUS_EVTCHN_ABI;
+
+#define XENBUS_EVTCHN_ABI(_Method, _Abi, ...)   \
+    (_Abi)->EvtchnAbi ## _Method((_Abi)->Context, __VA_ARGS__)
+
+#endif  // _XENBUS_EVTCHN_ABI_H
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index a648bce..6cd12d1 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -88,6 +88,7 @@
 		<ClCompile Include="..\..\src\xenbus\debug.c" />
 		<ClCompile Include="..\..\src\xenbus\driver.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
+		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
 		<ClCompile Include="..\..\src\xenbus\fdo.c" />
 		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
 		<ClCompile Include="..\..\src\xenbus\pdo.c" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 2c34ed1..0f37f68 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -128,6 +128,7 @@
     <ClCompile Include="..\..\src\xenbus\debug.c" />
     <ClCompile Include="..\..\src\xenbus\driver.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn.c" />
+    <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
-- 
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 Nov 06 14:24:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:24: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 1XmNzV-0001ai-W5; Thu, 06 Nov 2014 14:24:49 +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 1XmNzU-0001Yx-50
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:24:48 +0000
Received: from [85.158.137.68] by server-10.bemta-3.messagelabs.com id
	18/AC-24859-FA48B545; Thu, 06 Nov 2014 14:24:47 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-31.messagelabs.com!1415283882!10878952!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9080 invoked from network); 6 Nov 2014 14:24:46 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-7.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:24:46 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188771863"
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.181.6;
	Thu, 6 Nov 2014 09:24:38 -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 1XmNzK-0008E8-Ap;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:19 +0000
Message-ID: <1415283861-26028-9-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-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 07/10] Separate event channel ABI from core
	evtchn interface code
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 event channel ABI now known as two-level is implemented using the
domain shared info. Use of the SHARED_INFO interface is therefore baked
into the EVTCHN interface.
Xen has recently acquired a new event channel ABI called fifo, which
improves on both scalability and performance as compared to two-level.
Hence this patch separates the ABI code from the core EVTCHN interface
code so that a subsequent patch can add support for the fifo ABI on
capable versions of Xen.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn.c          | 180 +++++++++++++++++++++-----
 src/xenbus/evtchn_2l.c       | 293 +++++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_2l.h       |  59 +++++++++
 src/xenbus/evtchn_abi.h      | 109 ++++++++++++++++
 vs2012/xenbus/xenbus.vcxproj |   1 +
 vs2013/xenbus/xenbus.vcxproj |   1 +
 6 files changed, 609 insertions(+), 34 deletions(-)
 create mode 100644 src/xenbus/evtchn_2l.c
 create mode 100644 src/xenbus/evtchn_2l.h
 create mode 100644 src/xenbus/evtchn_abi.h

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 5a0822d..f13667e 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -35,6 +35,7 @@
 #include <util.h>
 
 #include "evtchn.h"
+#include "evtchn_2l.h"
 #include "fdo.h"
 #include "hash_table.h"
 #include "dbg_print.h"
@@ -89,9 +90,12 @@ struct _XENBUS_EVTCHN_CONTEXT {
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
+    PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
     XENBUS_DEBUG_INTERFACE          DebugInterface;
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
+    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
+    XENBUS_EVTCHN_ABI               EvtchnAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
@@ -345,11 +349,17 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    status = XENBUS_EVTCHN_ABI(PortEnable,
+                               &Context->EvtchnAbi,
+                               LocalPort);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = HashTableAdd(Context->Table,
                           LocalPort,
                           (ULONG_PTR)Channel);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
 
     Channel->Active = TRUE;
 
@@ -368,6 +378,13 @@ EvtchnOpen(
 
     return Channel;
 
+fail4:
+    Error("fail4\n");
+
+    XENBUS_EVTCHN_ABI(PortDisable,
+                      &Context->EvtchnAbi,
+                      LocalPort);
+
 fail3:
     Error("fail3\n");
 
@@ -415,14 +432,14 @@ EvtchnUnmask(
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
     if (Channel->Active) {
-        Pending = XENBUS_SHARED_INFO(EvtchnUnmask,
-                                     &Context->SharedInfoInterface,
-                                     Channel->LocalPort);
+        Pending = XENBUS_EVTCHN_ABI(PortUnmask,
+                                    &Context->EvtchnAbi,
+                                    Channel->LocalPort);
 
         if (Pending && Channel->Mask)
-            XENBUS_SHARED_INFO(EvtchnMask,
-                               &Context->SharedInfoInterface,
-                               Channel->LocalPort);
+            XENBUS_EVTCHN_ABI(PortMask,
+                              &Context->EvtchnAbi,
+                              Channel->LocalPort);
     }
 
     if (!InCallback)
@@ -538,9 +555,9 @@ EvtchnClose(
 
         Channel->Active = FALSE;
 
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
         if (Channel->Type != XENBUS_EVTCHN_TYPE_FIXED)
             (VOID) EventChannelClose(LocalPort);
@@ -598,22 +615,22 @@ EvtchnPollCallback(
     if (!NT_SUCCESS(status)) {
         Warning("[%d]: INVALID PORT\n", LocalPort);
 
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
         DoneSomething = FALSE;
         goto done;
     }
 
     if (Channel->Mask)
-        XENBUS_SHARED_INFO(EvtchnMask,
-                           &Context->SharedInfoInterface,
-                           LocalPort);
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          LocalPort);
 
-    XENBUS_SHARED_INFO(EvtchnAck,
-                       &Context->SharedInfoInterface,
-                       LocalPort);
+    XENBUS_EVTCHN_ABI(PortAck,
+                      &Context->EvtchnAbi,
+                      LocalPort);
 
     DoneSomething = EvtchnCallback(Context, Channel);
 
@@ -633,15 +650,47 @@ EvtchnInterrupt(
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
                               0))
-        DoneSomething |= XENBUS_SHARED_INFO(EvtchnPoll,
-                                            &Context->SharedInfoInterface,
-                                            0,
-                                            EvtchnPollCallback,
-                                            Context);
+        DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
+                                           &Context->EvtchnAbi,
+                                           0,
+                                           EvtchnPollCallback,
+                                           Context);
 
     return DoneSomething;
 }
 
+static NTSTATUS
+EvtchnAbiAcquire(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    )
+{
+    NTSTATUS                    status;
+
+    EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
+                         &Context->EvtchnAbi);
+
+    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static VOID
+EvtchnAbiRelease(
+    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    )
+{
+    XENBUS_EVTCHN_ABI(Release, &Context->EvtchnAbi);
+
+    RtlZeroMemory(&Context->EvtchnAbi, sizeof (XENBUS_EVTCHN_ABI));
+}
+
 static VOID
 EvtchnSuspendCallbackEarly(
     IN  PVOID               Argument
@@ -667,6 +716,20 @@ EvtchnSuspendCallbackEarly(
             ASSERT(NT_SUCCESS(status));
         }
     }
+}
+
+static VOID
+EvtchnSuspendCallbackLate(
+    IN  PVOID               Argument
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    NTSTATUS                status;
+
+    EvtchnAbiRelease(Context);
+
+    status = EvtchnAbiAcquire(Context);
+    ASSERT(NT_SUCCESS(status));
 
     if (Context->Enabled)
         EvtchnInterruptEnable(Context);
@@ -772,6 +835,8 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
+    Context->Vector = FdoGetInterruptVector(Fdo);
+
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -785,10 +850,19 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = XENBUS_DEBUG(Acquire, &Context->DebugInterface);
+    status = XENBUS_SUSPEND(Register,
+                            &Context->SuspendInterface,
+                            SUSPEND_CALLBACK_LATE,
+                            EvtchnSuspendCallbackLate,
+                            Context,
+                            &Context->SuspendCallbackLate);
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_DEBUG(Acquire, &Context->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = XENBUS_DEBUG(Register,
                           &Context->DebugInterface,
                           __MODULE__ "|EVTCHN",
@@ -796,13 +870,15 @@ EvtchnAcquire(
                           Context,
                           &Context->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     status = XENBUS_SHARED_INFO(Acquire, &Context->SharedInfoInterface);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
+    status = EvtchnAbiAcquire(Context);
+    if (!NT_SUCCESS(status))
+        goto fail7;
 
     Trace("<====\n");
 
@@ -811,18 +887,31 @@ done:
 
     return STATUS_SUCCESS;
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+fail6:
+    Error("fail6\n");
 
     XENBUS_DEBUG(Deregister,
                  &Context->DebugInterface,
                  Context->DebugCallback);
     Context->DebugCallback = NULL;
 
+fail5:
+    Error("fail5\n");
+
+    XENBUS_DEBUG(Release, &Context->DebugInterface);
+
 fail4:
     Error("fail4\n");
 
-    XENBUS_DEBUG(Release, &Context->DebugInterface);
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
 
 fail3:
     Error("fail3\n");
@@ -837,6 +926,8 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
+    Context->Vector = 0;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -865,7 +956,7 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    Context->Vector = 0;
+    EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
 
@@ -878,11 +969,18 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Deregister,
                    &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
                    Context->SuspendCallbackEarly);
     Context->SuspendCallbackEarly = NULL;
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
+    Context->Vector = 0;
+
     Trace("<====\n");
 
 done:
@@ -921,6 +1019,11 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = EvtchnTwoLevelInitialize(Fdo,
+                                      &(*Context)->EvtchnTwoLevelContext);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -951,11 +1054,17 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
+    HashTableDestroy((*Context)->Table);
+    (*Context)->Table = NULL;
+
 fail2:
     Error("fail2\n");
 
-    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
-    __EvtchnFree(Context);
+    ASSERT(IsZeroMemory(*Context, sizeof (XENBUS_EVTCHN_CONTEXT)));
+    __EvtchnFree(*Context);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -1022,6 +1131,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
+    Context->EvtchnTwoLevelContext = NULL;
+
     HashTableDestroy(Context->Table);
     Context->Table = NULL;
 
diff --git a/src/xenbus/evtchn_2l.c b/src/xenbus/evtchn_2l.c
new file mode 100644
index 0000000..0f839ee
--- /dev/null
+++ b/src/xenbus/evtchn_2l.c
@@ -0,0 +1,293 @@
+/* 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 "evtchn_2l.h"
+#include "shared_info.h"
+#include "fdo.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+typedef struct _XENBUS_EVTCHN_TWO_LEVEL_CONTEXT {
+    PXENBUS_FDO                     Fdo;
+    KSPIN_LOCK                      Lock;
+    LONG                            References;
+    XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
+} XENBUS_EVTCHN_TWO_LEVEL_CONTEXT, *PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT;
+
+#define XENBUS_EVTCHN_TWO_LEVEL_TAG  'L2'
+
+static FORCEINLINE PVOID
+__EvtchnTwoLevelAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_EVTCHN_TWO_LEVEL_TAG);
+}
+
+static FORCEINLINE VOID
+__EvtchnTwoLevelFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_TWO_LEVEL_TAG);
+}
+
+static BOOLEAN
+EvtchnTwoLevelPoll(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT         Event,
+    IN  PVOID                           Argument
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    return XENBUS_SHARED_INFO(EvtchnPoll,
+                              &Context->SharedInfoInterface,
+                              Cpu,
+                              Event,
+                              Argument);
+}
+
+static NTSTATUS
+EvtchnTwoLevelPortEnable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    UNREFERENCED_PARAMETER(_Context);
+    UNREFERENCED_PARAMETER(Port);
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+EvtchnTwoLevelPortDisable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnMask,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static VOID
+EvtchnTwoLevelPortAck(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnAck,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static VOID
+EvtchnTwoLevelPortMask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    XENBUS_SHARED_INFO(EvtchnMask,
+                       &Context->SharedInfoInterface,
+                       Port);
+}
+
+static BOOLEAN
+EvtchnTwoLevelPortUnmask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    IN  ULONG                           Port
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    return XENBUS_SHARED_INFO(EvtchnUnmask,
+                              &Context->SharedInfoInterface,
+                              Port);
+}
+
+static NTSTATUS
+EvtchnTwoLevelAcquire(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+    KIRQL                               Irql;
+    NTSTATUS                            status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    status = XENBUS_SHARED_INFO(Acquire, &Context->SharedInfoInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+    --Context->References;
+    ASSERT3U(Context->References, ==, 0);
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+VOID
+EvtchnTwoLevelRelease(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+    KIRQL                               Irql;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static XENBUS_EVTCHN_ABI EvtchnAbiTwoLevel = {
+    NULL,
+    EvtchnTwoLevelAcquire,
+    EvtchnTwoLevelRelease,
+    EvtchnTwoLevelPoll,
+    EvtchnTwoLevelPortEnable,
+    EvtchnTwoLevelPortDisable,
+    EvtchnTwoLevelPortAck,
+    EvtchnTwoLevelPortMask,
+    EvtchnTwoLevelPortUnmask
+};
+
+NTSTATUS
+EvtchnTwoLevelInitialize(
+    IN  PXENBUS_FDO                     Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context;
+    NTSTATUS                            status;
+
+    Trace("====>\n");
+
+    Context = __EvtchnTwoLevelAllocate(sizeof (XENBUS_EVTCHN_TWO_LEVEL_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (Context == NULL)
+        goto fail1;
+
+    status = SharedInfoGetInterface(FdoGetSharedInfoContext(Fdo),
+                                    XENBUS_SHARED_INFO_INTERFACE_VERSION_MAX,
+                                    (PINTERFACE)&Context->SharedInfoInterface,
+                                    sizeof (Context->SharedInfoInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT(Context->SharedInfoInterface.Interface.Context != NULL);
+
+    KeInitializeSpinLock(&Context->Lock);
+
+    Context->Fdo = Fdo;
+
+    *_Context = (PVOID)Context;
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+EvtchnTwoLevelGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    OUT PXENBUS_EVTCHN_ABI              Abi)
+{
+    *Abi = EvtchnAbiTwoLevel;
+
+    Abi->Context = (PVOID)_Context;
+}
+
+VOID
+EvtchnTwoLevelTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_TWO_LEVEL_CONTEXT    Context = (PVOID)_Context;
+
+    Trace("====>\n");
+
+    Context->Fdo = NULL;
+
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    RtlZeroMemory(&Context->SharedInfoInterface,
+                  sizeof (XENBUS_SHARED_INFO_INTERFACE));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_TWO_LEVEL_CONTEXT)));
+    __EvtchnTwoLevelFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenbus/evtchn_2l.h b/src/xenbus/evtchn_2l.h
new file mode 100644
index 0000000..c69c555
--- /dev/null
+++ b/src/xenbus/evtchn_2l.h
@@ -0,0 +1,59 @@
+/* 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 _XENBUS_EVTCHN_2L_H
+#define _XENBUS_EVTCHN_2L_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+#include "evtchn_abi.h"
+#include "fdo.h"
+
+extern NTSTATUS
+EvtchnTwoLevelInitialize(
+    IN  PXENBUS_FDO                 Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
+    );
+
+extern VOID
+EvtchnTwoLevelGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    OUT PXENBUS_EVTCHN_ABI          Abi
+    );
+
+extern VOID
+EvtchnTwoLevelTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+#endif  // _XENBUS_EVTCHN_H
+
diff --git a/src/xenbus/evtchn_abi.h b/src/xenbus/evtchn_abi.h
new file mode 100644
index 0000000..237ce7d
--- /dev/null
+++ b/src/xenbus/evtchn_abi.h
@@ -0,0 +1,109 @@
+/* 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 WARRAN4TIES, 
+ * 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 _XENBUS_EVTCHN_ABI_H
+#define _XENBUS_EVTCHN_ABI_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+typedef PVOID *PXENBUS_EVTCHN_ABI_CONTEXT;
+
+typedef NTSTATUS
+(*XENBUS_EVTCHN_ABI_ACQUIRE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_RELEASE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_EVENT)(
+    IN  PVOID   Argument,
+    IN  ULONG   Port
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_POLL)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    );
+
+typedef NTSTATUS
+(*XENBUS_EVTCHN_ABI_PORT_ENABLE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_DISABLE)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_ACK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef VOID
+(*XENBUS_EVTCHN_ABI_PORT_MASK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef BOOLEAN
+(*XENBUS_EVTCHN_ABI_PORT_UNMASK)(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    IN  ULONG                       Port
+    );
+
+typedef struct _XENBUS_EVTCHN_ABI {
+    PXENBUS_EVTCHN_ABI_CONTEXT      Context;
+    XENBUS_EVTCHN_ABI_ACQUIRE       EvtchnAbiAcquire;
+    XENBUS_EVTCHN_ABI_RELEASE       EvtchnAbiRelease;
+    XENBUS_EVTCHN_ABI_POLL          EvtchnAbiPoll;
+    XENBUS_EVTCHN_ABI_PORT_ENABLE   EvtchnAbiPortEnable;
+    XENBUS_EVTCHN_ABI_PORT_DISABLE  EvtchnAbiPortDisable;
+    XENBUS_EVTCHN_ABI_PORT_ACK      EvtchnAbiPortAck;
+    XENBUS_EVTCHN_ABI_PORT_MASK     EvtchnAbiPortMask;
+    XENBUS_EVTCHN_ABI_PORT_UNMASK   EvtchnAbiPortUnmask;
+} XENBUS_EVTCHN_ABI, *PXENBUS_EVTCHN_ABI;
+
+#define XENBUS_EVTCHN_ABI(_Method, _Abi, ...)   \
+    (_Abi)->EvtchnAbi ## _Method((_Abi)->Context, __VA_ARGS__)
+
+#endif  // _XENBUS_EVTCHN_ABI_H
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index a648bce..6cd12d1 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -88,6 +88,7 @@
 		<ClCompile Include="..\..\src\xenbus\debug.c" />
 		<ClCompile Include="..\..\src\xenbus\driver.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
+		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
 		<ClCompile Include="..\..\src\xenbus\fdo.c" />
 		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
 		<ClCompile Include="..\..\src\xenbus\pdo.c" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 2c34ed1..0f37f68 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -128,6 +128,7 @@
     <ClCompile Include="..\..\src\xenbus\debug.c" />
     <ClCompile Include="..\..\src\xenbus\driver.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn.c" />
+    <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
-- 
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 Nov 06 14:28:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:28:49 +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 1XmO3N-0001bU-Bc; Thu, 06 Nov 2014 14:28:49 +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 1XmO3L-0001bP-JR
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:28:47 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	6A/6B-09936-E958B545; Thu, 06 Nov 2014 14:28:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-21.messagelabs.com!1415284125!11962794!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	UPPERCASE_25_50,received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20139 invoked from network); 6 Nov 2014 14:28:45 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:28:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="26611186"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 05/10] Use a hash table for event channel lookup
Thread-Index: AQHP+c1yBv8AvrUifkWaC0Q0a3TOlZxTqBOA
Date: Thu, 6 Nov 2014 14:28:44 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111462A2@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-7-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415283861-26028-7-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 05/10] Use a hash table for event channel
	lookup
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

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBQYXVsIER1cnJhbnQgW21haWx0
bzpwYXVsLmR1cnJhbnRAY2l0cml4LmNvbV0NCj4gU2VudDogMDYgTm92ZW1iZXIgMjAxNCAxNDoy
NA0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQo+IENjOiBQYXVsIER1
cnJhbnQNCj4gU3ViamVjdDogW1BBVENIIDA1LzEwXSBVc2UgYSBoYXNoIHRhYmxlIGZvciBldmVu
dCBjaGFubmVsIGxvb2t1cA0KPiANCj4gUmF0aGVyIHRoYW4gdXNpbmcgYSBsYXJnZSBhcnJheSBm
b3IgbWFwcGluZyBwb3J0IHZhbHVlcyB0byBjaGFubmVsDQo+IHN0cnVjdHVyZXMsIHVzZSBhIGhh
c2ggdGFibGUuIFRoaXMgbWVhbnMgd2Ugbm8gbG9uZ2VyIG5lZWQgdG8gY29kZSBhDQo+IGhhcmQg
cG9ydCBudW1iZXIgbGltaXQgaW50byB0aGUgRVZUQ0hOIGltcGxlbWVudGF0aW9uLg0KPiANCj4g
QmVjYXVzZSB0aGUgaGFzaCB0YWJsZSBpbXBsZW1lbnRhdGlvbiBtYW5hZ2VzIGl0cyBvd24gbG9j
a2luZywgd2UgYWxzbyBubw0KPiBsb25nZXIgbmVlZCB0byBtYWtlIHN1Y2ggbGliZXJhbCB1c2Ug
b2YgdGhlIGludGVycnVwdCBsb2NrIGluIHRoZSBFVlRDSE4NCj4gaW1wbGVtZW50YXRpb24gYW5k
IGNhbiB1c2UgdGhlIHNwaW5sb2NrIGluc3RlYWQuDQo+IA0KPiBTaWduZWQtb2ZmLWJ5OiBQYXVs
IER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPg0KDQpUaGVyZSB3YXMgc29tZSBjaGFy
YWN0ZXIgZW5jb2Rpbmcgd2VpcmRuZXNzIHdoaWNoIHVuZm9ydHVuYXRlbHkgbWVhbnQgdHdvIHNs
aWdodGx5IGRpZmZlcmVudCB2YXJpYW50cyBvZiB0aGlzIHBhdGNoIHdlcmUgcG9zdGVkLiBUaGVy
ZSBpcyBubyBmdW5jdGlvbmFsIGRpZmZlcmVuY2UuDQoNCiAgUGF1bA0KDQo+IC0tLQ0KPiAgaW5j
bHVkZS9ldnRjaG5faW50ZXJmYWNlLmggICAgICB8ICAgNCArLQ0KPiAgaW5jbHVkZS9zaGFyZWRf
aW5mb19pbnRlcmZhY2UuaCB8ICAgMyAtDQo+ICBzcmMveGVuYnVzL2V2dGNobi5jICAgICAgICAg
ICAgIHwgIDg5ICsrKysrKy0tLS0NCj4gIHNyYy94ZW5idXMvaGFzaF90YWJsZS5jICAgICAgICAg
fCAzNjcNCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiAgc3Jj
L3hlbmJ1cy9oYXNoX3RhYmxlLmggICAgICAgICB8ICA3MCArKysrKysrKw0KPiAgc3JjL3hlbmJ1
cy9zaGFyZWRfaW5mby5jICAgICAgICB8ICAgMyArDQo+ICB2czIwMTIveGVuYnVzL3hlbmJ1cy52
Y3hwcm9qICAgIHwgICAxICsNCj4gIHZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHByb2ogICAgfCAg
IDMgKy0NCj4gIDggZmlsZXMgY2hhbmdlZCwgNTA0IGluc2VydGlvbnMoKyksIDM2IGRlbGV0aW9u
cygtKQ0KPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IHNyYy94ZW5idXMvaGFzaF90YWJsZS5jDQo+ICBj
cmVhdGUgbW9kZSAxMDA2NDQgc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmgNCj4gDQo+IGRpZmYgLS1n
aXQgYS9pbmNsdWRlL2V2dGNobl9pbnRlcmZhY2UuaCBiL2luY2x1ZGUvZXZ0Y2huX2ludGVyZmFj
ZS5oDQo+IGluZGV4IDk5MWQ2MTAuLjNhNDg5MTUgMTAwNjQ0DQo+IC0tLSBhL2luY2x1ZGUvZXZ0
Y2huX2ludGVyZmFjZS5oDQo+ICsrKyBiL2luY2x1ZGUvZXZ0Y2huX2ludGVyZmFjZS5oDQo+IEBA
IC0xMTcsMTQgKzExNywxNCBAQCB0eXBlZGVmIFBYRU5CVVNfRVZUQ0hOX0NIQU5ORUwNCj4gDQo+
ICAgICAgXHBhcmFtIEludGVyZmFjZSBUaGUgaW50ZXJmYWNlIGhlYWRlcg0KPiAgICAgIFxwYXJh
bSBDaGFubmVsIFRoZSBjaGFubmVsIGhhbmRsZQ0KPiAtICAgIFxwYXJhbSBMb2NrZWQgU2V0IHRv
IFRSVUUgaWYgdGhpcyBtZXRob2QgaXMgaW52b2tlZCBpbiBjb250ZXh0IG9mIHRoZQ0KPiBjaGFu
bmVsIGNhbGxiYWNrDQo+ICsgICAgXHBhcmFtIEluQ2FsbGJhY2sgU2V0IHRvIFRSVUUgaWYgdGhp
cyBtZXRob2QgaXMgaW52b2tlZCBpbiBjb250ZXh0IG9mIHRoZQ0KPiBjaGFubmVsIGNhbGxiYWNr
DQo+ICAgICAgXHJldHVybiBUUlVFIGlmIHRoZXJlIHdhcyBhbiBldmVudCBwZW5kaW5nIGF0IHRo
ZSBwb2ludCBvZiB1bm1hc2ssIEZBTFNFDQo+IG90aGVyd2lzZQ0KPiAgKi8NCj4gIHR5cGVkZWYg
Qk9PTEVBTg0KPiAgKCpYRU5CVVNfRVZUQ0hOX1VOTUFTSykoDQo+ICAgICAgSU4gIFBJTlRFUkZB
Q0UgICAgICAgICAgICAgIEludGVyZmFjZSwNCj4gICAgICBJTiAgUFhFTkJVU19FVlRDSE5fQ0hB
Tk5FTCAgQ2hhbm5lbCwNCj4gLSAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTG9ja2Vk
DQo+ICsgICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAgICAgIEluQ2FsbGJhY2sNCj4gICAgICAp
Ow0KPiANCj4gIC8qISBcdHlwZWRlZiBYRU5CVVNfRVZUQ0hOX1NFTkQNCj4gZGlmZiAtLWdpdCBh
L2luY2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmgNCj4gYi9pbmNsdWRlL3NoYXJlZF9pbmZv
X2ludGVyZmFjZS5oDQo+IGluZGV4IDBkMzZhYzguLjBlNWEwZDcgMTAwNjQ0DQo+IC0tLSBhL2lu
Y2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmgNCj4gKysrIGIvaW5jbHVkZS9zaGFyZWRfaW5m
b19pbnRlcmZhY2UuaA0KPiBAQCAtNDAsOSArNDAsNiBAQA0KPiANCj4gICNpZm5kZWYgX1dJTkRM
TA0KPiANCj4gLSNkZWZpbmUgWEVOQlVTX1NIQVJFRF9JTkZPX0VWVENITl9QRVJfU0VMRUNUT1Ig
ICAgIChzaXplb2YNCj4gKFVMT05HX1BUUikgKiA4KQ0KPiAtI2RlZmluZSBYRU5CVVNfU0hBUkVE
X0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UDQo+IChSVExfRklFTERfU0laRShzaGFyZWRfaW5m
b190LCBldnRjaG5fcGVuZGluZykgLyBzaXplb2YgKFVMT05HX1BUUikpDQo+IC0NCj4gIC8qISBc
dHlwZWRlZiBYRU5CVVNfU0hBUkVEX0lORk9fQUNRVUlSRQ0KPiAgICAgIFxicmllZiBBY3F1aXJl
IGEgcmVmZXJlbmNlIHRvIHRoZSBTSEFSRURfSU5GTyBpbnRlcmZhY2UNCj4gDQo+IGRpZmYgLS1n
aXQgYS9zcmMveGVuYnVzL2V2dGNobi5jIGIvc3JjL3hlbmJ1cy9ldnRjaG4uYw0KPiBpbmRleCAz
NWFkNDRhLi4zMzhhOTBmIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuYnVzL2V2dGNobi5jDQo+ICsr
KyBiL3NyYy94ZW5idXMvZXZ0Y2huLmMNCj4gQEAgLTM2LDYgKzM2LDcgQEANCj4gDQo+ICAjaW5j
bHVkZSAiZXZ0Y2huLmgiDQo+ICAjaW5jbHVkZSAiZmRvLmgiDQo+ICsjaW5jbHVkZSAiaGFzaF90
YWJsZS5oIg0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUgImFzc2VydC5o
Ig0KPiANCj4gQEAgLTk3LDcgKzk4LDcgQEAgc3RydWN0IF9YRU5CVVNfRVZUQ0hOX0NPTlRFWFQg
ew0KPiAgICAgIFhFTkJVU19ERUJVR19JTlRFUkZBQ0UgICAgICAgICAgRGVidWdJbnRlcmZhY2U7
DQo+ICAgICAgUFhFTkJVU19ERUJVR19DQUxMQkFDSyAgICAgICAgICBEZWJ1Z0NhbGxiYWNrOw0K
PiAgICAgIFhFTkJVU19TSEFSRURfSU5GT19JTlRFUkZBQ0UgICAgU2hhcmVkSW5mb0ludGVyZmFj
ZTsNCj4gLSAgICBQWEVOQlVTX0VWVENITl9DSEFOTkVMDQo+IENoYW5uZWxbWEVOQlVTX1NIQVJF
RF9JTkZPX0VWVENITl9TRUxFQ1RPUl9DT1VOVCAqDQo+IFhFTkJVU19TSEFSRURfSU5GT19FVlRD
SE5fUEVSX1NFTEVDVE9SXTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICAgICAgICAg
IFRhYmxlOw0KPiAgICAgIExJU1RfRU5UUlkgICAgICAgICAgICAgICAgICAgICAgTGlzdDsNCj4g
IH07DQo+IA0KPiBAQCAtMzUxLDE0ICszNTIsMTYgQEAgRXZ0Y2huT3BlbigNCj4gDQo+ICAgICAg
TG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0Ow0KPiANCj4gLSAgICBBU1NFUlQzVShMb2Nh
bFBvcnQsIDwsIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtDQo+
ID5DaGFubmVsWzBdKSk7DQo+IC0NCj4gLSAgICAoVk9JRCkgX19FdnRjaG5BY3F1aXJlSW50ZXJy
dXB0TG9jayhDb250ZXh0KTsNCj4gKyAgICBzdGF0dXMgPSBIYXNoVGFibGVBZGQoQ29udGV4dC0+
VGFibGUsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwNCj4gKyAgICAg
ICAgICAgICAgICAgICAgICAgICAgKFVMT05HX1BUUilDaGFubmVsKTsNCj4gKyAgICBpZiAoIU5U
X1NVQ0NFU1Moc3RhdHVzKSkNCj4gKyAgICAgICAgZ290byBmYWlsMzsNCj4gDQo+IC0gICAgQVNT
RVJUM1AoQ29udGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdLCA9PSwgTlVMTCk7DQo+IC0gICAgQ29u
dGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdID0gQ2hhbm5lbDsNCj4gICAgICBDaGFubmVsLT5BY3Rp
dmUgPSBUUlVFOw0KPiANCj4gKyAgICBLZUFjcXVpcmVTcGluTG9ja0F0RHBjTGV2ZWwoJkNvbnRl
eHQtPkxvY2spOw0KPiArDQo+ICAgICAgSW5zZXJ0VGFpbExpc3QoJkNvbnRleHQtPkxpc3QsICZD
aGFubmVsLT5MaXN0RW50cnkpOw0KPiANCj4gICAgICBpZiAoIUlzTGlzdEVtcHR5KCZDb250ZXh0
LT5MaXN0KSAmJiAhQ29udGV4dC0+RW5hYmxlZCkgew0KPiBAQCAtMzY2LDEyICszNjksMTggQEAg
RXZ0Y2huT3BlbigNCj4gICAgICAgICAgQ29udGV4dC0+RW5hYmxlZCA9IFRSVUU7DQo+ICAgICAg
fQ0KPiANCj4gLSAgICBfX0V2dGNoblJlbGVhc2VJbnRlcnJ1cHRMb2NrKENvbnRleHQsIERJU1BB
VENIX0xFVkVMKTsNCj4gKyAgICBLZVJlbGVhc2VTcGluTG9ja0Zyb21EcGNMZXZlbCgmQ29udGV4
dC0+TG9jayk7DQo+IA0KPiAgICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiANCj4gICAgICByZXR1
cm4gQ2hhbm5lbDsNCj4gDQo+ICtmYWlsMzoNCj4gKyAgICBFcnJvcigiZmFpbDNcbiIpOw0KPiAr
DQo+ICsgICAgQ2hhbm5lbC0+TG9jYWxQb3J0ID0gMDsNCj4gKyAgICBSdGxaZXJvTWVtb3J5KCZD
aGFubmVsLT5QYXJhbWV0ZXJzLCBzaXplb2YNCj4gKFhFTkJVU19FVlRDSE5fUEFSQU1FVEVSUykp
Ow0KPiArDQo+ICBmYWlsMjoNCj4gICAgICBFcnJvcigiZmFpbDJcbiIpOw0KPiANCj4gQEAgLTM5
OCw3ICs0MDcsNyBAQCBzdGF0aWMgQk9PTEVBTg0KPiAgRXZ0Y2huVW5tYXNrKA0KPiAgICAgIElO
ICBQSU5URVJGQUNFICAgICAgICAgICAgICBJbnRlcmZhY2UsDQo+ICAgICAgSU4gIFBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwgIENoYW5uZWwsDQo+IC0gICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAg
ICAgIExvY2tlZA0KPiArICAgIElOICBCT09MRUFOICAgICAgICAgICAgICAgICBJbkNhbGxiYWNr
DQo+ICAgICAgKQ0KPiAgew0KPiAgICAgIFBYRU5CVVNfRVZUQ0hOX0NPTlRFWFQgICAgICBDb250
ZXh0ID0gSW50ZXJmYWNlLT5Db250ZXh0Ow0KPiBAQCAtNDA3LDggKzQxNiwxMCBAQCBFdnRjaG5V
bm1hc2soDQo+IA0KPiAgICAgIEFTU0VSVDNVKENoYW5uZWwtPk1hZ2ljLCA9PSwgWEVOQlVTX0VW
VENITl9DSEFOTkVMX01BR0lDKTsNCj4gDQo+IC0gICAgaWYgKCFMb2NrZWQpDQo+IC0gICAgICAg
IElycWwgPSBfX0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2NrKENvbnRleHQpOw0KPiArICAgIGlm
ICghSW5DYWxsYmFjaykNCj4gKyAgICAgICAgS2VSYWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJ
cnFsKTsgLy8gUHJldmVudCBzdXNwZW5kDQo+ICsNCj4gKyAgICBBU1NFUlQzVShLZUdldEN1cnJl
bnRJcnFsKCksID49LCBESVNQQVRDSF9MRVZFTCk7DQo+IA0KPiAgICAgIGlmIChDaGFubmVsLT5B
Y3RpdmUpIHsNCj4gICAgICAgICAgUGVuZGluZyA9IFhFTkJVU19TSEFSRURfSU5GTyhFdnRjaG5V
bm1hc2ssDQo+IEBAIC00NDYsOCArNDU3LDggQEAgRXZ0Y2huVW5tYXNrKA0KPiAgICAgICAgICB9
DQo+ICAgICAgfQ0KPiANCj4gLSAgICBpZiAoIUxvY2tlZCkNCj4gLSAgICAgICAgX19FdnRjaG5S
ZWxlYXNlSW50ZXJydXB0TG9jayhDb250ZXh0LCBJcnFsKTsNCj4gKyAgICBpZiAoIUluQ2FsbGJh
Y2spDQo+ICsgICAgICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiANCj4gICAgICByZXR1cm4gUGVu
ZGluZzsNCj4gIH0NCj4gQEAgLTUxMyw2ICs1MjQsOCBAQCBFdnRjaG5UcmlnZ2VyKA0KPiANCj4g
ICAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhDb250ZXh0KTsNCj4gDQo+
ICsgICAgQVNTRVJUM1UoS2VHZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFUQ0hfTEVWRUwpOw0K
PiArDQo+ICAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgew0KPiAgICAgICAgICBEb25lU29tZXRo
aW5nID0gRXZ0Y2huQ2FsbGJhY2soQ29udGV4dCwgQ2hhbm5lbCk7DQo+ICAgICAgfSBlbHNlIHsN
Cj4gQEAgLTUzNiw3ICs1NDksOSBAQCBFdnRjaG5DbG9zZSgNCj4gDQo+ICAgICAgQVNTRVJUM1Uo
Q2hhbm5lbC0+TWFnaWMsID09LCBYRU5CVVNfRVZUQ0hOX0NIQU5ORUxfTUFHSUMpOw0KPiANCj4g
LSAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhDb250ZXh0KTsNCj4gKyAg
ICBLZVJhaXNlSXJxbChESVNQQVRDSF9MRVZFTCwgJklycWwpOyAvLyBQcmV2ZW50IHN1c3BlbmQN
Cj4gKw0KPiArICAgIEtlQWNxdWlyZVNwaW5Mb2NrQXREcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7
DQo+IA0KPiAgICAgIFJlbW92ZUVudHJ5TGlzdCgmQ2hhbm5lbC0+TGlzdEVudHJ5KTsNCj4gDQo+
IEBAIC01NDUsMTIgKzU2MCwxMyBAQCBFdnRjaG5DbG9zZSgNCj4gICAgICAgICAgQ29udGV4dC0+
RW5hYmxlZCA9IEZBTFNFOw0KPiAgICAgIH0NCj4gDQo+ICsgICAgS2VSZWxlYXNlU3BpbkxvY2tG
cm9tRHBjTGV2ZWwoJkNvbnRleHQtPkxvY2spOw0KPiArDQo+ICAgICAgUnRsWmVyb01lbW9yeSgm
Q2hhbm5lbC0+TGlzdEVudHJ5LCBzaXplb2YgKExJU1RfRU5UUlkpKTsNCj4gDQo+ICAgICAgaWYg
KENoYW5uZWwtPkFjdGl2ZSkgew0KPiAtICAgICAgICBVTE9ORyAgIExvY2FsUG9ydCA9IENoYW5u
ZWwtPkxvY2FsUG9ydDsNCj4gLQ0KPiAtICAgICAgICBBU1NFUlQzVShMb2NhbFBvcnQsIDwsIHNp
emVvZiAoQ29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtDQo+ID5DaGFubmVsWzBd
KSk7DQo+ICsgICAgICAgIFVMT05HICAgICAgIExvY2FsUG9ydCA9IENoYW5uZWwtPkxvY2FsUG9y
dDsNCj4gKyAgICAgICAgTlRTVEFUVVMgICAgc3RhdHVzOw0KPiANCj4gICAgICAgICAgQ2hhbm5l
bC0+QWN0aXZlID0gRkFMU0U7DQo+IA0KPiBAQCAtNTYxLDEyICs1NzcsMTAgQEAgRXZ0Y2huQ2xv
c2UoDQo+ICAgICAgICAgIGlmIChDaGFubmVsLT5UeXBlICE9IFhFTkJVU19FVlRDSE5fVFlQRV9G
SVhFRCkNCj4gICAgICAgICAgICAgIChWT0lEKSBFdmVudENoYW5uZWxDbG9zZShMb2NhbFBvcnQp
Ow0KPiANCj4gLSAgICAgICAgQVNTRVJUKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSAhPSBO
VUxMKTsNCj4gLSAgICAgICAgQ29udGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdID0gTlVMTDsNCj4g
KyAgICAgICAgc3RhdHVzID0gSGFzaFRhYmxlUmVtb3ZlKENvbnRleHQtPlRhYmxlLCBMb2NhbFBv
cnQpOw0KPiArICAgICAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsNCj4gICAgICB9DQo+
IA0KPiAtICAgIF9fRXZ0Y2huUmVsZWFzZUludGVycnVwdExvY2soQ29udGV4dCwgSXJxbCk7DQo+
IC0NCj4gICAgICBDaGFubmVsLT5Mb2NhbFBvcnQgPSAwOw0KPiAgICAgIFJ0bFplcm9NZW1vcnko
JkNoYW5uZWwtPlBhcmFtZXRlcnMsIHNpemVvZg0KPiAoWEVOQlVTX0VWVENITl9QQVJBTUVURVJT
KSk7DQo+IA0KPiBAQCAtNTgwLDYgKzU5NCw4IEBAIEV2dGNobkNsb3NlKA0KPiANCj4gICAgICBB
U1NFUlQoSXNaZXJvTWVtb3J5KENoYW5uZWwsIHNpemVvZiAoWEVOQlVTX0VWVENITl9DSEFOTkVM
KSkpOw0KPiAgICAgIF9fRXZ0Y2huRnJlZShDaGFubmVsKTsNCj4gKw0KPiArICAgIEtlTG93ZXJJ
cnFsKElycWwpOw0KPiAgfQ0KPiANCj4gIHN0YXRpYyBVTE9ORw0KPiBAQCAtNjA2LDEyICs2MjIs
MTMgQEAgRXZ0Y2huUG9sbENhbGxiYWNrKA0KPiAgICAgIFBYRU5CVVNfRVZUQ0hOX0NIQU5ORUwg
IENoYW5uZWw7DQo+ICAgICAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTWFzazsNCj4gICAgICBC
T09MRUFOICAgICAgICAgICAgICAgICBEb25lU29tZXRoaW5nOw0KPiArICAgIE5UU1RBVFVTICAg
ICAgICAgICAgICAgIHN0YXR1czsNCj4gDQo+IC0gICAgQVNTRVJUM1UoTG9jYWxQb3J0LCA8LCBz
aXplb2YgKENvbnRleHQtPkNoYW5uZWwpIC8gc2l6ZW9mIChDb250ZXh0LQ0KPiA+Q2hhbm5lbFsw
XSkpOw0KPiAtDQo+IC0gICAgQ2hhbm5lbCA9IENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XTsN
Cj4gLQ0KPiAtICAgIGlmIChDaGFubmVsID09IE5VTEwpIHsNCj4gKyAgICBzdGF0dXMgPSBIYXNo
VGFibGVMb29rdXAoQ29udGV4dC0+VGFibGUsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIExvY2FsUG9ydCwNCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFBVTE9OR19Q
VFIpJkNoYW5uZWwpOw0KPiArDQo+ICsgICAgaWYgKCFOVF9TVUNDRVNTKHN0YXR1cykpIHsNCj4g
ICAgICAgICAgV2FybmluZygiWyVkXTogSU5WQUxJRCBQT1JUXG4iLCBMb2NhbFBvcnQpOw0KPiAN
Cj4gICAgICAgICAgWEVOQlVTX1NIQVJFRF9JTkZPKEV2dGNobk1hc2ssDQo+IEBAIC02OTcsMTQg
KzcxNCwxMyBAQCBFdnRjaG5TdXNwZW5kQ2FsbGJhY2tFYXJseSgNCj4gICAgICAgICAgQ2hhbm5l
bCA9IENPTlRBSU5JTkdfUkVDT1JEKExpc3RFbnRyeSwNCj4gWEVOQlVTX0VWVENITl9DSEFOTkVM
LCBMaXN0RW50cnkpOw0KPiANCj4gICAgICAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgew0KPiAt
ICAgICAgICAgICAgVUxPTkcgICBMb2NhbFBvcnQgPSBDaGFubmVsLT5Mb2NhbFBvcnQ7DQo+IC0N
Cj4gLSAgICAgICAgICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwgc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0NCj4gPkNoYW5uZWxbMF0pKTsNCj4gKyAgICAgICAg
ICAgIFVMT05HICAgICAgIExvY2FsUG9ydCA9IENoYW5uZWwtPkxvY2FsUG9ydDsNCj4gKyAgICAg
ICAgICAgIE5UU1RBVFVTICAgIHN0YXR1czsNCj4gDQo+ICAgICAgICAgICAgICBDaGFubmVsLT5B
Y3RpdmUgPSBGQUxTRTsNCj4gDQo+IC0gICAgICAgICAgICBBU1NFUlQoQ29udGV4dC0+Q2hhbm5l
bFtMb2NhbFBvcnRdICE9IE5VTEwpOw0KPiAtICAgICAgICAgICAgQ29udGV4dC0+Q2hhbm5lbFtM
b2NhbFBvcnRdID0gTlVMTDsNCj4gKyAgICAgICAgICAgIHN0YXR1cyA9IEhhc2hUYWJsZVJlbW92
ZShDb250ZXh0LT5UYWJsZSwgTG9jYWxQb3J0KTsNCj4gKyAgICAgICAgICAgIEFTU0VSVChOVF9T
VUNDRVNTKHN0YXR1cykpOw0KPiAgICAgICAgICB9DQo+ICAgICAgfQ0KPiANCj4gQEAgLTk1OCw2
ICs5NzQsMTAgQEAgRXZ0Y2huSW5pdGlhbGl6ZSgNCj4gICAgICBpZiAoKkNvbnRleHQgPT0gTlVM
TCkNCj4gICAgICAgICAgZ290byBmYWlsMTsNCj4gDQo+ICsgICAgc3RhdHVzID0gSGFzaFRhYmxl
Q3JlYXRlKCYoKkNvbnRleHQpLT5UYWJsZSk7DQo+ICsgICAgaWYgKCFOVF9TVUNDRVNTKHN0YXR1
cykpDQo+ICsgICAgICAgIGdvdG8gZmFpbDI7DQo+ICsNCj4gICAgICBzdGF0dXMgPSBTdXNwZW5k
R2V0SW50ZXJmYWNlKEZkb0dldFN1c3BlbmRDb250ZXh0KEZkbyksDQo+ICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBYRU5CVVNfU1VTUEVORF9JTlRFUkZBQ0VfVkVSU0lPTl9NQVgs
DQo+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoUElOVEVSRkFDRSkmKCpDb250
ZXh0KS0+U3VzcGVuZEludGVyZmFjZSwNCj4gQEAgLTk4OCw2ICsxMDA4LDEyIEBAIEV2dGNobklu
aXRpYWxpemUoDQo+IA0KPiAgICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsNCj4gDQo+ICtmYWls
MjoNCj4gKyAgICBFcnJvcigiZmFpbDJcbiIpOw0KPiArDQo+ICsgICAgQVNTRVJUKElzWmVyb01l
bW9yeShDb250ZXh0LCBzaXplb2YgKFhFTkJVU19FVlRDSE5fQ09OVEVYVCkpKTsNCj4gKyAgICBf
X0V2dGNobkZyZWUoQ29udGV4dCk7DQo+ICsNCj4gIGZhaWwxOg0KPiAgICAgIEVycm9yKCJmYWls
MSAoJTA4eClcbiIsIHN0YXR1cyk7DQo+IA0KPiBAQCAtMTA1Myw2ICsxMDc5LDkgQEAgRXZ0Y2hu
VGVhcmRvd24oDQo+ICAgICAgUnRsWmVyb01lbW9yeSgmQ29udGV4dC0+U3VzcGVuZEludGVyZmFj
ZSwNCj4gICAgICAgICAgICAgICAgICAgIHNpemVvZiAoWEVOQlVTX1NVU1BFTkRfSU5URVJGQUNF
KSk7DQo+IA0KPiArICAgIEhhc2hUYWJsZURlc3Ryb3koQ29udGV4dC0+VGFibGUpOw0KPiArICAg
IENvbnRleHQtPlRhYmxlID0gTlVMTDsNCj4gKw0KPiAgICAgIEFTU0VSVChJc1plcm9NZW1vcnko
Q29udGV4dCwgc2l6ZW9mIChYRU5CVVNfRVZUQ0hOX0NPTlRFWFQpKSk7DQo+ICAgICAgX19FdnRj
aG5GcmVlKENvbnRleHQpOw0KPiANCj4gZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvaGFzaF90YWJs
ZS5jIGIvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMNCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4g
aW5kZXggMDAwMDAwMC4uYjhlMjdkOA0KPiAtLS0gL2Rldi9udWxsDQo+ICsrKyBiL3NyYy94ZW5i
dXMvaGFzaF90YWJsZS5jDQo+IEBAIC0wLDAgKzEsMzY3IEBADQo+ICsvKiBDb3B5cmlnaHQgKGMp
IENpdHJpeCBTeXN0ZW1zIEluYy4NCj4gKyAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQo+ICsgKg0K
PiArICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3JtcywN
Cj4gKyAqIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlk
ZWQNCj4gKyAqIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6DQo+ICsgKg0K
PiArICogKiAgIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUg
YWJvdmUNCj4gKyAqICAgICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9u
cyBhbmQgdGhlDQo+ICsgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIuDQo+ICsgKiAqICAgUmVk
aXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZQ0KPiAr
ICogICAgIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUN
Cj4gKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQv
b3Igb3RoZXINCj4gKyAqICAgICBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0
aW9uLg0KPiArICoNCj4gKyAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlS
SUdIVCBIT0xERVJTIEFORA0KPiArICogQ09OVFJJQlVUT1JTICJBUyBJUyIgQU5EIEFOWSBFWFBS
RVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywNCj4gKyAqIElOQ0xVRElORywgQlVUIE5PVCBMSU1J
VEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GDQo+ICsgKiBNRVJDSEFOVEFCSUxJVFkg
QU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRQ0KPiArICogRElTQ0xBSU1F
RC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1INCj4gKyAqIENPTlRS
SUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLA0K
PiArICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xV
RElORywNCj4gKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVU
RSBHT09EUyBPUg0KPiArICogU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRT
OyBPUiBCVVNJTkVTUw0KPiArICogSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04g
QU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksDQo+ICsgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcNCj4gKyAqIE5FR0xJR0VOQ0UgT1IgT1RI
RVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UNCj4gKyAqIE9GIFRISVMg
U09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YNCj4gKyAqIFNV
Q0ggREFNQUdFLg0KPiArICovDQo+ICsNCj4gKyNpbmNsdWRlIDxudGRkay5oPg0KPiArI2luY2x1
ZGUgPHN0ZGFyZy5oPg0KPiArI2luY2x1ZGUgPHhlbi5oPg0KPiArI2luY2x1ZGUgPHV0aWwuaD4N
Cj4gKw0KPiArI2luY2x1ZGUgImhhc2hfdGFibGUuaCINCj4gKyNpbmNsdWRlICJkYmdfcHJpbnQu
aCINCj4gKyNpbmNsdWRlICJhc3NlcnQuaCINCj4gKw0KPiArdHlwZWRlZiBzdHJ1Y3QgX1hFTkJV
U19IQVNIX1RBQkxFX05PREUgew0KPiArICAgIExJU1RfRU5UUlkgIExpc3RFbnRyeTsNCj4gKyAg
ICBVTE9OR19QVFIgICBLZXk7DQo+ICsgICAgVUxPTkdfUFRSICAgVmFsdWU7DQo+ICt9IFhFTkJV
U19IQVNIX1RBQkxFX05PREUsICpQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERTsNCj4gKw0KPiArdHlw
ZWRlZiBzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCB7DQo+ICsgICAgTE9ORyAgICAg
ICAgTG9jazsNCj4gKyAgICBMSVNUX0VOVFJZICBMaXN0Ow0KPiArfSBYRU5CVVNfSEFTSF9UQUJM
RV9CVUNLRVQsICpQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUOw0KPiArDQo+ICsjZGVmaW5lIFhF
TkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFMgXA0KPiArICAgICgxIDw8IChzaXplb2YgKFVDSEFS
KSAqIDgpKQ0KPiArDQo+ICtzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFIHsNCj4gKyAgICBYRU5C
VVNfSEFTSF9UQUJMRV9CVUNLRVQNCj4gQnVja2V0W1hFTkJVU19IQVNIX1RBQkxFX05SX0JVQ0tF
VFNdOw0KPiArfTsNCj4gKw0KPiArI2RlZmluZSBYRU5CVVNfSEFTSF9UQUJMRV9UQUcgICAnSFNB
SCcNCj4gKw0KPiArc3RhdGljIEZPUkNFSU5MSU5FIFBWT0lEDQo+ICtfX0hhc2hUYWJsZUFsbG9j
YXRlKA0KPiArICAgIElOICBVTE9ORyAgIExlbmd0aA0KPiArICAgICkNCj4gK3sNCj4gKyAgICBy
ZXR1cm4gX19BbGxvY2F0ZVBvb2xXaXRoVGFnKE5vblBhZ2VkUG9vbCwgTGVuZ3RoLA0KPiBYRU5C
VVNfSEFTSF9UQUJMRV9UQUcpOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgRk9SQ0VJTkxJTkUgVk9J
RA0KPiArX19IYXNoVGFibGVGcmVlKA0KPiArICAgIElOICBQVk9JRCAgIEJ1ZmZlcg0KPiArICAg
ICkNCj4gK3sNCj4gKyAgICBFeEZyZWVQb29sV2l0aFRhZyhCdWZmZXIsIFhFTkJVU19IQVNIX1RB
QkxFX1RBRyk7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBVTE9ORw0KPiArSGFzaFRhYmxlSGFzaCgN
Cj4gKyAgICBJTiAgVUxPTkdfUFRSICAgS2V5DQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBVQ0hB
UiAgICAgICAgICBBcnJheSA9IChQVUNIQVIpJktleTsNCj4gKyAgICBVTE9ORyAgICAgICAgICAg
QWNjdW11bGF0b3I7DQo+ICsgICAgVUxPTkcgICAgICAgICAgIEluZGV4Ow0KPiArDQo+ICsgICAg
QWNjdW11bGF0b3IgPSAwOw0KPiArDQo+ICsgICAgZm9yIChJbmRleCA9IDA7IEluZGV4IDwgc2l6
ZW9mIChVTE9OR19QVFIpOyBJbmRleCsrKSB7DQo+ICsgICAgICAgIFVMT05HICAgT3ZlcmZsb3c7
DQo+ICsNCj4gKyAgICAgICAgQWNjdW11bGF0b3IgPSAoQWNjdW11bGF0b3IgPDwgNCkgKyBBcnJh
eVtJbmRleF07DQo+ICsNCj4gKyAgICAgICAgT3ZlcmZsb3cgPSBBY2N1bXVsYXRvciAmIDB4MDAw
MDBmMDA7DQo+ICsgICAgICAgIGlmIChPdmVyZmxvdyAhPSAwKSB7DQo+ICsgICAgICAgICAgICBB
Y2N1bXVsYXRvciBePSBPdmVyZmxvdyA+PiA4Ow0KPiArICAgICAgICAgICAgQWNjdW11bGF0b3Ig
Xj0gT3ZlcmZsb3c7DQo+ICsgICAgICAgIH0NCj4gKyAgICB9DQo+ICsNCj4gKyAgICBBU1NFUlQz
VShBY2N1bXVsYXRvciwgPCwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUyk7DQo+ICsNCj4g
KyAgICByZXR1cm4gQWNjdW11bGF0b3I7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYw0KPiArX0lSUUxf
cmVxdWlyZXNfbWF4XyhISUdIX0xFVkVMKQ0KPiArX0lSUUxfc2F2ZXNfDQo+ICtfSVJRTF9yYWlz
ZXNfKEhJR0hfTEVWRUwpDQo+ICtLSVJRTA0KPiArX19IYXNoVGFibGVCdWNrZXRMb2NrKA0KPiAr
ICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0LA0KPiArICAgIElOICBC
T09MRUFOICAgICAgICAgICAgICAgICAgICAgV3JpdGVyDQo+ICsgICAgKQ0KPiArew0KPiArICAg
IEtJUlFMICAgICAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKw0KPiArICAgIEtlUmFp
c2VJcnFsKEhJR0hfTEVWRUwsICZJcnFsKTsNCj4gKw0KPiArICAgIGZvciAoOzspIHsNCj4gKyAg
ICAgICAgTE9ORyAgICBMb2NrOw0KPiArICAgICAgICBMT05HICAgIFJlYWRlcnM7DQo+ICsgICAg
ICAgIExPTkcgICAgV3JpdGVyczsNCj4gKyAgICAgICAgTE9ORyAgICBPbGQ7DQo+ICsgICAgICAg
IExPTkcgICAgTmV3Ow0KPiArDQo+ICsgICAgICAgIEtlTWVtb3J5QmFycmllcigpOw0KPiArDQo+
ICsgICAgICAgIExvY2sgPSBCdWNrZXQtPkxvY2s7DQo+ICsgICAgICAgIFJlYWRlcnMgPSBMb2Nr
ID4+IDE7DQo+ICsgICAgICAgIFdyaXRlcnMgPSBMb2NrICYgMTsNCj4gKw0KPiArICAgICAgICAv
LyBUaGVyZSBtdXN0IGJlIG5vIGV4aXN0aW5nIHdyaXRlcg0KPiArICAgICAgICBPbGQgPSBSZWFk
ZXJzIDw8IDE7DQo+ICsNCj4gKyAgICAgICAgaWYgKFdyaXRlcikNCj4gKyAgICAgICAgICAgIFdy
aXRlcnMrKzsNCj4gKyAgICAgICAgZWxzZQ0KPiArICAgICAgICAgICAgUmVhZGVycysrOw0KPiAr
DQo+ICsgICAgICAgIE5ldyA9IChSZWFkZXJzIDw8IDEpIHwgKFdyaXRlcnMgJiAxKTsNCj4gKw0K
PiArICAgICAgICBpZiAoSW50ZXJsb2NrZWRDb21wYXJlRXhjaGFuZ2UoJkJ1Y2tldC0+TG9jaywg
TmV3LCBPbGQpICE9IE9sZCkNCj4gKyAgICAgICAgICAgIGNvbnRpbnVlOw0KPiArDQo+ICsgICAg
ICAgIC8vDQo+ICsgICAgICAgIC8vIFdlIGFyZSBkb25lIGlmIHdlJ3JlIG5vdCBhIHdyaXRlciwg
b3IgdGhlcmUgYXJlIG5vIHJlYWRlcnMNCj4gKyAgICAgICAgLy8gbGVmdC4NCj4gKyAgICAgICAg
Ly8NCj4gKyAgICAgICAgaWYgKCFXcml0ZXIgfHwgUmVhZGVycyA9PSAwKQ0KPiArICAgICAgICAg
ICAgYnJlYWs7DQo+ICsgICAgfQ0KPiArDQo+ICsgICAgcmV0dXJuIElycWw7DQo+ICt9DQo+ICsN
Cj4gKyNkZWZpbmUgSGFzaFRhYmxlQnVja2V0TG9jayhfQnVja2V0LCBfV3JpdGVyLCBfSXJxbCkg
ICAgICAgICAgICBcDQo+ICsgICAgZG8geyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgXA0KPiArICAgICAgICAqKF9JcnFsKSA9IF9fSGFzaFRh
YmxlQnVja2V0TG9jaygoX0J1Y2tldCksIChfV3JpdGVyKSk7IFwNCj4gKyAgICB9IHdoaWxlIChG
QUxTRSkNCj4gKw0KPiArc3RhdGljDQo+ICtfX2Rydl9yZXF1aXJlc0lSUUwoSElHSF9MRVZFTCkN
Cj4gK1ZPSUQNCj4gK0hhc2hUYWJsZUJ1Y2tldFVubG9jaygNCj4gKyAgICBJTiAgUFhFTkJVU19I
QVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCwNCj4gKyAgICBJTiAgQk9PTEVBTiAgICAgICAgICAg
ICAgICAgICAgIFdyaXRlciwNCj4gKyAgICBJTiAgX19kcnZfcmVzdG9yZXNJUlFMIEtJUlFMICAg
IElycWwNCj4gKyAgICApDQo+ICt7DQo+ICsgICAgZm9yICg7Oykgew0KPiArICAgICAgICBMT05H
ICAgIExvY2s7DQo+ICsgICAgICAgIExPTkcgICAgUmVhZGVyczsNCj4gKyAgICAgICAgTE9ORyAg
ICBXcml0ZXJzOw0KPiArICAgICAgICBMT05HICAgIE9sZDsNCj4gKyAgICAgICAgTE9ORyAgICBO
ZXc7DQo+ICsNCj4gKyAgICAgICAgS2VNZW1vcnlCYXJyaWVyKCk7DQo+ICsNCj4gKyAgICAgICAg
TG9jayA9IEJ1Y2tldC0+TG9jazsNCj4gKyAgICAgICAgUmVhZGVycyA9IExvY2sgPj4gMTsNCj4g
KyAgICAgICAgV3JpdGVycyA9IExvY2sgJiAxOw0KPiArDQo+ICsgICAgICAgIE9sZCA9IChSZWFk
ZXJzIDw8IDEpIHwgKFdyaXRlcnMgJiAxKTsNCj4gKw0KPiArICAgICAgICBpZiAoV3JpdGVyKSB7
DQo+ICsgICAgICAgICAgICBBU1NFUlQoV3JpdGVycyAhPSAwKTsNCj4gKyAgICAgICAgICAgIC0t
V3JpdGVyczsNCj4gKyAgICAgICAgfSBlbHNlIHsNCj4gKyAgICAgICAgICAgIC0tUmVhZGVyczsN
Cj4gKyAgICAgICAgfQ0KPiArDQo+ICsgICAgICAgIE5ldyA9IChSZWFkZXJzIDw8IDEpIHwgKFdy
aXRlcnMgJiAxKTsNCj4gKw0KPiArICAgICAgICBpZiAoSW50ZXJsb2NrZWRDb21wYXJlRXhjaGFu
Z2UoJkJ1Y2tldC0+TG9jaywgTmV3LCBPbGQpID09IE9sZCkNCj4gKyAgICAgICAgICAgIGJyZWFr
Ow0KPiArICAgIH0NCj4gKw0KPiArICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiArfQ0KPiArDQo+
ICtOVFNUQVRVUw0KPiArSGFzaFRhYmxlQWRkKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFC
TEUgICAgICBUYWJsZSwNCj4gKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAgICAgICAgS2V5LA0K
PiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBWYWx1ZQ0KPiArICAgICkNCj4gK3sN
Cj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsNCj4gKyAgICBQWEVOQlVT
X0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0Ow0KPiArICAgIEtJUlFMICAgICAgICAgICAgICAg
ICAgICAgICBJcnFsOw0KPiArICAgIE5UU1RBVFVTICAgICAgICAgICAgICAgICAgICBzdGF0dXM7
DQo+ICsNCj4gKyAgICBOb2RlID0gX19IYXNoVGFibGVBbGxvY2F0ZShzaXplb2YgKFhFTkJVU19I
QVNIX1RBQkxFX05PREUpKTsNCj4gKw0KPiArICAgIHN0YXR1cyA9IFNUQVRVU19OT19NRU1PUlk7
DQo+ICsgICAgaWYgKE5vZGUgPT0gTlVMTCkNCj4gKyAgICAgICAgZ290byBmYWlsMTsNCj4gKw0K
PiArICAgIE5vZGUtPktleSA9IEtleTsNCj4gKyAgICBOb2RlLT5WYWx1ZSA9IFZhbHVlOw0KPiAr
DQo+ICsgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkpXTsNCj4g
Kw0KPiArICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0LCBUUlVFLCAmSXJxbCk7DQo+ICsg
ICAgSW5zZXJ0VGFpbExpc3QoJkJ1Y2tldC0+TGlzdCwgJk5vZGUtPkxpc3RFbnRyeSk7DQo+ICsg
ICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJxbCk7DQo+ICsNCj4gKyAg
ICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7DQo+ICsNCj4gK2ZhaWwxOg0KPiArICAgIEVycm9yKCJm
YWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7DQo+ICsNCj4gKyAgICByZXR1cm4gc3RhdHVzOw0KPiAr
fQ0KPiArDQo+ICtOVFNUQVRVUw0KPiArSGFzaFRhYmxlUmVtb3ZlKA0KPiArICAgIElOICBQWEVO
QlVTX0hBU0hfVEFCTEUgICAgICBUYWJsZSwNCj4gKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAg
ICAgICAgS2V5DQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9CVUNL
RVQgICBCdWNrZXQ7DQo+ICsgICAgUExJU1RfRU5UUlkgICAgICAgICAgICAgICAgIExpc3RFbnRy
eTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsNCj4gKyAgICBLSVJR
TCAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKyAgICBOVFNUQVRVUyAgICAgICAgICAg
ICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFz
aFRhYmxlSGFzaChLZXkpXTsNCj4gKw0KPiArICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0
LCBUUlVFLCAmSXJxbCk7DQo+ICsNCj4gKyAgICBMaXN0RW50cnkgPSBCdWNrZXQtPkxpc3QuRmxp
bms7DQo+ICsgICAgd2hpbGUgKExpc3RFbnRyeSAhPSAmQnVja2V0LT5MaXN0KSB7DQo+ICsgICAg
ICAgIE5vZGUgPSBDT05UQUlOSU5HX1JFQ09SRChMaXN0RW50cnksIFhFTkJVU19IQVNIX1RBQkxF
X05PREUsDQo+IExpc3RFbnRyeSk7DQo+ICsNCj4gKyAgICAgICAgaWYgKE5vZGUtPktleSA9PSBL
ZXkpDQo+ICsgICAgICAgICAgICBnb3RvIGZvdW5kOw0KPiArICAgIH0NCj4gKw0KPiArICAgIEhh
c2hUYWJsZUJ1Y2tldFVubG9jayhCdWNrZXQsIFRSVUUsIElycWwpOw0KPiArDQo+ICsgICAgc3Rh
dHVzID0gU1RBVFVTX09CSkVDVF9OQU1FX05PVF9GT1VORDsNCj4gKyAgICBnb3RvIGZhaWwxOw0K
PiArDQo+ICtmb3VuZDoNCj4gKyAgICBSZW1vdmVFbnRyeUxpc3QoTGlzdEVudHJ5KTsNCj4gKyAg
ICBfX0hhc2hUYWJsZUZyZWUoTm9kZSk7DQo+ICsNCj4gKyAgICBIYXNoVGFibGVCdWNrZXRVbmxv
Y2soQnVja2V0LCBUUlVFLCBJcnFsKTsNCj4gKw0KPiArICAgIHJldHVybiBTVEFUVVNfU1VDQ0VT
UzsNCj4gKw0KPiArZmFpbDE6DQo+ICsgICAgRXJyb3IoImZhaWwxICglMDh4KVxuIiwgc3RhdHVz
KTsNCj4gKw0KPiArICAgIHJldHVybiBzdGF0dXM7DQo+ICt9DQo+ICsNCj4gK05UU1RBVFVTDQo+
ICtIYXNoVGFibGVMb29rdXAoDQo+ICsgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgICAgIFRh
YmxlLA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBLZXksDQo+ICsgICAgT1VU
IFBVTE9OR19QVFIgICAgICAgICAgICAgIFZhbHVlDQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBY
RU5CVVNfSEFTSF9UQUJMRV9CVUNLRVQgICBCdWNrZXQ7DQo+ICsgICAgUExJU1RfRU5UUlkgICAg
ICAgICAgICAgICAgIExpc3RFbnRyeTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAg
ICAgTm9kZTsNCj4gKyAgICBLSVJRTCAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKyAg
ICBOVFNUQVRVUyAgICAgICAgICAgICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgQnVja2V0
ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkpXTsNCj4gKw0KPiArICAgIEhhc2hU
YWJsZUJ1Y2tldExvY2soQnVja2V0LCBGQUxTRSwgJklycWwpOw0KPiArDQo+ICsgICAgTGlzdEVu
dHJ5ID0gQnVja2V0LT5MaXN0LkZsaW5rOw0KPiArICAgIHdoaWxlIChMaXN0RW50cnkgIT0gJkJ1
Y2tldC0+TGlzdCkgew0KPiArICAgICAgICBOb2RlID0gQ09OVEFJTklOR19SRUNPUkQoTGlzdEVu
dHJ5LCBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLA0KPiBMaXN0RW50cnkpOw0KPiArDQo+ICsgICAg
ICAgIGlmIChOb2RlLT5LZXkgPT0gS2V5KQ0KPiArICAgICAgICAgICAgZ290byBmb3VuZDsNCj4g
KyAgICB9DQo+ICsNCj4gKyAgICBIYXNoVGFibGVCdWNrZXRVbmxvY2soQnVja2V0LCBGQUxTRSwg
SXJxbCk7DQo+ICsNCj4gKyAgICBzdGF0dXMgPSBTVEFUVVNfT0JKRUNUX05BTUVfTk9UX0ZPVU5E
Ow0KPiArICAgIGdvdG8gZmFpbDE7DQo+ICsNCj4gK2ZvdW5kOg0KPiArICAgICpWYWx1ZSA9IE5v
ZGUtPlZhbHVlOw0KPiArDQo+ICsgICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgRkFM
U0UsIElycWwpOw0KPiArDQo+ICsgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOw0KPiArDQo+ICtm
YWlsMToNCj4gKyAgICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOw0KPiArDQo+ICsg
ICAgcmV0dXJuIHN0YXR1czsNCj4gK30NCj4gKw0KPiArTlRTVEFUVVMNCj4gK0hhc2hUYWJsZUNy
ZWF0ZSgNCj4gKyAgICBPVVQgUFhFTkJVU19IQVNIX1RBQkxFICAqVGFibGUNCj4gKyAgICApDQo+
ICt7DQo+ICsgICAgVUxPTkcgICAgICAgICAgICAgICAgICAgSW5kZXg7DQo+ICsgICAgTlRTVEFU
VVMgICAgICAgICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgKlRhYmxlID0gX19IYXNoVGFi
bGVBbGxvY2F0ZShzaXplb2YgKFhFTkJVU19IQVNIX1RBQkxFKSk7DQo+ICsNCj4gKyAgICBzdGF0
dXMgPSBTVEFUVVNfTk9fTUVNT1JZOw0KPiArICAgIGlmICgqVGFibGUgPT0gTlVMTCkNCj4gKyAg
ICAgICAgZ290byBmYWlsMTsNCj4gKw0KPiArICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IFhF
TkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFM7IEluZGV4KyspIHsNCj4gKyAgICAgICAgUFhFTkJV
U19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCA9ICYoKlRhYmxlKS0+QnVja2V0W0luZGV4XTsN
Cj4gKw0KPiArICAgICAgICBJbml0aWFsaXplTGlzdEhlYWQoJkJ1Y2tldC0+TGlzdCk7DQo+ICsg
ICAgfQ0KPiArDQo+ICsgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOw0KPiArDQo+ICtmYWlsMToN
Cj4gKyAgICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOw0KPiArDQo+ICsgICAgcmV0
dXJuIHN0YXR1czsNCj4gK30NCj4gKw0KPiArVk9JRA0KPiArSGFzaFRhYmxlRGVzdHJveSgNCj4g
KyAgICBJTiAgUFhFTkJVU19IQVNIX1RBQkxFICBUYWJsZQ0KPiArICAgICkNCj4gK3sNCj4gKyAg
ICBVTE9ORyAgICAgICAgICAgICAgICAgICBJbmRleDsNCj4gKw0KPiArICAgIGZvciAoSW5kZXgg
PSAwOyBJbmRleCA8IFhFTkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFM7IEluZGV4KyspIHsNCj4g
KyAgICAgICAgUFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCA9ICZUYWJsZS0+QnVj
a2V0W0luZGV4XTsNCj4gKw0KPiArICAgICAgICBBU1NFUlQoSXNMaXN0RW1wdHkoJkJ1Y2tldC0+
TGlzdCkpOw0KPiArICAgICAgICBSdGxaZXJvTWVtb3J5KCZCdWNrZXQtPkxpc3QsIHNpemVvZiAo
TElTVF9FTlRSWSkpOw0KPiArICAgIH0NCj4gKw0KPiArICAgIEFTU0VSVChJc1plcm9NZW1vcnko
VGFibGUsIHNpemVvZiAoWEVOQlVTX0hBU0hfVEFCTEUpKSk7DQo+ICsgICAgX19IYXNoVGFibGVG
cmVlKFRhYmxlKTsNCj4gK30NCj4gKw0KPiBkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9oYXNoX3Rh
YmxlLmggYi9zcmMveGVuYnVzL2hhc2hfdGFibGUuaA0KPiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0K
PiBpbmRleCAwMDAwMDAwLi5jZTBjOTA2DQo+IC0tLSAvZGV2L251bGwNCj4gKysrIGIvc3JjL3hl
bmJ1cy9oYXNoX3RhYmxlLmgNCj4gQEAgLTAsMCArMSw3MCBAQA0KPiArLyogQ29weXJpZ2h0IChj
KSBDaXRyaXggU3lzdGVtcyBJbmMuDQo+ICsgKiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KPiArICoN
Cj4gKyAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMs
DQo+ICsgKiB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3Zp
ZGVkDQo+ICsgKiB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0Og0KPiArICoN
Cj4gKyAqICogICBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhl
IGFib3ZlDQo+ICsgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlv
bnMgYW5kIHRoZQ0KPiArICogICAgIGZvbGxvd2luZyBkaXNjbGFpbWVyLg0KPiArICogKiAgIFJl
ZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUNCj4g
KyAqICAgICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhl
DQo+ICsgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5k
L29yIG90aGVyDQo+ICsgKiAgICAgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1
dGlvbi4NCj4gKyAqDQo+ICsgKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZ
UklHSFQgSE9MREVSUyBBTkQNCj4gKyAqIENPTlRSSUJVVE9SUyAiQVMgSVMiIEFORCBBTlkgRVhQ
UkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsDQo+ICsgKiBJTkNMVURJTkcsIEJVVCBOT1QgTElN
SVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRg0KPiArICogTUVSQ0hBTlRBQklMSVRZ
IEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUNCj4gKyAqIERJU0NMQUlN
RUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SDQo+ICsgKiBDT05U
UklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwN
Cj4gKyAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNM
VURJTkcsDQo+ICsgKiBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRV
VEUgR09PRFMgT1INCj4gKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklU
UzsgT1IgQlVTSU5FU1MNCj4gKyAqIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9O
IEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLA0KPiArICogV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RS
SUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HDQo+ICsgKiBORUdMSUdFTkNFIE9SIE9U
SEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFDQo+ICsgKiBPRiBUSElT
IFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GDQo+ICsgKiBT
VUNIIERBTUFHRS4NCj4gKyAqLw0KPiArDQo+ICsjaWZuZGVmIF9YRU5CVVNfSEFTSF9UQUJMRV9I
DQo+ICsjZGVmaW5lIF9YRU5CVVNfSEFTSF9UQUJMRV9IDQo+ICsNCj4gKyNpbmNsdWRlIDxudGRk
ay5oPg0KPiArDQo+ICt0eXBlZGVmIHN0cnVjdCBfWEVOQlVTX0hBU0hfVEFCTEUgWEVOQlVTX0hB
U0hfVEFCTEUsDQo+ICpQWEVOQlVTX0hBU0hfVEFCTEU7DQo+ICsNCj4gK2V4dGVybiBOVFNUQVRV
Uw0KPiArSGFzaFRhYmxlQWRkKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxl
LA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleSwNCj4gKyAgICBJTiAgVUxPTkdf
UFRSICAgICAgICAgICBWYWx1ZQ0KPiArICAgICk7DQo+ICsNCj4gK2V4dGVybiBOVFNUQVRVUw0K
PiArSGFzaFRhYmxlUmVtb3ZlKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxl
LA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleQ0KPiArICAgICk7DQo+ICsNCj4g
K2V4dGVybiBOVFNUQVRVUw0KPiArSGFzaFRhYmxlTG9va3VwKA0KPiArICAgIElOICBQWEVOQlVT
X0hBU0hfVEFCTEUgIFRhYmxlLA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleSwN
Cj4gKyAgICBPVVQgUFVMT05HX1BUUiAgICAgICAgICBWYWx1ZQ0KPiArICAgICk7DQo+ICsNCj4g
K2V4dGVybiBOVFNUQVRVUw0KPiArSGFzaFRhYmxlQ3JlYXRlKA0KPiArICAgIE9VVCBQWEVOQlVT
X0hBU0hfVEFCTEUgICpUYWJsZQ0KPiArICAgICk7DQo+ICsNCj4gK2V4dGVybiBWT0lEDQo+ICtI
YXNoVGFibGVEZXN0cm95KA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxlDQo+
ICsgICAgKTsNCj4gKw0KPiArI2VuZGlmICAvLyBfWEVOQlVTX0hBU0hfVEFCTEVfSA0KPiArDQo+
IGRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3NoYXJlZF9pbmZvLmMgYi9zcmMveGVuYnVzL3NoYXJl
ZF9pbmZvLmMNCj4gaW5kZXggMGFmYzIxOC4uNjdiZTIwYyAxMDA2NDQNCj4gLS0tIGEvc3JjL3hl
bmJ1cy9zaGFyZWRfaW5mby5jDQo+ICsrKyBiL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYw0KPiBA
QCAtMzgsNiArMzgsOSBAQA0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUg
ImFzc2VydC5oIg0KPiANCj4gKyNkZWZpbmUgWEVOQlVTX1NIQVJFRF9JTkZPX0VWVENITl9QRVJf
U0VMRUNUT1IgICAgIChzaXplb2YNCj4gKFVMT05HX1BUUikgKiA4KQ0KPiArI2RlZmluZSBYRU5C
VVNfU0hBUkVEX0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UDQo+IChSVExfRklFTERfU0laRShz
aGFyZWRfaW5mb190LCBldnRjaG5fcGVuZGluZykgLyBzaXplb2YgKFVMT05HX1BUUikpDQo+ICsN
Cj4gIHN0cnVjdCBfWEVOQlVTX1NIQVJFRF9JTkZPX0NPTlRFWFQgew0KPiAgICAgIFBYRU5CVVNf
RkRPICAgICAgICAgICAgICAgICBGZG87DQo+ICAgICAgS1NQSU5fTE9DSyAgICAgICAgICAgICAg
ICAgIExvY2s7DQo+IGRpZmYgLS1naXQgYS92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qIGIv
dnMyMDEyL3hlbmJ1cy94ZW5idXMudmN4cHJvag0KPiBpbmRleCBjMzA3NzRlLi5hNjQ4YmNlIDEw
MDY0NA0KPiAtLS0gYS92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qDQo+ICsrKyBiL3ZzMjAx
Mi94ZW5idXMveGVuYnVzLnZjeHByb2oNCj4gQEAgLTk5LDYgKzk5LDcgQEANCj4gIAkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXHJhbmdlX3NldC5jIiAvPg0KPiAgCQk8Q2xD
b21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNcYmFsbG9vbi5jIiAvPg0KPiAgCQk8Q2xD
b21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNcY2FjaGUuYyIgLz4NCj4gKwkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGhhc2hfdGFibGUuYyIgLz4NCj4gIAk8L0l0
ZW1Hcm91cD4NCj4gIAk8SXRlbUdyb3VwPg0KPiAgCQk8UmVzb3VyY2VDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5idXNceGVuYnVzLnJjIiAvPg0KPiBkaWZmIC0tZ2l0IGEvdnMyMDEzL3hl
bmJ1cy94ZW5idXMudmN4cHJvaiBiL3ZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHByb2oNCj4gaW5k
ZXggNTg4YjBjNS4uMmMzNGVkMSAxMDA2NDQNCj4gLS0tIGEvdnMyMDEzL3hlbmJ1cy94ZW5idXMu
dmN4cHJvag0KPiArKysgYi92czIwMTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qDQo+IEBAIC0xLDQg
KzEsNCBAQA0KPiAt77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCj4g
Kzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+ICA8UHJvamVjdCBEZWZh
dWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIuMCINCj4geG1sbnM9Imh0dHA6Ly9z
Y2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVpbGQvMjAwMyI+DQo+ICAgIDxJbXBv
cnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4gICAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9Ikdsb2JhbHMiPg0KPiBAQCAtMTM5LDYgKzEzOSw3IEBADQo+ICAgICAgPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXHJhbmdlX3NldC5jIiAvPg0KPiAgICAgIDxDbENvbXBp
bGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlbmJ1c1xiYWxsb29uLmMiIC8+DQo+ICAgICAgPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGNhY2hlLmMiIC8+DQo+ICsgICAgPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGhhc2hfdGFibGUuYyIgLz4NCj4gICAgPC9J
dGVtR3JvdXA+DQo+ICAgIDxJdGVtR3JvdXA+DQo+ICAgICAgPFJlc291cmNlQ29tcGlsZSBJbmNs
dWRlPSIuLlwuLlxzcmNceGVuYnVzXHhlbmJ1cy5yYyIgLz4NCj4gLS0NCj4gMi4xLjENCg0KX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVs
IG1haWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xp
c3RzLnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 06 14:28:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:28:49 +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 1XmO3N-0001bU-Bc; Thu, 06 Nov 2014 14:28:49 +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 1XmO3L-0001bP-JR
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:28:47 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	6A/6B-09936-E958B545; Thu, 06 Nov 2014 14:28:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-21.messagelabs.com!1415284125!11962794!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	UPPERCASE_25_50,received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20139 invoked from network); 6 Nov 2014 14:28:45 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:28:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="26611186"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 05/10] Use a hash table for event channel lookup
Thread-Index: AQHP+c1yBv8AvrUifkWaC0Q0a3TOlZxTqBOA
Date: Thu, 6 Nov 2014 14:28:44 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111462A2@AMSPEX01CL01.citrite.net>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
	<1415283861-26028-7-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415283861-26028-7-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 05/10] Use a hash table for event channel
	lookup
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

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBQYXVsIER1cnJhbnQgW21haWx0
bzpwYXVsLmR1cnJhbnRAY2l0cml4LmNvbV0NCj4gU2VudDogMDYgTm92ZW1iZXIgMjAxNCAxNDoy
NA0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQo+IENjOiBQYXVsIER1
cnJhbnQNCj4gU3ViamVjdDogW1BBVENIIDA1LzEwXSBVc2UgYSBoYXNoIHRhYmxlIGZvciBldmVu
dCBjaGFubmVsIGxvb2t1cA0KPiANCj4gUmF0aGVyIHRoYW4gdXNpbmcgYSBsYXJnZSBhcnJheSBm
b3IgbWFwcGluZyBwb3J0IHZhbHVlcyB0byBjaGFubmVsDQo+IHN0cnVjdHVyZXMsIHVzZSBhIGhh
c2ggdGFibGUuIFRoaXMgbWVhbnMgd2Ugbm8gbG9uZ2VyIG5lZWQgdG8gY29kZSBhDQo+IGhhcmQg
cG9ydCBudW1iZXIgbGltaXQgaW50byB0aGUgRVZUQ0hOIGltcGxlbWVudGF0aW9uLg0KPiANCj4g
QmVjYXVzZSB0aGUgaGFzaCB0YWJsZSBpbXBsZW1lbnRhdGlvbiBtYW5hZ2VzIGl0cyBvd24gbG9j
a2luZywgd2UgYWxzbyBubw0KPiBsb25nZXIgbmVlZCB0byBtYWtlIHN1Y2ggbGliZXJhbCB1c2Ug
b2YgdGhlIGludGVycnVwdCBsb2NrIGluIHRoZSBFVlRDSE4NCj4gaW1wbGVtZW50YXRpb24gYW5k
IGNhbiB1c2UgdGhlIHNwaW5sb2NrIGluc3RlYWQuDQo+IA0KPiBTaWduZWQtb2ZmLWJ5OiBQYXVs
IER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPg0KDQpUaGVyZSB3YXMgc29tZSBjaGFy
YWN0ZXIgZW5jb2Rpbmcgd2VpcmRuZXNzIHdoaWNoIHVuZm9ydHVuYXRlbHkgbWVhbnQgdHdvIHNs
aWdodGx5IGRpZmZlcmVudCB2YXJpYW50cyBvZiB0aGlzIHBhdGNoIHdlcmUgcG9zdGVkLiBUaGVy
ZSBpcyBubyBmdW5jdGlvbmFsIGRpZmZlcmVuY2UuDQoNCiAgUGF1bA0KDQo+IC0tLQ0KPiAgaW5j
bHVkZS9ldnRjaG5faW50ZXJmYWNlLmggICAgICB8ICAgNCArLQ0KPiAgaW5jbHVkZS9zaGFyZWRf
aW5mb19pbnRlcmZhY2UuaCB8ICAgMyAtDQo+ICBzcmMveGVuYnVzL2V2dGNobi5jICAgICAgICAg
ICAgIHwgIDg5ICsrKysrKy0tLS0NCj4gIHNyYy94ZW5idXMvaGFzaF90YWJsZS5jICAgICAgICAg
fCAzNjcNCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiAgc3Jj
L3hlbmJ1cy9oYXNoX3RhYmxlLmggICAgICAgICB8ICA3MCArKysrKysrKw0KPiAgc3JjL3hlbmJ1
cy9zaGFyZWRfaW5mby5jICAgICAgICB8ICAgMyArDQo+ICB2czIwMTIveGVuYnVzL3hlbmJ1cy52
Y3hwcm9qICAgIHwgICAxICsNCj4gIHZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHByb2ogICAgfCAg
IDMgKy0NCj4gIDggZmlsZXMgY2hhbmdlZCwgNTA0IGluc2VydGlvbnMoKyksIDM2IGRlbGV0aW9u
cygtKQ0KPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IHNyYy94ZW5idXMvaGFzaF90YWJsZS5jDQo+ICBj
cmVhdGUgbW9kZSAxMDA2NDQgc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmgNCj4gDQo+IGRpZmYgLS1n
aXQgYS9pbmNsdWRlL2V2dGNobl9pbnRlcmZhY2UuaCBiL2luY2x1ZGUvZXZ0Y2huX2ludGVyZmFj
ZS5oDQo+IGluZGV4IDk5MWQ2MTAuLjNhNDg5MTUgMTAwNjQ0DQo+IC0tLSBhL2luY2x1ZGUvZXZ0
Y2huX2ludGVyZmFjZS5oDQo+ICsrKyBiL2luY2x1ZGUvZXZ0Y2huX2ludGVyZmFjZS5oDQo+IEBA
IC0xMTcsMTQgKzExNywxNCBAQCB0eXBlZGVmIFBYRU5CVVNfRVZUQ0hOX0NIQU5ORUwNCj4gDQo+
ICAgICAgXHBhcmFtIEludGVyZmFjZSBUaGUgaW50ZXJmYWNlIGhlYWRlcg0KPiAgICAgIFxwYXJh
bSBDaGFubmVsIFRoZSBjaGFubmVsIGhhbmRsZQ0KPiAtICAgIFxwYXJhbSBMb2NrZWQgU2V0IHRv
IFRSVUUgaWYgdGhpcyBtZXRob2QgaXMgaW52b2tlZCBpbiBjb250ZXh0IG9mIHRoZQ0KPiBjaGFu
bmVsIGNhbGxiYWNrDQo+ICsgICAgXHBhcmFtIEluQ2FsbGJhY2sgU2V0IHRvIFRSVUUgaWYgdGhp
cyBtZXRob2QgaXMgaW52b2tlZCBpbiBjb250ZXh0IG9mIHRoZQ0KPiBjaGFubmVsIGNhbGxiYWNr
DQo+ICAgICAgXHJldHVybiBUUlVFIGlmIHRoZXJlIHdhcyBhbiBldmVudCBwZW5kaW5nIGF0IHRo
ZSBwb2ludCBvZiB1bm1hc2ssIEZBTFNFDQo+IG90aGVyd2lzZQ0KPiAgKi8NCj4gIHR5cGVkZWYg
Qk9PTEVBTg0KPiAgKCpYRU5CVVNfRVZUQ0hOX1VOTUFTSykoDQo+ICAgICAgSU4gIFBJTlRFUkZB
Q0UgICAgICAgICAgICAgIEludGVyZmFjZSwNCj4gICAgICBJTiAgUFhFTkJVU19FVlRDSE5fQ0hB
Tk5FTCAgQ2hhbm5lbCwNCj4gLSAgICBJTiAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTG9ja2Vk
DQo+ICsgICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAgICAgIEluQ2FsbGJhY2sNCj4gICAgICAp
Ow0KPiANCj4gIC8qISBcdHlwZWRlZiBYRU5CVVNfRVZUQ0hOX1NFTkQNCj4gZGlmZiAtLWdpdCBh
L2luY2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmgNCj4gYi9pbmNsdWRlL3NoYXJlZF9pbmZv
X2ludGVyZmFjZS5oDQo+IGluZGV4IDBkMzZhYzguLjBlNWEwZDcgMTAwNjQ0DQo+IC0tLSBhL2lu
Y2x1ZGUvc2hhcmVkX2luZm9faW50ZXJmYWNlLmgNCj4gKysrIGIvaW5jbHVkZS9zaGFyZWRfaW5m
b19pbnRlcmZhY2UuaA0KPiBAQCAtNDAsOSArNDAsNiBAQA0KPiANCj4gICNpZm5kZWYgX1dJTkRM
TA0KPiANCj4gLSNkZWZpbmUgWEVOQlVTX1NIQVJFRF9JTkZPX0VWVENITl9QRVJfU0VMRUNUT1Ig
ICAgIChzaXplb2YNCj4gKFVMT05HX1BUUikgKiA4KQ0KPiAtI2RlZmluZSBYRU5CVVNfU0hBUkVE
X0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UDQo+IChSVExfRklFTERfU0laRShzaGFyZWRfaW5m
b190LCBldnRjaG5fcGVuZGluZykgLyBzaXplb2YgKFVMT05HX1BUUikpDQo+IC0NCj4gIC8qISBc
dHlwZWRlZiBYRU5CVVNfU0hBUkVEX0lORk9fQUNRVUlSRQ0KPiAgICAgIFxicmllZiBBY3F1aXJl
IGEgcmVmZXJlbmNlIHRvIHRoZSBTSEFSRURfSU5GTyBpbnRlcmZhY2UNCj4gDQo+IGRpZmYgLS1n
aXQgYS9zcmMveGVuYnVzL2V2dGNobi5jIGIvc3JjL3hlbmJ1cy9ldnRjaG4uYw0KPiBpbmRleCAz
NWFkNDRhLi4zMzhhOTBmIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuYnVzL2V2dGNobi5jDQo+ICsr
KyBiL3NyYy94ZW5idXMvZXZ0Y2huLmMNCj4gQEAgLTM2LDYgKzM2LDcgQEANCj4gDQo+ICAjaW5j
bHVkZSAiZXZ0Y2huLmgiDQo+ICAjaW5jbHVkZSAiZmRvLmgiDQo+ICsjaW5jbHVkZSAiaGFzaF90
YWJsZS5oIg0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUgImFzc2VydC5o
Ig0KPiANCj4gQEAgLTk3LDcgKzk4LDcgQEAgc3RydWN0IF9YRU5CVVNfRVZUQ0hOX0NPTlRFWFQg
ew0KPiAgICAgIFhFTkJVU19ERUJVR19JTlRFUkZBQ0UgICAgICAgICAgRGVidWdJbnRlcmZhY2U7
DQo+ICAgICAgUFhFTkJVU19ERUJVR19DQUxMQkFDSyAgICAgICAgICBEZWJ1Z0NhbGxiYWNrOw0K
PiAgICAgIFhFTkJVU19TSEFSRURfSU5GT19JTlRFUkZBQ0UgICAgU2hhcmVkSW5mb0ludGVyZmFj
ZTsNCj4gLSAgICBQWEVOQlVTX0VWVENITl9DSEFOTkVMDQo+IENoYW5uZWxbWEVOQlVTX1NIQVJF
RF9JTkZPX0VWVENITl9TRUxFQ1RPUl9DT1VOVCAqDQo+IFhFTkJVU19TSEFSRURfSU5GT19FVlRD
SE5fUEVSX1NFTEVDVE9SXTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEUgICAgICAgICAgICAg
IFRhYmxlOw0KPiAgICAgIExJU1RfRU5UUlkgICAgICAgICAgICAgICAgICAgICAgTGlzdDsNCj4g
IH07DQo+IA0KPiBAQCAtMzUxLDE0ICszNTIsMTYgQEAgRXZ0Y2huT3BlbigNCj4gDQo+ICAgICAg
TG9jYWxQb3J0ID0gQ2hhbm5lbC0+TG9jYWxQb3J0Ow0KPiANCj4gLSAgICBBU1NFUlQzVShMb2Nh
bFBvcnQsIDwsIHNpemVvZiAoQ29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtDQo+
ID5DaGFubmVsWzBdKSk7DQo+IC0NCj4gLSAgICAoVk9JRCkgX19FdnRjaG5BY3F1aXJlSW50ZXJy
dXB0TG9jayhDb250ZXh0KTsNCj4gKyAgICBzdGF0dXMgPSBIYXNoVGFibGVBZGQoQ29udGV4dC0+
VGFibGUsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2FsUG9ydCwNCj4gKyAgICAg
ICAgICAgICAgICAgICAgICAgICAgKFVMT05HX1BUUilDaGFubmVsKTsNCj4gKyAgICBpZiAoIU5U
X1NVQ0NFU1Moc3RhdHVzKSkNCj4gKyAgICAgICAgZ290byBmYWlsMzsNCj4gDQo+IC0gICAgQVNT
RVJUM1AoQ29udGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdLCA9PSwgTlVMTCk7DQo+IC0gICAgQ29u
dGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdID0gQ2hhbm5lbDsNCj4gICAgICBDaGFubmVsLT5BY3Rp
dmUgPSBUUlVFOw0KPiANCj4gKyAgICBLZUFjcXVpcmVTcGluTG9ja0F0RHBjTGV2ZWwoJkNvbnRl
eHQtPkxvY2spOw0KPiArDQo+ICAgICAgSW5zZXJ0VGFpbExpc3QoJkNvbnRleHQtPkxpc3QsICZD
aGFubmVsLT5MaXN0RW50cnkpOw0KPiANCj4gICAgICBpZiAoIUlzTGlzdEVtcHR5KCZDb250ZXh0
LT5MaXN0KSAmJiAhQ29udGV4dC0+RW5hYmxlZCkgew0KPiBAQCAtMzY2LDEyICszNjksMTggQEAg
RXZ0Y2huT3BlbigNCj4gICAgICAgICAgQ29udGV4dC0+RW5hYmxlZCA9IFRSVUU7DQo+ICAgICAg
fQ0KPiANCj4gLSAgICBfX0V2dGNoblJlbGVhc2VJbnRlcnJ1cHRMb2NrKENvbnRleHQsIERJU1BB
VENIX0xFVkVMKTsNCj4gKyAgICBLZVJlbGVhc2VTcGluTG9ja0Zyb21EcGNMZXZlbCgmQ29udGV4
dC0+TG9jayk7DQo+IA0KPiAgICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiANCj4gICAgICByZXR1
cm4gQ2hhbm5lbDsNCj4gDQo+ICtmYWlsMzoNCj4gKyAgICBFcnJvcigiZmFpbDNcbiIpOw0KPiAr
DQo+ICsgICAgQ2hhbm5lbC0+TG9jYWxQb3J0ID0gMDsNCj4gKyAgICBSdGxaZXJvTWVtb3J5KCZD
aGFubmVsLT5QYXJhbWV0ZXJzLCBzaXplb2YNCj4gKFhFTkJVU19FVlRDSE5fUEFSQU1FVEVSUykp
Ow0KPiArDQo+ICBmYWlsMjoNCj4gICAgICBFcnJvcigiZmFpbDJcbiIpOw0KPiANCj4gQEAgLTM5
OCw3ICs0MDcsNyBAQCBzdGF0aWMgQk9PTEVBTg0KPiAgRXZ0Y2huVW5tYXNrKA0KPiAgICAgIElO
ICBQSU5URVJGQUNFICAgICAgICAgICAgICBJbnRlcmZhY2UsDQo+ICAgICAgSU4gIFBYRU5CVVNf
RVZUQ0hOX0NIQU5ORUwgIENoYW5uZWwsDQo+IC0gICAgSU4gIEJPT0xFQU4gICAgICAgICAgICAg
ICAgIExvY2tlZA0KPiArICAgIElOICBCT09MRUFOICAgICAgICAgICAgICAgICBJbkNhbGxiYWNr
DQo+ICAgICAgKQ0KPiAgew0KPiAgICAgIFBYRU5CVVNfRVZUQ0hOX0NPTlRFWFQgICAgICBDb250
ZXh0ID0gSW50ZXJmYWNlLT5Db250ZXh0Ow0KPiBAQCAtNDA3LDggKzQxNiwxMCBAQCBFdnRjaG5V
bm1hc2soDQo+IA0KPiAgICAgIEFTU0VSVDNVKENoYW5uZWwtPk1hZ2ljLCA9PSwgWEVOQlVTX0VW
VENITl9DSEFOTkVMX01BR0lDKTsNCj4gDQo+IC0gICAgaWYgKCFMb2NrZWQpDQo+IC0gICAgICAg
IElycWwgPSBfX0V2dGNobkFjcXVpcmVJbnRlcnJ1cHRMb2NrKENvbnRleHQpOw0KPiArICAgIGlm
ICghSW5DYWxsYmFjaykNCj4gKyAgICAgICAgS2VSYWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJ
cnFsKTsgLy8gUHJldmVudCBzdXNwZW5kDQo+ICsNCj4gKyAgICBBU1NFUlQzVShLZUdldEN1cnJl
bnRJcnFsKCksID49LCBESVNQQVRDSF9MRVZFTCk7DQo+IA0KPiAgICAgIGlmIChDaGFubmVsLT5B
Y3RpdmUpIHsNCj4gICAgICAgICAgUGVuZGluZyA9IFhFTkJVU19TSEFSRURfSU5GTyhFdnRjaG5V
bm1hc2ssDQo+IEBAIC00NDYsOCArNDU3LDggQEAgRXZ0Y2huVW5tYXNrKA0KPiAgICAgICAgICB9
DQo+ICAgICAgfQ0KPiANCj4gLSAgICBpZiAoIUxvY2tlZCkNCj4gLSAgICAgICAgX19FdnRjaG5S
ZWxlYXNlSW50ZXJydXB0TG9jayhDb250ZXh0LCBJcnFsKTsNCj4gKyAgICBpZiAoIUluQ2FsbGJh
Y2spDQo+ICsgICAgICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiANCj4gICAgICByZXR1cm4gUGVu
ZGluZzsNCj4gIH0NCj4gQEAgLTUxMyw2ICs1MjQsOCBAQCBFdnRjaG5UcmlnZ2VyKA0KPiANCj4g
ICAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhDb250ZXh0KTsNCj4gDQo+
ICsgICAgQVNTRVJUM1UoS2VHZXRDdXJyZW50SXJxbCgpLCA+PSwgRElTUEFUQ0hfTEVWRUwpOw0K
PiArDQo+ICAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgew0KPiAgICAgICAgICBEb25lU29tZXRo
aW5nID0gRXZ0Y2huQ2FsbGJhY2soQ29udGV4dCwgQ2hhbm5lbCk7DQo+ICAgICAgfSBlbHNlIHsN
Cj4gQEAgLTUzNiw3ICs1NDksOSBAQCBFdnRjaG5DbG9zZSgNCj4gDQo+ICAgICAgQVNTRVJUM1Uo
Q2hhbm5lbC0+TWFnaWMsID09LCBYRU5CVVNfRVZUQ0hOX0NIQU5ORUxfTUFHSUMpOw0KPiANCj4g
LSAgICBJcnFsID0gX19FdnRjaG5BY3F1aXJlSW50ZXJydXB0TG9jayhDb250ZXh0KTsNCj4gKyAg
ICBLZVJhaXNlSXJxbChESVNQQVRDSF9MRVZFTCwgJklycWwpOyAvLyBQcmV2ZW50IHN1c3BlbmQN
Cj4gKw0KPiArICAgIEtlQWNxdWlyZVNwaW5Mb2NrQXREcGNMZXZlbCgmQ29udGV4dC0+TG9jayk7
DQo+IA0KPiAgICAgIFJlbW92ZUVudHJ5TGlzdCgmQ2hhbm5lbC0+TGlzdEVudHJ5KTsNCj4gDQo+
IEBAIC01NDUsMTIgKzU2MCwxMyBAQCBFdnRjaG5DbG9zZSgNCj4gICAgICAgICAgQ29udGV4dC0+
RW5hYmxlZCA9IEZBTFNFOw0KPiAgICAgIH0NCj4gDQo+ICsgICAgS2VSZWxlYXNlU3BpbkxvY2tG
cm9tRHBjTGV2ZWwoJkNvbnRleHQtPkxvY2spOw0KPiArDQo+ICAgICAgUnRsWmVyb01lbW9yeSgm
Q2hhbm5lbC0+TGlzdEVudHJ5LCBzaXplb2YgKExJU1RfRU5UUlkpKTsNCj4gDQo+ICAgICAgaWYg
KENoYW5uZWwtPkFjdGl2ZSkgew0KPiAtICAgICAgICBVTE9ORyAgIExvY2FsUG9ydCA9IENoYW5u
ZWwtPkxvY2FsUG9ydDsNCj4gLQ0KPiAtICAgICAgICBBU1NFUlQzVShMb2NhbFBvcnQsIDwsIHNp
emVvZiAoQ29udGV4dC0+Q2hhbm5lbCkgLyBzaXplb2YgKENvbnRleHQtDQo+ID5DaGFubmVsWzBd
KSk7DQo+ICsgICAgICAgIFVMT05HICAgICAgIExvY2FsUG9ydCA9IENoYW5uZWwtPkxvY2FsUG9y
dDsNCj4gKyAgICAgICAgTlRTVEFUVVMgICAgc3RhdHVzOw0KPiANCj4gICAgICAgICAgQ2hhbm5l
bC0+QWN0aXZlID0gRkFMU0U7DQo+IA0KPiBAQCAtNTYxLDEyICs1NzcsMTAgQEAgRXZ0Y2huQ2xv
c2UoDQo+ICAgICAgICAgIGlmIChDaGFubmVsLT5UeXBlICE9IFhFTkJVU19FVlRDSE5fVFlQRV9G
SVhFRCkNCj4gICAgICAgICAgICAgIChWT0lEKSBFdmVudENoYW5uZWxDbG9zZShMb2NhbFBvcnQp
Ow0KPiANCj4gLSAgICAgICAgQVNTRVJUKENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XSAhPSBO
VUxMKTsNCj4gLSAgICAgICAgQ29udGV4dC0+Q2hhbm5lbFtMb2NhbFBvcnRdID0gTlVMTDsNCj4g
KyAgICAgICAgc3RhdHVzID0gSGFzaFRhYmxlUmVtb3ZlKENvbnRleHQtPlRhYmxlLCBMb2NhbFBv
cnQpOw0KPiArICAgICAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsNCj4gICAgICB9DQo+
IA0KPiAtICAgIF9fRXZ0Y2huUmVsZWFzZUludGVycnVwdExvY2soQ29udGV4dCwgSXJxbCk7DQo+
IC0NCj4gICAgICBDaGFubmVsLT5Mb2NhbFBvcnQgPSAwOw0KPiAgICAgIFJ0bFplcm9NZW1vcnko
JkNoYW5uZWwtPlBhcmFtZXRlcnMsIHNpemVvZg0KPiAoWEVOQlVTX0VWVENITl9QQVJBTUVURVJT
KSk7DQo+IA0KPiBAQCAtNTgwLDYgKzU5NCw4IEBAIEV2dGNobkNsb3NlKA0KPiANCj4gICAgICBB
U1NFUlQoSXNaZXJvTWVtb3J5KENoYW5uZWwsIHNpemVvZiAoWEVOQlVTX0VWVENITl9DSEFOTkVM
KSkpOw0KPiAgICAgIF9fRXZ0Y2huRnJlZShDaGFubmVsKTsNCj4gKw0KPiArICAgIEtlTG93ZXJJ
cnFsKElycWwpOw0KPiAgfQ0KPiANCj4gIHN0YXRpYyBVTE9ORw0KPiBAQCAtNjA2LDEyICs2MjIs
MTMgQEAgRXZ0Y2huUG9sbENhbGxiYWNrKA0KPiAgICAgIFBYRU5CVVNfRVZUQ0hOX0NIQU5ORUwg
IENoYW5uZWw7DQo+ICAgICAgQk9PTEVBTiAgICAgICAgICAgICAgICAgTWFzazsNCj4gICAgICBC
T09MRUFOICAgICAgICAgICAgICAgICBEb25lU29tZXRoaW5nOw0KPiArICAgIE5UU1RBVFVTICAg
ICAgICAgICAgICAgIHN0YXR1czsNCj4gDQo+IC0gICAgQVNTRVJUM1UoTG9jYWxQb3J0LCA8LCBz
aXplb2YgKENvbnRleHQtPkNoYW5uZWwpIC8gc2l6ZW9mIChDb250ZXh0LQ0KPiA+Q2hhbm5lbFsw
XSkpOw0KPiAtDQo+IC0gICAgQ2hhbm5lbCA9IENvbnRleHQtPkNoYW5uZWxbTG9jYWxQb3J0XTsN
Cj4gLQ0KPiAtICAgIGlmIChDaGFubmVsID09IE5VTEwpIHsNCj4gKyAgICBzdGF0dXMgPSBIYXNo
VGFibGVMb29rdXAoQ29udGV4dC0+VGFibGUsDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIExvY2FsUG9ydCwNCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFBVTE9OR19Q
VFIpJkNoYW5uZWwpOw0KPiArDQo+ICsgICAgaWYgKCFOVF9TVUNDRVNTKHN0YXR1cykpIHsNCj4g
ICAgICAgICAgV2FybmluZygiWyVkXTogSU5WQUxJRCBQT1JUXG4iLCBMb2NhbFBvcnQpOw0KPiAN
Cj4gICAgICAgICAgWEVOQlVTX1NIQVJFRF9JTkZPKEV2dGNobk1hc2ssDQo+IEBAIC02OTcsMTQg
KzcxNCwxMyBAQCBFdnRjaG5TdXNwZW5kQ2FsbGJhY2tFYXJseSgNCj4gICAgICAgICAgQ2hhbm5l
bCA9IENPTlRBSU5JTkdfUkVDT1JEKExpc3RFbnRyeSwNCj4gWEVOQlVTX0VWVENITl9DSEFOTkVM
LCBMaXN0RW50cnkpOw0KPiANCj4gICAgICAgICAgaWYgKENoYW5uZWwtPkFjdGl2ZSkgew0KPiAt
ICAgICAgICAgICAgVUxPTkcgICBMb2NhbFBvcnQgPSBDaGFubmVsLT5Mb2NhbFBvcnQ7DQo+IC0N
Cj4gLSAgICAgICAgICAgIEFTU0VSVDNVKExvY2FsUG9ydCwgPCwgc2l6ZW9mIChDb250ZXh0LT5D
aGFubmVsKSAvIHNpemVvZiAoQ29udGV4dC0NCj4gPkNoYW5uZWxbMF0pKTsNCj4gKyAgICAgICAg
ICAgIFVMT05HICAgICAgIExvY2FsUG9ydCA9IENoYW5uZWwtPkxvY2FsUG9ydDsNCj4gKyAgICAg
ICAgICAgIE5UU1RBVFVTICAgIHN0YXR1czsNCj4gDQo+ICAgICAgICAgICAgICBDaGFubmVsLT5B
Y3RpdmUgPSBGQUxTRTsNCj4gDQo+IC0gICAgICAgICAgICBBU1NFUlQoQ29udGV4dC0+Q2hhbm5l
bFtMb2NhbFBvcnRdICE9IE5VTEwpOw0KPiAtICAgICAgICAgICAgQ29udGV4dC0+Q2hhbm5lbFtM
b2NhbFBvcnRdID0gTlVMTDsNCj4gKyAgICAgICAgICAgIHN0YXR1cyA9IEhhc2hUYWJsZVJlbW92
ZShDb250ZXh0LT5UYWJsZSwgTG9jYWxQb3J0KTsNCj4gKyAgICAgICAgICAgIEFTU0VSVChOVF9T
VUNDRVNTKHN0YXR1cykpOw0KPiAgICAgICAgICB9DQo+ICAgICAgfQ0KPiANCj4gQEAgLTk1OCw2
ICs5NzQsMTAgQEAgRXZ0Y2huSW5pdGlhbGl6ZSgNCj4gICAgICBpZiAoKkNvbnRleHQgPT0gTlVM
TCkNCj4gICAgICAgICAgZ290byBmYWlsMTsNCj4gDQo+ICsgICAgc3RhdHVzID0gSGFzaFRhYmxl
Q3JlYXRlKCYoKkNvbnRleHQpLT5UYWJsZSk7DQo+ICsgICAgaWYgKCFOVF9TVUNDRVNTKHN0YXR1
cykpDQo+ICsgICAgICAgIGdvdG8gZmFpbDI7DQo+ICsNCj4gICAgICBzdGF0dXMgPSBTdXNwZW5k
R2V0SW50ZXJmYWNlKEZkb0dldFN1c3BlbmRDb250ZXh0KEZkbyksDQo+ICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICBYRU5CVVNfU1VTUEVORF9JTlRFUkZBQ0VfVkVSU0lPTl9NQVgs
DQo+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoUElOVEVSRkFDRSkmKCpDb250
ZXh0KS0+U3VzcGVuZEludGVyZmFjZSwNCj4gQEAgLTk4OCw2ICsxMDA4LDEyIEBAIEV2dGNobklu
aXRpYWxpemUoDQo+IA0KPiAgICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsNCj4gDQo+ICtmYWls
MjoNCj4gKyAgICBFcnJvcigiZmFpbDJcbiIpOw0KPiArDQo+ICsgICAgQVNTRVJUKElzWmVyb01l
bW9yeShDb250ZXh0LCBzaXplb2YgKFhFTkJVU19FVlRDSE5fQ09OVEVYVCkpKTsNCj4gKyAgICBf
X0V2dGNobkZyZWUoQ29udGV4dCk7DQo+ICsNCj4gIGZhaWwxOg0KPiAgICAgIEVycm9yKCJmYWls
MSAoJTA4eClcbiIsIHN0YXR1cyk7DQo+IA0KPiBAQCAtMTA1Myw2ICsxMDc5LDkgQEAgRXZ0Y2hu
VGVhcmRvd24oDQo+ICAgICAgUnRsWmVyb01lbW9yeSgmQ29udGV4dC0+U3VzcGVuZEludGVyZmFj
ZSwNCj4gICAgICAgICAgICAgICAgICAgIHNpemVvZiAoWEVOQlVTX1NVU1BFTkRfSU5URVJGQUNF
KSk7DQo+IA0KPiArICAgIEhhc2hUYWJsZURlc3Ryb3koQ29udGV4dC0+VGFibGUpOw0KPiArICAg
IENvbnRleHQtPlRhYmxlID0gTlVMTDsNCj4gKw0KPiAgICAgIEFTU0VSVChJc1plcm9NZW1vcnko
Q29udGV4dCwgc2l6ZW9mIChYRU5CVVNfRVZUQ0hOX0NPTlRFWFQpKSk7DQo+ICAgICAgX19FdnRj
aG5GcmVlKENvbnRleHQpOw0KPiANCj4gZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvaGFzaF90YWJs
ZS5jIGIvc3JjL3hlbmJ1cy9oYXNoX3RhYmxlLmMNCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4g
aW5kZXggMDAwMDAwMC4uYjhlMjdkOA0KPiAtLS0gL2Rldi9udWxsDQo+ICsrKyBiL3NyYy94ZW5i
dXMvaGFzaF90YWJsZS5jDQo+IEBAIC0wLDAgKzEsMzY3IEBADQo+ICsvKiBDb3B5cmlnaHQgKGMp
IENpdHJpeCBTeXN0ZW1zIEluYy4NCj4gKyAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuDQo+ICsgKg0K
PiArICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3JtcywN
Cj4gKyAqIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlk
ZWQNCj4gKyAqIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6DQo+ICsgKg0K
PiArICogKiAgIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUg
YWJvdmUNCj4gKyAqICAgICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9u
cyBhbmQgdGhlDQo+ICsgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIuDQo+ICsgKiAqICAgUmVk
aXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZQ0KPiAr
ICogICAgIGNvcHlyaWdodCBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUN
Cj4gKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQv
b3Igb3RoZXINCj4gKyAqICAgICBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0
aW9uLg0KPiArICoNCj4gKyAqIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlS
SUdIVCBIT0xERVJTIEFORA0KPiArICogQ09OVFJJQlVUT1JTICJBUyBJUyIgQU5EIEFOWSBFWFBS
RVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywNCj4gKyAqIElOQ0xVRElORywgQlVUIE5PVCBMSU1J
VEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTIE9GDQo+ICsgKiBNRVJDSEFOVEFCSUxJVFkg
QU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRQ0KPiArICogRElTQ0xBSU1F
RC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1INCj4gKyAqIENPTlRS
SUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLA0K
PiArICogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xV
RElORywNCj4gKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVU
RSBHT09EUyBPUg0KPiArICogU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRT
OyBPUiBCVVNJTkVTUw0KPiArICogSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04g
QU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksDQo+ICsgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcNCj4gKyAqIE5FR0xJR0VOQ0UgT1IgT1RI
RVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UNCj4gKyAqIE9GIFRISVMg
U09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YNCj4gKyAqIFNV
Q0ggREFNQUdFLg0KPiArICovDQo+ICsNCj4gKyNpbmNsdWRlIDxudGRkay5oPg0KPiArI2luY2x1
ZGUgPHN0ZGFyZy5oPg0KPiArI2luY2x1ZGUgPHhlbi5oPg0KPiArI2luY2x1ZGUgPHV0aWwuaD4N
Cj4gKw0KPiArI2luY2x1ZGUgImhhc2hfdGFibGUuaCINCj4gKyNpbmNsdWRlICJkYmdfcHJpbnQu
aCINCj4gKyNpbmNsdWRlICJhc3NlcnQuaCINCj4gKw0KPiArdHlwZWRlZiBzdHJ1Y3QgX1hFTkJV
U19IQVNIX1RBQkxFX05PREUgew0KPiArICAgIExJU1RfRU5UUlkgIExpc3RFbnRyeTsNCj4gKyAg
ICBVTE9OR19QVFIgICBLZXk7DQo+ICsgICAgVUxPTkdfUFRSICAgVmFsdWU7DQo+ICt9IFhFTkJV
U19IQVNIX1RBQkxFX05PREUsICpQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERTsNCj4gKw0KPiArdHlw
ZWRlZiBzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCB7DQo+ICsgICAgTE9ORyAgICAg
ICAgTG9jazsNCj4gKyAgICBMSVNUX0VOVFJZICBMaXN0Ow0KPiArfSBYRU5CVVNfSEFTSF9UQUJM
RV9CVUNLRVQsICpQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUOw0KPiArDQo+ICsjZGVmaW5lIFhF
TkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFMgXA0KPiArICAgICgxIDw8IChzaXplb2YgKFVDSEFS
KSAqIDgpKQ0KPiArDQo+ICtzdHJ1Y3QgX1hFTkJVU19IQVNIX1RBQkxFIHsNCj4gKyAgICBYRU5C
VVNfSEFTSF9UQUJMRV9CVUNLRVQNCj4gQnVja2V0W1hFTkJVU19IQVNIX1RBQkxFX05SX0JVQ0tF
VFNdOw0KPiArfTsNCj4gKw0KPiArI2RlZmluZSBYRU5CVVNfSEFTSF9UQUJMRV9UQUcgICAnSFNB
SCcNCj4gKw0KPiArc3RhdGljIEZPUkNFSU5MSU5FIFBWT0lEDQo+ICtfX0hhc2hUYWJsZUFsbG9j
YXRlKA0KPiArICAgIElOICBVTE9ORyAgIExlbmd0aA0KPiArICAgICkNCj4gK3sNCj4gKyAgICBy
ZXR1cm4gX19BbGxvY2F0ZVBvb2xXaXRoVGFnKE5vblBhZ2VkUG9vbCwgTGVuZ3RoLA0KPiBYRU5C
VVNfSEFTSF9UQUJMRV9UQUcpOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgRk9SQ0VJTkxJTkUgVk9J
RA0KPiArX19IYXNoVGFibGVGcmVlKA0KPiArICAgIElOICBQVk9JRCAgIEJ1ZmZlcg0KPiArICAg
ICkNCj4gK3sNCj4gKyAgICBFeEZyZWVQb29sV2l0aFRhZyhCdWZmZXIsIFhFTkJVU19IQVNIX1RB
QkxFX1RBRyk7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBVTE9ORw0KPiArSGFzaFRhYmxlSGFzaCgN
Cj4gKyAgICBJTiAgVUxPTkdfUFRSICAgS2V5DQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBVQ0hB
UiAgICAgICAgICBBcnJheSA9IChQVUNIQVIpJktleTsNCj4gKyAgICBVTE9ORyAgICAgICAgICAg
QWNjdW11bGF0b3I7DQo+ICsgICAgVUxPTkcgICAgICAgICAgIEluZGV4Ow0KPiArDQo+ICsgICAg
QWNjdW11bGF0b3IgPSAwOw0KPiArDQo+ICsgICAgZm9yIChJbmRleCA9IDA7IEluZGV4IDwgc2l6
ZW9mIChVTE9OR19QVFIpOyBJbmRleCsrKSB7DQo+ICsgICAgICAgIFVMT05HICAgT3ZlcmZsb3c7
DQo+ICsNCj4gKyAgICAgICAgQWNjdW11bGF0b3IgPSAoQWNjdW11bGF0b3IgPDwgNCkgKyBBcnJh
eVtJbmRleF07DQo+ICsNCj4gKyAgICAgICAgT3ZlcmZsb3cgPSBBY2N1bXVsYXRvciAmIDB4MDAw
MDBmMDA7DQo+ICsgICAgICAgIGlmIChPdmVyZmxvdyAhPSAwKSB7DQo+ICsgICAgICAgICAgICBB
Y2N1bXVsYXRvciBePSBPdmVyZmxvdyA+PiA4Ow0KPiArICAgICAgICAgICAgQWNjdW11bGF0b3Ig
Xj0gT3ZlcmZsb3c7DQo+ICsgICAgICAgIH0NCj4gKyAgICB9DQo+ICsNCj4gKyAgICBBU1NFUlQz
VShBY2N1bXVsYXRvciwgPCwgWEVOQlVTX0hBU0hfVEFCTEVfTlJfQlVDS0VUUyk7DQo+ICsNCj4g
KyAgICByZXR1cm4gQWNjdW11bGF0b3I7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYw0KPiArX0lSUUxf
cmVxdWlyZXNfbWF4XyhISUdIX0xFVkVMKQ0KPiArX0lSUUxfc2F2ZXNfDQo+ICtfSVJRTF9yYWlz
ZXNfKEhJR0hfTEVWRUwpDQo+ICtLSVJRTA0KPiArX19IYXNoVGFibGVCdWNrZXRMb2NrKA0KPiAr
ICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0LA0KPiArICAgIElOICBC
T09MRUFOICAgICAgICAgICAgICAgICAgICAgV3JpdGVyDQo+ICsgICAgKQ0KPiArew0KPiArICAg
IEtJUlFMICAgICAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKw0KPiArICAgIEtlUmFp
c2VJcnFsKEhJR0hfTEVWRUwsICZJcnFsKTsNCj4gKw0KPiArICAgIGZvciAoOzspIHsNCj4gKyAg
ICAgICAgTE9ORyAgICBMb2NrOw0KPiArICAgICAgICBMT05HICAgIFJlYWRlcnM7DQo+ICsgICAg
ICAgIExPTkcgICAgV3JpdGVyczsNCj4gKyAgICAgICAgTE9ORyAgICBPbGQ7DQo+ICsgICAgICAg
IExPTkcgICAgTmV3Ow0KPiArDQo+ICsgICAgICAgIEtlTWVtb3J5QmFycmllcigpOw0KPiArDQo+
ICsgICAgICAgIExvY2sgPSBCdWNrZXQtPkxvY2s7DQo+ICsgICAgICAgIFJlYWRlcnMgPSBMb2Nr
ID4+IDE7DQo+ICsgICAgICAgIFdyaXRlcnMgPSBMb2NrICYgMTsNCj4gKw0KPiArICAgICAgICAv
LyBUaGVyZSBtdXN0IGJlIG5vIGV4aXN0aW5nIHdyaXRlcg0KPiArICAgICAgICBPbGQgPSBSZWFk
ZXJzIDw8IDE7DQo+ICsNCj4gKyAgICAgICAgaWYgKFdyaXRlcikNCj4gKyAgICAgICAgICAgIFdy
aXRlcnMrKzsNCj4gKyAgICAgICAgZWxzZQ0KPiArICAgICAgICAgICAgUmVhZGVycysrOw0KPiAr
DQo+ICsgICAgICAgIE5ldyA9IChSZWFkZXJzIDw8IDEpIHwgKFdyaXRlcnMgJiAxKTsNCj4gKw0K
PiArICAgICAgICBpZiAoSW50ZXJsb2NrZWRDb21wYXJlRXhjaGFuZ2UoJkJ1Y2tldC0+TG9jaywg
TmV3LCBPbGQpICE9IE9sZCkNCj4gKyAgICAgICAgICAgIGNvbnRpbnVlOw0KPiArDQo+ICsgICAg
ICAgIC8vDQo+ICsgICAgICAgIC8vIFdlIGFyZSBkb25lIGlmIHdlJ3JlIG5vdCBhIHdyaXRlciwg
b3IgdGhlcmUgYXJlIG5vIHJlYWRlcnMNCj4gKyAgICAgICAgLy8gbGVmdC4NCj4gKyAgICAgICAg
Ly8NCj4gKyAgICAgICAgaWYgKCFXcml0ZXIgfHwgUmVhZGVycyA9PSAwKQ0KPiArICAgICAgICAg
ICAgYnJlYWs7DQo+ICsgICAgfQ0KPiArDQo+ICsgICAgcmV0dXJuIElycWw7DQo+ICt9DQo+ICsN
Cj4gKyNkZWZpbmUgSGFzaFRhYmxlQnVja2V0TG9jayhfQnVja2V0LCBfV3JpdGVyLCBfSXJxbCkg
ICAgICAgICAgICBcDQo+ICsgICAgZG8geyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgXA0KPiArICAgICAgICAqKF9JcnFsKSA9IF9fSGFzaFRh
YmxlQnVja2V0TG9jaygoX0J1Y2tldCksIChfV3JpdGVyKSk7IFwNCj4gKyAgICB9IHdoaWxlIChG
QUxTRSkNCj4gKw0KPiArc3RhdGljDQo+ICtfX2Rydl9yZXF1aXJlc0lSUUwoSElHSF9MRVZFTCkN
Cj4gK1ZPSUQNCj4gK0hhc2hUYWJsZUJ1Y2tldFVubG9jaygNCj4gKyAgICBJTiAgUFhFTkJVU19I
QVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCwNCj4gKyAgICBJTiAgQk9PTEVBTiAgICAgICAgICAg
ICAgICAgICAgIFdyaXRlciwNCj4gKyAgICBJTiAgX19kcnZfcmVzdG9yZXNJUlFMIEtJUlFMICAg
IElycWwNCj4gKyAgICApDQo+ICt7DQo+ICsgICAgZm9yICg7Oykgew0KPiArICAgICAgICBMT05H
ICAgIExvY2s7DQo+ICsgICAgICAgIExPTkcgICAgUmVhZGVyczsNCj4gKyAgICAgICAgTE9ORyAg
ICBXcml0ZXJzOw0KPiArICAgICAgICBMT05HICAgIE9sZDsNCj4gKyAgICAgICAgTE9ORyAgICBO
ZXc7DQo+ICsNCj4gKyAgICAgICAgS2VNZW1vcnlCYXJyaWVyKCk7DQo+ICsNCj4gKyAgICAgICAg
TG9jayA9IEJ1Y2tldC0+TG9jazsNCj4gKyAgICAgICAgUmVhZGVycyA9IExvY2sgPj4gMTsNCj4g
KyAgICAgICAgV3JpdGVycyA9IExvY2sgJiAxOw0KPiArDQo+ICsgICAgICAgIE9sZCA9IChSZWFk
ZXJzIDw8IDEpIHwgKFdyaXRlcnMgJiAxKTsNCj4gKw0KPiArICAgICAgICBpZiAoV3JpdGVyKSB7
DQo+ICsgICAgICAgICAgICBBU1NFUlQoV3JpdGVycyAhPSAwKTsNCj4gKyAgICAgICAgICAgIC0t
V3JpdGVyczsNCj4gKyAgICAgICAgfSBlbHNlIHsNCj4gKyAgICAgICAgICAgIC0tUmVhZGVyczsN
Cj4gKyAgICAgICAgfQ0KPiArDQo+ICsgICAgICAgIE5ldyA9IChSZWFkZXJzIDw8IDEpIHwgKFdy
aXRlcnMgJiAxKTsNCj4gKw0KPiArICAgICAgICBpZiAoSW50ZXJsb2NrZWRDb21wYXJlRXhjaGFu
Z2UoJkJ1Y2tldC0+TG9jaywgTmV3LCBPbGQpID09IE9sZCkNCj4gKyAgICAgICAgICAgIGJyZWFr
Ow0KPiArICAgIH0NCj4gKw0KPiArICAgIEtlTG93ZXJJcnFsKElycWwpOw0KPiArfQ0KPiArDQo+
ICtOVFNUQVRVUw0KPiArSGFzaFRhYmxlQWRkKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFC
TEUgICAgICBUYWJsZSwNCj4gKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAgICAgICAgS2V5LA0K
PiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBWYWx1ZQ0KPiArICAgICkNCj4gK3sN
Cj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsNCj4gKyAgICBQWEVOQlVT
X0hBU0hfVEFCTEVfQlVDS0VUICAgQnVja2V0Ow0KPiArICAgIEtJUlFMICAgICAgICAgICAgICAg
ICAgICAgICBJcnFsOw0KPiArICAgIE5UU1RBVFVTICAgICAgICAgICAgICAgICAgICBzdGF0dXM7
DQo+ICsNCj4gKyAgICBOb2RlID0gX19IYXNoVGFibGVBbGxvY2F0ZShzaXplb2YgKFhFTkJVU19I
QVNIX1RBQkxFX05PREUpKTsNCj4gKw0KPiArICAgIHN0YXR1cyA9IFNUQVRVU19OT19NRU1PUlk7
DQo+ICsgICAgaWYgKE5vZGUgPT0gTlVMTCkNCj4gKyAgICAgICAgZ290byBmYWlsMTsNCj4gKw0K
PiArICAgIE5vZGUtPktleSA9IEtleTsNCj4gKyAgICBOb2RlLT5WYWx1ZSA9IFZhbHVlOw0KPiAr
DQo+ICsgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkpXTsNCj4g
Kw0KPiArICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0LCBUUlVFLCAmSXJxbCk7DQo+ICsg
ICAgSW5zZXJ0VGFpbExpc3QoJkJ1Y2tldC0+TGlzdCwgJk5vZGUtPkxpc3RFbnRyeSk7DQo+ICsg
ICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgVFJVRSwgSXJxbCk7DQo+ICsNCj4gKyAg
ICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7DQo+ICsNCj4gK2ZhaWwxOg0KPiArICAgIEVycm9yKCJm
YWlsMSAoJTA4eClcbiIsIHN0YXR1cyk7DQo+ICsNCj4gKyAgICByZXR1cm4gc3RhdHVzOw0KPiAr
fQ0KPiArDQo+ICtOVFNUQVRVUw0KPiArSGFzaFRhYmxlUmVtb3ZlKA0KPiArICAgIElOICBQWEVO
QlVTX0hBU0hfVEFCTEUgICAgICBUYWJsZSwNCj4gKyAgICBJTiAgVUxPTkdfUFRSICAgICAgICAg
ICAgICAgS2V5DQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBYRU5CVVNfSEFTSF9UQUJMRV9CVUNL
RVQgICBCdWNrZXQ7DQo+ICsgICAgUExJU1RfRU5UUlkgICAgICAgICAgICAgICAgIExpc3RFbnRy
eTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAgICAgTm9kZTsNCj4gKyAgICBLSVJR
TCAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKyAgICBOVFNUQVRVUyAgICAgICAgICAg
ICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgQnVja2V0ID0gJlRhYmxlLT5CdWNrZXRbSGFz
aFRhYmxlSGFzaChLZXkpXTsNCj4gKw0KPiArICAgIEhhc2hUYWJsZUJ1Y2tldExvY2soQnVja2V0
LCBUUlVFLCAmSXJxbCk7DQo+ICsNCj4gKyAgICBMaXN0RW50cnkgPSBCdWNrZXQtPkxpc3QuRmxp
bms7DQo+ICsgICAgd2hpbGUgKExpc3RFbnRyeSAhPSAmQnVja2V0LT5MaXN0KSB7DQo+ICsgICAg
ICAgIE5vZGUgPSBDT05UQUlOSU5HX1JFQ09SRChMaXN0RW50cnksIFhFTkJVU19IQVNIX1RBQkxF
X05PREUsDQo+IExpc3RFbnRyeSk7DQo+ICsNCj4gKyAgICAgICAgaWYgKE5vZGUtPktleSA9PSBL
ZXkpDQo+ICsgICAgICAgICAgICBnb3RvIGZvdW5kOw0KPiArICAgIH0NCj4gKw0KPiArICAgIEhh
c2hUYWJsZUJ1Y2tldFVubG9jayhCdWNrZXQsIFRSVUUsIElycWwpOw0KPiArDQo+ICsgICAgc3Rh
dHVzID0gU1RBVFVTX09CSkVDVF9OQU1FX05PVF9GT1VORDsNCj4gKyAgICBnb3RvIGZhaWwxOw0K
PiArDQo+ICtmb3VuZDoNCj4gKyAgICBSZW1vdmVFbnRyeUxpc3QoTGlzdEVudHJ5KTsNCj4gKyAg
ICBfX0hhc2hUYWJsZUZyZWUoTm9kZSk7DQo+ICsNCj4gKyAgICBIYXNoVGFibGVCdWNrZXRVbmxv
Y2soQnVja2V0LCBUUlVFLCBJcnFsKTsNCj4gKw0KPiArICAgIHJldHVybiBTVEFUVVNfU1VDQ0VT
UzsNCj4gKw0KPiArZmFpbDE6DQo+ICsgICAgRXJyb3IoImZhaWwxICglMDh4KVxuIiwgc3RhdHVz
KTsNCj4gKw0KPiArICAgIHJldHVybiBzdGF0dXM7DQo+ICt9DQo+ICsNCj4gK05UU1RBVFVTDQo+
ICtIYXNoVGFibGVMb29rdXAoDQo+ICsgICAgSU4gIFBYRU5CVVNfSEFTSF9UQUJMRSAgICAgIFRh
YmxlLA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgICAgICBLZXksDQo+ICsgICAgT1VU
IFBVTE9OR19QVFIgICAgICAgICAgICAgIFZhbHVlDQo+ICsgICAgKQ0KPiArew0KPiArICAgIFBY
RU5CVVNfSEFTSF9UQUJMRV9CVUNLRVQgICBCdWNrZXQ7DQo+ICsgICAgUExJU1RfRU5UUlkgICAg
ICAgICAgICAgICAgIExpc3RFbnRyeTsNCj4gKyAgICBQWEVOQlVTX0hBU0hfVEFCTEVfTk9ERSAg
ICAgTm9kZTsNCj4gKyAgICBLSVJRTCAgICAgICAgICAgICAgICAgICAgICAgSXJxbDsNCj4gKyAg
ICBOVFNUQVRVUyAgICAgICAgICAgICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgQnVja2V0
ID0gJlRhYmxlLT5CdWNrZXRbSGFzaFRhYmxlSGFzaChLZXkpXTsNCj4gKw0KPiArICAgIEhhc2hU
YWJsZUJ1Y2tldExvY2soQnVja2V0LCBGQUxTRSwgJklycWwpOw0KPiArDQo+ICsgICAgTGlzdEVu
dHJ5ID0gQnVja2V0LT5MaXN0LkZsaW5rOw0KPiArICAgIHdoaWxlIChMaXN0RW50cnkgIT0gJkJ1
Y2tldC0+TGlzdCkgew0KPiArICAgICAgICBOb2RlID0gQ09OVEFJTklOR19SRUNPUkQoTGlzdEVu
dHJ5LCBYRU5CVVNfSEFTSF9UQUJMRV9OT0RFLA0KPiBMaXN0RW50cnkpOw0KPiArDQo+ICsgICAg
ICAgIGlmIChOb2RlLT5LZXkgPT0gS2V5KQ0KPiArICAgICAgICAgICAgZ290byBmb3VuZDsNCj4g
KyAgICB9DQo+ICsNCj4gKyAgICBIYXNoVGFibGVCdWNrZXRVbmxvY2soQnVja2V0LCBGQUxTRSwg
SXJxbCk7DQo+ICsNCj4gKyAgICBzdGF0dXMgPSBTVEFUVVNfT0JKRUNUX05BTUVfTk9UX0ZPVU5E
Ow0KPiArICAgIGdvdG8gZmFpbDE7DQo+ICsNCj4gK2ZvdW5kOg0KPiArICAgICpWYWx1ZSA9IE5v
ZGUtPlZhbHVlOw0KPiArDQo+ICsgICAgSGFzaFRhYmxlQnVja2V0VW5sb2NrKEJ1Y2tldCwgRkFM
U0UsIElycWwpOw0KPiArDQo+ICsgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOw0KPiArDQo+ICtm
YWlsMToNCj4gKyAgICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOw0KPiArDQo+ICsg
ICAgcmV0dXJuIHN0YXR1czsNCj4gK30NCj4gKw0KPiArTlRTVEFUVVMNCj4gK0hhc2hUYWJsZUNy
ZWF0ZSgNCj4gKyAgICBPVVQgUFhFTkJVU19IQVNIX1RBQkxFICAqVGFibGUNCj4gKyAgICApDQo+
ICt7DQo+ICsgICAgVUxPTkcgICAgICAgICAgICAgICAgICAgSW5kZXg7DQo+ICsgICAgTlRTVEFU
VVMgICAgICAgICAgICAgICAgc3RhdHVzOw0KPiArDQo+ICsgICAgKlRhYmxlID0gX19IYXNoVGFi
bGVBbGxvY2F0ZShzaXplb2YgKFhFTkJVU19IQVNIX1RBQkxFKSk7DQo+ICsNCj4gKyAgICBzdGF0
dXMgPSBTVEFUVVNfTk9fTUVNT1JZOw0KPiArICAgIGlmICgqVGFibGUgPT0gTlVMTCkNCj4gKyAg
ICAgICAgZ290byBmYWlsMTsNCj4gKw0KPiArICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IFhF
TkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFM7IEluZGV4KyspIHsNCj4gKyAgICAgICAgUFhFTkJV
U19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCA9ICYoKlRhYmxlKS0+QnVja2V0W0luZGV4XTsN
Cj4gKw0KPiArICAgICAgICBJbml0aWFsaXplTGlzdEhlYWQoJkJ1Y2tldC0+TGlzdCk7DQo+ICsg
ICAgfQ0KPiArDQo+ICsgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOw0KPiArDQo+ICtmYWlsMToN
Cj4gKyAgICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOw0KPiArDQo+ICsgICAgcmV0
dXJuIHN0YXR1czsNCj4gK30NCj4gKw0KPiArVk9JRA0KPiArSGFzaFRhYmxlRGVzdHJveSgNCj4g
KyAgICBJTiAgUFhFTkJVU19IQVNIX1RBQkxFICBUYWJsZQ0KPiArICAgICkNCj4gK3sNCj4gKyAg
ICBVTE9ORyAgICAgICAgICAgICAgICAgICBJbmRleDsNCj4gKw0KPiArICAgIGZvciAoSW5kZXgg
PSAwOyBJbmRleCA8IFhFTkJVU19IQVNIX1RBQkxFX05SX0JVQ0tFVFM7IEluZGV4KyspIHsNCj4g
KyAgICAgICAgUFhFTkJVU19IQVNIX1RBQkxFX0JVQ0tFVCAgIEJ1Y2tldCA9ICZUYWJsZS0+QnVj
a2V0W0luZGV4XTsNCj4gKw0KPiArICAgICAgICBBU1NFUlQoSXNMaXN0RW1wdHkoJkJ1Y2tldC0+
TGlzdCkpOw0KPiArICAgICAgICBSdGxaZXJvTWVtb3J5KCZCdWNrZXQtPkxpc3QsIHNpemVvZiAo
TElTVF9FTlRSWSkpOw0KPiArICAgIH0NCj4gKw0KPiArICAgIEFTU0VSVChJc1plcm9NZW1vcnko
VGFibGUsIHNpemVvZiAoWEVOQlVTX0hBU0hfVEFCTEUpKSk7DQo+ICsgICAgX19IYXNoVGFibGVG
cmVlKFRhYmxlKTsNCj4gK30NCj4gKw0KPiBkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9oYXNoX3Rh
YmxlLmggYi9zcmMveGVuYnVzL2hhc2hfdGFibGUuaA0KPiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0K
PiBpbmRleCAwMDAwMDAwLi5jZTBjOTA2DQo+IC0tLSAvZGV2L251bGwNCj4gKysrIGIvc3JjL3hl
bmJ1cy9oYXNoX3RhYmxlLmgNCj4gQEAgLTAsMCArMSw3MCBAQA0KPiArLyogQ29weXJpZ2h0IChj
KSBDaXRyaXggU3lzdGVtcyBJbmMuDQo+ICsgKiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KPiArICoN
Cj4gKyAqIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMs
DQo+ICsgKiB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3Zp
ZGVkDQo+ICsgKiB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0Og0KPiArICoN
Cj4gKyAqICogICBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhl
IGFib3ZlDQo+ICsgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlv
bnMgYW5kIHRoZQ0KPiArICogICAgIGZvbGxvd2luZyBkaXNjbGFpbWVyLg0KPiArICogKiAgIFJl
ZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUNCj4g
KyAqICAgICBjb3B5cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhl
DQo+ICsgKiAgICAgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5k
L29yIG90aGVyDQo+ICsgKiAgICAgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1
dGlvbi4NCj4gKyAqDQo+ICsgKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZ
UklHSFQgSE9MREVSUyBBTkQNCj4gKyAqIENPTlRSSUJVVE9SUyAiQVMgSVMiIEFORCBBTlkgRVhQ
UkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsDQo+ICsgKiBJTkNMVURJTkcsIEJVVCBOT1QgTElN
SVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRg0KPiArICogTUVSQ0hBTlRBQklMSVRZ
IEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUNCj4gKyAqIERJU0NMQUlN
RUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SDQo+ICsgKiBDT05U
UklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwN
Cj4gKyAqIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNM
VURJTkcsDQo+ICsgKiBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRV
VEUgR09PRFMgT1INCj4gKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklU
UzsgT1IgQlVTSU5FU1MNCj4gKyAqIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9O
IEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLA0KPiArICogV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RS
SUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HDQo+ICsgKiBORUdMSUdFTkNFIE9SIE9U
SEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFDQo+ICsgKiBPRiBUSElT
IFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GDQo+ICsgKiBT
VUNIIERBTUFHRS4NCj4gKyAqLw0KPiArDQo+ICsjaWZuZGVmIF9YRU5CVVNfSEFTSF9UQUJMRV9I
DQo+ICsjZGVmaW5lIF9YRU5CVVNfSEFTSF9UQUJMRV9IDQo+ICsNCj4gKyNpbmNsdWRlIDxudGRk
ay5oPg0KPiArDQo+ICt0eXBlZGVmIHN0cnVjdCBfWEVOQlVTX0hBU0hfVEFCTEUgWEVOQlVTX0hB
U0hfVEFCTEUsDQo+ICpQWEVOQlVTX0hBU0hfVEFCTEU7DQo+ICsNCj4gK2V4dGVybiBOVFNUQVRV
Uw0KPiArSGFzaFRhYmxlQWRkKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxl
LA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleSwNCj4gKyAgICBJTiAgVUxPTkdf
UFRSICAgICAgICAgICBWYWx1ZQ0KPiArICAgICk7DQo+ICsNCj4gK2V4dGVybiBOVFNUQVRVUw0K
PiArSGFzaFRhYmxlUmVtb3ZlKA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxl
LA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleQ0KPiArICAgICk7DQo+ICsNCj4g
K2V4dGVybiBOVFNUQVRVUw0KPiArSGFzaFRhYmxlTG9va3VwKA0KPiArICAgIElOICBQWEVOQlVT
X0hBU0hfVEFCTEUgIFRhYmxlLA0KPiArICAgIElOICBVTE9OR19QVFIgICAgICAgICAgIEtleSwN
Cj4gKyAgICBPVVQgUFVMT05HX1BUUiAgICAgICAgICBWYWx1ZQ0KPiArICAgICk7DQo+ICsNCj4g
K2V4dGVybiBOVFNUQVRVUw0KPiArSGFzaFRhYmxlQ3JlYXRlKA0KPiArICAgIE9VVCBQWEVOQlVT
X0hBU0hfVEFCTEUgICpUYWJsZQ0KPiArICAgICk7DQo+ICsNCj4gK2V4dGVybiBWT0lEDQo+ICtI
YXNoVGFibGVEZXN0cm95KA0KPiArICAgIElOICBQWEVOQlVTX0hBU0hfVEFCTEUgIFRhYmxlDQo+
ICsgICAgKTsNCj4gKw0KPiArI2VuZGlmICAvLyBfWEVOQlVTX0hBU0hfVEFCTEVfSA0KPiArDQo+
IGRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3NoYXJlZF9pbmZvLmMgYi9zcmMveGVuYnVzL3NoYXJl
ZF9pbmZvLmMNCj4gaW5kZXggMGFmYzIxOC4uNjdiZTIwYyAxMDA2NDQNCj4gLS0tIGEvc3JjL3hl
bmJ1cy9zaGFyZWRfaW5mby5jDQo+ICsrKyBiL3NyYy94ZW5idXMvc2hhcmVkX2luZm8uYw0KPiBA
QCAtMzgsNiArMzgsOSBAQA0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUg
ImFzc2VydC5oIg0KPiANCj4gKyNkZWZpbmUgWEVOQlVTX1NIQVJFRF9JTkZPX0VWVENITl9QRVJf
U0VMRUNUT1IgICAgIChzaXplb2YNCj4gKFVMT05HX1BUUikgKiA4KQ0KPiArI2RlZmluZSBYRU5C
VVNfU0hBUkVEX0lORk9fRVZUQ0hOX1NFTEVDVE9SX0NPVU5UDQo+IChSVExfRklFTERfU0laRShz
aGFyZWRfaW5mb190LCBldnRjaG5fcGVuZGluZykgLyBzaXplb2YgKFVMT05HX1BUUikpDQo+ICsN
Cj4gIHN0cnVjdCBfWEVOQlVTX1NIQVJFRF9JTkZPX0NPTlRFWFQgew0KPiAgICAgIFBYRU5CVVNf
RkRPICAgICAgICAgICAgICAgICBGZG87DQo+ICAgICAgS1NQSU5fTE9DSyAgICAgICAgICAgICAg
ICAgIExvY2s7DQo+IGRpZmYgLS1naXQgYS92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qIGIv
dnMyMDEyL3hlbmJ1cy94ZW5idXMudmN4cHJvag0KPiBpbmRleCBjMzA3NzRlLi5hNjQ4YmNlIDEw
MDY0NA0KPiAtLS0gYS92czIwMTIveGVuYnVzL3hlbmJ1cy52Y3hwcm9qDQo+ICsrKyBiL3ZzMjAx
Mi94ZW5idXMveGVuYnVzLnZjeHByb2oNCj4gQEAgLTk5LDYgKzk5LDcgQEANCj4gIAkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXHJhbmdlX3NldC5jIiAvPg0KPiAgCQk8Q2xD
b21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNcYmFsbG9vbi5jIiAvPg0KPiAgCQk8Q2xD
b21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5idXNcY2FjaGUuYyIgLz4NCj4gKwkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGhhc2hfdGFibGUuYyIgLz4NCj4gIAk8L0l0
ZW1Hcm91cD4NCj4gIAk8SXRlbUdyb3VwPg0KPiAgCQk8UmVzb3VyY2VDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5idXNceGVuYnVzLnJjIiAvPg0KPiBkaWZmIC0tZ2l0IGEvdnMyMDEzL3hl
bmJ1cy94ZW5idXMudmN4cHJvaiBiL3ZzMjAxMy94ZW5idXMveGVuYnVzLnZjeHByb2oNCj4gaW5k
ZXggNTg4YjBjNS4uMmMzNGVkMSAxMDA2NDQNCj4gLS0tIGEvdnMyMDEzL3hlbmJ1cy94ZW5idXMu
dmN4cHJvag0KPiArKysgYi92czIwMTMveGVuYnVzL3hlbmJ1cy52Y3hwcm9qDQo+IEBAIC0xLDQg
KzEsNCBAQA0KPiAt77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCj4g
Kzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+ICA8UHJvamVjdCBEZWZh
dWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xzVmVyc2lvbj0iMTIuMCINCj4geG1sbnM9Imh0dHA6Ly9z
Y2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxvcGVyL21zYnVpbGQvMjAwMyI+DQo+ICAgIDxJbXBv
cnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIgLz4NCj4gICAgPFByb3BlcnR5R3JvdXAgTGFi
ZWw9Ikdsb2JhbHMiPg0KPiBAQCAtMTM5LDYgKzEzOSw3IEBADQo+ICAgICAgPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXHJhbmdlX3NldC5jIiAvPg0KPiAgICAgIDxDbENvbXBp
bGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlbmJ1c1xiYWxsb29uLmMiIC8+DQo+ICAgICAgPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGNhY2hlLmMiIC8+DQo+ICsgICAgPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuYnVzXGhhc2hfdGFibGUuYyIgLz4NCj4gICAgPC9J
dGVtR3JvdXA+DQo+ICAgIDxJdGVtR3JvdXA+DQo+ICAgICAgPFJlc291cmNlQ29tcGlsZSBJbmNs
dWRlPSIuLlwuLlxzcmNceGVuYnVzXHhlbmJ1cy5yYyIgLz4NCj4gLS0NCj4gMi4xLjENCg0KX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVs
IG1haWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xp
c3RzLnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 06 14:31:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:31: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 1XmO5n-0001cE-JV; Thu, 06 Nov 2014 14:31:19 +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 1XmO5m-0001c9-6O
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:31:18 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	EE/61-07724-5368B545; Thu, 06 Nov 2014 14:31:17 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415284274!10854701!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5081 invoked from network); 6 Nov 2014 14:31:16 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:31:16 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188774436"
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.181.6;
	Thu, 6 Nov 2014 09:31:05 -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 1XmO5Y-0008MN-Ni;
	Thu, 06 Nov 2014 14:31:04 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:30:54 +0000
Message-ID: <1415284254-25504-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 10/10] Add support for the FIFO event channel
	ABI
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

If it is available then the fifo ABI will be used. If it is not then the
two-level ABI will be used instead.
The ABI is released and re-acquired across suspend/resume so this should
allow moving between hosts with different capabilities.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/xen.h                |  41 ++-
 src/xen/event_channel.c      | 128 ++++++++
 src/xenbus/evtchn.c          |  27 +-
 src/xenbus/evtchn_fifo.c     | 702 +++++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_fifo.h     |  59 ++++
 src/xenbus/store.c           |  11 +-
 vs2012/xenbus/xenbus.vcxproj |   1 +
 vs2013/xenbus/xenbus.vcxproj |   1 +
 8 files changed, 962 insertions(+), 8 deletions(-)
 create mode 100644 src/xenbus/evtchn_fifo.c
 create mode 100644 src/xenbus/evtchn_fifo.h

diff --git a/include/xen.h b/include/xen.h
index 674676c..0039d7a 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -136,17 +136,26 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindInterDomain(
-    IN  domid_t                     RemoteDomain,
-    IN  evtchn_port_t               RemotePort,
-    OUT evtchn_port_t               *LocalPort
+    IN  domid_t         RemoteDomain,
+    IN  evtchn_port_t   RemotePort,
+    OUT evtchn_port_t   *LocalPort
     );
 
 __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindVirq(
-    IN  uint32_t            Virq,
-    OUT evtchn_port_t       *LocalPort
+    IN  uint32_t        Virq,
+    OUT evtchn_port_t   *LocalPort
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelQueryInterDomain(
+    IN  evtchn_port_t   LocalPort,
+    OUT domid_t         *RemoteDomain,
+    OUT evtchn_port_t   *RemotePort
     );
 
 __checkReturn
@@ -156,6 +165,28 @@ EventChannelClose(
     IN  evtchn_port_t   LocalPort
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelExpandArray(
+    IN  PFN_NUMBER              Pfn
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelInitControl(
+    IN  PFN_NUMBER              Pfn,
+    IN  unsigned int            vcpu_id
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelReset(
+    VOID
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index 23e4659..aa87fd4 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -175,6 +175,47 @@ fail1:
 __checkReturn
 XEN_API
 NTSTATUS
+EventChannelQueryInterDomain(
+    IN  evtchn_port_t               LocalPort,
+    OUT domid_t                     *RemoteDomain,
+    OUT evtchn_port_t               *RemotePort
+    )
+{
+    struct evtchn_status            op;
+    LONG_PTR                        rc;
+    NTSTATUS                        status;
+
+    op.dom = DOMID_SELF;
+    op.port = LocalPort;
+
+    rc = EventChannelOp(EVTCHNOP_status, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    status = STATUS_INVALID_PARAMETER;
+    if (op.status != EVTCHNSTAT_interdomain)
+        goto fail2;
+
+    *RemoteDomain = op.u.interdomain.dom;
+    *RemotePort = op.u.interdomain.port;
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
 EventChannelClose(
     IN  evtchn_port_t   LocalPort
     )
@@ -199,3 +240,90 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelExpandArray(
+    IN  PFN_NUMBER              Pfn
+    )
+{
+    struct evtchn_expand_array  op;
+    LONG_PTR                    rc;
+    NTSTATUS                    status;
+
+    op.array_gfn = Pfn;
+
+    rc = EventChannelOp(EVTCHNOP_expand_array, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelInitControl(
+    IN  PFN_NUMBER              Pfn,
+    IN  unsigned int            vcpu_id
+    )
+{
+    struct evtchn_init_control  op;
+    LONG_PTR                    rc;
+    NTSTATUS                    status;
+
+    op.control_gfn = Pfn;
+    op.offset = 0;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_init_control, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelReset(
+    VOID
+    )
+{
+    struct evtchn_reset op;
+    LONG_PTR            rc;
+    NTSTATUS            status;
+
+    op.dom = DOMID_SELF;
+
+    rc = EventChannelOp(EVTCHNOP_reset, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index f13667e..2be0da8 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -36,6 +36,7 @@
 
 #include "evtchn.h"
 #include "evtchn_2l.h"
+#include "evtchn_fifo.h"
 #include "fdo.h"
 #include "hash_table.h"
 #include "dbg_print.h"
@@ -95,6 +96,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
+    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
     XENBUS_EVTCHN_ABI               EvtchnAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
@@ -234,7 +236,9 @@ EvtchnOpenInterDomain(
     RemotePort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
 
-    status = EventChannelBindInterDomain(RemoteDomain, RemotePort, &LocalPort);
+    status = EventChannelBindInterDomain(RemoteDomain,
+                                         RemotePort,
+                                         &LocalPort);
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -666,6 +670,13 @@ EvtchnAbiAcquire(
 {
     NTSTATUS                    status;
 
+    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
+                     &Context->EvtchnAbi);
+
+    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+    if (NT_SUCCESS(status))
+        goto done;
+
     EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
                          &Context->EvtchnAbi);
 
@@ -673,6 +684,7 @@ EvtchnAbiAcquire(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+done:
     return STATUS_SUCCESS;
 
 fail1:
@@ -1024,6 +1036,10 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = EvtchnFifoInitialize(Fdo, &(*Context)->EvtchnFifoContext);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -1054,6 +1070,12 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+
+    EvtchnTwoLevelTeardown((*Context)->EvtchnTwoLevelContext);
+    (*Context)->EvtchnTwoLevelContext = NULL;
+
 fail3:
     Error("fail3\n");
 
@@ -1131,6 +1153,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    EvtchnFifoTeardown(Context->EvtchnFifoContext);
+    Context->EvtchnFifoContext = NULL;
+
     EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
     Context->EvtchnTwoLevelContext = NULL;
 
diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
new file mode 100644
index 0000000..d37b1cd
--- /dev/null
+++ b/src/xenbus/evtchn_fifo.c
@@ -0,0 +1,702 @@
+/* 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 "evtchn_fifo.h"
+#include "shared_info.h"
+#include "fdo.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define MAX_HVM_VCPUS   128
+
+typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT {
+    PXENBUS_FDO                     Fdo;
+    KSPIN_LOCK                      Lock;
+    LONG                            References;
+    PMDL                            ControlBlockMdl[MAX_HVM_VCPUS];
+    PMDL                            *EventPageMdl;
+    ULONG                           EventPageCount;
+    ULONG                           Head[EVTCHN_FIFO_MAX_QUEUES];
+} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT;
+
+#define EVENT_WORDS_PER_PAGE    (PAGE_SIZE / sizeof (event_word_t))
+
+#define XENBUS_EVTCHN_FIFO_TAG  'OFIF'
+
+static FORCEINLINE PVOID
+__EvtchnFifoAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_EVTCHN_FIFO_TAG);
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_FIFO_TAG);
+}
+
+static event_word_t *
+EvtchnFifoEventWord(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  ULONG                       Port
+    )
+{
+    ULONG                           Index;
+    PMDL                            Mdl;
+    event_word_t                    *EventWord;
+
+    Index = Port / EVENT_WORDS_PER_PAGE;
+    ASSERT3U(Index, <, Context->EventPageCount);
+
+    Mdl = Context->EventPageMdl[Index];
+
+    EventWord = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+    ASSERT(EventWord != NULL);
+
+    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
+    Port -= Index * EVENT_WORDS_PER_PAGE;
+
+    return &EventWord[Port];
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!(*EventWord & (1 << Flag));
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestAndSetFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestAndClearFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoSetFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    *EventWord |= (1 << Flag);
+    KeMemoryBarrier();
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoClearFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    *EventWord &= ~(1 << Flag);
+    KeMemoryBarrier();
+}
+
+static FORCEINLINE ULONG
+__EvtchnFifoUnlink(
+    IN  event_word_t    *EventWord
+    )
+{
+    LONG                Old;
+    LONG                New;
+
+    do {
+        Old = *EventWord;
+
+        // Clear linked bit and link value
+        New = Old & ~((1 << EVTCHN_FIFO_LINKED) | EVTCHN_FIFO_LINK_MASK);
+    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != Old);
+
+    return Old & EVTCHN_FIFO_LINK_MASK;
+}
+
+static NTSTATUS
+EvtchnFifoExpand(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  ULONG                       Port
+    )
+{
+    LONG                            Index;
+    ULONG                           EventPageCount;
+    PMDL                            *EventPageMdl;
+    PMDL                            Mdl;
+    ULONG                           Start;
+    ULONG                           End;
+    NTSTATUS                        status;
+
+    Index = Port / EVENT_WORDS_PER_PAGE;
+    ASSERT3U(Index, >=, (LONG)Context->EventPageCount);
+
+    EventPageCount = Index + 1;
+    EventPageMdl = __EvtchnFifoAllocate(sizeof (PMDL) * EventPageCount);
+
+    status = STATUS_NO_MEMORY;
+    if (EventPageMdl == NULL)
+        goto fail1;
+
+    for (Index = 0; Index < (LONG)Context->EventPageCount; Index++)
+        EventPageMdl[Index] = Context->EventPageMdl[Index];
+
+    Index = Context->EventPageCount;
+    while (Index < (LONG)EventPageCount) {
+        event_word_t        *EventWord;
+        PFN_NUMBER          Pfn;
+        PHYSICAL_ADDRESS    Address;
+
+        Mdl = __AllocatePage();
+
+        status = STATUS_NO_MEMORY;
+        if (Mdl == NULL)
+            goto fail2;
+
+        EventWord = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        ASSERT(EventWord != NULL);
+
+        for (Port = 0; Port < EVENT_WORDS_PER_PAGE; Port++)
+            __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
+
+        Pfn = MmGetMdlPfnArray(Mdl)[0];
+
+        status = EventChannelExpandArray(Pfn);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+
+        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
+
+        LogPrintf(LOG_LEVEL_INFO,
+                  "EVTCHN_FIFO: EVENTARRAY[%u] @ %08x.%08x\n",
+                  Index,
+                  Address.HighPart,
+                  Address.LowPart);
+
+        EventPageMdl[Index++] = Mdl;
+    }
+
+    Start = Context->EventPageCount * EVENT_WORDS_PER_PAGE;
+    End = (EventPageCount * EVENT_WORDS_PER_PAGE) - 1;
+
+    Info("added ports [%08x - %08x]\n", Start, End);
+
+    if (Context->EventPageMdl != NULL)
+        __EvtchnFifoFree(Context->EventPageMdl);
+
+    Context->EventPageMdl = EventPageMdl;
+    Context->EventPageCount = EventPageCount;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    __FreePage(Mdl);
+
+fail2:
+    Error("fail2\n");
+
+    while (--Index >= (LONG)Context->EventPageCount) {
+        Mdl = EventPageMdl[Index];
+
+        __FreePage(Mdl);
+    }
+
+    __EvtchnFifoFree(EventPageMdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static VOID
+EvtchnFifoContract(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
+    )
+{
+    LONG                            Index;
+
+    Index = Context->EventPageCount;
+    while (--Index >= 0) {
+        PMDL    Mdl;
+
+        Mdl = Context->EventPageMdl[Index];
+
+        __FreePage(Mdl);
+    }
+
+    __EvtchnFifoFree(Context->EventPageMdl);
+
+    Context->EventPageMdl = NULL;
+    Context->EventPageCount = 0;
+}
+
+static BOOLEAN
+EvtchnFifoPollPriority(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  evtchn_fifo_control_block_t *ControlBlock,
+    IN  ULONG                       Priority,
+    IN  PULONG                      Ready,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    )
+{
+    ULONG                           Head;
+    ULONG                           Port;
+    event_word_t                    *EventWord;
+    BOOLEAN                         DoneSomething;
+
+    Head = Context->Head[Priority];
+
+    if (Head == 0) {
+        KeMemoryBarrier();
+        Head = ControlBlock->head[Priority];
+    }
+
+    Port = Head;
+    EventWord = EvtchnFifoEventWord(Context, Port);
+
+    Head = __EvtchnFifoUnlink(EventWord);
+
+    if (Head == 0)
+        *Ready &= ~(1ull << Priority);
+
+    DoneSomething = FALSE;
+
+    if (!__EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_MASKED) &&
+        __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING))
+        DoneSomething = Event(Argument, Port);
+
+    Context->Head[Priority] = Head;
+
+    return DoneSomething;
+}
+
+static BOOLEAN
+EvtchnFifoPoll(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    unsigned int                    vcpu_id = SystemVirtualCpuIndex(Cpu);
+    PMDL                            Mdl;
+    evtchn_fifo_control_block_t     *ControlBlock;
+    ULONG                           Ready;
+    ULONG                           Priority;
+    BOOLEAN                         DoneSomething;
+
+    Mdl = Context->ControlBlockMdl[vcpu_id];
+
+    ControlBlock = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+    ASSERT(ControlBlock != NULL);
+
+    Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0);
+    DoneSomething = FALSE;
+
+    while (_BitScanReverse(&Priority, Ready)) {
+        DoneSomething |= EvtchnFifoPollPriority(Context,
+                                                ControlBlock,
+                                                Priority,
+                                                &Ready,
+                                                Event,
+                                                Argument);
+        Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0);
+    }
+
+    return DoneSomething;
+}
+
+static NTSTATUS
+EvtchnFifoPortEnable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    NTSTATUS                        status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Port / EVENT_WORDS_PER_PAGE >= Context->EventPageCount) {
+        status = EvtchnFifoExpand(Context, Port);
+
+        if (!NT_SUCCESS(status))
+            goto fail1;
+    }
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+static VOID
+EvtchnFifoPortAck(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+    __EvtchnFifoClearFlag(&EventWord[Port], EVTCHN_FIFO_PENDING);
+}
+
+static VOID
+EvtchnFifoPortMask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+    __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
+}
+
+static BOOLEAN
+EvtchnFifoPortUnmask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+    LONG                            Old;
+    LONG                            New;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+
+    // Clear masked bit, spinning if busy
+    do {
+        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
+        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
+    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != Old);
+
+    // Check whether the port was masked
+    if (~Old & (1 << EVTCHN_FIFO_MASKED))
+        return FALSE;
+
+    // If we cleared the mask then check whether something is pending
+    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
+        return FALSE;
+
+    return TRUE;
+}
+
+static VOID
+EvtchnFifoPortDisable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    EvtchnFifoPortMask(_Context, Port);
+}
+
+static VOID
+EvtchnFifoReset(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
+    )
+{
+    ULONGLONG                       Value;
+    ULONG                           LocalPort;
+    ULONG                           RemotePort;
+    USHORT                          RemoteDomain;
+    NTSTATUS                        status;
+
+    UNREFERENCED_PARAMETER(Context);
+
+    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
+    ASSERT(NT_SUCCESS(status));
+
+    LocalPort = (LONG)Value;
+
+    //
+    // When we reset the event channel ABI we will lose our
+    // binding to the STORE event channel, which was set up
+    // by the toolstack during domain build.
+    // We need to get the binding back, so we must query the
+    // remote domain and port, and then re-bind after the
+    // reset.
+    //
+
+    status = EventChannelQueryInterDomain(LocalPort,
+                                          &RemoteDomain,
+                                          &RemotePort);
+    ASSERT(NT_SUCCESS(status));
+
+    LogPrintf(LOG_LEVEL_INFO, "EVTCHN_FIFO: RESET\n");
+    (VOID) EventChannelReset();
+
+    status = EventChannelBindInterDomain(RemoteDomain,
+                                         RemotePort,
+                                         &LocalPort);
+    ASSERT(NT_SUCCESS(status));
+
+    Value = LocalPort;
+
+    status = HvmSetParam(HVM_PARAM_STORE_EVTCHN, Value);
+    ASSERT(NT_SUCCESS(status));
+}
+
+static NTSTATUS
+EvtchnFifoAcquire(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    LONG                            Cpu;
+    PMDL                            Mdl;
+    NTSTATUS                        status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int        vcpu_id;
+        PFN_NUMBER          Pfn;
+        PHYSICAL_ADDRESS    Address;
+
+        Mdl = __AllocatePage();
+
+        status = STATUS_NO_MEMORY;
+        if (Mdl == NULL)
+            goto fail1;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Pfn = MmGetMdlPfnArray(Mdl)[0];
+
+        status = EventChannelInitControl(Pfn, vcpu_id);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
+
+        LogPrintf(LOG_LEVEL_INFO,
+                  "EVTCHN_FIFO: CONTROLBLOCK[%u] @ %08x.%08x\n",
+                  vcpu_id,
+                  Address.HighPart,
+                  Address.LowPart);
+
+        Context->ControlBlockMdl[vcpu_id] = Mdl;
+        Cpu++;
+    }
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    __FreePage(Mdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    (VOID) EventChannelReset();
+
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        Mdl = Context->ControlBlockMdl[vcpu_id];
+        Context->ControlBlockMdl[vcpu_id] = NULL;
+
+        __FreePage(Mdl);
+    }
+
+    --Context->References;
+    ASSERT3U(Context->References, ==, 0);
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+VOID
+EvtchnFifoRelease(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    LONG                            Cpu;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    EvtchnFifoReset(Context);
+
+    EvtchnFifoContract(Context);
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+        PMDL            Mdl;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        Mdl = Context->ControlBlockMdl[vcpu_id];
+        Context->ControlBlockMdl[vcpu_id] = NULL;
+
+        __FreePage(Mdl);
+    }
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static XENBUS_EVTCHN_ABI EvtchnAbiFifo = {
+    NULL,
+    EvtchnFifoAcquire,
+    EvtchnFifoRelease,
+    EvtchnFifoPoll,
+    EvtchnFifoPortEnable,
+    EvtchnFifoPortDisable,
+    EvtchnFifoPortAck,
+    EvtchnFifoPortMask,
+    EvtchnFifoPortUnmask
+};
+
+NTSTATUS
+EvtchnFifoInitialize(
+    IN  PXENBUS_FDO                     Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT    Context;
+    NTSTATUS                            status;
+
+    Trace("====>\n");
+
+    Context = __EvtchnFifoAllocate(sizeof (XENBUS_EVTCHN_FIFO_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (Context == NULL)
+        goto fail1;
+
+    KeInitializeSpinLock(&Context->Lock);
+
+    Context->Fdo = Fdo;
+
+    *_Context = (PVOID)Context;
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+EvtchnFifoGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    OUT PXENBUS_EVTCHN_ABI              Abi)
+{
+    *Abi = EvtchnAbiFifo;
+
+    Abi->Context = (PVOID)_Context;
+}
+
+VOID
+EvtchnFifoTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT    Context = (PVOID)_Context;
+
+    Trace("====>\n");
+
+    Context->Fdo = NULL;
+
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_FIFO_CONTEXT)));
+    __EvtchnFifoFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenbus/evtchn_fifo.h b/src/xenbus/evtchn_fifo.h
new file mode 100644
index 0000000..bf96b19
--- /dev/null
+++ b/src/xenbus/evtchn_fifo.h
@@ -0,0 +1,59 @@
+/* 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 _XENBUS_EVTCHN_FIFO_H
+#define _XENBUS_EVTCHN_FIFO_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+#include "evtchn_abi.h"
+#include "fdo.h"
+
+extern NTSTATUS
+EvtchnFifoInitialize(
+    IN  PXENBUS_FDO                 Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
+    );
+
+extern VOID
+EvtchnFifoGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    OUT PXENBUS_EVTCHN_ABI          Abi
+    );
+
+extern VOID
+EvtchnFifoTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+#endif  // _XENBUS_EVTCHN_FIFO_H
+
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 62ec60b..22c2a12 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1825,13 +1825,20 @@ StoreEnable(
     IN PXENBUS_STORE_CONTEXT    Context
     )
 {
-    ULONGLONG                   Port;
+    ULONGLONG                   Value;
+    ULONG                       Port;
     BOOLEAN                     Pending;
     NTSTATUS                    status;
 
-    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Port);
+    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
     ASSERT(NT_SUCCESS(status));
 
+    Port = (ULONG)Value;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "STORE: EVTCHN %u\n",
+              Port);
+
     Context->Channel = XENBUS_EVTCHN(Open,
                                      &Context->EvtchnInterface,
                                      XENBUS_EVTCHN_TYPE_FIXED,
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index 6cd12d1..3c184e0 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -89,6 +89,7 @@
 		<ClCompile Include="..\..\src\xenbus\driver.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
+		<ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
 		<ClCompile Include="..\..\src\xenbus\fdo.c" />
 		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
 		<ClCompile Include="..\..\src\xenbus\pdo.c" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 0f37f68..ecb602b 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -129,6 +129,7 @@
     <ClCompile Include="..\..\src\xenbus\driver.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
+    <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
-- 
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 Nov 06 14:31:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:31: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 1XmO5n-0001cE-JV; Thu, 06 Nov 2014 14:31:19 +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 1XmO5m-0001c9-6O
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:31:18 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	EE/61-07724-5368B545; Thu, 06 Nov 2014 14:31:17 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415284274!10854701!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5081 invoked from network); 6 Nov 2014 14:31:16 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:31:16 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="188774436"
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.181.6;
	Thu, 6 Nov 2014 09:31:05 -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 1XmO5Y-0008MN-Ni;
	Thu, 06 Nov 2014 14:31:04 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:30:54 +0000
Message-ID: <1415284254-25504-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 10/10] Add support for the FIFO event channel
	ABI
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

If it is available then the fifo ABI will be used. If it is not then the
two-level ABI will be used instead.
The ABI is released and re-acquired across suspend/resume so this should
allow moving between hosts with different capabilities.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/xen.h                |  41 ++-
 src/xen/event_channel.c      | 128 ++++++++
 src/xenbus/evtchn.c          |  27 +-
 src/xenbus/evtchn_fifo.c     | 702 +++++++++++++++++++++++++++++++++++++++++++
 src/xenbus/evtchn_fifo.h     |  59 ++++
 src/xenbus/store.c           |  11 +-
 vs2012/xenbus/xenbus.vcxproj |   1 +
 vs2013/xenbus/xenbus.vcxproj |   1 +
 8 files changed, 962 insertions(+), 8 deletions(-)
 create mode 100644 src/xenbus/evtchn_fifo.c
 create mode 100644 src/xenbus/evtchn_fifo.h

diff --git a/include/xen.h b/include/xen.h
index 674676c..0039d7a 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -136,17 +136,26 @@ __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindInterDomain(
-    IN  domid_t                     RemoteDomain,
-    IN  evtchn_port_t               RemotePort,
-    OUT evtchn_port_t               *LocalPort
+    IN  domid_t         RemoteDomain,
+    IN  evtchn_port_t   RemotePort,
+    OUT evtchn_port_t   *LocalPort
     );
 
 __checkReturn
 XEN_API
 NTSTATUS
 EventChannelBindVirq(
-    IN  uint32_t            Virq,
-    OUT evtchn_port_t       *LocalPort
+    IN  uint32_t        Virq,
+    OUT evtchn_port_t   *LocalPort
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelQueryInterDomain(
+    IN  evtchn_port_t   LocalPort,
+    OUT domid_t         *RemoteDomain,
+    OUT evtchn_port_t   *RemotePort
     );
 
 __checkReturn
@@ -156,6 +165,28 @@ EventChannelClose(
     IN  evtchn_port_t   LocalPort
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelExpandArray(
+    IN  PFN_NUMBER              Pfn
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelInitControl(
+    IN  PFN_NUMBER              Pfn,
+    IN  unsigned int            vcpu_id
+    );
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelReset(
+    VOID
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index 23e4659..aa87fd4 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -175,6 +175,47 @@ fail1:
 __checkReturn
 XEN_API
 NTSTATUS
+EventChannelQueryInterDomain(
+    IN  evtchn_port_t               LocalPort,
+    OUT domid_t                     *RemoteDomain,
+    OUT evtchn_port_t               *RemotePort
+    )
+{
+    struct evtchn_status            op;
+    LONG_PTR                        rc;
+    NTSTATUS                        status;
+
+    op.dom = DOMID_SELF;
+    op.port = LocalPort;
+
+    rc = EventChannelOp(EVTCHNOP_status, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    status = STATUS_INVALID_PARAMETER;
+    if (op.status != EVTCHNSTAT_interdomain)
+        goto fail2;
+
+    *RemoteDomain = op.u.interdomain.dom;
+    *RemotePort = op.u.interdomain.port;
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
 EventChannelClose(
     IN  evtchn_port_t   LocalPort
     )
@@ -199,3 +240,90 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelExpandArray(
+    IN  PFN_NUMBER              Pfn
+    )
+{
+    struct evtchn_expand_array  op;
+    LONG_PTR                    rc;
+    NTSTATUS                    status;
+
+    op.array_gfn = Pfn;
+
+    rc = EventChannelOp(EVTCHNOP_expand_array, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelInitControl(
+    IN  PFN_NUMBER              Pfn,
+    IN  unsigned int            vcpu_id
+    )
+{
+    struct evtchn_init_control  op;
+    LONG_PTR                    rc;
+    NTSTATUS                    status;
+
+    op.control_gfn = Pfn;
+    op.offset = 0;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_init_control, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelReset(
+    VOID
+    )
+{
+    struct evtchn_reset op;
+    LONG_PTR            rc;
+    NTSTATUS            status;
+
+    op.dom = DOMID_SELF;
+
+    rc = EventChannelOp(EVTCHNOP_reset, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index f13667e..2be0da8 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -36,6 +36,7 @@
 
 #include "evtchn.h"
 #include "evtchn_2l.h"
+#include "evtchn_fifo.h"
 #include "fdo.h"
 #include "hash_table.h"
 #include "dbg_print.h"
@@ -95,6 +96,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_DEBUG_CALLBACK          DebugCallback;
     XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
+    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
     XENBUS_EVTCHN_ABI               EvtchnAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
@@ -234,7 +236,9 @@ EvtchnOpenInterDomain(
     RemotePort = va_arg(Arguments, ULONG);
     Mask = va_arg(Arguments, BOOLEAN);
 
-    status = EventChannelBindInterDomain(RemoteDomain, RemotePort, &LocalPort);
+    status = EventChannelBindInterDomain(RemoteDomain,
+                                         RemotePort,
+                                         &LocalPort);
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -666,6 +670,13 @@ EvtchnAbiAcquire(
 {
     NTSTATUS                    status;
 
+    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
+                     &Context->EvtchnAbi);
+
+    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+    if (NT_SUCCESS(status))
+        goto done;
+
     EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
                          &Context->EvtchnAbi);
 
@@ -673,6 +684,7 @@ EvtchnAbiAcquire(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+done:
     return STATUS_SUCCESS;
 
 fail1:
@@ -1024,6 +1036,10 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = EvtchnFifoInitialize(Fdo, &(*Context)->EvtchnFifoContext);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -1054,6 +1070,12 @@ EvtchnInitialize(
 
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+
+    EvtchnTwoLevelTeardown((*Context)->EvtchnTwoLevelContext);
+    (*Context)->EvtchnTwoLevelContext = NULL;
+
 fail3:
     Error("fail3\n");
 
@@ -1131,6 +1153,9 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    EvtchnFifoTeardown(Context->EvtchnFifoContext);
+    Context->EvtchnFifoContext = NULL;
+
     EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
     Context->EvtchnTwoLevelContext = NULL;
 
diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
new file mode 100644
index 0000000..d37b1cd
--- /dev/null
+++ b/src/xenbus/evtchn_fifo.c
@@ -0,0 +1,702 @@
+/* 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 "evtchn_fifo.h"
+#include "shared_info.h"
+#include "fdo.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+#define MAX_HVM_VCPUS   128
+
+typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT {
+    PXENBUS_FDO                     Fdo;
+    KSPIN_LOCK                      Lock;
+    LONG                            References;
+    PMDL                            ControlBlockMdl[MAX_HVM_VCPUS];
+    PMDL                            *EventPageMdl;
+    ULONG                           EventPageCount;
+    ULONG                           Head[EVTCHN_FIFO_MAX_QUEUES];
+} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT;
+
+#define EVENT_WORDS_PER_PAGE    (PAGE_SIZE / sizeof (event_word_t))
+
+#define XENBUS_EVTCHN_FIFO_TAG  'OFIF'
+
+static FORCEINLINE PVOID
+__EvtchnFifoAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_EVTCHN_FIFO_TAG);
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_FIFO_TAG);
+}
+
+static event_word_t *
+EvtchnFifoEventWord(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  ULONG                       Port
+    )
+{
+    ULONG                           Index;
+    PMDL                            Mdl;
+    event_word_t                    *EventWord;
+
+    Index = Port / EVENT_WORDS_PER_PAGE;
+    ASSERT3U(Index, <, Context->EventPageCount);
+
+    Mdl = Context->EventPageMdl[Index];
+
+    EventWord = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+    ASSERT(EventWord != NULL);
+
+    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
+    Port -= Index * EVENT_WORDS_PER_PAGE;
+
+    return &EventWord[Port];
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!(*EventWord & (1 << Flag));
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestAndSetFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+}
+
+static FORCEINLINE BOOLEAN
+__EvtchnFifoTestAndClearFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    KeMemoryBarrier();
+
+    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoSetFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    *EventWord |= (1 << Flag);
+    KeMemoryBarrier();
+}
+
+static FORCEINLINE VOID
+__EvtchnFifoClearFlag(
+    IN  event_word_t    *EventWord,
+    IN  ULONG           Flag
+    )
+{
+    *EventWord &= ~(1 << Flag);
+    KeMemoryBarrier();
+}
+
+static FORCEINLINE ULONG
+__EvtchnFifoUnlink(
+    IN  event_word_t    *EventWord
+    )
+{
+    LONG                Old;
+    LONG                New;
+
+    do {
+        Old = *EventWord;
+
+        // Clear linked bit and link value
+        New = Old & ~((1 << EVTCHN_FIFO_LINKED) | EVTCHN_FIFO_LINK_MASK);
+    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != Old);
+
+    return Old & EVTCHN_FIFO_LINK_MASK;
+}
+
+static NTSTATUS
+EvtchnFifoExpand(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  ULONG                       Port
+    )
+{
+    LONG                            Index;
+    ULONG                           EventPageCount;
+    PMDL                            *EventPageMdl;
+    PMDL                            Mdl;
+    ULONG                           Start;
+    ULONG                           End;
+    NTSTATUS                        status;
+
+    Index = Port / EVENT_WORDS_PER_PAGE;
+    ASSERT3U(Index, >=, (LONG)Context->EventPageCount);
+
+    EventPageCount = Index + 1;
+    EventPageMdl = __EvtchnFifoAllocate(sizeof (PMDL) * EventPageCount);
+
+    status = STATUS_NO_MEMORY;
+    if (EventPageMdl == NULL)
+        goto fail1;
+
+    for (Index = 0; Index < (LONG)Context->EventPageCount; Index++)
+        EventPageMdl[Index] = Context->EventPageMdl[Index];
+
+    Index = Context->EventPageCount;
+    while (Index < (LONG)EventPageCount) {
+        event_word_t        *EventWord;
+        PFN_NUMBER          Pfn;
+        PHYSICAL_ADDRESS    Address;
+
+        Mdl = __AllocatePage();
+
+        status = STATUS_NO_MEMORY;
+        if (Mdl == NULL)
+            goto fail2;
+
+        EventWord = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        ASSERT(EventWord != NULL);
+
+        for (Port = 0; Port < EVENT_WORDS_PER_PAGE; Port++)
+            __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
+
+        Pfn = MmGetMdlPfnArray(Mdl)[0];
+
+        status = EventChannelExpandArray(Pfn);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+
+        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
+
+        LogPrintf(LOG_LEVEL_INFO,
+                  "EVTCHN_FIFO: EVENTARRAY[%u] @ %08x.%08x\n",
+                  Index,
+                  Address.HighPart,
+                  Address.LowPart);
+
+        EventPageMdl[Index++] = Mdl;
+    }
+
+    Start = Context->EventPageCount * EVENT_WORDS_PER_PAGE;
+    End = (EventPageCount * EVENT_WORDS_PER_PAGE) - 1;
+
+    Info("added ports [%08x - %08x]\n", Start, End);
+
+    if (Context->EventPageMdl != NULL)
+        __EvtchnFifoFree(Context->EventPageMdl);
+
+    Context->EventPageMdl = EventPageMdl;
+    Context->EventPageCount = EventPageCount;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    __FreePage(Mdl);
+
+fail2:
+    Error("fail2\n");
+
+    while (--Index >= (LONG)Context->EventPageCount) {
+        Mdl = EventPageMdl[Index];
+
+        __FreePage(Mdl);
+    }
+
+    __EvtchnFifoFree(EventPageMdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static VOID
+EvtchnFifoContract(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
+    )
+{
+    LONG                            Index;
+
+    Index = Context->EventPageCount;
+    while (--Index >= 0) {
+        PMDL    Mdl;
+
+        Mdl = Context->EventPageMdl[Index];
+
+        __FreePage(Mdl);
+    }
+
+    __EvtchnFifoFree(Context->EventPageMdl);
+
+    Context->EventPageMdl = NULL;
+    Context->EventPageCount = 0;
+}
+
+static BOOLEAN
+EvtchnFifoPollPriority(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
+    IN  evtchn_fifo_control_block_t *ControlBlock,
+    IN  ULONG                       Priority,
+    IN  PULONG                      Ready,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    )
+{
+    ULONG                           Head;
+    ULONG                           Port;
+    event_word_t                    *EventWord;
+    BOOLEAN                         DoneSomething;
+
+    Head = Context->Head[Priority];
+
+    if (Head == 0) {
+        KeMemoryBarrier();
+        Head = ControlBlock->head[Priority];
+    }
+
+    Port = Head;
+    EventWord = EvtchnFifoEventWord(Context, Port);
+
+    Head = __EvtchnFifoUnlink(EventWord);
+
+    if (Head == 0)
+        *Ready &= ~(1ull << Priority);
+
+    DoneSomething = FALSE;
+
+    if (!__EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_MASKED) &&
+        __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING))
+        DoneSomething = Event(Argument, Port);
+
+    Context->Head[Priority] = Head;
+
+    return DoneSomething;
+}
+
+static BOOLEAN
+EvtchnFifoPoll(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Cpu,
+    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
+    IN  PVOID                       Argument
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    unsigned int                    vcpu_id = SystemVirtualCpuIndex(Cpu);
+    PMDL                            Mdl;
+    evtchn_fifo_control_block_t     *ControlBlock;
+    ULONG                           Ready;
+    ULONG                           Priority;
+    BOOLEAN                         DoneSomething;
+
+    Mdl = Context->ControlBlockMdl[vcpu_id];
+
+    ControlBlock = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+    ASSERT(ControlBlock != NULL);
+
+    Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0);
+    DoneSomething = FALSE;
+
+    while (_BitScanReverse(&Priority, Ready)) {
+        DoneSomething |= EvtchnFifoPollPriority(Context,
+                                                ControlBlock,
+                                                Priority,
+                                                &Ready,
+                                                Event,
+                                                Argument);
+        Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0);
+    }
+
+    return DoneSomething;
+}
+
+static NTSTATUS
+EvtchnFifoPortEnable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    NTSTATUS                        status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Port / EVENT_WORDS_PER_PAGE >= Context->EventPageCount) {
+        status = EvtchnFifoExpand(Context, Port);
+
+        if (!NT_SUCCESS(status))
+            goto fail1;
+    }
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+static VOID
+EvtchnFifoPortAck(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+    __EvtchnFifoClearFlag(&EventWord[Port], EVTCHN_FIFO_PENDING);
+}
+
+static VOID
+EvtchnFifoPortMask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+    __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
+}
+
+static BOOLEAN
+EvtchnFifoPortUnmask(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    event_word_t                    *EventWord;
+    LONG                            Old;
+    LONG                            New;
+
+    EventWord = EvtchnFifoEventWord(Context, Port);
+
+    // Clear masked bit, spinning if busy
+    do {
+        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
+        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
+    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) != Old);
+
+    // Check whether the port was masked
+    if (~Old & (1 << EVTCHN_FIFO_MASKED))
+        return FALSE;
+
+    // If we cleared the mask then check whether something is pending
+    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
+        return FALSE;
+
+    return TRUE;
+}
+
+static VOID
+EvtchnFifoPortDisable(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
+    IN  ULONG                       Port
+    )
+{
+    EvtchnFifoPortMask(_Context, Port);
+}
+
+static VOID
+EvtchnFifoReset(
+    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
+    )
+{
+    ULONGLONG                       Value;
+    ULONG                           LocalPort;
+    ULONG                           RemotePort;
+    USHORT                          RemoteDomain;
+    NTSTATUS                        status;
+
+    UNREFERENCED_PARAMETER(Context);
+
+    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
+    ASSERT(NT_SUCCESS(status));
+
+    LocalPort = (LONG)Value;
+
+    //
+    // When we reset the event channel ABI we will lose our
+    // binding to the STORE event channel, which was set up
+    // by the toolstack during domain build.
+    // We need to get the binding back, so we must query the
+    // remote domain and port, and then re-bind after the
+    // reset.
+    //
+
+    status = EventChannelQueryInterDomain(LocalPort,
+                                          &RemoteDomain,
+                                          &RemotePort);
+    ASSERT(NT_SUCCESS(status));
+
+    LogPrintf(LOG_LEVEL_INFO, "EVTCHN_FIFO: RESET\n");
+    (VOID) EventChannelReset();
+
+    status = EventChannelBindInterDomain(RemoteDomain,
+                                         RemotePort,
+                                         &LocalPort);
+    ASSERT(NT_SUCCESS(status));
+
+    Value = LocalPort;
+
+    status = HvmSetParam(HVM_PARAM_STORE_EVTCHN, Value);
+    ASSERT(NT_SUCCESS(status));
+}
+
+static NTSTATUS
+EvtchnFifoAcquire(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    LONG                            Cpu;
+    PMDL                            Mdl;
+    NTSTATUS                        status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int        vcpu_id;
+        PFN_NUMBER          Pfn;
+        PHYSICAL_ADDRESS    Address;
+
+        Mdl = __AllocatePage();
+
+        status = STATUS_NO_MEMORY;
+        if (Mdl == NULL)
+            goto fail1;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Pfn = MmGetMdlPfnArray(Mdl)[0];
+
+        status = EventChannelInitControl(Pfn, vcpu_id);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
+
+        LogPrintf(LOG_LEVEL_INFO,
+                  "EVTCHN_FIFO: CONTROLBLOCK[%u] @ %08x.%08x\n",
+                  vcpu_id,
+                  Address.HighPart,
+                  Address.LowPart);
+
+        Context->ControlBlockMdl[vcpu_id] = Mdl;
+        Cpu++;
+    }
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    __FreePage(Mdl);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    (VOID) EventChannelReset();
+
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        Mdl = Context->ControlBlockMdl[vcpu_id];
+        Context->ControlBlockMdl[vcpu_id] = NULL;
+
+        __FreePage(Mdl);
+    }
+
+    --Context->References;
+    ASSERT3U(Context->References, ==, 0);
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+VOID
+EvtchnFifoRelease(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
+    KIRQL                           Irql;
+    LONG                            Cpu;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    EvtchnFifoReset(Context);
+
+    EvtchnFifoContract(Context);
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+        PMDL            Mdl;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        Mdl = Context->ControlBlockMdl[vcpu_id];
+        Context->ControlBlockMdl[vcpu_id] = NULL;
+
+        __FreePage(Mdl);
+    }
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static XENBUS_EVTCHN_ABI EvtchnAbiFifo = {
+    NULL,
+    EvtchnFifoAcquire,
+    EvtchnFifoRelease,
+    EvtchnFifoPoll,
+    EvtchnFifoPortEnable,
+    EvtchnFifoPortDisable,
+    EvtchnFifoPortAck,
+    EvtchnFifoPortMask,
+    EvtchnFifoPortUnmask
+};
+
+NTSTATUS
+EvtchnFifoInitialize(
+    IN  PXENBUS_FDO                     Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT    Context;
+    NTSTATUS                            status;
+
+    Trace("====>\n");
+
+    Context = __EvtchnFifoAllocate(sizeof (XENBUS_EVTCHN_FIFO_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (Context == NULL)
+        goto fail1;
+
+    KeInitializeSpinLock(&Context->Lock);
+
+    Context->Fdo = Fdo;
+
+    *_Context = (PVOID)Context;
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+VOID
+EvtchnFifoGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
+    OUT PXENBUS_EVTCHN_ABI              Abi)
+{
+    *Abi = EvtchnAbiFifo;
+
+    Abi->Context = (PVOID)_Context;
+}
+
+VOID
+EvtchnFifoTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
+    )
+{
+    PXENBUS_EVTCHN_FIFO_CONTEXT    Context = (PVOID)_Context;
+
+    Trace("====>\n");
+
+    Context->Fdo = NULL;
+
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_EVTCHN_FIFO_CONTEXT)));
+    __EvtchnFifoFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenbus/evtchn_fifo.h b/src/xenbus/evtchn_fifo.h
new file mode 100644
index 0000000..bf96b19
--- /dev/null
+++ b/src/xenbus/evtchn_fifo.h
@@ -0,0 +1,59 @@
+/* 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 _XENBUS_EVTCHN_FIFO_H
+#define _XENBUS_EVTCHN_FIFO_H
+
+#include <ntddk.h>
+#include <xen.h>
+
+#include "evtchn_abi.h"
+#include "fdo.h"
+
+extern NTSTATUS
+EvtchnFifoInitialize(
+    IN  PXENBUS_FDO                 Fdo,
+    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
+    );
+
+extern VOID
+EvtchnFifoGetAbi(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
+    OUT PXENBUS_EVTCHN_ABI          Abi
+    );
+
+extern VOID
+EvtchnFifoTeardown(
+    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
+    );
+
+#endif  // _XENBUS_EVTCHN_FIFO_H
+
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 62ec60b..22c2a12 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1825,13 +1825,20 @@ StoreEnable(
     IN PXENBUS_STORE_CONTEXT    Context
     )
 {
-    ULONGLONG                   Port;
+    ULONGLONG                   Value;
+    ULONG                       Port;
     BOOLEAN                     Pending;
     NTSTATUS                    status;
 
-    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Port);
+    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
     ASSERT(NT_SUCCESS(status));
 
+    Port = (ULONG)Value;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "STORE: EVTCHN %u\n",
+              Port);
+
     Context->Channel = XENBUS_EVTCHN(Open,
                                      &Context->EvtchnInterface,
                                      XENBUS_EVTCHN_TYPE_FIXED,
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index 6cd12d1..3c184e0 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -89,6 +89,7 @@
 		<ClCompile Include="..\..\src\xenbus\driver.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
 		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
+		<ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
 		<ClCompile Include="..\..\src\xenbus\fdo.c" />
 		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
 		<ClCompile Include="..\..\src\xenbus\pdo.c" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index 0f37f68..ecb602b 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -129,6 +129,7 @@
     <ClCompile Include="..\..\src\xenbus\driver.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
+    <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
-- 
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 Nov 06 14:48:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:48: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 1XmOM3-0002AP-Dm; Thu, 06 Nov 2014 14:48:07 +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 1XmOLz-0002AK-FQ
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:48:06 +0000
Received: from [193.109.254.147] by server-6.bemta-14.messagelabs.com id
	8D/D4-03145-22A8B545; Thu, 06 Nov 2014 14:48:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-27.messagelabs.com!1415285278!11811091!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16656 invoked from network); 6 Nov 2014 14:48:00 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:48:00 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="190196754"
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.181.6;
	Thu, 6 Nov 2014 09:47:47 -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 1XmNzK-0008E8-DG;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:21 +0000
Message-ID: <1415283861-26028-11-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 09/10] Update Xen headers to RELEASE-4.4.1
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>
---
 include/xen/arch-x86/xen.h  |   9 ++
 include/xen/event_channel.h |  91 +++++++++++++++++++++
 include/xen/hvm/hvm_op.h    | 195 ++++++++++++++++++++++++++++++++++----------
 include/xen/hvm/params.h    |  48 ++++++++++-
 include/xen/io/xs_wire.h    |  16 +++-
 include/xen/memory.h        | 130 +++++++++++++++++++++++++++--
 include/xen/sched.h         |   7 +-
 include/xen/trace.h         |  25 +++++-
 include/xen/xen-compat.h    |   2 +-
 include/xen/xen.h           |  16 ++--
 10 files changed, 471 insertions(+), 68 deletions(-)

diff --git a/include/xen/arch-x86/xen.h b/include/xen/arch-x86/xen.h
index 5cc22fb..1880f89 100644
--- a/include/xen/arch-x86/xen.h
+++ b/include/xen/arch-x86/xen.h
@@ -154,6 +154,15 @@ typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled 
  * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
+ *
+ * Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
+ * for HVM and PVH guests, not all information in this structure is updated:
+ *
+ * - For HVM guests, the structures read include: fpu_ctxt (if
+ * VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
+ *
+ * - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
+ * set cr3. All other fields not used should be set to 0.
  */
 struct vcpu_guest_context {
     /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
diff --git a/include/xen/event_channel.h b/include/xen/event_channel.h
index 472efdb..05e531d 100644
--- a/include/xen/event_channel.h
+++ b/include/xen/event_channel.h
@@ -71,6 +71,9 @@
 #define EVTCHNOP_bind_vcpu        8
 #define EVTCHNOP_unmask           9
 #define EVTCHNOP_reset           10
+#define EVTCHNOP_init_control    11
+#define EVTCHNOP_expand_array    12
+#define EVTCHNOP_set_priority    13
 /* ` } */
 
 typedef uint32_t evtchn_port_t;
@@ -98,6 +101,17 @@ typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
  * a port that is unbound and marked as accepting bindings from the calling
  * domain. A fresh port is allocated in the calling domain and returned as
  * <local_port>.
+ *
+ * In case the peer domain has already tried to set our event channel
+ * pending, before it was bound, EVTCHNOP_bind_interdomain always sets
+ * the local event channel pending.
+ *
+ * The usual pattern of use, in the guest's upcall (or subsequent
+ * handler) is as follows: (Re-enable the event channel for subsequent
+ * signalling and then) check for the existence of whatever condition
+ * is being waited for by other means, and take whatever action is
+ * needed (if any).
+ *
  * NOTES:
  *  1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
  */
@@ -250,6 +264,10 @@ typedef struct evtchn_unmask evtchn_unmask_t;
  * NOTES:
  *  1. <dom> may be specified as DOMID_SELF.
  *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ *  3. Destroys all control blocks and event array, resets event channel
+ *     operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
+ *     ABI was used. Guests should not bind events during EVTCHNOP_reset call
+ *     as these events are likely to be lost.
  */
 struct evtchn_reset {
     /* IN parameters. */
@@ -258,6 +276,43 @@ struct evtchn_reset {
 typedef struct evtchn_reset evtchn_reset_t;
 
 /*
+ * EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
+ *
+ * Note: any events that are currently pending will not be resent and
+ * will be lost.  Guests should call this before binding any event to
+ * avoid losing any events.
+ */
+struct evtchn_init_control {
+    /* IN parameters. */
+    uint64_t control_gfn;
+    uint32_t offset;
+    uint32_t vcpu;
+    /* OUT parameters. */
+    uint8_t link_bits;
+    uint8_t _pad[7];
+};
+typedef struct evtchn_init_control evtchn_init_control_t;
+
+/*
+ * EVTCHNOP_expand_array: add an additional page to the event array.
+ */
+struct evtchn_expand_array {
+    /* IN parameters. */
+    uint64_t array_gfn;
+};
+typedef struct evtchn_expand_array evtchn_expand_array_t;
+
+/*
+ * EVTCHNOP_set_priority: set the priority for an event channel.
+ */
+struct evtchn_set_priority {
+    /* IN parameters. */
+    uint32_t port;
+    uint32_t priority;
+};
+typedef struct evtchn_set_priority evtchn_set_priority_t;
+
+/*
  * ` enum neg_errnoval
  * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
  * `
@@ -281,6 +336,42 @@ struct evtchn_op {
 typedef struct evtchn_op evtchn_op_t;
 DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
 
+/*
+ * 2-level ABI
+ */
+
+#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+
+/*
+ * FIFO ABI
+ */
+
+/* Events may have priorities from 0 (highest) to 15 (lowest). */
+#define EVTCHN_FIFO_PRIORITY_MAX     0
+#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
+#define EVTCHN_FIFO_PRIORITY_MIN     15
+
+#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
+
+typedef uint32_t event_word_t;
+
+#define EVTCHN_FIFO_PENDING 31
+#define EVTCHN_FIFO_MASKED  30
+#define EVTCHN_FIFO_LINKED  29
+#define EVTCHN_FIFO_BUSY    28
+
+#define EVTCHN_FIFO_LINK_BITS 17
+#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
+
+#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
+
+struct evtchn_fifo_control_block {
+    uint32_t ready;
+    uint32_t _rsvd;
+    uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
+};
+typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
+
 #endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index a9aab4b..eeb0a60 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -23,6 +23,7 @@
 
 #include "../xen.h"
 #include "../trace.h"
+#include "../event_channel.h"
 
 /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
 #define HVMOP_set_param           0
@@ -90,10 +91,10 @@ typedef enum {
 struct xen_hvm_track_dirty_vram {
     /* Domain to be tracked. */
     domid_t  domid;
+    /* Number of pages to track. */
+    uint32_t nr;
     /* First pfn to track. */
     uint64_aligned_t first_pfn;
-    /* Number of pages to track. */
-    uint64_aligned_t nr;
     /* OUT variable. */
     /* Dirty bitmap buffer. */
     XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
@@ -106,10 +107,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
 struct xen_hvm_modified_memory {
     /* Domain to be updated. */
     domid_t  domid;
+    /* Number of pages. */
+    uint32_t nr;
     /* First pfn. */
     uint64_aligned_t first_pfn;
-    /* Number of pages. */
-    uint64_aligned_t nr;
 };
 typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
@@ -162,49 +163,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
 /* Following tools-only interfaces may change in future. */
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
 
+/* Deprecated by XENMEM_access_op_set_access */
 #define HVMOP_set_mem_access        12
-typedef enum {
-    HVMMEM_access_n,
-    HVMMEM_access_r,
-    HVMMEM_access_w,
-    HVMMEM_access_rw,
-    HVMMEM_access_x,
-    HVMMEM_access_rx,
-    HVMMEM_access_wx,
-    HVMMEM_access_rwx,
-    HVMMEM_access_rx2rw,       /* Page starts off as r-x, but automatically
-                                * change to r-w on a write */
-    HVMMEM_access_n2rwx,       /* Log access: starts off as n, automatically 
-                                * goes to rwx, generating an event without
-                                * pausing the vcpu */
-    HVMMEM_access_default      /* Take the domain default */
-} hvmmem_access_t;
-/* Notify that a region of memory is to have specific access types */
-struct xen_hvm_set_mem_access {
-    /* Domain to be updated. */
-    domid_t domid;
-    /* Memory type */
-    uint16_t hvmmem_access; /* hvm_access_t */
-    /* Number of pages, ignored on setting default access */
-    uint32_t nr;
-    /* First pfn, or ~0ull to set the default access for new pages */
-    uint64_aligned_t first_pfn;
-};
-typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t);
 
+/* Deprecated by XENMEM_access_op_get_access */
 #define HVMOP_get_mem_access        13
-/* Get the specific access type for that region of memory */
-struct xen_hvm_get_mem_access {
-    /* Domain to be queried. */
-    domid_t domid;
-    /* Memory type: OUT */
-    uint16_t hvmmem_access; /* hvm_access_t */
-    /* pfn, or ~0ull for default access for new pages.  IN */
-    uint64_aligned_t pfn;
-};
-typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t);
 
 #define HVMOP_inject_trap            14
 /* Inject a trap into a VCPU, which will get taken up on the next
@@ -270,6 +233,150 @@ struct xen_hvm_inject_msi {
 typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
 
+/*
+ * IOREQ Servers
+ *
+ * The interface between an I/O emulator an Xen is called an IOREQ Server.
+ * A domain supports a single 'legacy' IOREQ Server which is instantiated if
+ * parameter...
+ *
+ * HVM_PARAM_IOREQ_PFN is read (to get the gmfn containing the synchronous
+ * ioreq structures), or...
+ * HVM_PARAM_BUFIOREQ_PFN is read (to get the gmfn containing the buffered
+ * ioreq ring), or...
+ * HVM_PARAM_BUFIOREQ_EVTCHN is read (to get the event channel that Xen uses
+ * to request buffered I/O emulation).
+ * 
+ * The following hypercalls facilitate the creation of IOREQ Servers for
+ * 'secondary' emulators which are invoked to implement port I/O, memory, or
+ * PCI config space ranges which they explicitly register.
+ */
+
+typedef uint16_t ioservid_t;
+
+/*
+ * HVMOP_create_ioreq_server: Instantiate a new IOREQ Server for a secondary
+ *                            emulator servicing domain <domid>.
+ *
+ * The <id> handed back is unique for <domid>. If <handle_bufioreq> is zero
+ * the buffered ioreq ring will not be allocated and hence all emulation
+ * requestes to this server will be synchronous.
+ */
+#define HVMOP_create_ioreq_server 17
+struct xen_hvm_create_ioreq_server {
+    domid_t domid;           /* IN - domain to be serviced */
+    uint8_t handle_bufioreq; /* IN - should server handle buffered ioreqs */
+    ioservid_t id;           /* OUT - server id */
+};
+typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
+
+/*
+ * HVMOP_get_ioreq_server_info: Get all the information necessary to access
+ *                              IOREQ Server <id>. 
+ *
+ * The emulator needs to map the synchronous ioreq structures and buffered
+ * ioreq ring (if it exists) that Xen uses to request emulation. These are
+ * hosted in domain <domid>'s gmfns <ioreq_pfn> and <bufioreq_pfn>
+ * respectively. In addition, if the IOREQ Server is handling buffered
+ * emulation requests, the emulator needs to bind to event channel
+ * <bufioreq_port> to listen for them. (The event channels used for
+ * synchronous emulation requests are specified in the per-CPU ioreq
+ * structures in <ioreq_pfn>).
+ * If the IOREQ Server is not handling buffered emulation requests then the
+ * values handed back in <bufioreq_pfn> and <bufioreq_port> will both be 0.
+ */
+#define HVMOP_get_ioreq_server_info 18
+struct xen_hvm_get_ioreq_server_info {
+    domid_t domid;                 /* IN - domain to be serviced */
+    ioservid_t id;                 /* IN - server id */
+    evtchn_port_t bufioreq_port;   /* OUT - buffered ioreq port */
+    uint64_aligned_t ioreq_pfn;    /* OUT - sync ioreq pfn */
+    uint64_aligned_t bufioreq_pfn; /* OUT - buffered ioreq pfn */
+};
+typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
+
+/*
+ * HVM_map_io_range_to_ioreq_server: Register an I/O range of domain <domid>
+ *                                   for emulation by the client of IOREQ
+ *                                   Server <id>
+ * HVM_unmap_io_range_from_ioreq_server: Deregister an I/O range of <domid>
+ *                                       for emulation by the client of IOREQ
+ *                                       Server <id>
+ *
+ * There are three types of I/O that can be emulated: port I/O, memory accesses
+ * and PCI config space accesses. The <type> field denotes which type of range
+ * the <start> and <end> (inclusive) fields are specifying.
+ * PCI config space ranges are specified by segment/bus/device/function values
+ * which should be encoded using the HVMOP_PCI_SBDF helper macro below.
+ *
+ * NOTE: unless an emulation request falls entirely within a range mapped
+ * by a secondary emulator, it will not be passed to that emulator.
+ */
+#define HVMOP_map_io_range_to_ioreq_server 19
+#define HVMOP_unmap_io_range_from_ioreq_server 20
+struct xen_hvm_io_range {
+    domid_t domid;               /* IN - domain to be serviced */
+    ioservid_t id;               /* IN - server id */
+    uint32_t type;               /* IN - type of range */
+# define HVMOP_IO_RANGE_PORT   0 /* I/O port range */
+# define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */
+# define HVMOP_IO_RANGE_PCI    2 /* PCI segment/bus/dev/func range */
+    uint64_aligned_t start, end; /* IN - inclusive start and end of range */
+};
+typedef struct xen_hvm_io_range xen_hvm_io_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_io_range_t);
+
+#define HVMOP_PCI_SBDF(s,b,d,f)                 \
+	((((s) & 0xffff) << 16) |                   \
+	 (((b) & 0xff) << 8) |                      \
+	 (((d) & 0x1f) << 3) |                      \
+	 ((f) & 0x07))
+
+/*
+ * HVMOP_destroy_ioreq_server: Destroy the IOREQ Server <id> servicing domain
+ *                             <domid>.
+ *
+ * Any registered I/O ranges will be automatically deregistered.
+ */
+#define HVMOP_destroy_ioreq_server 21
+struct xen_hvm_destroy_ioreq_server {
+    domid_t domid; /* IN - domain to be serviced */
+    ioservid_t id; /* IN - server id */
+};
+typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
+
+/*
+ * HVMOP_set_ioreq_server_state: Enable or disable the IOREQ Server <id> servicing
+ *                               domain <domid>.
+ *
+ * The IOREQ Server will not be passed any emulation requests until it is in the
+ * enabled state.
+ * Note that the contents of the ioreq_pfn and bufioreq_fn (see
+ * HVMOP_get_ioreq_server_info) are not meaningful until the IOREQ Server is in
+ * the enabled state.
+ */
+#define HVMOP_set_ioreq_server_state 22
+struct xen_hvm_set_ioreq_server_state {
+    domid_t domid;   /* IN - domain to be serviced */
+    ioservid_t id;   /* IN - server id */
+    uint8_t enabled; /* IN - enabled? */    
+};
+typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
+
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/hvm/params.h b/include/xen/hvm/params.h
index 517a184..3c51072 100644
--- a/include/xen/hvm/params.h
+++ b/include/xen/hvm/params.h
@@ -56,9 +56,47 @@
 
 #if defined(__i386__) || defined(__x86_64__)
 
-/* Expose Viridian interfaces to this HVM guest? */
+/*
+ * Viridian enlightenments
+ *
+ * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
+ *
+ * To expose viridian enlightenments to the guest set this parameter
+ * to the desired feature mask. The base feature set must be present
+ * in any valid feature mask.
+ */
 #define HVM_PARAM_VIRIDIAN     9
 
+/* Base+Freq viridian feature sets:
+ *
+ * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
+ * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
+ * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ *   HV_X64_MSR_APIC_FREQUENCY)
+ */
+#define _HVMPV_base_freq 0
+#define HVMPV_base_freq  (1 << _HVMPV_base_freq)
+
+/* Feature set modifications */
+
+/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY).
+ * This modification restores the viridian feature set to the
+ * original 'base' set exposed in releases prior to Xen 4.4.
+ */
+#define _HVMPV_no_freq 1
+#define HVMPV_no_freq  (1 << _HVMPV_no_freq)
+
+/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
+#define _HVMPV_time_ref_count 2
+#define HVMPV_time_ref_count  (1 << _HVMPV_time_ref_count)
+
+#define HVMPV_feature_mask \
+	(HVMPV_base_freq | \
+	 HVMPV_no_freq | \
+	 HVMPV_time_ref_count)
+
 #endif
 
 /*
@@ -145,6 +183,12 @@
 /* SHUTDOWN_* action in case of a triple fault */
 #define HVM_PARAM_TRIPLE_FAULT_REASON 31
 
-#define HVM_NR_PARAMS          32
+#define HVM_PARAM_IOREQ_SERVER_PFN 32
+#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
+
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+#define HVM_NR_PARAMS          35
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/include/xen/io/xs_wire.h b/include/xen/io/xs_wire.h
index 99d24e3..0a0cdbc 100644
--- a/include/xen/io/xs_wire.h
+++ b/include/xen/io/xs_wire.h
@@ -49,7 +49,9 @@ enum xsd_sockmsg_type
     XS_RESUME,
     XS_SET_TARGET,
     XS_RESTRICT,
-    XS_RESET_WATCHES
+    XS_RESET_WATCHES,
+
+    XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
 };
 
 #define XS_WRITE_NONE "NONE"
@@ -83,7 +85,8 @@ __attribute__((unused))
     XSD_ERROR(EROFS),
     XSD_ERROR(EBUSY),
     XSD_ERROR(EAGAIN),
-    XSD_ERROR(EISCONN)
+    XSD_ERROR(EISCONN),
+    XSD_ERROR(E2BIG)
 };
 #endif
 
@@ -115,6 +118,8 @@ struct xenstore_domain_interface {
     char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
     XENSTORE_RING_IDX req_cons, req_prod;
     XENSTORE_RING_IDX rsp_cons, rsp_prod;
+    uint32_t server_features; /* Bitmap of features supported by the server */
+    uint32_t connection;
 };
 
 /* Violating this is very bad.  See docs/misc/xenstore.txt. */
@@ -124,6 +129,13 @@ struct xenstore_domain_interface {
 #define XENSTORE_ABS_PATH_MAX 3072
 #define XENSTORE_REL_PATH_MAX 2048
 
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
+
 #endif /* _XS_WIRE_H */
 
 /*
diff --git a/include/xen/memory.h b/include/xen/memory.h
index 7a26dee..f021958 100644
--- a/include/xen/memory.h
+++ b/include/xen/memory.h
@@ -187,6 +187,15 @@ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
 DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
 
 /*
+ * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
+ *
+ * For a non compat caller, this functions similarly to
+ * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
+ * m2p table.
+ */
+#define XENMEM_machphys_compat_mfn_list     25
+
+/*
  * Returns the location in virtual address space of the machine_to_phys
  * mapping table. Architectures which do not have a m2p table, or which do not
  * map it by default into guest address space, do not implement this command.
@@ -207,8 +216,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
 #define XENMAPSPACE_gmfn         2 /* GMFN */
 #define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
 #define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
-                                    * XENMEM_add_to_physmap_range only.
-                                    */
+                                    * XENMEM_add_to_physmap_batch only. */
 /* ` } */
 
 /*
@@ -238,8 +246,8 @@ typedef struct xen_add_to_physmap xen_add_to_physmap_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
 
 /* A batched version of add_to_physmap. */
-#define XENMEM_add_to_physmap_range 23
-struct xen_add_to_physmap_range {
+#define XENMEM_add_to_physmap_batch 23
+struct xen_add_to_physmap_batch {
     /* IN */
     /* Which domain to change the mapping for. */
     domid_t domid;
@@ -260,8 +268,15 @@ struct xen_add_to_physmap_range {
     /* Per index error code. */
     XEN_GUEST_HANDLE(int) errs;
 };
-typedef struct xen_add_to_physmap_range xen_add_to_physmap_range_t;
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+#define XENMEM_add_to_physmap_range XENMEM_add_to_physmap_batch
+#define xen_add_to_physmap_range xen_add_to_physmap_batch
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_range_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
+#endif
 
 /*
  * Unmaps the page appearing at a particular GPFN from the specified guest's
@@ -357,9 +372,6 @@ typedef struct xen_pod_target xen_pod_target_t;
 #define XENMEM_paging_op_evict              1
 #define XENMEM_paging_op_prep               2
 
-#define XENMEM_access_op                    21
-#define XENMEM_access_op_resume             0
-
 struct xen_mem_event_op {
     uint8_t     op;         /* XENMEM_*_op_* */
     domid_t     domain;
@@ -373,6 +385,56 @@ struct xen_mem_event_op {
 typedef struct xen_mem_event_op xen_mem_event_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
 
+#define XENMEM_access_op                    21
+#define XENMEM_access_op_resume             0
+#define XENMEM_access_op_set_access         1
+#define XENMEM_access_op_get_access         2
+
+typedef enum {
+    XENMEM_access_n,
+    XENMEM_access_r,
+    XENMEM_access_w,
+    XENMEM_access_rw,
+    XENMEM_access_x,
+    XENMEM_access_rx,
+    XENMEM_access_wx,
+    XENMEM_access_rwx,
+    /*
+     * Page starts off as r-x, but automatically
+     * change to r-w on a write
+     */
+    XENMEM_access_rx2rw,
+    /*
+     * Log access: starts off as n, automatically
+     * goes to rwx, generating an event without
+     * pausing the vcpu
+     */
+    XENMEM_access_n2rwx,
+    /* Take the domain default */
+    XENMEM_access_default
+} xenmem_access_t;
+
+struct xen_mem_access_op {
+    /* XENMEM_access_op_* */
+    uint8_t op;
+    /* xenmem_access_t */
+    uint8_t access;
+    domid_t domid;
+    /*
+     * Number of pages for set op
+     * Ignored on setting default access and other ops
+     */
+    uint32_t nr;
+    /*
+     * First pfn for set op
+     * pfn for get op
+     * ~0ull is used to set and get the default access for pages
+     */
+    uint64_aligned_t pfn;
+};
+typedef struct xen_mem_access_op xen_mem_access_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
+
 #define XENMEM_sharing_op                   22
 #define XENMEM_sharing_op_nominate_gfn      0
 #define XENMEM_sharing_op_nominate_gref     1
@@ -461,6 +523,58 @@ DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+/*
+ * XENMEM_get_vnumainfo used by guest to get
+ * vNUMA topology from hypervisor.
+ */
+#define XENMEM_get_vnumainfo                26
+
+/* vNUMA node memory ranges */
+struct vmemrange {
+    uint64_t start, end;
+    unsigned int flags;
+    unsigned int nid;
+};
+
+typedef struct vmemrange vmemrange_t;
+DEFINE_XEN_GUEST_HANDLE(vmemrange_t);
+
+/*
+ * vNUMA topology specifies vNUMA node number, distance table,
+ * memory ranges and vcpu mapping provided for guests.
+ * XENMEM_get_vnumainfo hypercall expects to see from guest
+ * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
+ * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
+ * copied back to guest. Domain returns expected values of nr_vnodes,
+ * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
+ */
+struct vnuma_topology_info {
+    /* IN */
+    domid_t domid;
+    uint16_t pad;
+    /* IN/OUT */
+    unsigned int nr_vnodes;
+    unsigned int nr_vcpus;
+    unsigned int nr_vmemranges;
+    /* OUT */
+    union {
+        XEN_GUEST_HANDLE(uint) h;
+        uint64_t pad;
+    } vdistance;
+    union {
+        XEN_GUEST_HANDLE(uint) h;
+        uint64_t pad;
+    } vcpu_to_vnode;
+    union {
+        XEN_GUEST_HANDLE(vmemrange_t) h;
+        uint64_t pad;
+    } vmemrange;
+};
+typedef struct vnuma_topology_info vnuma_topology_info_t;
+DEFINE_XEN_GUEST_HANDLE(vnuma_topology_info_t);
+
+/* Next available subop number is 27 */
+
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
 
 /*
diff --git a/include/xen/sched.h b/include/xen/sched.h
index 2d0148b..25b140d 100644
--- a/include/xen/sched.h
+++ b/include/xen/sched.h
@@ -76,9 +76,10 @@
  * Halt execution of this domain (all VCPUs) and notify the system controller.
  * @arg == pointer to sched_shutdown_t structure.
  *
- * If the sched_shutdown_t reason is SHUTDOWN_suspend then this
- * hypercall takes an additional extra argument which should be the
- * MFN of the guest's start_info_t.
+ * If the sched_shutdown_t reason is SHUTDOWN_suspend then
+ * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
+ * of the guest's start info page.  RDX/EDX is the third hypercall
+ * argument.
  *
  * In addition, which reason is SHUTDOWN_suspend this hypercall
  * returns 1 if suspend was cancelled or the domain was merely
diff --git a/include/xen/trace.h b/include/xen/trace.h
index 48cc5f5..8de630d 100644
--- a/include/xen/trace.h
+++ b/include/xen/trace.h
@@ -50,8 +50,9 @@
 #define TRC_SUBCLS_SHIFT 12
 
 /* trace subclasses for SVM */
-#define TRC_HVM_ENTRYEXIT 0x00081000   /* VMENTRY and #VMEXIT       */
-#define TRC_HVM_HANDLER   0x00082000   /* various HVM handlers      */
+#define TRC_HVM_ENTRYEXIT   0x00081000   /* VMENTRY and #VMEXIT       */
+#define TRC_HVM_HANDLER     0x00082000   /* various HVM handlers      */
+#define TRC_HVM_EMUL        0x00084000   /* emulated devices */
 
 #define TRC_SCHED_MIN       0x00021000   /* Just runstate changes */
 #define TRC_SCHED_CLASS     0x00022000   /* Scheduler-specific    */
@@ -76,6 +77,7 @@
 #define TRC_SCHED_CSCHED2  1
 #define TRC_SCHED_SEDF     2
 #define TRC_SCHED_ARINC653 3
+#define TRC_SCHED_RTDS     4
 
 /* Per-scheduler tracing */
 #define TRC_SCHED_CLASS_EVT(_c, _e) \
@@ -229,6 +231,25 @@
 #define TRC_HVM_IOPORT_WRITE    (TRC_HVM_HANDLER + 0x216)
 #define TRC_HVM_IOMEM_WRITE     (TRC_HVM_HANDLER + 0x217)
 
+/* Trace events for emulated devices */
+#define TRC_HVM_EMUL_HPET_START_TIMER  (TRC_HVM_EMUL + 0x1)
+#define TRC_HVM_EMUL_PIT_START_TIMER   (TRC_HVM_EMUL + 0x2)
+#define TRC_HVM_EMUL_RTC_START_TIMER   (TRC_HVM_EMUL + 0x3)
+#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
+#define TRC_HVM_EMUL_HPET_STOP_TIMER   (TRC_HVM_EMUL + 0x5)
+#define TRC_HVM_EMUL_PIT_STOP_TIMER    (TRC_HVM_EMUL + 0x6)
+#define TRC_HVM_EMUL_RTC_STOP_TIMER    (TRC_HVM_EMUL + 0x7)
+#define TRC_HVM_EMUL_LAPIC_STOP_TIMER  (TRC_HVM_EMUL + 0x8)
+#define TRC_HVM_EMUL_PIT_TIMER_CB      (TRC_HVM_EMUL + 0x9)
+#define TRC_HVM_EMUL_LAPIC_TIMER_CB    (TRC_HVM_EMUL + 0xA)
+#define TRC_HVM_EMUL_PIC_INT_OUTPUT    (TRC_HVM_EMUL + 0xB)
+#define TRC_HVM_EMUL_PIC_KICK          (TRC_HVM_EMUL + 0xC)
+#define TRC_HVM_EMUL_PIC_INTACK        (TRC_HVM_EMUL + 0xD)
+#define TRC_HVM_EMUL_PIC_POSEDGE       (TRC_HVM_EMUL + 0xE)
+#define TRC_HVM_EMUL_PIC_NEGEDGE       (TRC_HVM_EMUL + 0xF)
+#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
+#define TRC_HVM_EMUL_LAPIC_PIC_INTR    (TRC_HVM_EMUL + 0x11)
+
 /* trace events for per class */
 #define TRC_PM_FREQ_CHANGE      (TRC_HW_PM + 0x01)
 #define TRC_PM_IDLE_ENTRY       (TRC_HW_PM + 0x02)
diff --git a/include/xen/xen-compat.h b/include/xen/xen-compat.h
index 69141c4..3eb80a0 100644
--- a/include/xen/xen-compat.h
+++ b/include/xen/xen-compat.h
@@ -27,7 +27,7 @@
 #ifndef __XEN_PUBLIC_XEN_COMPAT_H__
 #define __XEN_PUBLIC_XEN_COMPAT_H__
 
-#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040300
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
 
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
 /* Xen is built with matching headers and implements the latest interface. */
diff --git a/include/xen/xen.h b/include/xen/xen.h
index c14f9ae..1ca65b0 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -541,22 +541,26 @@ DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
 /*
  * ` enum neg_errnoval
  * ` HYPERVISOR_multicall(multicall_entry_t call_list[],
- * `                      unsigned int nr_calls);
+ * `                      uint32_t nr_calls);
  *
- * NB. The fields are natural register size for this architecture.
+ * NB. The fields are logically the natural register size for this
+ * architecture. In cases where xen_ulong_t is larger than this then
+ * any unused bits in the upper portion must be zero.
  */
 struct multicall_entry {
-    ULONG_PTR op, result;
-    ULONG_PTR args[6];
+    xen_ulong_t op, result;
+    xen_ulong_t args[6];
 };
 typedef struct multicall_entry multicall_entry_t;
 DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
 
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
 /*
- * Event channel endpoints per domain:
+ * Event channel endpoints per domain (when using the 2-level ABI):
  *  1024 if a LONG_PTR is 32 bits; 4096 if a LONG_PTR is 64 bits.
  */
-#define NR_EVENT_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
+#endif
 
 struct vcpu_time_info {
     /*
-- 
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 Nov 06 14:48:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 06 Nov 2014 14:48: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 1XmOM3-0002AP-Dm; Thu, 06 Nov 2014 14:48:07 +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 1XmOLz-0002AK-FQ
	for win-pv-devel@lists.xenproject.org; Thu, 06 Nov 2014 14:48:06 +0000
Received: from [193.109.254.147] by server-6.bemta-14.messagelabs.com id
	8D/D4-03145-22A8B545; Thu, 06 Nov 2014 14:48:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-27.messagelabs.com!1415285278!11811091!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16656 invoked from network); 6 Nov 2014 14:48:00 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	6 Nov 2014 14:48:00 -0000
X-IronPort-AV: E=Sophos;i="5.07,326,1413244800"; d="scan'208";a="190196754"
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.181.6;
	Thu, 6 Nov 2014 09:47:47 -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 1XmNzK-0008E8-DG;
	Thu, 06 Nov 2014 14:24:38 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 6 Nov 2014 14:24:21 +0000
Message-ID: <1415283861-26028-11-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
References: <1415283861-26028-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 09/10] Update Xen headers to RELEASE-4.4.1
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>
---
 include/xen/arch-x86/xen.h  |   9 ++
 include/xen/event_channel.h |  91 +++++++++++++++++++++
 include/xen/hvm/hvm_op.h    | 195 ++++++++++++++++++++++++++++++++++----------
 include/xen/hvm/params.h    |  48 ++++++++++-
 include/xen/io/xs_wire.h    |  16 +++-
 include/xen/memory.h        | 130 +++++++++++++++++++++++++++--
 include/xen/sched.h         |   7 +-
 include/xen/trace.h         |  25 +++++-
 include/xen/xen-compat.h    |   2 +-
 include/xen/xen.h           |  16 ++--
 10 files changed, 471 insertions(+), 68 deletions(-)

diff --git a/include/xen/arch-x86/xen.h b/include/xen/arch-x86/xen.h
index 5cc22fb..1880f89 100644
--- a/include/xen/arch-x86/xen.h
+++ b/include/xen/arch-x86/xen.h
@@ -154,6 +154,15 @@ typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled 
  * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
+ *
+ * Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
+ * for HVM and PVH guests, not all information in this structure is updated:
+ *
+ * - For HVM guests, the structures read include: fpu_ctxt (if
+ * VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
+ *
+ * - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
+ * set cr3. All other fields not used should be set to 0.
  */
 struct vcpu_guest_context {
     /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
diff --git a/include/xen/event_channel.h b/include/xen/event_channel.h
index 472efdb..05e531d 100644
--- a/include/xen/event_channel.h
+++ b/include/xen/event_channel.h
@@ -71,6 +71,9 @@
 #define EVTCHNOP_bind_vcpu        8
 #define EVTCHNOP_unmask           9
 #define EVTCHNOP_reset           10
+#define EVTCHNOP_init_control    11
+#define EVTCHNOP_expand_array    12
+#define EVTCHNOP_set_priority    13
 /* ` } */
 
 typedef uint32_t evtchn_port_t;
@@ -98,6 +101,17 @@ typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
  * a port that is unbound and marked as accepting bindings from the calling
  * domain. A fresh port is allocated in the calling domain and returned as
  * <local_port>.
+ *
+ * In case the peer domain has already tried to set our event channel
+ * pending, before it was bound, EVTCHNOP_bind_interdomain always sets
+ * the local event channel pending.
+ *
+ * The usual pattern of use, in the guest's upcall (or subsequent
+ * handler) is as follows: (Re-enable the event channel for subsequent
+ * signalling and then) check for the existence of whatever condition
+ * is being waited for by other means, and take whatever action is
+ * needed (if any).
+ *
  * NOTES:
  *  1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
  */
@@ -250,6 +264,10 @@ typedef struct evtchn_unmask evtchn_unmask_t;
  * NOTES:
  *  1. <dom> may be specified as DOMID_SELF.
  *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
+ *  3. Destroys all control blocks and event array, resets event channel
+ *     operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO
+ *     ABI was used. Guests should not bind events during EVTCHNOP_reset call
+ *     as these events are likely to be lost.
  */
 struct evtchn_reset {
     /* IN parameters. */
@@ -258,6 +276,43 @@ struct evtchn_reset {
 typedef struct evtchn_reset evtchn_reset_t;
 
 /*
+ * EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
+ *
+ * Note: any events that are currently pending will not be resent and
+ * will be lost.  Guests should call this before binding any event to
+ * avoid losing any events.
+ */
+struct evtchn_init_control {
+    /* IN parameters. */
+    uint64_t control_gfn;
+    uint32_t offset;
+    uint32_t vcpu;
+    /* OUT parameters. */
+    uint8_t link_bits;
+    uint8_t _pad[7];
+};
+typedef struct evtchn_init_control evtchn_init_control_t;
+
+/*
+ * EVTCHNOP_expand_array: add an additional page to the event array.
+ */
+struct evtchn_expand_array {
+    /* IN parameters. */
+    uint64_t array_gfn;
+};
+typedef struct evtchn_expand_array evtchn_expand_array_t;
+
+/*
+ * EVTCHNOP_set_priority: set the priority for an event channel.
+ */
+struct evtchn_set_priority {
+    /* IN parameters. */
+    uint32_t port;
+    uint32_t priority;
+};
+typedef struct evtchn_set_priority evtchn_set_priority_t;
+
+/*
  * ` enum neg_errnoval
  * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
  * `
@@ -281,6 +336,42 @@ struct evtchn_op {
 typedef struct evtchn_op evtchn_op_t;
 DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
 
+/*
+ * 2-level ABI
+ */
+
+#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+
+/*
+ * FIFO ABI
+ */
+
+/* Events may have priorities from 0 (highest) to 15 (lowest). */
+#define EVTCHN_FIFO_PRIORITY_MAX     0
+#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
+#define EVTCHN_FIFO_PRIORITY_MIN     15
+
+#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
+
+typedef uint32_t event_word_t;
+
+#define EVTCHN_FIFO_PENDING 31
+#define EVTCHN_FIFO_MASKED  30
+#define EVTCHN_FIFO_LINKED  29
+#define EVTCHN_FIFO_BUSY    28
+
+#define EVTCHN_FIFO_LINK_BITS 17
+#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
+
+#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
+
+struct evtchn_fifo_control_block {
+    uint32_t ready;
+    uint32_t _rsvd;
+    uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
+};
+typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
+
 #endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index a9aab4b..eeb0a60 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -23,6 +23,7 @@
 
 #include "../xen.h"
 #include "../trace.h"
+#include "../event_channel.h"
 
 /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
 #define HVMOP_set_param           0
@@ -90,10 +91,10 @@ typedef enum {
 struct xen_hvm_track_dirty_vram {
     /* Domain to be tracked. */
     domid_t  domid;
+    /* Number of pages to track. */
+    uint32_t nr;
     /* First pfn to track. */
     uint64_aligned_t first_pfn;
-    /* Number of pages to track. */
-    uint64_aligned_t nr;
     /* OUT variable. */
     /* Dirty bitmap buffer. */
     XEN_GUEST_HANDLE_64(uint8) dirty_bitmap;
@@ -106,10 +107,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t);
 struct xen_hvm_modified_memory {
     /* Domain to be updated. */
     domid_t  domid;
+    /* Number of pages. */
+    uint32_t nr;
     /* First pfn. */
     uint64_aligned_t first_pfn;
-    /* Number of pages. */
-    uint64_aligned_t nr;
 };
 typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t);
@@ -162,49 +163,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t);
 /* Following tools-only interfaces may change in future. */
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
 
+/* Deprecated by XENMEM_access_op_set_access */
 #define HVMOP_set_mem_access        12
-typedef enum {
-    HVMMEM_access_n,
-    HVMMEM_access_r,
-    HVMMEM_access_w,
-    HVMMEM_access_rw,
-    HVMMEM_access_x,
-    HVMMEM_access_rx,
-    HVMMEM_access_wx,
-    HVMMEM_access_rwx,
-    HVMMEM_access_rx2rw,       /* Page starts off as r-x, but automatically
-                                * change to r-w on a write */
-    HVMMEM_access_n2rwx,       /* Log access: starts off as n, automatically 
-                                * goes to rwx, generating an event without
-                                * pausing the vcpu */
-    HVMMEM_access_default      /* Take the domain default */
-} hvmmem_access_t;
-/* Notify that a region of memory is to have specific access types */
-struct xen_hvm_set_mem_access {
-    /* Domain to be updated. */
-    domid_t domid;
-    /* Memory type */
-    uint16_t hvmmem_access; /* hvm_access_t */
-    /* Number of pages, ignored on setting default access */
-    uint32_t nr;
-    /* First pfn, or ~0ull to set the default access for new pages */
-    uint64_aligned_t first_pfn;
-};
-typedef struct xen_hvm_set_mem_access xen_hvm_set_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_access_t);
 
+/* Deprecated by XENMEM_access_op_get_access */
 #define HVMOP_get_mem_access        13
-/* Get the specific access type for that region of memory */
-struct xen_hvm_get_mem_access {
-    /* Domain to be queried. */
-    domid_t domid;
-    /* Memory type: OUT */
-    uint16_t hvmmem_access; /* hvm_access_t */
-    /* pfn, or ~0ull for default access for new pages.  IN */
-    uint64_aligned_t pfn;
-};
-typedef struct xen_hvm_get_mem_access xen_hvm_get_mem_access_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_access_t);
 
 #define HVMOP_inject_trap            14
 /* Inject a trap into a VCPU, which will get taken up on the next
@@ -270,6 +233,150 @@ struct xen_hvm_inject_msi {
 typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
 
+/*
+ * IOREQ Servers
+ *
+ * The interface between an I/O emulator an Xen is called an IOREQ Server.
+ * A domain supports a single 'legacy' IOREQ Server which is instantiated if
+ * parameter...
+ *
+ * HVM_PARAM_IOREQ_PFN is read (to get the gmfn containing the synchronous
+ * ioreq structures), or...
+ * HVM_PARAM_BUFIOREQ_PFN is read (to get the gmfn containing the buffered
+ * ioreq ring), or...
+ * HVM_PARAM_BUFIOREQ_EVTCHN is read (to get the event channel that Xen uses
+ * to request buffered I/O emulation).
+ * 
+ * The following hypercalls facilitate the creation of IOREQ Servers for
+ * 'secondary' emulators which are invoked to implement port I/O, memory, or
+ * PCI config space ranges which they explicitly register.
+ */
+
+typedef uint16_t ioservid_t;
+
+/*
+ * HVMOP_create_ioreq_server: Instantiate a new IOREQ Server for a secondary
+ *                            emulator servicing domain <domid>.
+ *
+ * The <id> handed back is unique for <domid>. If <handle_bufioreq> is zero
+ * the buffered ioreq ring will not be allocated and hence all emulation
+ * requestes to this server will be synchronous.
+ */
+#define HVMOP_create_ioreq_server 17
+struct xen_hvm_create_ioreq_server {
+    domid_t domid;           /* IN - domain to be serviced */
+    uint8_t handle_bufioreq; /* IN - should server handle buffered ioreqs */
+    ioservid_t id;           /* OUT - server id */
+};
+typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
+
+/*
+ * HVMOP_get_ioreq_server_info: Get all the information necessary to access
+ *                              IOREQ Server <id>. 
+ *
+ * The emulator needs to map the synchronous ioreq structures and buffered
+ * ioreq ring (if it exists) that Xen uses to request emulation. These are
+ * hosted in domain <domid>'s gmfns <ioreq_pfn> and <bufioreq_pfn>
+ * respectively. In addition, if the IOREQ Server is handling buffered
+ * emulation requests, the emulator needs to bind to event channel
+ * <bufioreq_port> to listen for them. (The event channels used for
+ * synchronous emulation requests are specified in the per-CPU ioreq
+ * structures in <ioreq_pfn>).
+ * If the IOREQ Server is not handling buffered emulation requests then the
+ * values handed back in <bufioreq_pfn> and <bufioreq_port> will both be 0.
+ */
+#define HVMOP_get_ioreq_server_info 18
+struct xen_hvm_get_ioreq_server_info {
+    domid_t domid;                 /* IN - domain to be serviced */
+    ioservid_t id;                 /* IN - server id */
+    evtchn_port_t bufioreq_port;   /* OUT - buffered ioreq port */
+    uint64_aligned_t ioreq_pfn;    /* OUT - sync ioreq pfn */
+    uint64_aligned_t bufioreq_pfn; /* OUT - buffered ioreq pfn */
+};
+typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
+
+/*
+ * HVM_map_io_range_to_ioreq_server: Register an I/O range of domain <domid>
+ *                                   for emulation by the client of IOREQ
+ *                                   Server <id>
+ * HVM_unmap_io_range_from_ioreq_server: Deregister an I/O range of <domid>
+ *                                       for emulation by the client of IOREQ
+ *                                       Server <id>
+ *
+ * There are three types of I/O that can be emulated: port I/O, memory accesses
+ * and PCI config space accesses. The <type> field denotes which type of range
+ * the <start> and <end> (inclusive) fields are specifying.
+ * PCI config space ranges are specified by segment/bus/device/function values
+ * which should be encoded using the HVMOP_PCI_SBDF helper macro below.
+ *
+ * NOTE: unless an emulation request falls entirely within a range mapped
+ * by a secondary emulator, it will not be passed to that emulator.
+ */
+#define HVMOP_map_io_range_to_ioreq_server 19
+#define HVMOP_unmap_io_range_from_ioreq_server 20
+struct xen_hvm_io_range {
+    domid_t domid;               /* IN - domain to be serviced */
+    ioservid_t id;               /* IN - server id */
+    uint32_t type;               /* IN - type of range */
+# define HVMOP_IO_RANGE_PORT   0 /* I/O port range */
+# define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */
+# define HVMOP_IO_RANGE_PCI    2 /* PCI segment/bus/dev/func range */
+    uint64_aligned_t start, end; /* IN - inclusive start and end of range */
+};
+typedef struct xen_hvm_io_range xen_hvm_io_range_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_io_range_t);
+
+#define HVMOP_PCI_SBDF(s,b,d,f)                 \
+	((((s) & 0xffff) << 16) |                   \
+	 (((b) & 0xff) << 8) |                      \
+	 (((d) & 0x1f) << 3) |                      \
+	 ((f) & 0x07))
+
+/*
+ * HVMOP_destroy_ioreq_server: Destroy the IOREQ Server <id> servicing domain
+ *                             <domid>.
+ *
+ * Any registered I/O ranges will be automatically deregistered.
+ */
+#define HVMOP_destroy_ioreq_server 21
+struct xen_hvm_destroy_ioreq_server {
+    domid_t domid; /* IN - domain to be serviced */
+    ioservid_t id; /* IN - server id */
+};
+typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
+
+/*
+ * HVMOP_set_ioreq_server_state: Enable or disable the IOREQ Server <id> servicing
+ *                               domain <domid>.
+ *
+ * The IOREQ Server will not be passed any emulation requests until it is in the
+ * enabled state.
+ * Note that the contents of the ioreq_pfn and bufioreq_fn (see
+ * HVMOP_get_ioreq_server_info) are not meaningful until the IOREQ Server is in
+ * the enabled state.
+ */
+#define HVMOP_set_ioreq_server_state 22
+struct xen_hvm_set_ioreq_server_state {
+    domid_t domid;   /* IN - domain to be serviced */
+    ioservid_t id;   /* IN - server id */
+    uint8_t enabled; /* IN - enabled? */    
+};
+typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
+
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/xen/hvm/params.h b/include/xen/hvm/params.h
index 517a184..3c51072 100644
--- a/include/xen/hvm/params.h
+++ b/include/xen/hvm/params.h
@@ -56,9 +56,47 @@
 
 #if defined(__i386__) || defined(__x86_64__)
 
-/* Expose Viridian interfaces to this HVM guest? */
+/*
+ * Viridian enlightenments
+ *
+ * (See http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor%20Top%20Level%20Functional%20Specification%20v4.0.docx)
+ *
+ * To expose viridian enlightenments to the guest set this parameter
+ * to the desired feature mask. The base feature set must be present
+ * in any valid feature mask.
+ */
 #define HVM_PARAM_VIRIDIAN     9
 
+/* Base+Freq viridian feature sets:
+ *
+ * - Hypercall MSRs (HV_X64_MSR_GUEST_OS_ID and HV_X64_MSR_HYPERCALL)
+ * - APIC access MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR)
+ * - Virtual Processor index MSR (HV_X64_MSR_VP_INDEX)
+ * - Timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ *   HV_X64_MSR_APIC_FREQUENCY)
+ */
+#define _HVMPV_base_freq 0
+#define HVMPV_base_freq  (1 << _HVMPV_base_freq)
+
+/* Feature set modifications */
+
+/* Disable timer frequency MSRs (HV_X64_MSR_TSC_FREQUENCY and
+ * HV_X64_MSR_APIC_FREQUENCY).
+ * This modification restores the viridian feature set to the
+ * original 'base' set exposed in releases prior to Xen 4.4.
+ */
+#define _HVMPV_no_freq 1
+#define HVMPV_no_freq  (1 << _HVMPV_no_freq)
+
+/* Enable Partition Time Reference Counter (HV_X64_MSR_TIME_REF_COUNT) */
+#define _HVMPV_time_ref_count 2
+#define HVMPV_time_ref_count  (1 << _HVMPV_time_ref_count)
+
+#define HVMPV_feature_mask \
+	(HVMPV_base_freq | \
+	 HVMPV_no_freq | \
+	 HVMPV_time_ref_count)
+
 #endif
 
 /*
@@ -145,6 +183,12 @@
 /* SHUTDOWN_* action in case of a triple fault */
 #define HVM_PARAM_TRIPLE_FAULT_REASON 31
 
-#define HVM_NR_PARAMS          32
+#define HVM_PARAM_IOREQ_SERVER_PFN 32
+#define HVM_PARAM_NR_IOREQ_SERVER_PAGES 33
+
+/* Location of the VM Generation ID in guest physical address space. */
+#define HVM_PARAM_VM_GENERATION_ID_ADDR 34
+
+#define HVM_NR_PARAMS          35
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/include/xen/io/xs_wire.h b/include/xen/io/xs_wire.h
index 99d24e3..0a0cdbc 100644
--- a/include/xen/io/xs_wire.h
+++ b/include/xen/io/xs_wire.h
@@ -49,7 +49,9 @@ enum xsd_sockmsg_type
     XS_RESUME,
     XS_SET_TARGET,
     XS_RESTRICT,
-    XS_RESET_WATCHES
+    XS_RESET_WATCHES,
+
+    XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
 };
 
 #define XS_WRITE_NONE "NONE"
@@ -83,7 +85,8 @@ __attribute__((unused))
     XSD_ERROR(EROFS),
     XSD_ERROR(EBUSY),
     XSD_ERROR(EAGAIN),
-    XSD_ERROR(EISCONN)
+    XSD_ERROR(EISCONN),
+    XSD_ERROR(E2BIG)
 };
 #endif
 
@@ -115,6 +118,8 @@ struct xenstore_domain_interface {
     char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
     XENSTORE_RING_IDX req_cons, req_prod;
     XENSTORE_RING_IDX rsp_cons, rsp_prod;
+    uint32_t server_features; /* Bitmap of features supported by the server */
+    uint32_t connection;
 };
 
 /* Violating this is very bad.  See docs/misc/xenstore.txt. */
@@ -124,6 +129,13 @@ struct xenstore_domain_interface {
 #define XENSTORE_ABS_PATH_MAX 3072
 #define XENSTORE_REL_PATH_MAX 2048
 
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
+
 #endif /* _XS_WIRE_H */
 
 /*
diff --git a/include/xen/memory.h b/include/xen/memory.h
index 7a26dee..f021958 100644
--- a/include/xen/memory.h
+++ b/include/xen/memory.h
@@ -187,6 +187,15 @@ typedef struct xen_machphys_mfn_list xen_machphys_mfn_list_t;
 DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn_list_t);
 
 /*
+ * For a compat caller, this is identical to XENMEM_machphys_mfn_list.
+ *
+ * For a non compat caller, this functions similarly to
+ * XENMEM_machphys_mfn_list, but returns the mfns making up the compatibility
+ * m2p table.
+ */
+#define XENMEM_machphys_compat_mfn_list     25
+
+/*
  * Returns the location in virtual address space of the machine_to_phys
  * mapping table. Architectures which do not have a m2p table, or which do not
  * map it by default into guest address space, do not implement this command.
@@ -207,8 +216,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
 #define XENMAPSPACE_gmfn         2 /* GMFN */
 #define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
 #define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
-                                    * XENMEM_add_to_physmap_range only.
-                                    */
+                                    * XENMEM_add_to_physmap_batch only. */
 /* ` } */
 
 /*
@@ -238,8 +246,8 @@ typedef struct xen_add_to_physmap xen_add_to_physmap_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
 
 /* A batched version of add_to_physmap. */
-#define XENMEM_add_to_physmap_range 23
-struct xen_add_to_physmap_range {
+#define XENMEM_add_to_physmap_batch 23
+struct xen_add_to_physmap_batch {
     /* IN */
     /* Which domain to change the mapping for. */
     domid_t domid;
@@ -260,8 +268,15 @@ struct xen_add_to_physmap_range {
     /* Per index error code. */
     XEN_GUEST_HANDLE(int) errs;
 };
-typedef struct xen_add_to_physmap_range xen_add_to_physmap_range_t;
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_batch_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_batch_t);
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+#define XENMEM_add_to_physmap_range XENMEM_add_to_physmap_batch
+#define xen_add_to_physmap_range xen_add_to_physmap_batch
+typedef struct xen_add_to_physmap_batch xen_add_to_physmap_range_t;
 DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_range_t);
+#endif
 
 /*
  * Unmaps the page appearing at a particular GPFN from the specified guest's
@@ -357,9 +372,6 @@ typedef struct xen_pod_target xen_pod_target_t;
 #define XENMEM_paging_op_evict              1
 #define XENMEM_paging_op_prep               2
 
-#define XENMEM_access_op                    21
-#define XENMEM_access_op_resume             0
-
 struct xen_mem_event_op {
     uint8_t     op;         /* XENMEM_*_op_* */
     domid_t     domain;
@@ -373,6 +385,56 @@ struct xen_mem_event_op {
 typedef struct xen_mem_event_op xen_mem_event_op_t;
 DEFINE_XEN_GUEST_HANDLE(xen_mem_event_op_t);
 
+#define XENMEM_access_op                    21
+#define XENMEM_access_op_resume             0
+#define XENMEM_access_op_set_access         1
+#define XENMEM_access_op_get_access         2
+
+typedef enum {
+    XENMEM_access_n,
+    XENMEM_access_r,
+    XENMEM_access_w,
+    XENMEM_access_rw,
+    XENMEM_access_x,
+    XENMEM_access_rx,
+    XENMEM_access_wx,
+    XENMEM_access_rwx,
+    /*
+     * Page starts off as r-x, but automatically
+     * change to r-w on a write
+     */
+    XENMEM_access_rx2rw,
+    /*
+     * Log access: starts off as n, automatically
+     * goes to rwx, generating an event without
+     * pausing the vcpu
+     */
+    XENMEM_access_n2rwx,
+    /* Take the domain default */
+    XENMEM_access_default
+} xenmem_access_t;
+
+struct xen_mem_access_op {
+    /* XENMEM_access_op_* */
+    uint8_t op;
+    /* xenmem_access_t */
+    uint8_t access;
+    domid_t domid;
+    /*
+     * Number of pages for set op
+     * Ignored on setting default access and other ops
+     */
+    uint32_t nr;
+    /*
+     * First pfn for set op
+     * pfn for get op
+     * ~0ull is used to set and get the default access for pages
+     */
+    uint64_aligned_t pfn;
+};
+typedef struct xen_mem_access_op xen_mem_access_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_access_op_t);
+
 #define XENMEM_sharing_op                   22
 #define XENMEM_sharing_op_nominate_gfn      0
 #define XENMEM_sharing_op_nominate_gref     1
@@ -461,6 +523,58 @@ DEFINE_XEN_GUEST_HANDLE(xen_mem_sharing_op_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+/*
+ * XENMEM_get_vnumainfo used by guest to get
+ * vNUMA topology from hypervisor.
+ */
+#define XENMEM_get_vnumainfo                26
+
+/* vNUMA node memory ranges */
+struct vmemrange {
+    uint64_t start, end;
+    unsigned int flags;
+    unsigned int nid;
+};
+
+typedef struct vmemrange vmemrange_t;
+DEFINE_XEN_GUEST_HANDLE(vmemrange_t);
+
+/*
+ * vNUMA topology specifies vNUMA node number, distance table,
+ * memory ranges and vcpu mapping provided for guests.
+ * XENMEM_get_vnumainfo hypercall expects to see from guest
+ * nr_vnodes, nr_vmemranges and nr_vcpus to indicate available memory.
+ * After filling guests structures, nr_vnodes, nr_vmemranges and nr_vcpus
+ * copied back to guest. Domain returns expected values of nr_vnodes,
+ * nr_vmemranges and nr_vcpus to guest if the values where incorrect.
+ */
+struct vnuma_topology_info {
+    /* IN */
+    domid_t domid;
+    uint16_t pad;
+    /* IN/OUT */
+    unsigned int nr_vnodes;
+    unsigned int nr_vcpus;
+    unsigned int nr_vmemranges;
+    /* OUT */
+    union {
+        XEN_GUEST_HANDLE(uint) h;
+        uint64_t pad;
+    } vdistance;
+    union {
+        XEN_GUEST_HANDLE(uint) h;
+        uint64_t pad;
+    } vcpu_to_vnode;
+    union {
+        XEN_GUEST_HANDLE(vmemrange_t) h;
+        uint64_t pad;
+    } vmemrange;
+};
+typedef struct vnuma_topology_info vnuma_topology_info_t;
+DEFINE_XEN_GUEST_HANDLE(vnuma_topology_info_t);
+
+/* Next available subop number is 27 */
+
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
 
 /*
diff --git a/include/xen/sched.h b/include/xen/sched.h
index 2d0148b..25b140d 100644
--- a/include/xen/sched.h
+++ b/include/xen/sched.h
@@ -76,9 +76,10 @@
  * Halt execution of this domain (all VCPUs) and notify the system controller.
  * @arg == pointer to sched_shutdown_t structure.
  *
- * If the sched_shutdown_t reason is SHUTDOWN_suspend then this
- * hypercall takes an additional extra argument which should be the
- * MFN of the guest's start_info_t.
+ * If the sched_shutdown_t reason is SHUTDOWN_suspend then
+ * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN
+ * of the guest's start info page.  RDX/EDX is the third hypercall
+ * argument.
  *
  * In addition, which reason is SHUTDOWN_suspend this hypercall
  * returns 1 if suspend was cancelled or the domain was merely
diff --git a/include/xen/trace.h b/include/xen/trace.h
index 48cc5f5..8de630d 100644
--- a/include/xen/trace.h
+++ b/include/xen/trace.h
@@ -50,8 +50,9 @@
 #define TRC_SUBCLS_SHIFT 12
 
 /* trace subclasses for SVM */
-#define TRC_HVM_ENTRYEXIT 0x00081000   /* VMENTRY and #VMEXIT       */
-#define TRC_HVM_HANDLER   0x00082000   /* various HVM handlers      */
+#define TRC_HVM_ENTRYEXIT   0x00081000   /* VMENTRY and #VMEXIT       */
+#define TRC_HVM_HANDLER     0x00082000   /* various HVM handlers      */
+#define TRC_HVM_EMUL        0x00084000   /* emulated devices */
 
 #define TRC_SCHED_MIN       0x00021000   /* Just runstate changes */
 #define TRC_SCHED_CLASS     0x00022000   /* Scheduler-specific    */
@@ -76,6 +77,7 @@
 #define TRC_SCHED_CSCHED2  1
 #define TRC_SCHED_SEDF     2
 #define TRC_SCHED_ARINC653 3
+#define TRC_SCHED_RTDS     4
 
 /* Per-scheduler tracing */
 #define TRC_SCHED_CLASS_EVT(_c, _e) \
@@ -229,6 +231,25 @@
 #define TRC_HVM_IOPORT_WRITE    (TRC_HVM_HANDLER + 0x216)
 #define TRC_HVM_IOMEM_WRITE     (TRC_HVM_HANDLER + 0x217)
 
+/* Trace events for emulated devices */
+#define TRC_HVM_EMUL_HPET_START_TIMER  (TRC_HVM_EMUL + 0x1)
+#define TRC_HVM_EMUL_PIT_START_TIMER   (TRC_HVM_EMUL + 0x2)
+#define TRC_HVM_EMUL_RTC_START_TIMER   (TRC_HVM_EMUL + 0x3)
+#define TRC_HVM_EMUL_LAPIC_START_TIMER (TRC_HVM_EMUL + 0x4)
+#define TRC_HVM_EMUL_HPET_STOP_TIMER   (TRC_HVM_EMUL + 0x5)
+#define TRC_HVM_EMUL_PIT_STOP_TIMER    (TRC_HVM_EMUL + 0x6)
+#define TRC_HVM_EMUL_RTC_STOP_TIMER    (TRC_HVM_EMUL + 0x7)
+#define TRC_HVM_EMUL_LAPIC_STOP_TIMER  (TRC_HVM_EMUL + 0x8)
+#define TRC_HVM_EMUL_PIT_TIMER_CB      (TRC_HVM_EMUL + 0x9)
+#define TRC_HVM_EMUL_LAPIC_TIMER_CB    (TRC_HVM_EMUL + 0xA)
+#define TRC_HVM_EMUL_PIC_INT_OUTPUT    (TRC_HVM_EMUL + 0xB)
+#define TRC_HVM_EMUL_PIC_KICK          (TRC_HVM_EMUL + 0xC)
+#define TRC_HVM_EMUL_PIC_INTACK        (TRC_HVM_EMUL + 0xD)
+#define TRC_HVM_EMUL_PIC_POSEDGE       (TRC_HVM_EMUL + 0xE)
+#define TRC_HVM_EMUL_PIC_NEGEDGE       (TRC_HVM_EMUL + 0xF)
+#define TRC_HVM_EMUL_PIC_PEND_IRQ_CALL (TRC_HVM_EMUL + 0x10)
+#define TRC_HVM_EMUL_LAPIC_PIC_INTR    (TRC_HVM_EMUL + 0x11)
+
 /* trace events for per class */
 #define TRC_PM_FREQ_CHANGE      (TRC_HW_PM + 0x01)
 #define TRC_PM_IDLE_ENTRY       (TRC_HW_PM + 0x02)
diff --git a/include/xen/xen-compat.h b/include/xen/xen-compat.h
index 69141c4..3eb80a0 100644
--- a/include/xen/xen-compat.h
+++ b/include/xen/xen-compat.h
@@ -27,7 +27,7 @@
 #ifndef __XEN_PUBLIC_XEN_COMPAT_H__
 #define __XEN_PUBLIC_XEN_COMPAT_H__
 
-#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040300
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
 
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
 /* Xen is built with matching headers and implements the latest interface. */
diff --git a/include/xen/xen.h b/include/xen/xen.h
index c14f9ae..1ca65b0 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -541,22 +541,26 @@ DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
 /*
  * ` enum neg_errnoval
  * ` HYPERVISOR_multicall(multicall_entry_t call_list[],
- * `                      unsigned int nr_calls);
+ * `                      uint32_t nr_calls);
  *
- * NB. The fields are natural register size for this architecture.
+ * NB. The fields are logically the natural register size for this
+ * architecture. In cases where xen_ulong_t is larger than this then
+ * any unused bits in the upper portion must be zero.
  */
 struct multicall_entry {
-    ULONG_PTR op, result;
-    ULONG_PTR args[6];
+    xen_ulong_t op, result;
+    xen_ulong_t args[6];
 };
 typedef struct multicall_entry multicall_entry_t;
 DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
 
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
 /*
- * Event channel endpoints per domain:
+ * Event channel endpoints per domain (when using the 2-level ABI):
  *  1024 if a LONG_PTR is 32 bits; 4096 if a LONG_PTR is 64 bits.
  */
-#define NR_EVENT_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
+#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
+#endif
 
 struct vcpu_time_info {
     /*
-- 
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 Nov 07 12:52:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 12:52: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 1Xmj1l-0003E8-1b; Fri, 07 Nov 2014 12:52:33 +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 1Xmj1k-0003Dy-BA
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 12:52:32 +0000
Received: from [85.158.137.68] by server-10.bemta-3.messagelabs.com id
	06/B6-24859-F80CC545; Fri, 07 Nov 2014 12:52:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1415364749!11048593!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 28601 invoked from network); 7 Nov 2014 12:52:31 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 12:52:31 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190540061"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 07:52:28 -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 1Xmj1g-0003Y9-C6;
	Fri, 07 Nov 2014 12:52:28 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 12:52:16 +0000
Message-ID: <1415364736-28452-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415364736-28452-1-git-send-email-paul.durrant@citrix.com>
References: <1415364736-28452-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Remove needless checks on ParametersKey
	validity
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

It used to be the case that XENBUS would tolerate a lack of Parameters key
in its Service key but that has not been true for some time, so remove
validity checks that are no longer needed.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/bus.c     | 15 ++++++---------
 src/xenbus/fdo.c     | 12 ++++--------
 src/xenfilt/driver.c |  3 ---
 3 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/src/xenbus/bus.c b/src/xenbus/bus.c
index af95422..bf0bec7 100644
--- a/src/xenbus/bus.c
+++ b/src/xenbus/bus.c
@@ -190,6 +190,7 @@ BusInitialize(
 {
     PXENBUS_BUS_CONTEXT         Context;
     HANDLE                      ParametersKey;
+    ULONG                       InterceptDmaAdapter;
     NTSTATUS                    status;
 
     Trace("====>\n");
@@ -206,15 +207,11 @@ BusInitialize(
 
     Context->InterceptDmaAdapter = 0;
 
-    if (ParametersKey != NULL) {
-        ULONG   InterceptDmaAdapter;
-
-        status = RegistryQueryDwordValue(ParametersKey,
-                                         "InterceptDmaAdapter",
-                                         &InterceptDmaAdapter);
-        if (NT_SUCCESS(status))
-            Context->InterceptDmaAdapter = InterceptDmaAdapter;
-    }
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "InterceptDmaAdapter",
+                                     &InterceptDmaAdapter);
+    if (NT_SUCCESS(status))
+        Context->InterceptDmaAdapter = InterceptDmaAdapter;
 
     Interface->Size = sizeof (BUS_INTERFACE_STANDARD);
     Interface->Version = 1;
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 7c6f5cd..59442bd 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -971,15 +971,11 @@ FdoScan(
             StoreClasses = NULL;
         }
 
-        if (ParametersKey != NULL) {
-            status = RegistryQuerySzValue(ParametersKey,
-                                          "SyntheticClasses",
-                                          &SyntheticClasses);
-            if (!NT_SUCCESS(status))
-                SyntheticClasses = NULL;
-        } else {
+        status = RegistryQuerySzValue(ParametersKey,
+                                      "SyntheticClasses",
+                                      &SyntheticClasses);
+        if (!NT_SUCCESS(status))
             SyntheticClasses = NULL;
-        }
 
         Classes = FdoCombineAnsi(StoreClasses, SyntheticClasses);
 
diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c
index 86c6800..36a761c 100644
--- a/src/xenfilt/driver.c
+++ b/src/xenfilt/driver.c
@@ -486,8 +486,6 @@ DriverAddDevice(
     ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
     ParametersKey = __DriverGetParametersKey();
-    if (ParametersKey == NULL)
-        goto done;
 
     status = DriverQueryId(PhysicalDeviceObject, BusQueryDeviceID, &DeviceID);
     if (!NT_SUCCESS(status))
@@ -522,7 +520,6 @@ DriverAddDevice(
     ExFreePool(InstanceID);
     ExFreePool(DeviceID);
 
-done:
     return STATUS_SUCCESS;
 
 fail4:
-- 
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 Nov 07 12:52:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 12:52: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 1Xmj1l-0003E8-1b; Fri, 07 Nov 2014 12:52:33 +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 1Xmj1k-0003Dy-BA
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 12:52:32 +0000
Received: from [85.158.137.68] by server-10.bemta-3.messagelabs.com id
	06/B6-24859-F80CC545; Fri, 07 Nov 2014 12:52:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1415364749!11048593!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 28601 invoked from network); 7 Nov 2014 12:52:31 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 12:52:31 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190540061"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 07:52:28 -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 1Xmj1g-0003Y9-C6;
	Fri, 07 Nov 2014 12:52:28 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 12:52:16 +0000
Message-ID: <1415364736-28452-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415364736-28452-1-git-send-email-paul.durrant@citrix.com>
References: <1415364736-28452-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Remove needless checks on ParametersKey
	validity
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

It used to be the case that XENBUS would tolerate a lack of Parameters key
in its Service key but that has not been true for some time, so remove
validity checks that are no longer needed.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/bus.c     | 15 ++++++---------
 src/xenbus/fdo.c     | 12 ++++--------
 src/xenfilt/driver.c |  3 ---
 3 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/src/xenbus/bus.c b/src/xenbus/bus.c
index af95422..bf0bec7 100644
--- a/src/xenbus/bus.c
+++ b/src/xenbus/bus.c
@@ -190,6 +190,7 @@ BusInitialize(
 {
     PXENBUS_BUS_CONTEXT         Context;
     HANDLE                      ParametersKey;
+    ULONG                       InterceptDmaAdapter;
     NTSTATUS                    status;
 
     Trace("====>\n");
@@ -206,15 +207,11 @@ BusInitialize(
 
     Context->InterceptDmaAdapter = 0;
 
-    if (ParametersKey != NULL) {
-        ULONG   InterceptDmaAdapter;
-
-        status = RegistryQueryDwordValue(ParametersKey,
-                                         "InterceptDmaAdapter",
-                                         &InterceptDmaAdapter);
-        if (NT_SUCCESS(status))
-            Context->InterceptDmaAdapter = InterceptDmaAdapter;
-    }
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "InterceptDmaAdapter",
+                                     &InterceptDmaAdapter);
+    if (NT_SUCCESS(status))
+        Context->InterceptDmaAdapter = InterceptDmaAdapter;
 
     Interface->Size = sizeof (BUS_INTERFACE_STANDARD);
     Interface->Version = 1;
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 7c6f5cd..59442bd 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -971,15 +971,11 @@ FdoScan(
             StoreClasses = NULL;
         }
 
-        if (ParametersKey != NULL) {
-            status = RegistryQuerySzValue(ParametersKey,
-                                          "SyntheticClasses",
-                                          &SyntheticClasses);
-            if (!NT_SUCCESS(status))
-                SyntheticClasses = NULL;
-        } else {
+        status = RegistryQuerySzValue(ParametersKey,
+                                      "SyntheticClasses",
+                                      &SyntheticClasses);
+        if (!NT_SUCCESS(status))
             SyntheticClasses = NULL;
-        }
 
         Classes = FdoCombineAnsi(StoreClasses, SyntheticClasses);
 
diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c
index 86c6800..36a761c 100644
--- a/src/xenfilt/driver.c
+++ b/src/xenfilt/driver.c
@@ -486,8 +486,6 @@ DriverAddDevice(
     ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
     ParametersKey = __DriverGetParametersKey();
-    if (ParametersKey == NULL)
-        goto done;
 
     status = DriverQueryId(PhysicalDeviceObject, BusQueryDeviceID, &DeviceID);
     if (!NT_SUCCESS(status))
@@ -522,7 +520,6 @@ DriverAddDevice(
     ExFreePool(InstanceID);
     ExFreePool(DeviceID);
 
-done:
     return STATUS_SUCCESS;
 
 fail4:
-- 
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 Nov 07 12:52:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 12:52: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 1Xmj1p-0003Ed-2h; Fri, 07 Nov 2014 12:52:37 +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 1Xmj1o-0003EW-0w
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 12:52:36 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	C5/D3-09936-390CC545; Fri, 07 Nov 2014 12:52:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1415364753!12226097!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26425 invoked from network); 7 Nov 2014 12:52:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 12:52:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189112151"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 07:52:26 -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 1Xmj1d-0003Y9-Rc;
	Fri, 07 Nov 2014 12:52:25 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 12:52:15 +0000
Message-ID: <1415364736-28452-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 1/2] Add registry override for EVTCHN ABI
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 a registry parameter DWORD:UseEvtchnFifoAbi than can be set to zero
to prevent use of the FIFO ABI or non-zero to allow it. The default value is
non-zero.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 2be0da8..1bd5e5f 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -39,6 +39,7 @@
 #include "evtchn_fifo.h"
 #include "fdo.h"
 #include "hash_table.h"
+#include "registry.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -98,6 +99,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
     XENBUS_EVTCHN_ABI               EvtchnAbi;
+    BOOLEAN                         UseEvtchnFifoAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
@@ -670,13 +672,19 @@ EvtchnAbiAcquire(
 {
     NTSTATUS                    status;
 
-    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
-                     &Context->EvtchnAbi);
+    if (Context->UseEvtchnFifoAbi) {
+        EvtchnFifoGetAbi(Context->EvtchnFifoContext,
+                         &Context->EvtchnAbi);
 
-    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
-    if (NT_SUCCESS(status))
+        status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+        if (!NT_SUCCESS(status))
+            goto use_two_level;
+
+        Info("FIFO\n");
         goto done;
+    }
 
+use_two_level:
     EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
                          &Context->EvtchnAbi);
 
@@ -684,6 +692,8 @@ EvtchnAbiAcquire(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    Info("TWO LEVEL\n");
+
 done:
     return STATUS_SUCCESS;
 
@@ -1017,6 +1027,8 @@ EvtchnInitialize(
     OUT PXENBUS_EVTCHN_CONTEXT  *Context
     )
 {
+    HANDLE                      ParametersKey;
+    ULONG                       UseEvtchnFifoAbi;
     NTSTATUS                    status;
 
     Trace("====>\n");
@@ -1040,6 +1052,16 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    ParametersKey = DriverGetParametersKey();
+
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "UseEvtchnFifoAbi",
+                                     &UseEvtchnFifoAbi);
+    if (!NT_SUCCESS(status))
+        UseEvtchnFifoAbi = 1;
+
+    (*Context)->UseEvtchnFifoAbi = (UseEvtchnFifoAbi != 0) ? TRUE : FALSE;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -1153,6 +1175,8 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    Context->UseEvtchnFifoAbi = FALSE;
+
     EvtchnFifoTeardown(Context->EvtchnFifoContext);
     Context->EvtchnFifoContext = 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 Nov 07 12:52:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 12:52: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 1Xmj1p-0003Ed-2h; Fri, 07 Nov 2014 12:52:37 +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 1Xmj1o-0003EW-0w
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 12:52:36 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	C5/D3-09936-390CC545; Fri, 07 Nov 2014 12:52:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1415364753!12226097!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26425 invoked from network); 7 Nov 2014 12:52:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 12:52:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189112151"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 07:52:26 -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 1Xmj1d-0003Y9-Rc;
	Fri, 07 Nov 2014 12:52:25 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 12:52:15 +0000
Message-ID: <1415364736-28452-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 1/2] Add registry override for EVTCHN ABI
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 a registry parameter DWORD:UseEvtchnFifoAbi than can be set to zero
to prevent use of the FIFO ABI or non-zero to allow it. The default value is
non-zero.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 2be0da8..1bd5e5f 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -39,6 +39,7 @@
 #include "evtchn_fifo.h"
 #include "fdo.h"
 #include "hash_table.h"
+#include "registry.h"
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -98,6 +99,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
     PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
     XENBUS_EVTCHN_ABI               EvtchnAbi;
+    BOOLEAN                         UseEvtchnFifoAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
 };
@@ -670,13 +672,19 @@ EvtchnAbiAcquire(
 {
     NTSTATUS                    status;
 
-    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
-                     &Context->EvtchnAbi);
+    if (Context->UseEvtchnFifoAbi) {
+        EvtchnFifoGetAbi(Context->EvtchnFifoContext,
+                         &Context->EvtchnAbi);
 
-    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
-    if (NT_SUCCESS(status))
+        status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
+        if (!NT_SUCCESS(status))
+            goto use_two_level;
+
+        Info("FIFO\n");
         goto done;
+    }
 
+use_two_level:
     EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
                          &Context->EvtchnAbi);
 
@@ -684,6 +692,8 @@ EvtchnAbiAcquire(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    Info("TWO LEVEL\n");
+
 done:
     return STATUS_SUCCESS;
 
@@ -1017,6 +1027,8 @@ EvtchnInitialize(
     OUT PXENBUS_EVTCHN_CONTEXT  *Context
     )
 {
+    HANDLE                      ParametersKey;
+    ULONG                       UseEvtchnFifoAbi;
     NTSTATUS                    status;
 
     Trace("====>\n");
@@ -1040,6 +1052,16 @@ EvtchnInitialize(
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    ParametersKey = DriverGetParametersKey();
+
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "UseEvtchnFifoAbi",
+                                     &UseEvtchnFifoAbi);
+    if (!NT_SUCCESS(status))
+        UseEvtchnFifoAbi = 1;
+
+    (*Context)->UseEvtchnFifoAbi = (UseEvtchnFifoAbi != 0) ? TRUE : FALSE;
+
     status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
                                  XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
                                  (PINTERFACE)&(*Context)->SuspendInterface,
@@ -1153,6 +1175,8 @@ EvtchnTeardown(
     RtlZeroMemory(&Context->SuspendInterface,
                   sizeof (XENBUS_SUSPEND_INTERFACE));
 
+    Context->UseEvtchnFifoAbi = FALSE;
+
     EvtchnFifoTeardown(Context->EvtchnFifoContext);
     Context->EvtchnFifoContext = 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 Nov 07 13:32:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:32: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 1Xmjer-0004Xf-QK; Fri, 07 Nov 2014 13:32:57 +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 1Xmjeq-0004XR-F5
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:56 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	82/C9-17958-70ACC545; Fri, 07 Nov 2014 13:32:55 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415367173!11133066!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14545 invoked from network); 7 Nov 2014 13:32:55 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:32:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190552364"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-JG	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:38 +0000
Message-ID: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Subject: [win-pv-devel] [PATCH 0/4] Use per-vcpu event channel upcalls if
	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be allocted,
one per CPU.i

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.


_______________________________________________
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 Nov 07 13:32:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:32: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 1Xmjer-0004Xf-QK; Fri, 07 Nov 2014 13:32:57 +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 1Xmjeq-0004XR-F5
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:56 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	82/C9-17958-70ACC545; Fri, 07 Nov 2014 13:32:55 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415367173!11133066!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14545 invoked from network); 7 Nov 2014 13:32:55 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:32:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190552364"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-JG	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:38 +0000
Message-ID: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Subject: [win-pv-devel] [PATCH 0/4] Use per-vcpu event channel upcalls if
	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be allocted,
one per CPU.i

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.


_______________________________________________
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 Nov 07 13:32:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:32: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 1Xmjes-0004Y1-RI; Fri, 07 Nov 2014 13:32:58 +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 1Xmjer-0004XS-0V
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:57 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	BC/22-07724-80ACC545; Fri, 07 Nov 2014 13:32:56 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415367173!11133066!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14640 invoked from network); 7 Nov 2014 13:32:55 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:32:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190552365"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-Md;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:41 +0000
Message-ID: <1415367162-28444-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-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 3/4] Update Xen headers to master (4.5-rc0 +
	HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 13:32:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:32: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 1Xmjes-0004Y1-RI; Fri, 07 Nov 2014 13:32:58 +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 1Xmjer-0004XS-0V
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:32:57 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	BC/22-07724-80ACC545; Fri, 07 Nov 2014 13:32:56 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415367173!11133066!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14640 invoked from network); 7 Nov 2014 13:32:55 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:32:55 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190552365"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-Md;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:41 +0000
Message-ID: <1415367162-28444-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-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 3/4] Update Xen headers to master (4.5-rc0 +
	HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 13:33:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:05 +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 1Xmjez-0004Yj-SX; Fri, 07 Nov 2014 13:33:05 +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 1Xmjex-0004YV-LU
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:03 +0000
Received: from [85.158.139.211] by server-8.bemta-5.messagelabs.com id
	DE/A4-11581-E0ACC545; Fri, 07 Nov 2014 13:33:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9879 invoked from network); 7 Nov 2014 13:33:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123550"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-L6;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:39 +0000
Message-ID: <1415367162-28444-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 22841
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuYnVzL2Zkby5j
ICAgICAgIHwgICAyICsKIHNyYy94ZW5idXMvc3VzcGVuZC5jICAgfCAgIDIgKwogdnMyMDEyL3hl
bi94ZW4udmN4cHJvaiB8ICAgMSArCiB2czIwMTMveGVuL3hlbi52Y3hwcm9qIHwgICAzICstCiAx
MCBmaWxlcyBjaGFuZ2VkLCAyOTkgaW5zZXJ0aW9ucygrKSwgMzEgZGVsZXRpb25zKC0pCiBjcmVh
dGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vZmVhdHVyZXMuaAogY3JlYXRlIG1vZGUgMTAwNjQ0
IGluY2x1ZGUveGVuL3ZlcnNpb24uaAoKZGlmZiAtLWdpdCBhL2dldF94ZW5faGVhZGVycy5weSBi
L2dldF94ZW5faGVhZGVycy5weQppbmRleCA1Y2E1YzkzLi5lZjFhMmM4IDEwMDY0NAotLS0gYS9n
ZXRfeGVuX2hlYWRlcnMucHkKKysrIGIvZ2V0X3hlbl9oZWFkZXJzLnB5CkBAIC02MSw2ICs2MSw4
IEBAIGlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICAgY29weV9maWxlKHdvcmtpbmcsICdw
dWJsaWMnLCAnLicsICdzY2hlZC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2V2ZW50X2NoYW5uZWwuaCcpCiAgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMn
LCAnLicsICdncmFudF90YWJsZS5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ3ZlcnNpb24uaCcpCisgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMnLCAnLics
ICdmZWF0dXJlcy5oJykKIAogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAneGVuJywgJy4nLCAnZXJy
bm8uaCcpCiAKZGlmZiAtLWdpdCBhL2luY2x1ZGUveGVuLmggYi9pbmNsdWRlL3hlbi5oCmluZGV4
IDAwMzlkN2EuLjBkYWJjNzQgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUveGVuLmgKKysrIGIvaW5jbHVk
ZS94ZW4uaApAQCAtNDQsNiArNDQsNyBAQAogI2luY2x1ZGUgPHhlbi9zY2hlZC5oPgogI2luY2x1
ZGUgPHhlbi9odm0vcGFyYW1zLmg+CiAjaW5jbHVkZSA8eGVuL2lvL3hzX3dpcmUuaD4KKyNpbmNs
dWRlIDx4ZW4vdmVyc2lvbi5oPgogCiAjaWZuZGVmIFhFTl9BUEkKICNkZWZpbmUgWEVOX0FQSSBf
X2RlY2xzcGVjKGRsbGltcG9ydCkKQEAgLTU2LDYgKzU3LDE0IEBAIFhlblRvdWNoKAogICAgIFZP
SUQKICAgICApOwogCisvLyBIWVBFUkNBTEwKKworWEVOX0FQSQorVk9JRAorSHlwZXJjYWxsUG9w
dWxhdGUoCisgICAgVk9JRAorICAgICk7CisKIC8vIEhWTQogCiBfX2NoZWNrUmV0dXJuCkBAIC0y
MzMsNiArMjQyLDIzIEBAIFNjaGVkWWllbGQoCiAgICAgVk9JRAogICAgICk7CiAKKy8vIFhFTiBW
RVJTSU9OCisKK19fY2hlY2tSZXR1cm4KK1hFTl9BUEkKK05UU1RBVFVTCitYZW5WZXJzaW9uKAor
ICAgIE9VVCBQVUxPTkcgIE1ham9yLAorICAgIE9VVCBQVUxPTkcgIE1pbm9yCisgICAgKTsKKwor
X19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBP
VVQgUENIQVIgICBFeHRyYQorICAgICk7CisKIC8vIE1PRFVMRQogCiBYRU5fQVBJCmRpZmYgLS1n
aXQgYS9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaApuZXcg
ZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5iN2JmODNmCi0tLSAvZGV2L251bGwKKysr
IGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaApAQCAtMCwwICsxLDExMiBAQAorLyoqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKgorICogZmVhdHVyZXMuaAorICogCisgKiBGZWF0dXJlIGZsYWdzLCByZXBvcnRl
ZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBn
cmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5Cisg
KiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRo
ZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJp
Y3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8gdXNl
LCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBh
bmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJz
b25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1Ympl
Y3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5cmln
aHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGlu
CisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4K
KyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5U
WSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1Qg
TElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRORVNT
IEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVO
VCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZP
UiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBB
TiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBGUk9N
LCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9S
IE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0IChj
KSAyMDA2LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNpZm5kZWYg
X19YRU5fUFVCTElDX0ZFQVRVUkVTX0hfXworI2RlZmluZSBfX1hFTl9QVUJMSUNfRkVBVFVSRVNf
SF9fCisKKy8qCisgKiBgaW5jb250ZW50cyAyMDAgZWxmbm90ZXNfZmVhdHVyZXMgWEVOX0VMRk5P
VEVfRkVBVFVSRVMKKyAqCisgKiBUaGUgbGlzdCBvZiBhbGwgdGhlIGZlYXR1cmVzIHRoZSBndWVz
dCBzdXBwb3J0cy4gVGhleSBhcmUgc2V0IGJ5CisgKiBwYXJzaW5nIHRoZSBYRU5fRUxGTk9URV9G
RUFUVVJFUyBhbmQgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVTCisgKiBzdHJpbmcuIFRo
ZSBmb3JtYXQgaXMgdGhlICBmZWF0dXJlIG5hbWVzIChhcyBnaXZlbiBoZXJlIHdpdGhvdXQgdGhl
CisgKiAiWEVORkVBVF8iIHByZWZpeCkgc2VwYXJhdGVkIGJ5ICd8JyBjaGFyYWN0ZXJzLgorICog
SWYgYSBmZWF0dXJlIGlzIHJlcXVpcmVkIGZvciB0aGUga2VybmVsIHRvIGZ1bmN0aW9uIHRoZW4g
dGhlIGZlYXR1cmUgbmFtZQorICogbXVzdCBiZSBwcmVjZWRlZCBieSBhICchJyBjaGFyYWN0ZXIu
CisgKgorICogTm90ZSB0aGF0IGlmIFhFTl9FTEZOT1RFX1NVUFBPUlRFRF9GRUFUVVJFUyBpcyB1
c2VkLCB0aGVuIGluIHRoZQorICogWEVORkVBVF9kb20wIE1VU1QgYmUgc2V0IGlmIHRoZSBndWVz
dCBpcyB0byBiZSBib290ZWQgYXMgZG9tMCwKKyAqLworCisvKgorICogSWYgc2V0LCB0aGUgZ3Vl
c3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBwYWdldGFibGVzLCBhbmQgY2Fu
CisgKiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAqLworI2RlZmluZSBYRU5GRUFU
X3dyaXRhYmxlX3BhZ2VfdGFibGVzICAgICAgIDAKKworLyoKKyAqIElmIHNldCwgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gd3JpdGUtcHJvdGVjdCBpdHMgc2VnbWVudCBkZXNjcmlwdG9yCisg
KiB0YWJsZXMsIGFuZCBjYW4gdXBkYXRlIHRoZW0gdmlhIGRpcmVjdCB3cml0ZXMuCisgKi8KKyNk
ZWZpbmUgWEVORkVBVF93cml0YWJsZV9kZXNjcmlwdG9yX3RhYmxlcyAxCisKKy8qCisgKiBJZiBz
ZXQsIHRyYW5zbGF0aW9uIGJldHdlZW4gdGhlIGd1ZXN0J3MgJ3BzZXVkby1waHlzaWNhbCcgYWRk
cmVzcyBzcGFjZQorICogYW5kIHRoZSBob3N0J3MgbWFjaGluZSBhZGRyZXNzIHNwYWNlIGFyZSBo
YW5kbGVkIGJ5IHRoZSBoeXBlcnZpc29yLiBJbiB0aGlzCisgKiBtb2RlIHRoZSBndWVzdCBkb2Vz
IG5vdCBuZWVkIHRvIHBlcmZvcm0gcGh5cy10by9mcm9tLW1hY2hpbmUgdHJhbnNsYXRpb25zCisg
KiB3aGVuIHBlcmZvcm1pbmcgcGFnZSB0YWJsZSBvcGVyYXRpb25zLgorICovCisjZGVmaW5lIFhF
TkZFQVRfYXV0b190cmFuc2xhdGVkX3BoeXNtYXAgICAgMgorCisvKiBJZiBzZXQsIHRoZSBndWVz
dCBpcyBydW5uaW5nIGluIHN1cGVydmlzb3IgbW9kZSAoZS5nLiwgeDg2IHJpbmcgMCkuICovCisj
ZGVmaW5lIFhFTkZFQVRfc3VwZXJ2aXNvcl9tb2RlX2tlcm5lbCAgICAgMworCisvKgorICogSWYg
c2V0LCB0aGUgZ3Vlc3QgZG9lcyBub3QgbmVlZCB0byBhbGxvY2F0ZSB4ODYgUEFFIHBhZ2UgZGly
ZWN0b3JpZXMKKyAqIGJlbG93IDRHQi4gVGhpcyBmbGFnIGlzIHVzdWFsbHkgaW1wbGllZCBieSBh
dXRvX3RyYW5zbGF0ZWRfcGh5c21hcC4KKyAqLworI2RlZmluZSBYRU5GRUFUX3BhZV9wZ2Rpcl9h
Ym92ZV80Z2IgICAgICAgIDQKKworLyogeDg2OiBEb2VzIHRoaXMgWGVuIGhvc3Qgc3VwcG9ydCB0
aGUgTU1VX1BUX1VQREFURV9QUkVTRVJWRV9BRCBoeXBlcmNhbGw/ICovCisjZGVmaW5lIFhFTkZF
QVRfbW11X3B0X3VwZGF0ZV9wcmVzZXJ2ZV9hZCAgNQorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4g
aG9zdCBzdXBwb3J0IHRoZSBNTVVfe0NMRUFSLENPUFl9X1BBR0UgaHlwZXJjYWxsPyAqLworI2Rl
ZmluZSBYRU5GRUFUX2hpZ2htZW1fYXNzaXN0ICAgICAgICAgICAgIDYKKworLyoKKyAqIElmIHNl
dCwgR05UVEFCT1BfbWFwX2dyYW50X3JlZiBob25vcnMgZmxhZ3MgdG8gYmUgcGxhY2VkIGludG8g
Z3Vlc3Qga2VybmVsCisgKiBhdmFpbGFibGUgcHRlIGJpdHMuCisgKi8KKyNkZWZpbmUgWEVORkVB
VF9nbnR0YWJfbWFwX2F2YWlsX2JpdHMgICAgICA3CisKKy8qIHg4NjogRG9lcyB0aGlzIFhlbiBo
b3N0IHN1cHBvcnQgdGhlIEhWTSBjYWxsYmFjayB2ZWN0b3IgdHlwZT8gKi8KKyNkZWZpbmUgWEVO
RkVBVF9odm1fY2FsbGJhY2tfdmVjdG9yICAgICAgICA4CisKKy8qIHg4NjogcHZjbG9jayBhbGdv
cml0aG0gaXMgc2FmZSB0byB1c2Ugb24gSFZNICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3NhZmVf
cHZjbG9jayAgICAgICAgICAgOQorCisvKiB4ODY6IHBpcnEgY2FuIGJlIHVzZWQgYnkgSFZNIGd1
ZXN0cyAqLworI2RlZmluZSBYRU5GRUFUX2h2bV9waXJxcyAgICAgICAgICAgICAgICAgMTAKKwor
Lyogb3BlcmF0aW9uIGFzIERvbTAgaXMgc3VwcG9ydGVkICovCisjZGVmaW5lIFhFTkZFQVRfZG9t
MCAgICAgICAgICAgICAgICAgICAgICAxMQorCisvKiBYZW4gYWxzbyBtYXBzIGdyYW50IHJlZmVy
ZW5jZXMgYXQgcGZuID0gbWZuICovCisjZGVmaW5lIFhFTkZFQVRfZ3JhbnRfbWFwX2lkZW50aXR5
ICAgICAgICAxMgorCisjZGVmaW5lIFhFTkZFQVRfTlJfU1VCTUFQUyAxCisKKyNlbmRpZiAvKiBf
X1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6Cisg
KiBtb2RlOiBDCisgKiBjLWZpbGUtc3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAor
ICogdGFiLXdpZHRoOiA0CisgKiBpbmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpk
aWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4vdmVyc2lvbi5oIGIvaW5jbHVkZS94ZW4vdmVyc2lvbi5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjQ0ZjI2YjAKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi92ZXJzaW9uLmgKQEAgLTAsMCArMSw5NiBAQAorLyoqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKgorICogdmVyc2lvbi5oCisgKiAKKyAqIFhlbiB2ZXJzaW9uLCB0eXBlLCBh
bmQgY29tcGlsZSBpbmZvcm1hdGlvbi4KKyAqIAorICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3Jh
bnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weQorICog
b2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUg
IlNvZnR3YXJlIiksIHRvCisgKiBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0
aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZQorICogcmlnaHRzIHRvIHVzZSwg
Y29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5k
L29yCisgKiBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29u
cyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcworICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0
IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKKyAqCisgKiBUaGUgYWJvdmUgY29weXJpZ2h0
IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbgor
ICogYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCisg
KgorICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkg
T0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJ
TUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAorICogRklUTkVTUyBG
T1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQg
U0hBTEwgVEhFCisgKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1Ig
QU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCisgKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4g
QUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORworICogRlJPTSwg
T1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBP
VEhFUgorICogREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgorICoKKyAqIENvcHlyaWdodCAoYykg
MjAwNSwgTmd1eWVuIEFuaCBRdXluaCA8YXF1eW5oQGdtYWlsLmNvbT4KKyAqIENvcHlyaWdodCAo
YykgMjAwNSwgS2VpciBGcmFzZXIgPGtlaXJAeGVuc291cmNlLmNvbT4KKyAqLworCisjaWZuZGVm
IF9fWEVOX1BVQkxJQ19WRVJTSU9OX0hfXworI2RlZmluZSBfX1hFTl9QVUJMSUNfVkVSU0lPTl9I
X18KKworI2luY2x1ZGUgInhlbi5oIgorCisvKiBOQi4gQWxsIG9wcyByZXR1cm4gemVybyBvbiBz
dWNjZXNzLCBleGNlcHQgWEVOVkVSX3t2ZXJzaW9uLHBhZ2VzaXplfSAqLworCisvKiBhcmcgPT0g
TlVMTDsgcmV0dXJucyBtYWpvcjptaW5vciAoMTY6MTYpLiAqLworI2RlZmluZSBYRU5WRVJfdmVy
c2lvbiAgICAgIDAKKworLyogYXJnID09IHhlbl9leHRyYXZlcnNpb25fdC4gKi8KKyNkZWZpbmUg
WEVOVkVSX2V4dHJhdmVyc2lvbiAxCit0eXBlZGVmIGNoYXIgeGVuX2V4dHJhdmVyc2lvbl90WzE2
XTsKKyNkZWZpbmUgWEVOX0VYVFJBVkVSU0lPTl9MRU4gKHNpemVvZih4ZW5fZXh0cmF2ZXJzaW9u
X3QpKQorCisvKiBhcmcgPT0geGVuX2NvbXBpbGVfaW5mb190LiAqLworI2RlZmluZSBYRU5WRVJf
Y29tcGlsZV9pbmZvIDIKK3N0cnVjdCB4ZW5fY29tcGlsZV9pbmZvIHsKKyAgICBjaGFyIGNvbXBp
bGVyWzY0XTsKKyAgICBjaGFyIGNvbXBpbGVfYnlbMTZdOworICAgIGNoYXIgY29tcGlsZV9kb21h
aW5bMzJdOworICAgIGNoYXIgY29tcGlsZV9kYXRlWzMyXTsKK307Cit0eXBlZGVmIHN0cnVjdCB4
ZW5fY29tcGlsZV9pbmZvIHhlbl9jb21waWxlX2luZm9fdDsKKworI2RlZmluZSBYRU5WRVJfY2Fw
YWJpbGl0aWVzIDMKK3R5cGVkZWYgY2hhciB4ZW5fY2FwYWJpbGl0aWVzX2luZm9fdFsxMDI0XTsK
KyNkZWZpbmUgWEVOX0NBUEFCSUxJVElFU19JTkZPX0xFTiAoc2l6ZW9mKHhlbl9jYXBhYmlsaXRp
ZXNfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfY2hhbmdlc2V0IDQKK3R5cGVkZWYgY2hhciB4
ZW5fY2hhbmdlc2V0X2luZm9fdFs2NF07CisjZGVmaW5lIFhFTl9DSEFOR0VTRVRfSU5GT19MRU4g
KHNpemVvZih4ZW5fY2hhbmdlc2V0X2luZm9fdCkpCisKKyNkZWZpbmUgWEVOVkVSX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgNQorc3RydWN0IHhlbl9wbGF0Zm9ybV9wYXJhbWV0ZXJzIHsKKyAgICB4ZW5f
dWxvbmdfdCB2aXJ0X3N0YXJ0OworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9wbGF0Zm9ybV9wYXJh
bWV0ZXJzIHhlbl9wbGF0Zm9ybV9wYXJhbWV0ZXJzX3Q7CisKKyNkZWZpbmUgWEVOVkVSX2dldF9m
ZWF0dXJlcyA2CitzdHJ1Y3QgeGVuX2ZlYXR1cmVfaW5mbyB7CisgICAgdW5zaWduZWQgaW50IHN1
Ym1hcF9pZHg7ICAgIC8qIElOOiB3aGljaCAzMi1iaXQgc3VibWFwIHRvIHJldHVybiAqLworICAg
IHVpbnQzMl90ICAgICBzdWJtYXA7ICAgICAgICAvKiBPVVQ6IDMyLWJpdCBzdWJtYXAgKi8KK307
Cit0eXBlZGVmIHN0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHhlbl9mZWF0dXJlX2luZm9fdDsKKwor
LyogRGVjbGFyZXMgdGhlIGZlYXR1cmVzIHJlcG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMu
ICovCisjaW5jbHVkZSAiZmVhdHVyZXMuaCIKKworLyogYXJnID09IE5VTEw7IHJldHVybnMgaG9z
dCBtZW1vcnkgcGFnZSBzaXplLiAqLworI2RlZmluZSBYRU5WRVJfcGFnZXNpemUgNworCisvKiBh
cmcgPT0geGVuX2RvbWFpbl9oYW5kbGVfdC4gKi8KKyNkZWZpbmUgWEVOVkVSX2d1ZXN0X2hhbmRs
ZSA4CisKKyNkZWZpbmUgWEVOVkVSX2NvbW1hbmRsaW5lIDkKK3R5cGVkZWYgY2hhciB4ZW5fY29t
bWFuZGxpbmVfdFsxMDI0XTsKKworI2VuZGlmIC8qIF9fWEVOX1BVQkxJQ19WRVJTSU9OX0hfXyAq
LworCisvKgorICogTG9jYWwgdmFyaWFibGVzOgorICogbW9kZTogQworICogYy1maWxlLXN0eWxl
OiAiQlNEIgorICogYy1iYXNpYy1vZmZzZXQ6IDQKKyAqIHRhYi13aWR0aDogNAorICogaW5kZW50
LXRhYnMtbW9kZTogbmlsCisgKiBFbmQ6CisgKi8KZGlmZiAtLWdpdCBhL3NyYy94ZW4vZHJpdmVy
LmMgYi9zcmMveGVuL2RyaXZlci5jCmluZGV4IGJhNTQxYjQuLmZjZTc1YWEgMTAwNjQ0Ci0tLSBh
L3NyYy94ZW4vZHJpdmVyLmMKKysrIGIvc3JjL3hlbi9kcml2ZXIuYwpAQCAtNTksNiArNTksMjYg
QEAgWGVuVG91Y2goCiAgICAgVk9JRAogICAgICkKIHsKKyAgICBzdGF0aWMgVUxPTkcgICAgUmVm
ZXJlbmNlOworICAgIFVMT05HICAgICAgICAgICBNYWpvcjsKKyAgICBVTE9ORyAgICAgICAgICAg
TWlub3I7CisgICAgQ0hBUiAgICAgICAgICAgIEV4dHJhW1hFTl9FWFRSQVZFUlNJT05fTEVOXTsK
KyAgICBOVFNUQVRVUyAgICAgICAgc3RhdHVzOworCisgICAgaWYgKFJlZmVyZW5jZSsrICE9IDAp
CisgICAgICAgIHJldHVybjsKKworICAgIHN0YXR1cyA9IFhlblZlcnNpb24oJk1ham9yLCAmTWlu
b3IpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykpOworCisgICAgc3RhdHVzID0gWGVu
VmVyc2lvbkV4dHJhKEV4dHJhKTsKKyAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsKKwor
ICAgIExvZ1ByaW50ZihMT0dfTEVWRUxfSU5GTywKKyAgICAgICAgICAgICAgIlhFTjogJXUuJXUl
c1xuIiwKKyAgICAgICAgICAgICAgTWFqb3IsCisgICAgICAgICAgICAgIE1pbm9yLAorICAgICAg
ICAgICAgICBFeHRyYSk7CiB9CiAKIHN0YXRpYyBWT0lECmRpZmYgLS1naXQgYS9zcmMveGVuL2h5
cGVyY2FsbC5jIGIvc3JjL3hlbi9oeXBlcmNhbGwuYwppbmRleCAwN2ViNDFhLi43MTdiOGMyIDEw
MDY0NAotLS0gYS9zcmMveGVuL2h5cGVyY2FsbC5jCisrKyBiL3NyYy94ZW4vaHlwZXJjYWxsLmMK
QEAgLTI5LDYgKzI5LDkgQEAKICAqIFNVQ0ggREFNQUdFLgogICovCiAKKyN1bmRlZiAgWEVOX0FQ
SQorI2RlZmluZSBYRU5fQVBJIF9fZGVjbHNwZWMoZGxsZXhwb3J0KQorCiAjaW5jbHVkZSA8bnRk
ZGsuaD4KICNpbmNsdWRlIDx4ZW4uaD4KICNpbmNsdWRlIDx1dGlsLmg+CkBAIC0zNywyNCArNDAs
NDEgQEAKICNpbmNsdWRlICJkYmdfcHJpbnQuaCIKICNpbmNsdWRlICJhc3NlcnQuaCIKIAotI2Rl
ZmluZSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQgMgorI2RlZmluZSBNQVhJTVVNX0hZUEVS
Q0FMTF9QQUdFX0NPVU5UIDIKIAogI3ByYWdtYSBjb2RlX3NlZygiaHlwZXJjYWxsIikKIF9fZGVj
bHNwZWMoYWxsb2NhdGUoImh5cGVyY2FsbCIpKQotc3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rp
b25bKE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCArIDEpICogUEFHRV9TSVpFXTsKK3N0YXRp
YyBVQ0hBUiAgICAgICAgX19TZWN0aW9uWyhNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UICsg
MSkgKiBQQUdFX1NJWkVdOwogCiBzdGF0aWMgVUxPTkcgICAgICAgIFhlbkJhc2VMZWFmID0gMHg0
MDAwMDAwMDsKIAotc3RhdGljIFVTSE9SVCAgICAgICBYZW5NYWpvclZlcnNpb247Ci1zdGF0aWMg
VVNIT1JUICAgICAgIFhlbk1pbm9yVmVyc2lvbjsKLQotc3RhdGljIFBGTl9OVU1CRVIgICBIeXBl
cmNhbGxQZm5bTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UXTsKLXN0YXRpYyBVTE9ORyAgICAg
ICAgSHlwZXJjYWxsUGZuQ291bnQ7CitzdGF0aWMgUEhZU0lDQUxfQUREUkVTUyBIeXBlcmNhbGxQ
YWdlW01BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09VTlRdOworc3RhdGljIFVMT05HICAgICAgICAg
ICAgSHlwZXJjYWxsUGFnZUNvdW50OwogCiB0eXBlZGVmIFVDSEFSICAgICAgICAgICBIWVBFUkNB
TExfR0FURVszMl07CiB0eXBlZGVmIEhZUEVSQ0FMTF9HQVRFICAqUEhZUEVSQ0FMTF9HQVRFOwog
CiBQSFlQRVJDQUxMX0dBVEUgICAgIEh5cGVyY2FsbDsKK1VMT05HICAgICAgICAgICAgICAgSHlw
ZXJjYWxsTXNyOworCitYRU5fQVBJCitWT0lECitIeXBlcmNhbGxQb3B1bGF0ZSgKKyAgICBWT0lE
CisgICAgKQoreworICAgIFVMT05HICAgICAgIEluZGV4OworCisgICAgZm9yIChJbmRleCA9IDA7
IEluZGV4IDwgSHlwZXJjYWxsUGFnZUNvdW50OyBJbmRleCsrKSB7CisgICAgICAgIExvZ1ByaW50
ZihMT0dfTEVWRUxfSU5GTywKKyAgICAgICAgICAgICAgICAgICJYRU46IEhZUEVSQ0FMTCBQQUdF
ICVkIEAgJTA4eC4lMDh4XG4iLAorICAgICAgICAgICAgICAgICAgSW5kZXgsCisgICAgICAgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4XS5IaWdoUGFydCwKKyAgICAgICAgICAgICAgICAg
IEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkxvd1BhcnQpOworCisgICAgICAgIF9fd3JpdGVtc3IoSHlw
ZXJjYWxsTXNyLCBIeXBlcmNhbGxQYWdlW0luZGV4XS5RdWFkUGFydCk7CisgICAgfQorfQogCiBO
VFNUQVRVUwogSHlwZXJjYWxsSW5pdGlhbGl6ZSgKQEAgLTY2LDcgKzg2LDYgQEAgSHlwZXJjYWxs
SW5pdGlhbGl6ZSgKICAgICBVTE9ORyAgICAgICBFQ1ggPSAnREVBRCc7CiAgICAgVUxPTkcgICAg
ICAgRURYID0gJ0RFQUQnOwogICAgIFVMT05HICAgICAgIEluZGV4OwotICAgIFVMT05HICAgICAg
IEh5cGVyY2FsbE1zcjsKICAgICBOVFNUQVRVUyAgICBzdGF0dXM7CiAKICAgICBzdGF0dXMgPSBT
VEFUVVNfVU5TVUNDRVNTRlVMOwpAQCAtODgsMTMgKzEwNyw2IEBAIEh5cGVyY2FsbEluaXRpYWxp
emUoCiAgICAgICAgICAgICBnb3RvIGZhaWwxOwogICAgIH0KIAotICAgIF9fQ3B1SWQoWGVuQmFz
ZUxlYWYgKyAxLCAmRUFYLCBOVUxMLCBOVUxMLCBOVUxMKTsKLSAgICBYZW5NYWpvclZlcnNpb24g
PSAoVVNIT1JUKShFQVggPj4gMTYpOwotICAgIFhlbk1pbm9yVmVyc2lvbiA9IChVU0hPUlQpKEVB
WCAmIDB4RkZGRik7Ci0KLSAgICBJbmZvKCJYRU4gJWQuJWRcbiIsIFhlbk1ham9yVmVyc2lvbiwg
WGVuTWlub3JWZXJzaW9uKTsKLSAgICBJbmZvKCJJTlRFUkZBQ0UgMHglMDh4XG4iLCBfX1hFTl9J
TlRFUkZBQ0VfVkVSU0lPTl9fKTsKLQogICAgIGlmICgoVUxPTkdfUFRSKV9fU2VjdGlvbiAmIChQ
QUdFX1NJWkUgLSAxKSkKICAgICAgICAgSHlwZXJjYWxsID0gKFBWT0lEKSgoKFVMT05HX1BUUilf
X1NlY3Rpb24gKyBQQUdFX1NJWkUgLSAxKSAmIH4oUEFHRV9TSVpFIC0gMSkpOwogICAgIGVsc2UK
QEAgLTEwMiwyMiArMTE0LDE2IEBAIEh5cGVyY2FsbEluaXRpYWxpemUoCiAKICAgICBBU1NFUlQz
VSgoKFVMT05HX1BUUilIeXBlcmNhbGwgJiAoUEFHRV9TSVpFIC0gMSkpLCA9PSwgMCk7CiAKLSAg
ICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IElu
ZGV4KyspIHsKLSAgICAgICAgUEhZU0lDQUxfQUREUkVTUyAgICBQaHlzaWNhbEFkZHJlc3M7Ci0K
LSAgICAgICAgUGh5c2ljYWxBZGRyZXNzID0gTW1HZXRQaHlzaWNhbEFkZHJlc3MoKFBVQ0hBUilI
eXBlcmNhbGwgKyAoSW5kZXggPDwgUEFHRV9TSElGVCkpOwotICAgICAgICBIeXBlcmNhbGxQZm5b
SW5kZXhdID0gKFBGTl9OVU1CRVIpKFBoeXNpY2FsQWRkcmVzcy5RdWFkUGFydCA+PiBQQUdFX1NI
SUZUKTsKLSAgICB9CisgICAgZm9yIChJbmRleCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNB
TExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAgICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0gPSBN
bUdldFBoeXNpY2FsQWRkcmVzcygoUFVDSEFSKUh5cGVyY2FsbCArCisgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKEluZGV4IDw8IFBBR0VfU0hJRlQp
KTsKIAogICAgIF9fQ3B1SWQoWGVuQmFzZUxlYWYgKyAyLCAmRUFYLCAmRUJYLCBOVUxMLCBOVUxM
KTsKLSAgICBIeXBlcmNhbGxQZm5Db3VudCA9IEVBWDsKLSAgICBBU1NFUlQoSHlwZXJjYWxsUGZu
Q291bnQgPD0gTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UKTsKKyAgICBIeXBlcmNhbGxQYWdl
Q291bnQgPSBFQVg7CisgICAgQVNTRVJUKEh5cGVyY2FsbFBhZ2VDb3VudCA8PSBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UKTsKICAgICBIeXBlcmNhbGxNc3IgPSBFQlg7CiAKLSAgICBmb3Ig
KEluZGV4ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQZm5Db3VudDsgSW5kZXgrKykgewotICAgICAg
ICBJbmZvKCJIeXBlcmNhbGxQZm5bJWRdOiAlcFxuIiwgSW5kZXgsIChQVk9JRClIeXBlcmNhbGxQ
Zm5bSW5kZXhdKTsKLSAgICAgICAgX193cml0ZW1zcihIeXBlcmNhbGxNc3IsIChVTE9ORzY0KUh5
cGVyY2FsbFBmbltJbmRleF0gPDwgUEFHRV9TSElGVCk7Ci0gICAgfQorICAgIEh5cGVyY2FsbFBv
cHVsYXRlKCk7CiAKICAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CiAKQEAgLTE3Nyw4ICsxODMs
OCBAQCBIeXBlcmNhbGxUZWFyZG93bigKIAogICAgIEh5cGVyY2FsbCA9IE5VTEw7CiAKLSAgICBm
b3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IEluZGV4
KyspCi0gICAgICAgIEh5cGVyY2FsbFBmbltJbmRleF0gPSAwOworICAgIGZvciAoSW5kZXggPSAw
OyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQ7IEluZGV4KyspCisgICAgICAg
IEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0ID0gMDsKIAotICAgIEh5cGVyY2FsbFBmbkNv
dW50ID0gMDsKKyAgICBIeXBlcmNhbGxQYWdlQ291bnQgPSAwOwogfQpkaWZmIC0tZ2l0IGEvc3Jj
L3hlbmJ1cy9mZG8uYyBiL3NyYy94ZW5idXMvZmRvLmMKaW5kZXggNTk0NDJiZC4uMjE1Yzk5NyAx
MDA2NDQKLS0tIGEvc3JjL3hlbmJ1cy9mZG8uYworKysgYi9zcmMveGVuYnVzL2Zkby5jCkBAIC0y
MTg2LDYgKzIxODYsOCBAQCBGZG9TNFRvUzMoCiAKICAgICBLZVJhaXNlSXJxbChESVNQQVRDSF9M
RVZFTCwgJklycWwpOwogCisgICAgSHlwZXJjYWxsUG9wdWxhdGUoKTsKKwogICAgIGlmIChGZG8t
PlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2UuQ29udGV4dCAhPSBOVUxMKQogICAgICAgICBYRU5G
SUxUX1VOUExVRyhSZXBsYXksICZGZG8tPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBh
L3NyYy94ZW5idXMvc3VzcGVuZC5jIGIvc3JjL3hlbmJ1cy9zdXNwZW5kLmMKaW5kZXggNmFiMmJk
Mi4uZGU3MGU0MiAxMDA2NDQKLS0tIGEvc3JjL3hlbmJ1cy9zdXNwZW5kLmMKKysrIGIvc3JjL3hl
bmJ1cy9zdXNwZW5kLmMKQEAgLTE3Myw2ICsxNzMsOCBAQCBTdXNwZW5kVHJpZ2dlcigKIAogICAg
ICAgICBDb250ZXh0LT5Db3VudCsrOwogCisgICAgICAgIEh5cGVyY2FsbFBvcHVsYXRlKCk7CisK
ICAgICAgICAgaWYgKENvbnRleHQtPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2UuQ29udGV4dCAh
PSBOVUxMKQogICAgICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmQ29udGV4dC0+VW5w
bHVnSW50ZXJmYWNlKTsKIApkaWZmIC0tZ2l0IGEvdnMyMDEyL3hlbi94ZW4udmN4cHJvaiBiL3Zz
MjAxMi94ZW4veGVuLnZjeHByb2oKaW5kZXggZWI1NDY5Mi4uMmY0ZDk1OCAxMDA2NDQKLS0tIGEv
dnMyMDEyL3hlbi94ZW4udmN4cHJvagorKysgYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCkBAIC04
OCw2ICs4OCw3IEBACiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxldmVudF9j
aGFubmVsLmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxncmFudF90
YWJsZS5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+
CisJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblx4ZW5fdmVyc2lvbi5jIiAvPgog
CQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHlwZXJjYWxsLmMiIC8+CiAJCTxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KIAkJPENsQ29tcGls
ZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHNjaGVkLmMiIC8+CmRpZmYgLS1naXQgYS92czIwMTMv
eGVuL3hlbi52Y3hwcm9qIGIvdnMyMDEzL3hlbi94ZW4udmN4cHJvagppbmRleCA0OTAyOTRjLi44
MWQ1MGVhIDEwMDY0NAotLS0gYS92czIwMTMveGVuL3hlbi52Y3hwcm9qCisrKyBiL3ZzMjAxMy94
ZW4veGVuLnZjeHByb2oKQEAgLTEsNCArMSw0IEBACi3vu788P3htbCB2ZXJzaW9uPSIxLjAiIGVu
Y29kaW5nPSJ1dGYtOCI/PgorPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4K
IDxQcm9qZWN0IERlZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIxMi4wIiB4bWxu
cz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWlsZC8yMDAzIj4K
ICAgPEltcG9ydCBQcm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgogICA8UHJvcGVydHlHcm91
cCBMYWJlbD0iR2xvYmFscyI+CkBAIC0xMjgsNiArMTI4LDcgQEAKICAgICA8Q2xDb21waWxlIElu
Y2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogICAgIDxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxncmFudF90YWJsZS5jIiAvPgogICAgIDxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxodm0uYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5ceGVuX3ZlcnNpb24uYyIgLz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5caHlwZXJjYWxsLmMiIC8+CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIu
LlwuLlxzcmNceGVuXG1lbW9yeS5jIiAvPgogICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5c
c3JjXHhlblxzY2hlZC5jIiAvPgotLSAKMi4xLjEKCgpfX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1k
ZXZlbEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dp
LWJpbi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 13:33:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:05 +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 1Xmjez-0004Yj-SX; Fri, 07 Nov 2014 13:33:05 +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 1Xmjex-0004YV-LU
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:03 +0000
Received: from [85.158.139.211] by server-8.bemta-5.messagelabs.com id
	DE/A4-11581-E0ACC545; Fri, 07 Nov 2014 13:33:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9879 invoked from network); 7 Nov 2014 13:33:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123550"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-L6;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:39 +0000
Message-ID: <1415367162-28444-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 22841
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuYnVzL2Zkby5j
ICAgICAgIHwgICAyICsKIHNyYy94ZW5idXMvc3VzcGVuZC5jICAgfCAgIDIgKwogdnMyMDEyL3hl
bi94ZW4udmN4cHJvaiB8ICAgMSArCiB2czIwMTMveGVuL3hlbi52Y3hwcm9qIHwgICAzICstCiAx
MCBmaWxlcyBjaGFuZ2VkLCAyOTkgaW5zZXJ0aW9ucygrKSwgMzEgZGVsZXRpb25zKC0pCiBjcmVh
dGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vZmVhdHVyZXMuaAogY3JlYXRlIG1vZGUgMTAwNjQ0
IGluY2x1ZGUveGVuL3ZlcnNpb24uaAoKZGlmZiAtLWdpdCBhL2dldF94ZW5faGVhZGVycy5weSBi
L2dldF94ZW5faGVhZGVycy5weQppbmRleCA1Y2E1YzkzLi5lZjFhMmM4IDEwMDY0NAotLS0gYS9n
ZXRfeGVuX2hlYWRlcnMucHkKKysrIGIvZ2V0X3hlbl9oZWFkZXJzLnB5CkBAIC02MSw2ICs2MSw4
IEBAIGlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6CiAgICAgY29weV9maWxlKHdvcmtpbmcsICdw
dWJsaWMnLCAnLicsICdzY2hlZC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2V2ZW50X2NoYW5uZWwuaCcpCiAgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMn
LCAnLicsICdncmFudF90YWJsZS5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ3ZlcnNpb24uaCcpCisgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMnLCAnLics
ICdmZWF0dXJlcy5oJykKIAogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAneGVuJywgJy4nLCAnZXJy
bm8uaCcpCiAKZGlmZiAtLWdpdCBhL2luY2x1ZGUveGVuLmggYi9pbmNsdWRlL3hlbi5oCmluZGV4
IDAwMzlkN2EuLjBkYWJjNzQgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUveGVuLmgKKysrIGIvaW5jbHVk
ZS94ZW4uaApAQCAtNDQsNiArNDQsNyBAQAogI2luY2x1ZGUgPHhlbi9zY2hlZC5oPgogI2luY2x1
ZGUgPHhlbi9odm0vcGFyYW1zLmg+CiAjaW5jbHVkZSA8eGVuL2lvL3hzX3dpcmUuaD4KKyNpbmNs
dWRlIDx4ZW4vdmVyc2lvbi5oPgogCiAjaWZuZGVmIFhFTl9BUEkKICNkZWZpbmUgWEVOX0FQSSBf
X2RlY2xzcGVjKGRsbGltcG9ydCkKQEAgLTU2LDYgKzU3LDE0IEBAIFhlblRvdWNoKAogICAgIFZP
SUQKICAgICApOwogCisvLyBIWVBFUkNBTEwKKworWEVOX0FQSQorVk9JRAorSHlwZXJjYWxsUG9w
dWxhdGUoCisgICAgVk9JRAorICAgICk7CisKIC8vIEhWTQogCiBfX2NoZWNrUmV0dXJuCkBAIC0y
MzMsNiArMjQyLDIzIEBAIFNjaGVkWWllbGQoCiAgICAgVk9JRAogICAgICk7CiAKKy8vIFhFTiBW
RVJTSU9OCisKK19fY2hlY2tSZXR1cm4KK1hFTl9BUEkKK05UU1RBVFVTCitYZW5WZXJzaW9uKAor
ICAgIE9VVCBQVUxPTkcgIE1ham9yLAorICAgIE9VVCBQVUxPTkcgIE1pbm9yCisgICAgKTsKKwor
X19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBP
VVQgUENIQVIgICBFeHRyYQorICAgICk7CisKIC8vIE1PRFVMRQogCiBYRU5fQVBJCmRpZmYgLS1n
aXQgYS9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaApuZXcg
ZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5iN2JmODNmCi0tLSAvZGV2L251bGwKKysr
IGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaApAQCAtMCwwICsxLDExMiBAQAorLyoqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKgorICogZmVhdHVyZXMuaAorICogCisgKiBGZWF0dXJlIGZsYWdzLCByZXBvcnRl
ZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBn
cmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5Cisg
KiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRo
ZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJp
Y3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8gdXNl
LCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBh
bmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJz
b25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1Ympl
Y3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5cmln
aHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGlu
CisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4K
KyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5U
WSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1Qg
TElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRORVNT
IEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVO
VCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZP
UiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBB
TiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBGUk9N
LCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9S
IE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0IChj
KSAyMDA2LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNpZm5kZWYg
X19YRU5fUFVCTElDX0ZFQVRVUkVTX0hfXworI2RlZmluZSBfX1hFTl9QVUJMSUNfRkVBVFVSRVNf
SF9fCisKKy8qCisgKiBgaW5jb250ZW50cyAyMDAgZWxmbm90ZXNfZmVhdHVyZXMgWEVOX0VMRk5P
VEVfRkVBVFVSRVMKKyAqCisgKiBUaGUgbGlzdCBvZiBhbGwgdGhlIGZlYXR1cmVzIHRoZSBndWVz
dCBzdXBwb3J0cy4gVGhleSBhcmUgc2V0IGJ5CisgKiBwYXJzaW5nIHRoZSBYRU5fRUxGTk9URV9G
RUFUVVJFUyBhbmQgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVTCisgKiBzdHJpbmcuIFRo
ZSBmb3JtYXQgaXMgdGhlICBmZWF0dXJlIG5hbWVzIChhcyBnaXZlbiBoZXJlIHdpdGhvdXQgdGhl
CisgKiAiWEVORkVBVF8iIHByZWZpeCkgc2VwYXJhdGVkIGJ5ICd8JyBjaGFyYWN0ZXJzLgorICog
SWYgYSBmZWF0dXJlIGlzIHJlcXVpcmVkIGZvciB0aGUga2VybmVsIHRvIGZ1bmN0aW9uIHRoZW4g
dGhlIGZlYXR1cmUgbmFtZQorICogbXVzdCBiZSBwcmVjZWRlZCBieSBhICchJyBjaGFyYWN0ZXIu
CisgKgorICogTm90ZSB0aGF0IGlmIFhFTl9FTEZOT1RFX1NVUFBPUlRFRF9GRUFUVVJFUyBpcyB1
c2VkLCB0aGVuIGluIHRoZQorICogWEVORkVBVF9kb20wIE1VU1QgYmUgc2V0IGlmIHRoZSBndWVz
dCBpcyB0byBiZSBib290ZWQgYXMgZG9tMCwKKyAqLworCisvKgorICogSWYgc2V0LCB0aGUgZ3Vl
c3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBwYWdldGFibGVzLCBhbmQgY2Fu
CisgKiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAqLworI2RlZmluZSBYRU5GRUFU
X3dyaXRhYmxlX3BhZ2VfdGFibGVzICAgICAgIDAKKworLyoKKyAqIElmIHNldCwgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gd3JpdGUtcHJvdGVjdCBpdHMgc2VnbWVudCBkZXNjcmlwdG9yCisg
KiB0YWJsZXMsIGFuZCBjYW4gdXBkYXRlIHRoZW0gdmlhIGRpcmVjdCB3cml0ZXMuCisgKi8KKyNk
ZWZpbmUgWEVORkVBVF93cml0YWJsZV9kZXNjcmlwdG9yX3RhYmxlcyAxCisKKy8qCisgKiBJZiBz
ZXQsIHRyYW5zbGF0aW9uIGJldHdlZW4gdGhlIGd1ZXN0J3MgJ3BzZXVkby1waHlzaWNhbCcgYWRk
cmVzcyBzcGFjZQorICogYW5kIHRoZSBob3N0J3MgbWFjaGluZSBhZGRyZXNzIHNwYWNlIGFyZSBo
YW5kbGVkIGJ5IHRoZSBoeXBlcnZpc29yLiBJbiB0aGlzCisgKiBtb2RlIHRoZSBndWVzdCBkb2Vz
IG5vdCBuZWVkIHRvIHBlcmZvcm0gcGh5cy10by9mcm9tLW1hY2hpbmUgdHJhbnNsYXRpb25zCisg
KiB3aGVuIHBlcmZvcm1pbmcgcGFnZSB0YWJsZSBvcGVyYXRpb25zLgorICovCisjZGVmaW5lIFhF
TkZFQVRfYXV0b190cmFuc2xhdGVkX3BoeXNtYXAgICAgMgorCisvKiBJZiBzZXQsIHRoZSBndWVz
dCBpcyBydW5uaW5nIGluIHN1cGVydmlzb3IgbW9kZSAoZS5nLiwgeDg2IHJpbmcgMCkuICovCisj
ZGVmaW5lIFhFTkZFQVRfc3VwZXJ2aXNvcl9tb2RlX2tlcm5lbCAgICAgMworCisvKgorICogSWYg
c2V0LCB0aGUgZ3Vlc3QgZG9lcyBub3QgbmVlZCB0byBhbGxvY2F0ZSB4ODYgUEFFIHBhZ2UgZGly
ZWN0b3JpZXMKKyAqIGJlbG93IDRHQi4gVGhpcyBmbGFnIGlzIHVzdWFsbHkgaW1wbGllZCBieSBh
dXRvX3RyYW5zbGF0ZWRfcGh5c21hcC4KKyAqLworI2RlZmluZSBYRU5GRUFUX3BhZV9wZ2Rpcl9h
Ym92ZV80Z2IgICAgICAgIDQKKworLyogeDg2OiBEb2VzIHRoaXMgWGVuIGhvc3Qgc3VwcG9ydCB0
aGUgTU1VX1BUX1VQREFURV9QUkVTRVJWRV9BRCBoeXBlcmNhbGw/ICovCisjZGVmaW5lIFhFTkZF
QVRfbW11X3B0X3VwZGF0ZV9wcmVzZXJ2ZV9hZCAgNQorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4g
aG9zdCBzdXBwb3J0IHRoZSBNTVVfe0NMRUFSLENPUFl9X1BBR0UgaHlwZXJjYWxsPyAqLworI2Rl
ZmluZSBYRU5GRUFUX2hpZ2htZW1fYXNzaXN0ICAgICAgICAgICAgIDYKKworLyoKKyAqIElmIHNl
dCwgR05UVEFCT1BfbWFwX2dyYW50X3JlZiBob25vcnMgZmxhZ3MgdG8gYmUgcGxhY2VkIGludG8g
Z3Vlc3Qga2VybmVsCisgKiBhdmFpbGFibGUgcHRlIGJpdHMuCisgKi8KKyNkZWZpbmUgWEVORkVB
VF9nbnR0YWJfbWFwX2F2YWlsX2JpdHMgICAgICA3CisKKy8qIHg4NjogRG9lcyB0aGlzIFhlbiBo
b3N0IHN1cHBvcnQgdGhlIEhWTSBjYWxsYmFjayB2ZWN0b3IgdHlwZT8gKi8KKyNkZWZpbmUgWEVO
RkVBVF9odm1fY2FsbGJhY2tfdmVjdG9yICAgICAgICA4CisKKy8qIHg4NjogcHZjbG9jayBhbGdv
cml0aG0gaXMgc2FmZSB0byB1c2Ugb24gSFZNICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3NhZmVf
cHZjbG9jayAgICAgICAgICAgOQorCisvKiB4ODY6IHBpcnEgY2FuIGJlIHVzZWQgYnkgSFZNIGd1
ZXN0cyAqLworI2RlZmluZSBYRU5GRUFUX2h2bV9waXJxcyAgICAgICAgICAgICAgICAgMTAKKwor
Lyogb3BlcmF0aW9uIGFzIERvbTAgaXMgc3VwcG9ydGVkICovCisjZGVmaW5lIFhFTkZFQVRfZG9t
MCAgICAgICAgICAgICAgICAgICAgICAxMQorCisvKiBYZW4gYWxzbyBtYXBzIGdyYW50IHJlZmVy
ZW5jZXMgYXQgcGZuID0gbWZuICovCisjZGVmaW5lIFhFTkZFQVRfZ3JhbnRfbWFwX2lkZW50aXR5
ICAgICAgICAxMgorCisjZGVmaW5lIFhFTkZFQVRfTlJfU1VCTUFQUyAxCisKKyNlbmRpZiAvKiBf
X1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6Cisg
KiBtb2RlOiBDCisgKiBjLWZpbGUtc3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAor
ICogdGFiLXdpZHRoOiA0CisgKiBpbmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpk
aWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4vdmVyc2lvbi5oIGIvaW5jbHVkZS94ZW4vdmVyc2lvbi5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjQ0ZjI2YjAKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi92ZXJzaW9uLmgKQEAgLTAsMCArMSw5NiBAQAorLyoqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKgorICogdmVyc2lvbi5oCisgKiAKKyAqIFhlbiB2ZXJzaW9uLCB0eXBlLCBh
bmQgY29tcGlsZSBpbmZvcm1hdGlvbi4KKyAqIAorICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3Jh
bnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weQorICog
b2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUg
IlNvZnR3YXJlIiksIHRvCisgKiBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0
aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZQorICogcmlnaHRzIHRvIHVzZSwg
Y29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5k
L29yCisgKiBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29u
cyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcworICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0
IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKKyAqCisgKiBUaGUgYWJvdmUgY29weXJpZ2h0
IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbgor
ICogYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCisg
KgorICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkg
T0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1IKKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJ
TUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAorICogRklUTkVTUyBG
T1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQg
U0hBTEwgVEhFCisgKiBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1Ig
QU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCisgKiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4g
QUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORworICogRlJPTSwg
T1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBP
VEhFUgorICogREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgorICoKKyAqIENvcHlyaWdodCAoYykg
MjAwNSwgTmd1eWVuIEFuaCBRdXluaCA8YXF1eW5oQGdtYWlsLmNvbT4KKyAqIENvcHlyaWdodCAo
YykgMjAwNSwgS2VpciBGcmFzZXIgPGtlaXJAeGVuc291cmNlLmNvbT4KKyAqLworCisjaWZuZGVm
IF9fWEVOX1BVQkxJQ19WRVJTSU9OX0hfXworI2RlZmluZSBfX1hFTl9QVUJMSUNfVkVSU0lPTl9I
X18KKworI2luY2x1ZGUgInhlbi5oIgorCisvKiBOQi4gQWxsIG9wcyByZXR1cm4gemVybyBvbiBz
dWNjZXNzLCBleGNlcHQgWEVOVkVSX3t2ZXJzaW9uLHBhZ2VzaXplfSAqLworCisvKiBhcmcgPT0g
TlVMTDsgcmV0dXJucyBtYWpvcjptaW5vciAoMTY6MTYpLiAqLworI2RlZmluZSBYRU5WRVJfdmVy
c2lvbiAgICAgIDAKKworLyogYXJnID09IHhlbl9leHRyYXZlcnNpb25fdC4gKi8KKyNkZWZpbmUg
WEVOVkVSX2V4dHJhdmVyc2lvbiAxCit0eXBlZGVmIGNoYXIgeGVuX2V4dHJhdmVyc2lvbl90WzE2
XTsKKyNkZWZpbmUgWEVOX0VYVFJBVkVSU0lPTl9MRU4gKHNpemVvZih4ZW5fZXh0cmF2ZXJzaW9u
X3QpKQorCisvKiBhcmcgPT0geGVuX2NvbXBpbGVfaW5mb190LiAqLworI2RlZmluZSBYRU5WRVJf
Y29tcGlsZV9pbmZvIDIKK3N0cnVjdCB4ZW5fY29tcGlsZV9pbmZvIHsKKyAgICBjaGFyIGNvbXBp
bGVyWzY0XTsKKyAgICBjaGFyIGNvbXBpbGVfYnlbMTZdOworICAgIGNoYXIgY29tcGlsZV9kb21h
aW5bMzJdOworICAgIGNoYXIgY29tcGlsZV9kYXRlWzMyXTsKK307Cit0eXBlZGVmIHN0cnVjdCB4
ZW5fY29tcGlsZV9pbmZvIHhlbl9jb21waWxlX2luZm9fdDsKKworI2RlZmluZSBYRU5WRVJfY2Fw
YWJpbGl0aWVzIDMKK3R5cGVkZWYgY2hhciB4ZW5fY2FwYWJpbGl0aWVzX2luZm9fdFsxMDI0XTsK
KyNkZWZpbmUgWEVOX0NBUEFCSUxJVElFU19JTkZPX0xFTiAoc2l6ZW9mKHhlbl9jYXBhYmlsaXRp
ZXNfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfY2hhbmdlc2V0IDQKK3R5cGVkZWYgY2hhciB4
ZW5fY2hhbmdlc2V0X2luZm9fdFs2NF07CisjZGVmaW5lIFhFTl9DSEFOR0VTRVRfSU5GT19MRU4g
KHNpemVvZih4ZW5fY2hhbmdlc2V0X2luZm9fdCkpCisKKyNkZWZpbmUgWEVOVkVSX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgNQorc3RydWN0IHhlbl9wbGF0Zm9ybV9wYXJhbWV0ZXJzIHsKKyAgICB4ZW5f
dWxvbmdfdCB2aXJ0X3N0YXJ0OworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9wbGF0Zm9ybV9wYXJh
bWV0ZXJzIHhlbl9wbGF0Zm9ybV9wYXJhbWV0ZXJzX3Q7CisKKyNkZWZpbmUgWEVOVkVSX2dldF9m
ZWF0dXJlcyA2CitzdHJ1Y3QgeGVuX2ZlYXR1cmVfaW5mbyB7CisgICAgdW5zaWduZWQgaW50IHN1
Ym1hcF9pZHg7ICAgIC8qIElOOiB3aGljaCAzMi1iaXQgc3VibWFwIHRvIHJldHVybiAqLworICAg
IHVpbnQzMl90ICAgICBzdWJtYXA7ICAgICAgICAvKiBPVVQ6IDMyLWJpdCBzdWJtYXAgKi8KK307
Cit0eXBlZGVmIHN0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHhlbl9mZWF0dXJlX2luZm9fdDsKKwor
LyogRGVjbGFyZXMgdGhlIGZlYXR1cmVzIHJlcG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMu
ICovCisjaW5jbHVkZSAiZmVhdHVyZXMuaCIKKworLyogYXJnID09IE5VTEw7IHJldHVybnMgaG9z
dCBtZW1vcnkgcGFnZSBzaXplLiAqLworI2RlZmluZSBYRU5WRVJfcGFnZXNpemUgNworCisvKiBh
cmcgPT0geGVuX2RvbWFpbl9oYW5kbGVfdC4gKi8KKyNkZWZpbmUgWEVOVkVSX2d1ZXN0X2hhbmRs
ZSA4CisKKyNkZWZpbmUgWEVOVkVSX2NvbW1hbmRsaW5lIDkKK3R5cGVkZWYgY2hhciB4ZW5fY29t
bWFuZGxpbmVfdFsxMDI0XTsKKworI2VuZGlmIC8qIF9fWEVOX1BVQkxJQ19WRVJTSU9OX0hfXyAq
LworCisvKgorICogTG9jYWwgdmFyaWFibGVzOgorICogbW9kZTogQworICogYy1maWxlLXN0eWxl
OiAiQlNEIgorICogYy1iYXNpYy1vZmZzZXQ6IDQKKyAqIHRhYi13aWR0aDogNAorICogaW5kZW50
LXRhYnMtbW9kZTogbmlsCisgKiBFbmQ6CisgKi8KZGlmZiAtLWdpdCBhL3NyYy94ZW4vZHJpdmVy
LmMgYi9zcmMveGVuL2RyaXZlci5jCmluZGV4IGJhNTQxYjQuLmZjZTc1YWEgMTAwNjQ0Ci0tLSBh
L3NyYy94ZW4vZHJpdmVyLmMKKysrIGIvc3JjL3hlbi9kcml2ZXIuYwpAQCAtNTksNiArNTksMjYg
QEAgWGVuVG91Y2goCiAgICAgVk9JRAogICAgICkKIHsKKyAgICBzdGF0aWMgVUxPTkcgICAgUmVm
ZXJlbmNlOworICAgIFVMT05HICAgICAgICAgICBNYWpvcjsKKyAgICBVTE9ORyAgICAgICAgICAg
TWlub3I7CisgICAgQ0hBUiAgICAgICAgICAgIEV4dHJhW1hFTl9FWFRSQVZFUlNJT05fTEVOXTsK
KyAgICBOVFNUQVRVUyAgICAgICAgc3RhdHVzOworCisgICAgaWYgKFJlZmVyZW5jZSsrICE9IDAp
CisgICAgICAgIHJldHVybjsKKworICAgIHN0YXR1cyA9IFhlblZlcnNpb24oJk1ham9yLCAmTWlu
b3IpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykpOworCisgICAgc3RhdHVzID0gWGVu
VmVyc2lvbkV4dHJhKEV4dHJhKTsKKyAgICBBU1NFUlQoTlRfU1VDQ0VTUyhzdGF0dXMpKTsKKwor
ICAgIExvZ1ByaW50ZihMT0dfTEVWRUxfSU5GTywKKyAgICAgICAgICAgICAgIlhFTjogJXUuJXUl
c1xuIiwKKyAgICAgICAgICAgICAgTWFqb3IsCisgICAgICAgICAgICAgIE1pbm9yLAorICAgICAg
ICAgICAgICBFeHRyYSk7CiB9CiAKIHN0YXRpYyBWT0lECmRpZmYgLS1naXQgYS9zcmMveGVuL2h5
cGVyY2FsbC5jIGIvc3JjL3hlbi9oeXBlcmNhbGwuYwppbmRleCAwN2ViNDFhLi43MTdiOGMyIDEw
MDY0NAotLS0gYS9zcmMveGVuL2h5cGVyY2FsbC5jCisrKyBiL3NyYy94ZW4vaHlwZXJjYWxsLmMK
QEAgLTI5LDYgKzI5LDkgQEAKICAqIFNVQ0ggREFNQUdFLgogICovCiAKKyN1bmRlZiAgWEVOX0FQ
SQorI2RlZmluZSBYRU5fQVBJIF9fZGVjbHNwZWMoZGxsZXhwb3J0KQorCiAjaW5jbHVkZSA8bnRk
ZGsuaD4KICNpbmNsdWRlIDx4ZW4uaD4KICNpbmNsdWRlIDx1dGlsLmg+CkBAIC0zNywyNCArNDAs
NDEgQEAKICNpbmNsdWRlICJkYmdfcHJpbnQuaCIKICNpbmNsdWRlICJhc3NlcnQuaCIKIAotI2Rl
ZmluZSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQgMgorI2RlZmluZSBNQVhJTVVNX0hZUEVS
Q0FMTF9QQUdFX0NPVU5UIDIKIAogI3ByYWdtYSBjb2RlX3NlZygiaHlwZXJjYWxsIikKIF9fZGVj
bHNwZWMoYWxsb2NhdGUoImh5cGVyY2FsbCIpKQotc3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rp
b25bKE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCArIDEpICogUEFHRV9TSVpFXTsKK3N0YXRp
YyBVQ0hBUiAgICAgICAgX19TZWN0aW9uWyhNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UICsg
MSkgKiBQQUdFX1NJWkVdOwogCiBzdGF0aWMgVUxPTkcgICAgICAgIFhlbkJhc2VMZWFmID0gMHg0
MDAwMDAwMDsKIAotc3RhdGljIFVTSE9SVCAgICAgICBYZW5NYWpvclZlcnNpb247Ci1zdGF0aWMg
VVNIT1JUICAgICAgIFhlbk1pbm9yVmVyc2lvbjsKLQotc3RhdGljIFBGTl9OVU1CRVIgICBIeXBl
cmNhbGxQZm5bTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UXTsKLXN0YXRpYyBVTE9ORyAgICAg
ICAgSHlwZXJjYWxsUGZuQ291bnQ7CitzdGF0aWMgUEhZU0lDQUxfQUREUkVTUyBIeXBlcmNhbGxQ
YWdlW01BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09VTlRdOworc3RhdGljIFVMT05HICAgICAgICAg
ICAgSHlwZXJjYWxsUGFnZUNvdW50OwogCiB0eXBlZGVmIFVDSEFSICAgICAgICAgICBIWVBFUkNB
TExfR0FURVszMl07CiB0eXBlZGVmIEhZUEVSQ0FMTF9HQVRFICAqUEhZUEVSQ0FMTF9HQVRFOwog
CiBQSFlQRVJDQUxMX0dBVEUgICAgIEh5cGVyY2FsbDsKK1VMT05HICAgICAgICAgICAgICAgSHlw
ZXJjYWxsTXNyOworCitYRU5fQVBJCitWT0lECitIeXBlcmNhbGxQb3B1bGF0ZSgKKyAgICBWT0lE
CisgICAgKQoreworICAgIFVMT05HICAgICAgIEluZGV4OworCisgICAgZm9yIChJbmRleCA9IDA7
IEluZGV4IDwgSHlwZXJjYWxsUGFnZUNvdW50OyBJbmRleCsrKSB7CisgICAgICAgIExvZ1ByaW50
ZihMT0dfTEVWRUxfSU5GTywKKyAgICAgICAgICAgICAgICAgICJYRU46IEhZUEVSQ0FMTCBQQUdF
ICVkIEAgJTA4eC4lMDh4XG4iLAorICAgICAgICAgICAgICAgICAgSW5kZXgsCisgICAgICAgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4XS5IaWdoUGFydCwKKyAgICAgICAgICAgICAgICAg
IEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkxvd1BhcnQpOworCisgICAgICAgIF9fd3JpdGVtc3IoSHlw
ZXJjYWxsTXNyLCBIeXBlcmNhbGxQYWdlW0luZGV4XS5RdWFkUGFydCk7CisgICAgfQorfQogCiBO
VFNUQVRVUwogSHlwZXJjYWxsSW5pdGlhbGl6ZSgKQEAgLTY2LDcgKzg2LDYgQEAgSHlwZXJjYWxs
SW5pdGlhbGl6ZSgKICAgICBVTE9ORyAgICAgICBFQ1ggPSAnREVBRCc7CiAgICAgVUxPTkcgICAg
ICAgRURYID0gJ0RFQUQnOwogICAgIFVMT05HICAgICAgIEluZGV4OwotICAgIFVMT05HICAgICAg
IEh5cGVyY2FsbE1zcjsKICAgICBOVFNUQVRVUyAgICBzdGF0dXM7CiAKICAgICBzdGF0dXMgPSBT
VEFUVVNfVU5TVUNDRVNTRlVMOwpAQCAtODgsMTMgKzEwNyw2IEBAIEh5cGVyY2FsbEluaXRpYWxp
emUoCiAgICAgICAgICAgICBnb3RvIGZhaWwxOwogICAgIH0KIAotICAgIF9fQ3B1SWQoWGVuQmFz
ZUxlYWYgKyAxLCAmRUFYLCBOVUxMLCBOVUxMLCBOVUxMKTsKLSAgICBYZW5NYWpvclZlcnNpb24g
PSAoVVNIT1JUKShFQVggPj4gMTYpOwotICAgIFhlbk1pbm9yVmVyc2lvbiA9IChVU0hPUlQpKEVB
WCAmIDB4RkZGRik7Ci0KLSAgICBJbmZvKCJYRU4gJWQuJWRcbiIsIFhlbk1ham9yVmVyc2lvbiwg
WGVuTWlub3JWZXJzaW9uKTsKLSAgICBJbmZvKCJJTlRFUkZBQ0UgMHglMDh4XG4iLCBfX1hFTl9J
TlRFUkZBQ0VfVkVSU0lPTl9fKTsKLQogICAgIGlmICgoVUxPTkdfUFRSKV9fU2VjdGlvbiAmIChQ
QUdFX1NJWkUgLSAxKSkKICAgICAgICAgSHlwZXJjYWxsID0gKFBWT0lEKSgoKFVMT05HX1BUUilf
X1NlY3Rpb24gKyBQQUdFX1NJWkUgLSAxKSAmIH4oUEFHRV9TSVpFIC0gMSkpOwogICAgIGVsc2UK
QEAgLTEwMiwyMiArMTE0LDE2IEBAIEh5cGVyY2FsbEluaXRpYWxpemUoCiAKICAgICBBU1NFUlQz
VSgoKFVMT05HX1BUUilIeXBlcmNhbGwgJiAoUEFHRV9TSVpFIC0gMSkpLCA9PSwgMCk7CiAKLSAg
ICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IElu
ZGV4KyspIHsKLSAgICAgICAgUEhZU0lDQUxfQUREUkVTUyAgICBQaHlzaWNhbEFkZHJlc3M7Ci0K
LSAgICAgICAgUGh5c2ljYWxBZGRyZXNzID0gTW1HZXRQaHlzaWNhbEFkZHJlc3MoKFBVQ0hBUilI
eXBlcmNhbGwgKyAoSW5kZXggPDwgUEFHRV9TSElGVCkpOwotICAgICAgICBIeXBlcmNhbGxQZm5b
SW5kZXhdID0gKFBGTl9OVU1CRVIpKFBoeXNpY2FsQWRkcmVzcy5RdWFkUGFydCA+PiBQQUdFX1NI
SUZUKTsKLSAgICB9CisgICAgZm9yIChJbmRleCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNB
TExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAgICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0gPSBN
bUdldFBoeXNpY2FsQWRkcmVzcygoUFVDSEFSKUh5cGVyY2FsbCArCisgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKEluZGV4IDw8IFBBR0VfU0hJRlQp
KTsKIAogICAgIF9fQ3B1SWQoWGVuQmFzZUxlYWYgKyAyLCAmRUFYLCAmRUJYLCBOVUxMLCBOVUxM
KTsKLSAgICBIeXBlcmNhbGxQZm5Db3VudCA9IEVBWDsKLSAgICBBU1NFUlQoSHlwZXJjYWxsUGZu
Q291bnQgPD0gTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UKTsKKyAgICBIeXBlcmNhbGxQYWdl
Q291bnQgPSBFQVg7CisgICAgQVNTRVJUKEh5cGVyY2FsbFBhZ2VDb3VudCA8PSBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UKTsKICAgICBIeXBlcmNhbGxNc3IgPSBFQlg7CiAKLSAgICBmb3Ig
KEluZGV4ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQZm5Db3VudDsgSW5kZXgrKykgewotICAgICAg
ICBJbmZvKCJIeXBlcmNhbGxQZm5bJWRdOiAlcFxuIiwgSW5kZXgsIChQVk9JRClIeXBlcmNhbGxQ
Zm5bSW5kZXhdKTsKLSAgICAgICAgX193cml0ZW1zcihIeXBlcmNhbGxNc3IsIChVTE9ORzY0KUh5
cGVyY2FsbFBmbltJbmRleF0gPDwgUEFHRV9TSElGVCk7Ci0gICAgfQorICAgIEh5cGVyY2FsbFBv
cHVsYXRlKCk7CiAKICAgICByZXR1cm4gU1RBVFVTX1NVQ0NFU1M7CiAKQEAgLTE3Nyw4ICsxODMs
OCBAQCBIeXBlcmNhbGxUZWFyZG93bigKIAogICAgIEh5cGVyY2FsbCA9IE5VTEw7CiAKLSAgICBm
b3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IEluZGV4
KyspCi0gICAgICAgIEh5cGVyY2FsbFBmbltJbmRleF0gPSAwOworICAgIGZvciAoSW5kZXggPSAw
OyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQ7IEluZGV4KyspCisgICAgICAg
IEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0ID0gMDsKIAotICAgIEh5cGVyY2FsbFBmbkNv
dW50ID0gMDsKKyAgICBIeXBlcmNhbGxQYWdlQ291bnQgPSAwOwogfQpkaWZmIC0tZ2l0IGEvc3Jj
L3hlbmJ1cy9mZG8uYyBiL3NyYy94ZW5idXMvZmRvLmMKaW5kZXggNTk0NDJiZC4uMjE1Yzk5NyAx
MDA2NDQKLS0tIGEvc3JjL3hlbmJ1cy9mZG8uYworKysgYi9zcmMveGVuYnVzL2Zkby5jCkBAIC0y
MTg2LDYgKzIxODYsOCBAQCBGZG9TNFRvUzMoCiAKICAgICBLZVJhaXNlSXJxbChESVNQQVRDSF9M
RVZFTCwgJklycWwpOwogCisgICAgSHlwZXJjYWxsUG9wdWxhdGUoKTsKKwogICAgIGlmIChGZG8t
PlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2UuQ29udGV4dCAhPSBOVUxMKQogICAgICAgICBYRU5G
SUxUX1VOUExVRyhSZXBsYXksICZGZG8tPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBh
L3NyYy94ZW5idXMvc3VzcGVuZC5jIGIvc3JjL3hlbmJ1cy9zdXNwZW5kLmMKaW5kZXggNmFiMmJk
Mi4uZGU3MGU0MiAxMDA2NDQKLS0tIGEvc3JjL3hlbmJ1cy9zdXNwZW5kLmMKKysrIGIvc3JjL3hl
bmJ1cy9zdXNwZW5kLmMKQEAgLTE3Myw2ICsxNzMsOCBAQCBTdXNwZW5kVHJpZ2dlcigKIAogICAg
ICAgICBDb250ZXh0LT5Db3VudCsrOwogCisgICAgICAgIEh5cGVyY2FsbFBvcHVsYXRlKCk7CisK
ICAgICAgICAgaWYgKENvbnRleHQtPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2UuQ29udGV4dCAh
PSBOVUxMKQogICAgICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmQ29udGV4dC0+VW5w
bHVnSW50ZXJmYWNlKTsKIApkaWZmIC0tZ2l0IGEvdnMyMDEyL3hlbi94ZW4udmN4cHJvaiBiL3Zz
MjAxMi94ZW4veGVuLnZjeHByb2oKaW5kZXggZWI1NDY5Mi4uMmY0ZDk1OCAxMDA2NDQKLS0tIGEv
dnMyMDEyL3hlbi94ZW4udmN4cHJvagorKysgYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCkBAIC04
OCw2ICs4OCw3IEBACiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxldmVudF9j
aGFubmVsLmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxncmFudF90
YWJsZS5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+
CisJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblx4ZW5fdmVyc2lvbi5jIiAvPgog
CQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHlwZXJjYWxsLmMiIC8+CiAJCTxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KIAkJPENsQ29tcGls
ZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHNjaGVkLmMiIC8+CmRpZmYgLS1naXQgYS92czIwMTMv
eGVuL3hlbi52Y3hwcm9qIGIvdnMyMDEzL3hlbi94ZW4udmN4cHJvagppbmRleCA0OTAyOTRjLi44
MWQ1MGVhIDEwMDY0NAotLS0gYS92czIwMTMveGVuL3hlbi52Y3hwcm9qCisrKyBiL3ZzMjAxMy94
ZW4veGVuLnZjeHByb2oKQEAgLTEsNCArMSw0IEBACi3vu788P3htbCB2ZXJzaW9uPSIxLjAiIGVu
Y29kaW5nPSJ1dGYtOCI/PgorPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4K
IDxQcm9qZWN0IERlZmF1bHRUYXJnZXRzPSJCdWlsZCIgVG9vbHNWZXJzaW9uPSIxMi4wIiB4bWxu
cz0iaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS9kZXZlbG9wZXIvbXNidWlsZC8yMDAzIj4K
ICAgPEltcG9ydCBQcm9qZWN0PSIuLlxjb25maWdzLnByb3BzIiAvPgogICA8UHJvcGVydHlHcm91
cCBMYWJlbD0iR2xvYmFscyI+CkBAIC0xMjgsNiArMTI4LDcgQEAKICAgICA8Q2xDb21waWxlIElu
Y2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogICAgIDxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxncmFudF90YWJsZS5jIiAvPgogICAgIDxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxodm0uYyIgLz4KKyAgICA8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5ceGVuX3ZlcnNpb24uYyIgLz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9
Ii4uXC4uXHNyY1x4ZW5caHlwZXJjYWxsLmMiIC8+CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIu
LlwuLlxzcmNceGVuXG1lbW9yeS5jIiAvPgogICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5c
c3JjXHhlblxzY2hlZC5jIiAvPgotLSAKMi4xLjEKCgpfX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fXwp3aW4tcHYtZGV2ZWwgbWFpbGluZyBsaXN0Cndpbi1wdi1k
ZXZlbEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwpodHRwOi8vbGlzdHMueGVucHJvamVjdC5vcmcvY2dp
LWJpbi9tYWlsbWFuL2xpc3RpbmZvL3dpbi1wdi1kZXZlbA==

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 13:33:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:05 +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 1Xmjez-0004Yt-Tn; Fri, 07 Nov 2014 13:33:05 +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 1Xmjey-0004Yc-HZ
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:04 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	A9/B4-25714-F0ACC545; Fri, 07 Nov 2014 13:33:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9999 invoked from network); 7 Nov 2014 13:33:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123551"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-N5;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:42 +0000
Message-ID: <1415367162-28444-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-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 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 ++++++-
 include/xen.h              |  16 +++
 src/xen/event_channel.c    |  30 ++++++
 src/xen/hvm.c              |  28 ++++++
 src/xenbus/evtchn.c        | 239 ++++++++++++++++++++++++++++++++++++++++++---
 src/xenbus/store.c         |   9 ++
 6 files changed, 341 insertions(+), 16 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..aa26a31 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -82,13 +82,16 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,15 +130,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +170,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +201,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +213,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +402,10 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -422,6 +470,89 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto done;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -516,7 +647,7 @@ EvtchnTrigger(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
@@ -527,7 +658,7 @@ EvtchnTrigger(
         DoneSomething = FALSE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
 
     return DoneSomething;
 }
@@ -575,6 +706,8 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +750,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +763,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -767,8 +912,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1009,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1067,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1092,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1163,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1177,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1227,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1171,6 +1365,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 13:33:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:05 +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 1Xmjez-0004Yt-Tn; Fri, 07 Nov 2014 13:33:05 +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 1Xmjey-0004Yc-HZ
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:04 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	A9/B4-25714-F0ACC545; Fri, 07 Nov 2014 13:33:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9999 invoked from network); 7 Nov 2014 13:33:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123551"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-N5;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:42 +0000
Message-ID: <1415367162-28444-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-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 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 ++++++-
 include/xen.h              |  16 +++
 src/xen/event_channel.c    |  30 ++++++
 src/xen/hvm.c              |  28 ++++++
 src/xenbus/evtchn.c        | 239 ++++++++++++++++++++++++++++++++++++++++++---
 src/xenbus/store.c         |   9 ++
 6 files changed, 341 insertions(+), 16 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..aa26a31 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -82,13 +82,16 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,15 +130,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +170,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +201,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +213,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +402,10 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -422,6 +470,89 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto done;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -516,7 +647,7 @@ EvtchnTrigger(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
@@ -527,7 +658,7 @@ EvtchnTrigger(
         DoneSomething = FALSE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
 
     return DoneSomething;
 }
@@ -575,6 +706,8 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +750,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +763,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -767,8 +912,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1009,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1067,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1092,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1163,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1177,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1227,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1171,6 +1365,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 13:33:10 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:10 +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 1Xmjf4-0004Zg-0B; Fri, 07 Nov 2014 13:33:10 +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 1Xmjf3-0004Za-AP
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:09 +0000
Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id
	8E/B3-14214-41ACC545; Fri, 07 Nov 2014 13:33:08 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 10433 invoked from network); 7 Nov 2014 13:33:06 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:06 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123615"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-Lv;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:40 +0000
Message-ID: <1415367162-28444-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |  10 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 897 insertions(+), 225 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..b2c17c3 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service,
 [XenBus_Service] 
 DisplayName=%XenBusDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
-StartType=%SERVICE_BOOT_START% 
+StartType=%SERVICE_DEMAND_START% 
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 13:33:10 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 13:33:10 +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 1Xmjf4-0004Zg-0B; Fri, 07 Nov 2014 13:33:10 +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 1Xmjf3-0004Za-AP
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 13:33:09 +0000
Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id
	8E/B3-14214-41ACC545; Fri, 07 Nov 2014 13:33:08 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415367180!11108732!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 10433 invoked from network); 7 Nov 2014 13:33:06 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 13:33:06 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189123615"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 08:32: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 1Xmjem-0004Al-Lv;
	Fri, 07 Nov 2014 13:32:52 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 13:32:40 +0000
Message-ID: <1415367162-28444-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |  10 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 897 insertions(+), 225 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..b2c17c3 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service,
 [XenBus_Service] 
 DisplayName=%XenBusDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
-StartType=%SERVICE_BOOT_START% 
+StartType=%SERVICE_DEMAND_START% 
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 14:03:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:03:05 +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 1Xmk81-0005PS-Qz; Fri, 07 Nov 2014 14:03:05 +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 1Xmk80-0005PN-2Z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:03:04 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	E5/90-27623-711DC545; Fri, 07 Nov 2014 14:03:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415368981!11176179!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 903 invoked from network); 7 Nov 2014 14:03:01 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:03:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26636753"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ
Date: Fri, 7 Nov 2014 14:02:57 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415284254-25504-1-git-send-email-paul.durrant@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: David Vrabel <david.vrabel@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 06 November 2014 14:31
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> If it is available then the fifo ABI will be used. If it is not then the
> two-level ABI will be used instead.
> The ABI is released and re-acquired across suspend/resume so this should
> allow moving between hosts with different capabilities.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>

Cc-ing David Vrabel for review.

  Paul

> ---
>  include/xen.h                |  41 ++-
>  src/xen/event_channel.c      | 128 ++++++++
>  src/xenbus/evtchn.c          |  27 +-
>  src/xenbus/evtchn_fifo.c     | 702
> +++++++++++++++++++++++++++++++++++++++++++
>  src/xenbus/evtchn_fifo.h     |  59 ++++
>  src/xenbus/store.c           |  11 +-
>  vs2012/xenbus/xenbus.vcxproj |   1 +
>  vs2013/xenbus/xenbus.vcxproj |   1 +
>  8 files changed, 962 insertions(+), 8 deletions(-)
>  create mode 100644 src/xenbus/evtchn_fifo.c
>  create mode 100644 src/xenbus/evtchn_fifo.h
> 
> diff --git a/include/xen.h b/include/xen.h
> index 674676c..0039d7a 100644
> --- a/include/xen.h
> +++ b/include/xen.h
> @@ -136,17 +136,26 @@ __checkReturn
>  XEN_API
>  NTSTATUS
>  EventChannelBindInterDomain(
> -    IN  domid_t                     RemoteDomain,
> -    IN  evtchn_port_t               RemotePort,
> -    OUT evtchn_port_t               *LocalPort
> +    IN  domid_t         RemoteDomain,
> +    IN  evtchn_port_t   RemotePort,
> +    OUT evtchn_port_t   *LocalPort
>      );
> 
>  __checkReturn
>  XEN_API
>  NTSTATUS
>  EventChannelBindVirq(
> -    IN  uint32_t            Virq,
> -    OUT evtchn_port_t       *LocalPort
> +    IN  uint32_t        Virq,
> +    OUT evtchn_port_t   *LocalPort
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelQueryInterDomain(
> +    IN  evtchn_port_t   LocalPort,
> +    OUT domid_t         *RemoteDomain,
> +    OUT evtchn_port_t   *RemotePort
>      );
> 
>  __checkReturn
> @@ -156,6 +165,28 @@ EventChannelClose(
>      IN  evtchn_port_t   LocalPort
>      );
> 
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelExpandArray(
> +    IN  PFN_NUMBER              Pfn
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelInitControl(
> +    IN  PFN_NUMBER              Pfn,
> +    IN  unsigned int            vcpu_id
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelReset(
> +    VOID
> +    );
> +
>  // GRANT TABLE
> 
>  __checkReturn
> diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
> index 23e4659..aa87fd4 100644
> --- a/src/xen/event_channel.c
> +++ b/src/xen/event_channel.c
> @@ -175,6 +175,47 @@ fail1:
>  __checkReturn
>  XEN_API
>  NTSTATUS
> +EventChannelQueryInterDomain(
> +    IN  evtchn_port_t               LocalPort,
> +    OUT domid_t                     *RemoteDomain,
> +    OUT evtchn_port_t               *RemotePort
> +    )
> +{
> +    struct evtchn_status            op;
> +    LONG_PTR                        rc;
> +    NTSTATUS                        status;
> +
> +    op.dom = DOMID_SELF;
> +    op.port = LocalPort;
> +
> +    rc = EventChannelOp(EVTCHNOP_status, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    status = STATUS_INVALID_PARAMETER;
> +    if (op.status != EVTCHNSTAT_interdomain)
> +        goto fail2;
> +
> +    *RemoteDomain = op.u.interdomain.dom;
> +    *RemotePort = op.u.interdomain.port;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
>  EventChannelClose(
>      IN  evtchn_port_t   LocalPort
>      )
> @@ -199,3 +240,90 @@ fail1:
> 
>      return status;
>  }
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelExpandArray(
> +    IN  PFN_NUMBER              Pfn
> +    )
> +{
> +    struct evtchn_expand_array  op;
> +    LONG_PTR                    rc;
> +    NTSTATUS                    status;
> +
> +    op.array_gfn = Pfn;
> +
> +    rc = EventChannelOp(EVTCHNOP_expand_array, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelInitControl(
> +    IN  PFN_NUMBER              Pfn,
> +    IN  unsigned int            vcpu_id
> +    )
> +{
> +    struct evtchn_init_control  op;
> +    LONG_PTR                    rc;
> +    NTSTATUS                    status;
> +
> +    op.control_gfn = Pfn;
> +    op.offset = 0;
> +    op.vcpu = vcpu_id;
> +
> +    rc = EventChannelOp(EVTCHNOP_init_control, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelReset(
> +    VOID
> +    )
> +{
> +    struct evtchn_reset op;
> +    LONG_PTR            rc;
> +    NTSTATUS            status;
> +
> +    op.dom = DOMID_SELF;
> +
> +    rc = EventChannelOp(EVTCHNOP_reset, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
> index f13667e..2be0da8 100644
> --- a/src/xenbus/evtchn.c
> +++ b/src/xenbus/evtchn.c
> @@ -36,6 +36,7 @@
> 
>  #include "evtchn.h"
>  #include "evtchn_2l.h"
> +#include "evtchn_fifo.h"
>  #include "fdo.h"
>  #include "hash_table.h"
>  #include "dbg_print.h"
> @@ -95,6 +96,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
>      PXENBUS_DEBUG_CALLBACK          DebugCallback;
>      XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
>      PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
> +    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
>      XENBUS_EVTCHN_ABI               EvtchnAbi;
>      PXENBUS_HASH_TABLE              Table;
>      LIST_ENTRY                      List;
> @@ -234,7 +236,9 @@ EvtchnOpenInterDomain(
>      RemotePort = va_arg(Arguments, ULONG);
>      Mask = va_arg(Arguments, BOOLEAN);
> 
> -    status = EventChannelBindInterDomain(RemoteDomain, RemotePort,
> &LocalPort);
> +    status = EventChannelBindInterDomain(RemoteDomain,
> +                                         RemotePort,
> +                                         &LocalPort);
>      if (!NT_SUCCESS(status))
>          goto fail1;
> 
> @@ -666,6 +670,13 @@ EvtchnAbiAcquire(
>  {
>      NTSTATUS                    status;
> 
> +    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
> +                     &Context->EvtchnAbi);
> +
> +    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
> +    if (NT_SUCCESS(status))
> +        goto done;
> +
>      EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
>                           &Context->EvtchnAbi);
> 
> @@ -673,6 +684,7 @@ EvtchnAbiAcquire(
>      if (!NT_SUCCESS(status))
>          goto fail1;
> 
> +done:
>      return STATUS_SUCCESS;
> 
>  fail1:
> @@ -1024,6 +1036,10 @@ EvtchnInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail3;
> 
> +    status = EvtchnFifoInitialize(Fdo, &(*Context)->EvtchnFifoContext);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
>      status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
>                                   XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
>                                   (PINTERFACE)&(*Context)->SuspendInterface,
> @@ -1054,6 +1070,12 @@ EvtchnInitialize(
> 
>      return STATUS_SUCCESS;
> 
> +fail4:
> +    Error("fail4\n");
> +
> +    EvtchnTwoLevelTeardown((*Context)->EvtchnTwoLevelContext);
> +    (*Context)->EvtchnTwoLevelContext = NULL;
> +
>  fail3:
>      Error("fail3\n");
> 
> @@ -1131,6 +1153,9 @@ EvtchnTeardown(
>      RtlZeroMemory(&Context->SuspendInterface,
>                    sizeof (XENBUS_SUSPEND_INTERFACE));
> 
> +    EvtchnFifoTeardown(Context->EvtchnFifoContext);
> +    Context->EvtchnFifoContext = NULL;
> +
>      EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
>      Context->EvtchnTwoLevelContext = NULL;
> 
> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> new file mode 100644
> index 0000000..d37b1cd
> --- /dev/null
> +++ b/src/xenbus/evtchn_fifo.c
> @@ -0,0 +1,702 @@
> +/* 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 "evtchn_fifo.h"
> +#include "shared_info.h"
> +#include "fdo.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> +
> +#define MAX_HVM_VCPUS   128
> +
> +typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT {
> +    PXENBUS_FDO                     Fdo;
> +    KSPIN_LOCK                      Lock;
> +    LONG                            References;
> +    PMDL                            ControlBlockMdl[MAX_HVM_VCPUS];
> +    PMDL                            *EventPageMdl;
> +    ULONG                           EventPageCount;
> +    ULONG                           Head[EVTCHN_FIFO_MAX_QUEUES];
> +} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT;
> +
> +#define EVENT_WORDS_PER_PAGE    (PAGE_SIZE / sizeof (event_word_t))
> +
> +#define XENBUS_EVTCHN_FIFO_TAG  'OFIF'
> +
> +static FORCEINLINE PVOID
> +__EvtchnFifoAllocate(
> +    IN  ULONG   Length
> +    )
> +{
> +    return __AllocatePoolWithTag(NonPagedPool, Length,
> XENBUS_EVTCHN_FIFO_TAG);
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoFree(
> +    IN  PVOID   Buffer
> +    )
> +{
> +    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_FIFO_TAG);
> +}
> +
> +static event_word_t *
> +EvtchnFifoEventWord(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    ULONG                           Index;
> +    PMDL                            Mdl;
> +    event_word_t                    *EventWord;
> +
> +    Index = Port / EVENT_WORDS_PER_PAGE;
> +    ASSERT3U(Index, <, Context->EventPageCount);
> +
> +    Mdl = Context->EventPageMdl[Index];
> +
> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +    ASSERT(EventWord != NULL);
> +
> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
> +    Port -= Index * EVENT_WORDS_PER_PAGE;
> +
> +    return &EventWord[Port];
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!(*EventWord & (1 << Flag));
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestAndSetFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestAndClearFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoSetFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    *EventWord |= (1 << Flag);
> +    KeMemoryBarrier();
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoClearFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    *EventWord &= ~(1 << Flag);
> +    KeMemoryBarrier();
> +}
> +
> +static FORCEINLINE ULONG
> +__EvtchnFifoUnlink(
> +    IN  event_word_t    *EventWord
> +    )
> +{
> +    LONG                Old;
> +    LONG                New;
> +
> +    do {
> +        Old = *EventWord;
> +
> +        // Clear linked bit and link value
> +        New = Old & ~((1 << EVTCHN_FIFO_LINKED) |
> EVTCHN_FIFO_LINK_MASK);
> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
> Old);
> +
> +    return Old & EVTCHN_FIFO_LINK_MASK;
> +}
> +
> +static NTSTATUS
> +EvtchnFifoExpand(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    LONG                            Index;
> +    ULONG                           EventPageCount;
> +    PMDL                            *EventPageMdl;
> +    PMDL                            Mdl;
> +    ULONG                           Start;
> +    ULONG                           End;
> +    NTSTATUS                        status;
> +
> +    Index = Port / EVENT_WORDS_PER_PAGE;
> +    ASSERT3U(Index, >=, (LONG)Context->EventPageCount);
> +
> +    EventPageCount = Index + 1;
> +    EventPageMdl = __EvtchnFifoAllocate(sizeof (PMDL) * EventPageCount);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (EventPageMdl == NULL)
> +        goto fail1;
> +
> +    for (Index = 0; Index < (LONG)Context->EventPageCount; Index++)
> +        EventPageMdl[Index] = Context->EventPageMdl[Index];
> +
> +    Index = Context->EventPageCount;
> +    while (Index < (LONG)EventPageCount) {
> +        event_word_t        *EventWord;
> +        PFN_NUMBER          Pfn;
> +        PHYSICAL_ADDRESS    Address;
> +
> +        Mdl = __AllocatePage();
> +
> +        status = STATUS_NO_MEMORY;
> +        if (Mdl == NULL)
> +            goto fail2;
> +
> +        EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +        ASSERT(EventWord != NULL);
> +
> +        for (Port = 0; Port < EVENT_WORDS_PER_PAGE; Port++)
> +            __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
> +
> +        Pfn = MmGetMdlPfnArray(Mdl)[0];
> +
> +        status = EventChannelExpandArray(Pfn);
> +        if (!NT_SUCCESS(status))
> +            goto fail3;
> +
> +        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
> +
> +        LogPrintf(LOG_LEVEL_INFO,
> +                  "EVTCHN_FIFO: EVENTARRAY[%u] @ %08x.%08x\n",
> +                  Index,
> +                  Address.HighPart,
> +                  Address.LowPart);
> +
> +        EventPageMdl[Index++] = Mdl;
> +    }
> +
> +    Start = Context->EventPageCount * EVENT_WORDS_PER_PAGE;
> +    End = (EventPageCount * EVENT_WORDS_PER_PAGE) - 1;
> +
> +    Info("added ports [%08x - %08x]\n", Start, End);
> +
> +    if (Context->EventPageMdl != NULL)
> +        __EvtchnFifoFree(Context->EventPageMdl);
> +
> +    Context->EventPageMdl = EventPageMdl;
> +    Context->EventPageCount = EventPageCount;
> +
> +    return STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    __FreePage(Mdl);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    while (--Index >= (LONG)Context->EventPageCount) {
> +        Mdl = EventPageMdl[Index];
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    __EvtchnFifoFree(EventPageMdl);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +static VOID
> +EvtchnFifoContract(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> +    )
> +{
> +    LONG                            Index;
> +
> +    Index = Context->EventPageCount;
> +    while (--Index >= 0) {
> +        PMDL    Mdl;
> +
> +        Mdl = Context->EventPageMdl[Index];
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    __EvtchnFifoFree(Context->EventPageMdl);
> +
> +    Context->EventPageMdl = NULL;
> +    Context->EventPageCount = 0;
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPollPriority(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  evtchn_fifo_control_block_t *ControlBlock,
> +    IN  ULONG                       Priority,
> +    IN  PULONG                      Ready,
> +    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
> +    IN  PVOID                       Argument
> +    )
> +{
> +    ULONG                           Head;
> +    ULONG                           Port;
> +    event_word_t                    *EventWord;
> +    BOOLEAN                         DoneSomething;
> +
> +    Head = Context->Head[Priority];
> +
> +    if (Head == 0) {
> +        KeMemoryBarrier();
> +        Head = ControlBlock->head[Priority];
> +    }
> +
> +    Port = Head;
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +
> +    Head = __EvtchnFifoUnlink(EventWord);
> +
> +    if (Head == 0)
> +        *Ready &= ~(1ull << Priority);
> +
> +    DoneSomething = FALSE;
> +
> +    if (!__EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_MASKED) &&
> +        __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING))
> +        DoneSomething = Event(Argument, Port);
> +
> +    Context->Head[Priority] = Head;
> +
> +    return DoneSomething;
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPoll(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Cpu,
> +    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
> +    IN  PVOID                       Argument
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    unsigned int                    vcpu_id = SystemVirtualCpuIndex(Cpu);
> +    PMDL                            Mdl;
> +    evtchn_fifo_control_block_t     *ControlBlock;
> +    ULONG                           Ready;
> +    ULONG                           Priority;
> +    BOOLEAN                         DoneSomething;
> +
> +    Mdl = Context->ControlBlockMdl[vcpu_id];
> +
> +    ControlBlock = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +    ASSERT(ControlBlock != NULL);
> +
> +    Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0);
> +    DoneSomething = FALSE;
> +
> +    while (_BitScanReverse(&Priority, Ready)) {
> +        DoneSomething |= EvtchnFifoPollPriority(Context,
> +                                                ControlBlock,
> +                                                Priority,
> +                                                &Ready,
> +                                                Event,
> +                                                Argument);
> +        Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0);
> +    }
> +
> +    return DoneSomething;
> +}
> +
> +static NTSTATUS
> +EvtchnFifoPortEnable(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    NTSTATUS                        status;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (Port / EVENT_WORDS_PER_PAGE >= Context->EventPageCount) {
> +        status = EvtchnFifoExpand(Context, Port);
> +
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> +    }
> +
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return status;
> +}
> +
> +static VOID
> +EvtchnFifoPortAck(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +    __EvtchnFifoClearFlag(&EventWord[Port], EVTCHN_FIFO_PENDING);
> +}
> +
> +static VOID
> +EvtchnFifoPortMask(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +    __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPortUnmask(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +    LONG                            Old;
> +    LONG                            New;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +
> +    // Clear masked bit, spinning if busy
> +    do {
> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
> Old);
> +
> +    // Check whether the port was masked
> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> +        return FALSE;
> +
> +    // If we cleared the mask then check whether something is pending
> +    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
> +        return FALSE;
> +
> +    return TRUE;
> +}
> +
> +static VOID
> +EvtchnFifoPortDisable(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    EvtchnFifoPortMask(_Context, Port);
> +}
> +
> +static VOID
> +EvtchnFifoReset(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> +    )
> +{
> +    ULONGLONG                       Value;
> +    ULONG                           LocalPort;
> +    ULONG                           RemotePort;
> +    USHORT                          RemoteDomain;
> +    NTSTATUS                        status;
> +
> +    UNREFERENCED_PARAMETER(Context);
> +
> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    LocalPort = (LONG)Value;
> +
> +    //
> +    // When we reset the event channel ABI we will lose our
> +    // binding to the STORE event channel, which was set up
> +    // by the toolstack during domain build.
> +    // We need to get the binding back, so we must query the
> +    // remote domain and port, and then re-bind after the
> +    // reset.
> +    //
> +
> +    status = EventChannelQueryInterDomain(LocalPort,
> +                                          &RemoteDomain,
> +                                          &RemotePort);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    LogPrintf(LOG_LEVEL_INFO, "EVTCHN_FIFO: RESET\n");
> +    (VOID) EventChannelReset();
> +
> +    status = EventChannelBindInterDomain(RemoteDomain,
> +                                         RemotePort,
> +                                         &LocalPort);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    Value = LocalPort;
> +
> +    status = HvmSetParam(HVM_PARAM_STORE_EVTCHN, Value);
> +    ASSERT(NT_SUCCESS(status));
> +}
> +
> +static NTSTATUS
> +EvtchnFifoAcquire(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    LONG                            Cpu;
> +    PMDL                            Mdl;
> +    NTSTATUS                        status;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (Context->References++ != 0)
> +        goto done;
> +
> +    Trace("====>\n");
> +
> +    Cpu = 0;
> +    while (Cpu < KeNumberProcessors) {
> +        unsigned int        vcpu_id;
> +        PFN_NUMBER          Pfn;
> +        PHYSICAL_ADDRESS    Address;
> +
> +        Mdl = __AllocatePage();
> +
> +        status = STATUS_NO_MEMORY;
> +        if (Mdl == NULL)
> +            goto fail1;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +        Pfn = MmGetMdlPfnArray(Mdl)[0];
> +
> +        status = EventChannelInitControl(Pfn, vcpu_id);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +
> +        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
> +
> +        LogPrintf(LOG_LEVEL_INFO,
> +                  "EVTCHN_FIFO: CONTROLBLOCK[%u] @ %08x.%08x\n",
> +                  vcpu_id,
> +                  Address.HighPart,
> +                  Address.LowPart);
> +
> +        Context->ControlBlockMdl[vcpu_id] = Mdl;
> +        Cpu++;
> +    }
> +
> +    Trace("<====\n");
> +
> +done:
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    __FreePage(Mdl);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    (VOID) EventChannelReset();
> +
> +    while (--Cpu >= 0) {
> +        unsigned int    vcpu_id;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +
> +        Mdl = Context->ControlBlockMdl[vcpu_id];
> +        Context->ControlBlockMdl[vcpu_id] = NULL;
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    --Context->References;
> +    ASSERT3U(Context->References, ==, 0);
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return status;
> +}
> +
> +VOID
> +EvtchnFifoRelease(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    LONG                            Cpu;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (--Context->References > 0)
> +        goto done;
> +
> +    Trace("====>\n");
> +
> +    EvtchnFifoReset(Context);
> +
> +    EvtchnFifoContract(Context);
> +
> +    Cpu = KeNumberProcessors;
> +    while (--Cpu >= 0) {
> +        unsigned int    vcpu_id;
> +        PMDL            Mdl;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +
> +        Mdl = Context->ControlBlockMdl[vcpu_id];
> +        Context->ControlBlockMdl[vcpu_id] = NULL;
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    Trace("<====\n");
> +
> +done:
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +}
> +
> +static XENBUS_EVTCHN_ABI EvtchnAbiFifo = {
> +    NULL,
> +    EvtchnFifoAcquire,
> +    EvtchnFifoRelease,
> +    EvtchnFifoPoll,
> +    EvtchnFifoPortEnable,
> +    EvtchnFifoPortDisable,
> +    EvtchnFifoPortAck,
> +    EvtchnFifoPortMask,
> +    EvtchnFifoPortUnmask
> +};
> +
> +NTSTATUS
> +EvtchnFifoInitialize(
> +    IN  PXENBUS_FDO                     Fdo,
> +    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT    Context;
> +    NTSTATUS                            status;
> +
> +    Trace("====>\n");
> +
> +    Context = __EvtchnFifoAllocate(sizeof
> (XENBUS_EVTCHN_FIFO_CONTEXT));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Context == NULL)
> +        goto fail1;
> +
> +    KeInitializeSpinLock(&Context->Lock);
> +
> +    Context->Fdo = Fdo;
> +
> +    *_Context = (PVOID)Context;
> +
> +    Trace("<====\n");
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +VOID
> +EvtchnFifoGetAbi(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
> +    OUT PXENBUS_EVTCHN_ABI              Abi)
> +{
> +    *Abi = EvtchnAbiFifo;
> +
> +    Abi->Context = (PVOID)_Context;
> +}
> +
> +VOID
> +EvtchnFifoTeardown(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT    Context = (PVOID)_Context;
> +
> +    Trace("====>\n");
> +
> +    Context->Fdo = NULL;
> +
> +    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
> +
> +    ASSERT(IsZeroMemory(Context, sizeof
> (XENBUS_EVTCHN_FIFO_CONTEXT)));
> +    __EvtchnFifoFree(Context);
> +
> +    Trace("<====\n");
> +}
> diff --git a/src/xenbus/evtchn_fifo.h b/src/xenbus/evtchn_fifo.h
> new file mode 100644
> index 0000000..bf96b19
> --- /dev/null
> +++ b/src/xenbus/evtchn_fifo.h
> @@ -0,0 +1,59 @@
> +/* 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 _XENBUS_EVTCHN_FIFO_H
> +#define _XENBUS_EVTCHN_FIFO_H
> +
> +#include <ntddk.h>
> +#include <xen.h>
> +
> +#include "evtchn_abi.h"
> +#include "fdo.h"
> +
> +extern NTSTATUS
> +EvtchnFifoInitialize(
> +    IN  PXENBUS_FDO                 Fdo,
> +    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
> +    );
> +
> +extern VOID
> +EvtchnFifoGetAbi(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
> +    OUT PXENBUS_EVTCHN_ABI          Abi
> +    );
> +
> +extern VOID
> +EvtchnFifoTeardown(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
> +    );
> +
> +#endif  // _XENBUS_EVTCHN_FIFO_H
> +
> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
> index 62ec60b..22c2a12 100644
> --- a/src/xenbus/store.c
> +++ b/src/xenbus/store.c
> @@ -1825,13 +1825,20 @@ StoreEnable(
>      IN PXENBUS_STORE_CONTEXT    Context
>      )
>  {
> -    ULONGLONG                   Port;
> +    ULONGLONG                   Value;
> +    ULONG                       Port;
>      BOOLEAN                     Pending;
>      NTSTATUS                    status;
> 
> -    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Port);
> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
>      ASSERT(NT_SUCCESS(status));
> 
> +    Port = (ULONG)Value;
> +
> +    LogPrintf(LOG_LEVEL_INFO,
> +              "STORE: EVTCHN %u\n",
> +              Port);
> +
>      Context->Channel = XENBUS_EVTCHN(Open,
>                                       &Context->EvtchnInterface,
>                                       XENBUS_EVTCHN_TYPE_FIXED,
> diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
> index 6cd12d1..3c184e0 100644
> --- a/vs2012/xenbus/xenbus.vcxproj
> +++ b/vs2012/xenbus/xenbus.vcxproj
> @@ -89,6 +89,7 @@
>  		<ClCompile Include="..\..\src\xenbus\driver.c" />
>  		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
>  		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
> +		<ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
>  		<ClCompile Include="..\..\src\xenbus\fdo.c" />
>  		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
>  		<ClCompile Include="..\..\src\xenbus\pdo.c" />
> diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
> index 0f37f68..ecb602b 100644
> --- a/vs2013/xenbus/xenbus.vcxproj
> +++ b/vs2013/xenbus/xenbus.vcxproj
> @@ -129,6 +129,7 @@
>      <ClCompile Include="..\..\src\xenbus\driver.c" />
>      <ClCompile Include="..\..\src\xenbus\evtchn.c" />
>      <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
> +    <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
>      <ClCompile Include="..\..\src\xenbus\fdo.c" />
>      <ClCompile Include="..\..\src\xenbus\gnttab.c" />
>      <ClCompile Include="..\..\src\xenbus\pdo.c" />
> --
> 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 Nov 07 14:03:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:03:05 +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 1Xmk81-0005PS-Qz; Fri, 07 Nov 2014 14:03:05 +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 1Xmk80-0005PN-2Z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:03:04 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	E5/90-27623-711DC545; Fri, 07 Nov 2014 14:03:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-31.messagelabs.com!1415368981!11176179!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 903 invoked from network); 7 Nov 2014 14:03:01 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:03:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26636753"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ
Date: Fri, 7 Nov 2014 14:02:57 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415284254-25504-1-git-send-email-paul.durrant@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: David Vrabel <david.vrabel@citrix.com>
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 06 November 2014 14:31
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> If it is available then the fifo ABI will be used. If it is not then the
> two-level ABI will be used instead.
> The ABI is released and re-acquired across suspend/resume so this should
> allow moving between hosts with different capabilities.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>

Cc-ing David Vrabel for review.

  Paul

> ---
>  include/xen.h                |  41 ++-
>  src/xen/event_channel.c      | 128 ++++++++
>  src/xenbus/evtchn.c          |  27 +-
>  src/xenbus/evtchn_fifo.c     | 702
> +++++++++++++++++++++++++++++++++++++++++++
>  src/xenbus/evtchn_fifo.h     |  59 ++++
>  src/xenbus/store.c           |  11 +-
>  vs2012/xenbus/xenbus.vcxproj |   1 +
>  vs2013/xenbus/xenbus.vcxproj |   1 +
>  8 files changed, 962 insertions(+), 8 deletions(-)
>  create mode 100644 src/xenbus/evtchn_fifo.c
>  create mode 100644 src/xenbus/evtchn_fifo.h
> 
> diff --git a/include/xen.h b/include/xen.h
> index 674676c..0039d7a 100644
> --- a/include/xen.h
> +++ b/include/xen.h
> @@ -136,17 +136,26 @@ __checkReturn
>  XEN_API
>  NTSTATUS
>  EventChannelBindInterDomain(
> -    IN  domid_t                     RemoteDomain,
> -    IN  evtchn_port_t               RemotePort,
> -    OUT evtchn_port_t               *LocalPort
> +    IN  domid_t         RemoteDomain,
> +    IN  evtchn_port_t   RemotePort,
> +    OUT evtchn_port_t   *LocalPort
>      );
> 
>  __checkReturn
>  XEN_API
>  NTSTATUS
>  EventChannelBindVirq(
> -    IN  uint32_t            Virq,
> -    OUT evtchn_port_t       *LocalPort
> +    IN  uint32_t        Virq,
> +    OUT evtchn_port_t   *LocalPort
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelQueryInterDomain(
> +    IN  evtchn_port_t   LocalPort,
> +    OUT domid_t         *RemoteDomain,
> +    OUT evtchn_port_t   *RemotePort
>      );
> 
>  __checkReturn
> @@ -156,6 +165,28 @@ EventChannelClose(
>      IN  evtchn_port_t   LocalPort
>      );
> 
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelExpandArray(
> +    IN  PFN_NUMBER              Pfn
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelInitControl(
> +    IN  PFN_NUMBER              Pfn,
> +    IN  unsigned int            vcpu_id
> +    );
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelReset(
> +    VOID
> +    );
> +
>  // GRANT TABLE
> 
>  __checkReturn
> diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
> index 23e4659..aa87fd4 100644
> --- a/src/xen/event_channel.c
> +++ b/src/xen/event_channel.c
> @@ -175,6 +175,47 @@ fail1:
>  __checkReturn
>  XEN_API
>  NTSTATUS
> +EventChannelQueryInterDomain(
> +    IN  evtchn_port_t               LocalPort,
> +    OUT domid_t                     *RemoteDomain,
> +    OUT evtchn_port_t               *RemotePort
> +    )
> +{
> +    struct evtchn_status            op;
> +    LONG_PTR                        rc;
> +    NTSTATUS                        status;
> +
> +    op.dom = DOMID_SELF;
> +    op.port = LocalPort;
> +
> +    rc = EventChannelOp(EVTCHNOP_status, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    status = STATUS_INVALID_PARAMETER;
> +    if (op.status != EVTCHNSTAT_interdomain)
> +        goto fail2;
> +
> +    *RemoteDomain = op.u.interdomain.dom;
> +    *RemotePort = op.u.interdomain.port;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
>  EventChannelClose(
>      IN  evtchn_port_t   LocalPort
>      )
> @@ -199,3 +240,90 @@ fail1:
> 
>      return status;
>  }
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelExpandArray(
> +    IN  PFN_NUMBER              Pfn
> +    )
> +{
> +    struct evtchn_expand_array  op;
> +    LONG_PTR                    rc;
> +    NTSTATUS                    status;
> +
> +    op.array_gfn = Pfn;
> +
> +    rc = EventChannelOp(EVTCHNOP_expand_array, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelInitControl(
> +    IN  PFN_NUMBER              Pfn,
> +    IN  unsigned int            vcpu_id
> +    )
> +{
> +    struct evtchn_init_control  op;
> +    LONG_PTR                    rc;
> +    NTSTATUS                    status;
> +
> +    op.control_gfn = Pfn;
> +    op.offset = 0;
> +    op.vcpu = vcpu_id;
> +
> +    rc = EventChannelOp(EVTCHNOP_init_control, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +__checkReturn
> +XEN_API
> +NTSTATUS
> +EventChannelReset(
> +    VOID
> +    )
> +{
> +    struct evtchn_reset op;
> +    LONG_PTR            rc;
> +    NTSTATUS            status;
> +
> +    op.dom = DOMID_SELF;
> +
> +    rc = EventChannelOp(EVTCHNOP_reset, &op);
> +
> +    if (rc < 0) {
> +        ERRNO_TO_STATUS(-rc, status);
> +        goto fail1;
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
> index f13667e..2be0da8 100644
> --- a/src/xenbus/evtchn.c
> +++ b/src/xenbus/evtchn.c
> @@ -36,6 +36,7 @@
> 
>  #include "evtchn.h"
>  #include "evtchn_2l.h"
> +#include "evtchn_fifo.h"
>  #include "fdo.h"
>  #include "hash_table.h"
>  #include "dbg_print.h"
> @@ -95,6 +96,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
>      PXENBUS_DEBUG_CALLBACK          DebugCallback;
>      XENBUS_SHARED_INFO_INTERFACE    SharedInfoInterface;
>      PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnTwoLevelContext;
> +    PXENBUS_EVTCHN_ABI_CONTEXT      EvtchnFifoContext;
>      XENBUS_EVTCHN_ABI               EvtchnAbi;
>      PXENBUS_HASH_TABLE              Table;
>      LIST_ENTRY                      List;
> @@ -234,7 +236,9 @@ EvtchnOpenInterDomain(
>      RemotePort = va_arg(Arguments, ULONG);
>      Mask = va_arg(Arguments, BOOLEAN);
> 
> -    status = EventChannelBindInterDomain(RemoteDomain, RemotePort,
> &LocalPort);
> +    status = EventChannelBindInterDomain(RemoteDomain,
> +                                         RemotePort,
> +                                         &LocalPort);
>      if (!NT_SUCCESS(status))
>          goto fail1;
> 
> @@ -666,6 +670,13 @@ EvtchnAbiAcquire(
>  {
>      NTSTATUS                    status;
> 
> +    EvtchnFifoGetAbi(Context->EvtchnFifoContext,
> +                     &Context->EvtchnAbi);
> +
> +    status = XENBUS_EVTCHN_ABI(Acquire, &Context->EvtchnAbi);
> +    if (NT_SUCCESS(status))
> +        goto done;
> +
>      EvtchnTwoLevelGetAbi(Context->EvtchnTwoLevelContext,
>                           &Context->EvtchnAbi);
> 
> @@ -673,6 +684,7 @@ EvtchnAbiAcquire(
>      if (!NT_SUCCESS(status))
>          goto fail1;
> 
> +done:
>      return STATUS_SUCCESS;
> 
>  fail1:
> @@ -1024,6 +1036,10 @@ EvtchnInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail3;
> 
> +    status = EvtchnFifoInitialize(Fdo, &(*Context)->EvtchnFifoContext);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
>      status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
>                                   XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
>                                   (PINTERFACE)&(*Context)->SuspendInterface,
> @@ -1054,6 +1070,12 @@ EvtchnInitialize(
> 
>      return STATUS_SUCCESS;
> 
> +fail4:
> +    Error("fail4\n");
> +
> +    EvtchnTwoLevelTeardown((*Context)->EvtchnTwoLevelContext);
> +    (*Context)->EvtchnTwoLevelContext = NULL;
> +
>  fail3:
>      Error("fail3\n");
> 
> @@ -1131,6 +1153,9 @@ EvtchnTeardown(
>      RtlZeroMemory(&Context->SuspendInterface,
>                    sizeof (XENBUS_SUSPEND_INTERFACE));
> 
> +    EvtchnFifoTeardown(Context->EvtchnFifoContext);
> +    Context->EvtchnFifoContext = NULL;
> +
>      EvtchnTwoLevelTeardown(Context->EvtchnTwoLevelContext);
>      Context->EvtchnTwoLevelContext = NULL;
> 
> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> new file mode 100644
> index 0000000..d37b1cd
> --- /dev/null
> +++ b/src/xenbus/evtchn_fifo.c
> @@ -0,0 +1,702 @@
> +/* 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 "evtchn_fifo.h"
> +#include "shared_info.h"
> +#include "fdo.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> +
> +#define MAX_HVM_VCPUS   128
> +
> +typedef struct _XENBUS_EVTCHN_FIFO_CONTEXT {
> +    PXENBUS_FDO                     Fdo;
> +    KSPIN_LOCK                      Lock;
> +    LONG                            References;
> +    PMDL                            ControlBlockMdl[MAX_HVM_VCPUS];
> +    PMDL                            *EventPageMdl;
> +    ULONG                           EventPageCount;
> +    ULONG                           Head[EVTCHN_FIFO_MAX_QUEUES];
> +} XENBUS_EVTCHN_FIFO_CONTEXT, *PXENBUS_EVTCHN_FIFO_CONTEXT;
> +
> +#define EVENT_WORDS_PER_PAGE    (PAGE_SIZE / sizeof (event_word_t))
> +
> +#define XENBUS_EVTCHN_FIFO_TAG  'OFIF'
> +
> +static FORCEINLINE PVOID
> +__EvtchnFifoAllocate(
> +    IN  ULONG   Length
> +    )
> +{
> +    return __AllocatePoolWithTag(NonPagedPool, Length,
> XENBUS_EVTCHN_FIFO_TAG);
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoFree(
> +    IN  PVOID   Buffer
> +    )
> +{
> +    ExFreePoolWithTag(Buffer, XENBUS_EVTCHN_FIFO_TAG);
> +}
> +
> +static event_word_t *
> +EvtchnFifoEventWord(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    ULONG                           Index;
> +    PMDL                            Mdl;
> +    event_word_t                    *EventWord;
> +
> +    Index = Port / EVENT_WORDS_PER_PAGE;
> +    ASSERT3U(Index, <, Context->EventPageCount);
> +
> +    Mdl = Context->EventPageMdl[Index];
> +
> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +    ASSERT(EventWord != NULL);
> +
> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
> +    Port -= Index * EVENT_WORDS_PER_PAGE;
> +
> +    return &EventWord[Port];
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!(*EventWord & (1 << Flag));
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestAndSetFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> +}
> +
> +static FORCEINLINE BOOLEAN
> +__EvtchnFifoTestAndClearFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    KeMemoryBarrier();
> +
> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoSetFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    *EventWord |= (1 << Flag);
> +    KeMemoryBarrier();
> +}
> +
> +static FORCEINLINE VOID
> +__EvtchnFifoClearFlag(
> +    IN  event_word_t    *EventWord,
> +    IN  ULONG           Flag
> +    )
> +{
> +    *EventWord &= ~(1 << Flag);
> +    KeMemoryBarrier();
> +}
> +
> +static FORCEINLINE ULONG
> +__EvtchnFifoUnlink(
> +    IN  event_word_t    *EventWord
> +    )
> +{
> +    LONG                Old;
> +    LONG                New;
> +
> +    do {
> +        Old = *EventWord;
> +
> +        // Clear linked bit and link value
> +        New = Old & ~((1 << EVTCHN_FIFO_LINKED) |
> EVTCHN_FIFO_LINK_MASK);
> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
> Old);
> +
> +    return Old & EVTCHN_FIFO_LINK_MASK;
> +}
> +
> +static NTSTATUS
> +EvtchnFifoExpand(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    LONG                            Index;
> +    ULONG                           EventPageCount;
> +    PMDL                            *EventPageMdl;
> +    PMDL                            Mdl;
> +    ULONG                           Start;
> +    ULONG                           End;
> +    NTSTATUS                        status;
> +
> +    Index = Port / EVENT_WORDS_PER_PAGE;
> +    ASSERT3U(Index, >=, (LONG)Context->EventPageCount);
> +
> +    EventPageCount = Index + 1;
> +    EventPageMdl = __EvtchnFifoAllocate(sizeof (PMDL) * EventPageCount);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (EventPageMdl == NULL)
> +        goto fail1;
> +
> +    for (Index = 0; Index < (LONG)Context->EventPageCount; Index++)
> +        EventPageMdl[Index] = Context->EventPageMdl[Index];
> +
> +    Index = Context->EventPageCount;
> +    while (Index < (LONG)EventPageCount) {
> +        event_word_t        *EventWord;
> +        PFN_NUMBER          Pfn;
> +        PHYSICAL_ADDRESS    Address;
> +
> +        Mdl = __AllocatePage();
> +
> +        status = STATUS_NO_MEMORY;
> +        if (Mdl == NULL)
> +            goto fail2;
> +
> +        EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +        ASSERT(EventWord != NULL);
> +
> +        for (Port = 0; Port < EVENT_WORDS_PER_PAGE; Port++)
> +            __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
> +
> +        Pfn = MmGetMdlPfnArray(Mdl)[0];
> +
> +        status = EventChannelExpandArray(Pfn);
> +        if (!NT_SUCCESS(status))
> +            goto fail3;
> +
> +        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
> +
> +        LogPrintf(LOG_LEVEL_INFO,
> +                  "EVTCHN_FIFO: EVENTARRAY[%u] @ %08x.%08x\n",
> +                  Index,
> +                  Address.HighPart,
> +                  Address.LowPart);
> +
> +        EventPageMdl[Index++] = Mdl;
> +    }
> +
> +    Start = Context->EventPageCount * EVENT_WORDS_PER_PAGE;
> +    End = (EventPageCount * EVENT_WORDS_PER_PAGE) - 1;
> +
> +    Info("added ports [%08x - %08x]\n", Start, End);
> +
> +    if (Context->EventPageMdl != NULL)
> +        __EvtchnFifoFree(Context->EventPageMdl);
> +
> +    Context->EventPageMdl = EventPageMdl;
> +    Context->EventPageCount = EventPageCount;
> +
> +    return STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    __FreePage(Mdl);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    while (--Index >= (LONG)Context->EventPageCount) {
> +        Mdl = EventPageMdl[Index];
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    __EvtchnFifoFree(EventPageMdl);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +static VOID
> +EvtchnFifoContract(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> +    )
> +{
> +    LONG                            Index;
> +
> +    Index = Context->EventPageCount;
> +    while (--Index >= 0) {
> +        PMDL    Mdl;
> +
> +        Mdl = Context->EventPageMdl[Index];
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    __EvtchnFifoFree(Context->EventPageMdl);
> +
> +    Context->EventPageMdl = NULL;
> +    Context->EventPageCount = 0;
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPollPriority(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> +    IN  evtchn_fifo_control_block_t *ControlBlock,
> +    IN  ULONG                       Priority,
> +    IN  PULONG                      Ready,
> +    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
> +    IN  PVOID                       Argument
> +    )
> +{
> +    ULONG                           Head;
> +    ULONG                           Port;
> +    event_word_t                    *EventWord;
> +    BOOLEAN                         DoneSomething;
> +
> +    Head = Context->Head[Priority];
> +
> +    if (Head == 0) {
> +        KeMemoryBarrier();
> +        Head = ControlBlock->head[Priority];
> +    }
> +
> +    Port = Head;
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +
> +    Head = __EvtchnFifoUnlink(EventWord);
> +
> +    if (Head == 0)
> +        *Ready &= ~(1ull << Priority);
> +
> +    DoneSomething = FALSE;
> +
> +    if (!__EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_MASKED) &&
> +        __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING))
> +        DoneSomething = Event(Argument, Port);
> +
> +    Context->Head[Priority] = Head;
> +
> +    return DoneSomething;
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPoll(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Cpu,
> +    IN  XENBUS_EVTCHN_ABI_EVENT     Event,
> +    IN  PVOID                       Argument
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    unsigned int                    vcpu_id = SystemVirtualCpuIndex(Cpu);
> +    PMDL                            Mdl;
> +    evtchn_fifo_control_block_t     *ControlBlock;
> +    ULONG                           Ready;
> +    ULONG                           Priority;
> +    BOOLEAN                         DoneSomething;
> +
> +    Mdl = Context->ControlBlockMdl[vcpu_id];
> +
> +    ControlBlock = MmGetSystemAddressForMdlSafe(Mdl,
> NormalPagePriority);
> +    ASSERT(ControlBlock != NULL);
> +
> +    Ready = InterlockedExchange((LONG *)&ControlBlock->ready, 0);
> +    DoneSomething = FALSE;
> +
> +    while (_BitScanReverse(&Priority, Ready)) {
> +        DoneSomething |= EvtchnFifoPollPriority(Context,
> +                                                ControlBlock,
> +                                                Priority,
> +                                                &Ready,
> +                                                Event,
> +                                                Argument);
> +        Ready |= InterlockedExchange((LONG *)&ControlBlock->ready, 0);
> +    }
> +
> +    return DoneSomething;
> +}
> +
> +static NTSTATUS
> +EvtchnFifoPortEnable(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    NTSTATUS                        status;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (Port / EVENT_WORDS_PER_PAGE >= Context->EventPageCount) {
> +        status = EvtchnFifoExpand(Context, Port);
> +
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> +    }
> +
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return status;
> +}
> +
> +static VOID
> +EvtchnFifoPortAck(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +    __EvtchnFifoClearFlag(&EventWord[Port], EVTCHN_FIFO_PENDING);
> +}
> +
> +static VOID
> +EvtchnFifoPortMask(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +    __EvtchnFifoSetFlag(&EventWord[Port], EVTCHN_FIFO_MASKED);
> +}
> +
> +static BOOLEAN
> +EvtchnFifoPortUnmask(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    event_word_t                    *EventWord;
> +    LONG                            Old;
> +    LONG                            New;
> +
> +    EventWord = EvtchnFifoEventWord(Context, Port);
> +
> +    // Clear masked bit, spinning if busy
> +    do {
> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
> Old);
> +
> +    // Check whether the port was masked
> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> +        return FALSE;
> +
> +    // If we cleared the mask then check whether something is pending
> +    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
> +        return FALSE;
> +
> +    return TRUE;
> +}
> +
> +static VOID
> +EvtchnFifoPortDisable(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> +    IN  ULONG                       Port
> +    )
> +{
> +    EvtchnFifoPortMask(_Context, Port);
> +}
> +
> +static VOID
> +EvtchnFifoReset(
> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> +    )
> +{
> +    ULONGLONG                       Value;
> +    ULONG                           LocalPort;
> +    ULONG                           RemotePort;
> +    USHORT                          RemoteDomain;
> +    NTSTATUS                        status;
> +
> +    UNREFERENCED_PARAMETER(Context);
> +
> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    LocalPort = (LONG)Value;
> +
> +    //
> +    // When we reset the event channel ABI we will lose our
> +    // binding to the STORE event channel, which was set up
> +    // by the toolstack during domain build.
> +    // We need to get the binding back, so we must query the
> +    // remote domain and port, and then re-bind after the
> +    // reset.
> +    //
> +
> +    status = EventChannelQueryInterDomain(LocalPort,
> +                                          &RemoteDomain,
> +                                          &RemotePort);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    LogPrintf(LOG_LEVEL_INFO, "EVTCHN_FIFO: RESET\n");
> +    (VOID) EventChannelReset();
> +
> +    status = EventChannelBindInterDomain(RemoteDomain,
> +                                         RemotePort,
> +                                         &LocalPort);
> +    ASSERT(NT_SUCCESS(status));
> +
> +    Value = LocalPort;
> +
> +    status = HvmSetParam(HVM_PARAM_STORE_EVTCHN, Value);
> +    ASSERT(NT_SUCCESS(status));
> +}
> +
> +static NTSTATUS
> +EvtchnFifoAcquire(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    LONG                            Cpu;
> +    PMDL                            Mdl;
> +    NTSTATUS                        status;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (Context->References++ != 0)
> +        goto done;
> +
> +    Trace("====>\n");
> +
> +    Cpu = 0;
> +    while (Cpu < KeNumberProcessors) {
> +        unsigned int        vcpu_id;
> +        PFN_NUMBER          Pfn;
> +        PHYSICAL_ADDRESS    Address;
> +
> +        Mdl = __AllocatePage();
> +
> +        status = STATUS_NO_MEMORY;
> +        if (Mdl == NULL)
> +            goto fail1;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +        Pfn = MmGetMdlPfnArray(Mdl)[0];
> +
> +        status = EventChannelInitControl(Pfn, vcpu_id);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +
> +        Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
> +
> +        LogPrintf(LOG_LEVEL_INFO,
> +                  "EVTCHN_FIFO: CONTROLBLOCK[%u] @ %08x.%08x\n",
> +                  vcpu_id,
> +                  Address.HighPart,
> +                  Address.LowPart);
> +
> +        Context->ControlBlockMdl[vcpu_id] = Mdl;
> +        Cpu++;
> +    }
> +
> +    Trace("<====\n");
> +
> +done:
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    __FreePage(Mdl);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    (VOID) EventChannelReset();
> +
> +    while (--Cpu >= 0) {
> +        unsigned int    vcpu_id;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +
> +        Mdl = Context->ControlBlockMdl[vcpu_id];
> +        Context->ControlBlockMdl[vcpu_id] = NULL;
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    --Context->References;
> +    ASSERT3U(Context->References, ==, 0);
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +
> +    return status;
> +}
> +
> +VOID
> +EvtchnFifoRelease(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> +    KIRQL                           Irql;
> +    LONG                            Cpu;
> +
> +    KeAcquireSpinLock(&Context->Lock, &Irql);
> +
> +    if (--Context->References > 0)
> +        goto done;
> +
> +    Trace("====>\n");
> +
> +    EvtchnFifoReset(Context);
> +
> +    EvtchnFifoContract(Context);
> +
> +    Cpu = KeNumberProcessors;
> +    while (--Cpu >= 0) {
> +        unsigned int    vcpu_id;
> +        PMDL            Mdl;
> +
> +        vcpu_id = SystemVirtualCpuIndex(Cpu);
> +
> +        Mdl = Context->ControlBlockMdl[vcpu_id];
> +        Context->ControlBlockMdl[vcpu_id] = NULL;
> +
> +        __FreePage(Mdl);
> +    }
> +
> +    Trace("<====\n");
> +
> +done:
> +    KeReleaseSpinLock(&Context->Lock, Irql);
> +}
> +
> +static XENBUS_EVTCHN_ABI EvtchnAbiFifo = {
> +    NULL,
> +    EvtchnFifoAcquire,
> +    EvtchnFifoRelease,
> +    EvtchnFifoPoll,
> +    EvtchnFifoPortEnable,
> +    EvtchnFifoPortDisable,
> +    EvtchnFifoPortAck,
> +    EvtchnFifoPortMask,
> +    EvtchnFifoPortUnmask
> +};
> +
> +NTSTATUS
> +EvtchnFifoInitialize(
> +    IN  PXENBUS_FDO                     Fdo,
> +    OUT PXENBUS_EVTCHN_ABI_CONTEXT      *_Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT    Context;
> +    NTSTATUS                            status;
> +
> +    Trace("====>\n");
> +
> +    Context = __EvtchnFifoAllocate(sizeof
> (XENBUS_EVTCHN_FIFO_CONTEXT));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Context == NULL)
> +        goto fail1;
> +
> +    KeInitializeSpinLock(&Context->Lock);
> +
> +    Context->Fdo = Fdo;
> +
> +    *_Context = (PVOID)Context;
> +
> +    Trace("<====\n");
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +VOID
> +EvtchnFifoGetAbi(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context,
> +    OUT PXENBUS_EVTCHN_ABI              Abi)
> +{
> +    *Abi = EvtchnAbiFifo;
> +
> +    Abi->Context = (PVOID)_Context;
> +}
> +
> +VOID
> +EvtchnFifoTeardown(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT      _Context
> +    )
> +{
> +    PXENBUS_EVTCHN_FIFO_CONTEXT    Context = (PVOID)_Context;
> +
> +    Trace("====>\n");
> +
> +    Context->Fdo = NULL;
> +
> +    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
> +
> +    ASSERT(IsZeroMemory(Context, sizeof
> (XENBUS_EVTCHN_FIFO_CONTEXT)));
> +    __EvtchnFifoFree(Context);
> +
> +    Trace("<====\n");
> +}
> diff --git a/src/xenbus/evtchn_fifo.h b/src/xenbus/evtchn_fifo.h
> new file mode 100644
> index 0000000..bf96b19
> --- /dev/null
> +++ b/src/xenbus/evtchn_fifo.h
> @@ -0,0 +1,59 @@
> +/* 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 _XENBUS_EVTCHN_FIFO_H
> +#define _XENBUS_EVTCHN_FIFO_H
> +
> +#include <ntddk.h>
> +#include <xen.h>
> +
> +#include "evtchn_abi.h"
> +#include "fdo.h"
> +
> +extern NTSTATUS
> +EvtchnFifoInitialize(
> +    IN  PXENBUS_FDO                 Fdo,
> +    OUT PXENBUS_EVTCHN_ABI_CONTEXT  *Context
> +    );
> +
> +extern VOID
> +EvtchnFifoGetAbi(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context,
> +    OUT PXENBUS_EVTCHN_ABI          Abi
> +    );
> +
> +extern VOID
> +EvtchnFifoTeardown(
> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  Context
> +    );
> +
> +#endif  // _XENBUS_EVTCHN_FIFO_H
> +
> diff --git a/src/xenbus/store.c b/src/xenbus/store.c
> index 62ec60b..22c2a12 100644
> --- a/src/xenbus/store.c
> +++ b/src/xenbus/store.c
> @@ -1825,13 +1825,20 @@ StoreEnable(
>      IN PXENBUS_STORE_CONTEXT    Context
>      )
>  {
> -    ULONGLONG                   Port;
> +    ULONGLONG                   Value;
> +    ULONG                       Port;
>      BOOLEAN                     Pending;
>      NTSTATUS                    status;
> 
> -    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Port);
> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
>      ASSERT(NT_SUCCESS(status));
> 
> +    Port = (ULONG)Value;
> +
> +    LogPrintf(LOG_LEVEL_INFO,
> +              "STORE: EVTCHN %u\n",
> +              Port);
> +
>      Context->Channel = XENBUS_EVTCHN(Open,
>                                       &Context->EvtchnInterface,
>                                       XENBUS_EVTCHN_TYPE_FIXED,
> diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
> index 6cd12d1..3c184e0 100644
> --- a/vs2012/xenbus/xenbus.vcxproj
> +++ b/vs2012/xenbus/xenbus.vcxproj
> @@ -89,6 +89,7 @@
>  		<ClCompile Include="..\..\src\xenbus\driver.c" />
>  		<ClCompile Include="..\..\src\xenbus\evtchn.c" />
>  		<ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
> +		<ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
>  		<ClCompile Include="..\..\src\xenbus\fdo.c" />
>  		<ClCompile Include="..\..\src\xenbus\gnttab.c" />
>  		<ClCompile Include="..\..\src\xenbus\pdo.c" />
> diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
> index 0f37f68..ecb602b 100644
> --- a/vs2013/xenbus/xenbus.vcxproj
> +++ b/vs2013/xenbus/xenbus.vcxproj
> @@ -129,6 +129,7 @@
>      <ClCompile Include="..\..\src\xenbus\driver.c" />
>      <ClCompile Include="..\..\src\xenbus\evtchn.c" />
>      <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
> +    <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
>      <ClCompile Include="..\..\src\xenbus\fdo.c" />
>      <ClCompile Include="..\..\src\xenbus\gnttab.c" />
>      <ClCompile Include="..\..\src\xenbus\pdo.c" />
> --
> 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 Nov 07 14:19:40 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:19: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 1XmkO4-00067T-2B; Fri, 07 Nov 2014 14:19:40 +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 1XmkO2-00067M-CH
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:19:38 +0000
Received: from [193.109.254.147] by server-2.bemta-14.messagelabs.com id
	91/8C-02984-9F4DC545; Fri, 07 Nov 2014 14:19:37 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-27.messagelabs.com!1415369973!12042606!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16630 invoked from network); 7 Nov 2014 14:19:33 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:19:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26637410"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 1/4] Re-populate hypercall page on resume from
	suspend/hibernate
Thread-Index: AQHP+o9WzyEiWYuQq0ybrkk/X/DY3pxVNnJA
Date: Fri, 7 Nov 2014 14:19:33 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114844E@AMSPEX01CL01.citrite.net>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
	<1415367162-28444-2-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415367162-28444-2-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 1/4] Re-populate hypercall page on resume
 from suspend/hibernate
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

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBQYXVsIER1cnJhbnQgW21haWx0
bzpwYXVsLmR1cnJhbnRAY2l0cml4LmNvbV0NCj4gU2VudDogMDcgTm92ZW1iZXIgMjAxNCAxMzoz
Mw0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQo+IENjOiBQYXVsIER1
cnJhbnQNCj4gU3ViamVjdDogW1BBVENIIDEvNF0gUmUtcG9wdWxhdGUgaHlwZXJjYWxsIHBhZ2Ug
b24gcmVzdW1lIGZyb20NCj4gc3VzcGVuZC9oaWJlcm5hdGUNCj4gDQo+IERvaW5nIHRoaXMgaGFz
IHRoZSBzaWRlIGVmZmVjdCBvZiBsYXRjaGluZyB0aGUgc2hhcmVkIGluZm8gcGFnZSB3aWR0aCwN
Cj4gd2hpY2ggaXMgY3VycmVudGx5IGRvbmUgd2hlbiB0aGUgY2FsbGJhY2sgdmlhIGlzIHNldC4g
V2hlbiB3ZSBtb3ZlIHRvIGENCj4gcGVyLWNwdSBldmVudCBjaGFubmVsIHVwY2FsbCB0aGVuIHRo
aXMgc2lkZSBlZmZlY3Qgd2lsbCBiZSBsb3N0LCBzbw0KPiBkb2luZyB0aGlzIG1ha2VzIHN1cmUg
dGhhdCB0aGUgc2hhcmVkIGluZm8gaXMgc3RpbGwgb2YgdGhlIGNvcnJlY3Qgd2lkdGguDQo+IA0K
PiBBZGRpdGlvbmFsbHkgaW4gdGhpcyBwYXRjaCB0aGUgcmVwb3J0aW5nIG9mIHRoZSBYZW4gdmVy
c2lvbiBpcyBpbXByb3ZlZA0KPiBieSB1c2luZyB0aGUgWEVOVkVSIGh5cGVyY2FsbHMgdG8gZ2V0
IG1ham9yLCBtaW5vciBhbmQgZXh0cmEgdmVyc2lvbg0KPiBpbmZvcm1hdHRpb24uIEFzIHBhcnQg
b2YgdGhhdCBjaGFuZ2UsIG1vcmUgaGVhZGVycyBoYXZlIGJlZW4gY29waWVkIGluDQo+IGZyb20g
WGVuLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogUGF1bCBEdXJyYW50IDxwYXVsLmR1cnJhbnRAY2l0
cml4LmNvbT4NCg0KVGhpcyBwYXRjaCBpcyBtaXNzaW5nIGEgZmlsZSB0aGF0IEkgZm9yZ290IHRv
IGdpdCBhZGQuIEknbGwgcmUtcG9zdC4NCg0KICBQYXVsDQoNCj4gLS0tDQo+ICBnZXRfeGVuX2hl
YWRlcnMucHkgICAgIHwgICAyICsNCj4gIGluY2x1ZGUveGVuLmggICAgICAgICAgfCAgMjYgKysr
KysrKysrKysrDQo+ICBpbmNsdWRlL3hlbi9mZWF0dXJlcy5oIHwgMTEyDQo+ICsrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gIGluY2x1ZGUveGVuL3Zl
cnNpb24uaCAgfCAgOTYNCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrDQo+ICBzcmMveGVuL2RyaXZlci5jICAgICAgIHwgIDIwICsrKysrKysrKw0KPiAgc3JjL3hl
bi9oeXBlcmNhbGwuYyAgICB8ICA2NiArKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLQ0KPiAg
c3JjL3hlbmJ1cy9mZG8uYyAgICAgICB8ICAgMiArDQo+ICBzcmMveGVuYnVzL3N1c3BlbmQuYyAg
IHwgICAyICsNCj4gIHZzMjAxMi94ZW4veGVuLnZjeHByb2ogfCAgIDEgKw0KPiAgdnMyMDEzL3hl
bi94ZW4udmN4cHJvaiB8ICAgMyArLQ0KPiAgMTAgZmlsZXMgY2hhbmdlZCwgMjk5IGluc2VydGlv
bnMoKyksIDMxIGRlbGV0aW9ucygtKQ0KPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUveGVu
L2ZlYXR1cmVzLmgNCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi92ZXJzaW9uLmgN
Cj4gDQo+IGRpZmYgLS1naXQgYS9nZXRfeGVuX2hlYWRlcnMucHkgYi9nZXRfeGVuX2hlYWRlcnMu
cHkNCj4gaW5kZXggNWNhNWM5My4uZWYxYTJjOCAxMDA2NDQNCj4gLS0tIGEvZ2V0X3hlbl9oZWFk
ZXJzLnB5DQo+ICsrKyBiL2dldF94ZW5faGVhZGVycy5weQ0KPiBAQCAtNjEsNiArNjEsOCBAQCBp
ZiBfX25hbWVfXyA9PSAnX19tYWluX18nOg0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnc2NoZWQuaCcpDQo+ICAgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMn
LCAnLicsICdldmVudF9jaGFubmVsLmgnKQ0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZ3JhbnRfdGFibGUuaCcpDQo+ICsgICAgY29weV9maWxlKHdvcmtpbmcsICdw
dWJsaWMnLCAnLicsICd2ZXJzaW9uLmgnKQ0KPiArICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZmVhdHVyZXMuaCcpDQo+IA0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAn
eGVuJywgJy4nLCAnZXJybm8uaCcpDQo+IA0KPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBi
L2luY2x1ZGUveGVuLmgNCj4gaW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQNCj4gLS0tIGEv
aW5jbHVkZS94ZW4uaA0KPiArKysgYi9pbmNsdWRlL3hlbi5oDQo+IEBAIC00NCw2ICs0NCw3IEBA
DQo+ICAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+DQo+ICAjaW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMu
aD4NCj4gICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPg0KPiArI2luY2x1ZGUgPHhlbi92ZXJz
aW9uLmg+DQo+IA0KPiAgI2lmbmRlZiBYRU5fQVBJDQo+ICAjZGVmaW5lIFhFTl9BUEkgX19kZWNs
c3BlYyhkbGxpbXBvcnQpDQo+IEBAIC01Niw2ICs1NywxNCBAQCBYZW5Ub3VjaCgNCj4gICAgICBW
T0lEDQo+ICAgICAgKTsNCj4gDQo+ICsvLyBIWVBFUkNBTEwNCj4gKw0KPiArWEVOX0FQSQ0KPiAr
Vk9JRA0KPiArSHlwZXJjYWxsUG9wdWxhdGUoDQo+ICsgICAgVk9JRA0KPiArICAgICk7DQo+ICsN
Cj4gIC8vIEhWTQ0KPiANCj4gIF9fY2hlY2tSZXR1cm4NCj4gQEAgLTIzMyw2ICsyNDIsMjMgQEAg
U2NoZWRZaWVsZCgNCj4gICAgICBWT0lEDQo+ICAgICAgKTsNCj4gDQo+ICsvLyBYRU4gVkVSU0lP
Tg0KPiArDQo+ICtfX2NoZWNrUmV0dXJuDQo+ICtYRU5fQVBJDQo+ICtOVFNUQVRVUw0KPiArWGVu
VmVyc2lvbigNCj4gKyAgICBPVVQgUFVMT05HICBNYWpvciwNCj4gKyAgICBPVVQgUFVMT05HICBN
aW5vcg0KPiArICAgICk7DQo+ICsNCj4gK19fY2hlY2tSZXR1cm4NCj4gK1hFTl9BUEkNCj4gK05U
U1RBVFVTDQo+ICtYZW5WZXJzaW9uRXh0cmEoDQo+ICsgICAgT1VUIFBDSEFSICAgRXh0cmENCj4g
KyAgICApOw0KPiArDQo+ICAvLyBNT0RVTEUNCj4gDQo+ICBYRU5fQVBJDQo+IGRpZmYgLS1naXQg
YS9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaA0KPiBuZXcg
ZmlsZSBtb2RlIDEwMDY0NA0KPiBpbmRleCAwMDAwMDAwLi5iN2JmODNmDQo+IC0tLSAvZGV2L251
bGwNCj4gKysrIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaA0KPiBAQCAtMCwwICsxLDExMiBAQA0K
PiArLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKg0KPiAqKioqKioqKioqKioqKioqKioqKioNCj4gKyAqIGZlYXR1cmVzLmgNCj4gKyAqDQo+
ICsgKiBGZWF0dXJlIGZsYWdzLCByZXBvcnRlZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLg0KPiAr
ICoNCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0
byBhbnkgcGVyc29uIG9idGFpbmluZyBhDQo+IGNvcHkNCj4gKyAqIG9mIHRoaXMgc29mdHdhcmUg
YW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0bw0K
PiArICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5n
IHdpdGhvdXQgbGltaXRhdGlvbiB0aGUNCj4gKyAqIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlm
eSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vcg0KPiArICog
c2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hv
bSB0aGUgU29mdHdhcmUNCj4gaXMNCj4gKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0
byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQo+ICsgKg0KPiArICogVGhlIGFib3ZlIGNvcHly
aWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQg
aW4NCj4gKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLg0KPiArICoNCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRI
T1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELA0KPiBFWFBSRVNTIE9SDQo+ICsgKiBJTVBMSUVELCBJ
TkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GDQo+IE1FUkNIQU5U
QUJJTElUWSwNCj4gKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05J
TkZSSU5HRU1FTlQuIElOIE5PDQo+IEVWRU5UIFNIQUxMIFRIRQ0KPiArICogQVVUSE9SUyBPUiBD
T1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUw0KPiBPUiBP
VEhFUg0KPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwg
VE9SVCBPUiBPVEhFUldJU0UsDQo+IEFSSVNJTkcNCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBD
T05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1INCj4gT1RIRVINCj4gKyAq
IERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4NCj4gKyAqDQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIw
MDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+DQo+ICsgKi8NCj4gKw0KPiArI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fDQo+ICsjZGVmaW5lIF9fWEVOX1BVQkxJQ19G
RUFUVVJFU19IX18NCj4gKw0KPiArLyoNCj4gKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19m
ZWF0dXJlcyBYRU5fRUxGTk9URV9GRUFUVVJFUw0KPiArICoNCj4gKyAqIFRoZSBsaXN0IG9mIGFs
bCB0aGUgZmVhdHVyZXMgdGhlIGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkNCj4gKyAq
IHBhcnNpbmcgdGhlIFhFTl9FTEZOT1RFX0ZFQVRVUkVTIGFuZA0KPiBYRU5fRUxGTk9URV9TVVBQ
T1JURURfRkVBVFVSRVMNCj4gKyAqIHN0cmluZy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUg
bmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91dCB0aGUNCj4gKyAqICJYRU5GRUFUXyIgcHJlZml4
KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMuDQo+ICsgKiBJZiBhIGZlYXR1cmUgaXMgcmVx
dWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24gdGhlbiB0aGUgZmVhdHVyZSBuYW1lDQo+
ICsgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJhY3Rlci4NCj4gKyAqDQo+ICsgKiBO
b3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVTIGlzIHVzZWQsIHRoZW4g
aW4gdGhlDQo+ICsgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhlIGd1ZXN0IGlzIHRv
IGJlIGJvb3RlZCBhcyBkb20wLA0KPiArICovDQo+ICsNCj4gKy8qDQo+ICsgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4NCj4gKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLg0KPiArICovDQo+ICsj
ZGVmaW5lIFhFTkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMA0KPiArDQo+ICsvKg0K
PiArICogSWYgc2V0LCB0aGUgZ3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0
cyBzZWdtZW50IGRlc2NyaXB0b3INCj4gKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2
aWEgZGlyZWN0IHdyaXRlcy4NCj4gKyAqLw0KPiArI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rl
c2NyaXB0b3JfdGFibGVzIDENCj4gKw0KPiArLyoNCj4gKyAqIElmIHNldCwgdHJhbnNsYXRpb24g
YmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2FsJyBhZGRyZXNzIHNwYWNlDQo+ICsg
KiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2UgYXJlIGhhbmRsZWQgYnkgdGhl
IGh5cGVydmlzb3IuIEluDQo+IHRoaXMNCj4gKyAqIG1vZGUgdGhlIGd1ZXN0IGRvZXMgbm90IG5l
ZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZQ0KPiB0cmFuc2xhdGlvbnMNCj4gKyAq
IHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuDQo+ICsgKi8NCj4gKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyDQo+ICsNCj4gKy8qIElmIHNl
dCwgdGhlIGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmlu
ZyAwKS4gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAz
DQo+ICsNCj4gKy8qDQo+ICsgKiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFs
bG9jYXRlIHg4NiBQQUUgcGFnZSBkaXJlY3Rvcmllcw0KPiArICogYmVsb3cgNEdCLiBUaGlzIGZs
YWcgaXMgdXN1YWxseSBpbXBsaWVkIGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLg0KPiArICov
DQo+ICsjZGVmaW5lIFhFTkZFQVRfcGFlX3BnZGlyX2Fib3ZlXzRnYiAgICAgICAgNA0KPiArDQo+
ICsvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBwb3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BS
RVNFUlZFX0FEDQo+IGh5cGVyY2FsbD8gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9tbXVfcHRfdXBk
YXRlX3ByZXNlcnZlX2FkICA1DQo+ICsNCj4gKy8qIHg4NjogRG9lcyB0aGlzIFhlbiBob3N0IHN1
cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRQ0KPiBoeXBlcmNhbGw/ICovDQo+ICsjZGVm
aW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNg0KPiArDQo+ICsvKg0KPiAr
ICogSWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFj
ZWQgaW50byBndWVzdA0KPiBrZXJuZWwNCj4gKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4NCj4gKyAq
Lw0KPiArI2RlZmluZSBYRU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcNCj4gKw0K
PiArLyogeDg2OiBEb2VzIHRoaXMgWGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZl
Y3RvciB0eXBlPyAqLw0KPiArI2RlZmluZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAg
ICAgIDgNCj4gKw0KPiArLyogeDg2OiBwdmNsb2NrIGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBv
biBIVk0gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9odm1fc2FmZV9wdmNsb2NrICAgICAgICAgICA5
DQo+ICsNCj4gKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBIVk0gZ3Vlc3RzICovDQo+ICsj
ZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAxMA0KPiArDQo+ICsvKiBv
cGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9kb20w
ICAgICAgICAgICAgICAgICAgICAgIDExDQo+ICsNCj4gKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBf
aWRlbnRpdHkgICAgICAgIDEyDQo+ICsNCj4gKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEN
Cj4gKw0KPiArI2VuZGlmIC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8NCj4gKw0KPiAr
LyoNCj4gKyAqIExvY2FsIHZhcmlhYmxlczoNCj4gKyAqIG1vZGU6IEMNCj4gKyAqIGMtZmlsZS1z
dHlsZTogIkJTRCINCj4gKyAqIGMtYmFzaWMtb2Zmc2V0OiA0DQo+ICsgKiB0YWItd2lkdGg6IDQN
Cj4gKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbA0KPiArICogRW5kOg0KPiArICovDQo+IGRpZmYg
LS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJzaW9uLmgNCj4g
bmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gaW5kZXggMDAwMDAwMC4uNDRmMjZiMA0KPiAtLS0gL2Rl
di9udWxsDQo+ICsrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaA0KPiBAQCAtMCwwICsxLDk2IEBA
DQo+ICsvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqDQo+ICoqKioqKioqKioqKioqKioqKioqKg0KPiArICogdmVyc2lvbi5oDQo+ICsgKg0K
PiArICogWGVuIHZlcnNpb24sIHR5cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLg0KPiArICoN
Cj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBh
bnkgcGVyc29uIG9idGFpbmluZyBhDQo+IGNvcHkNCj4gKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5k
IGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0bw0KPiAr
ICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdp
dGhvdXQgbGltaXRhdGlvbiB0aGUNCj4gKyAqIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwg
bWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vcg0KPiArICogc2Vs
bCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0
aGUgU29mdHdhcmUNCj4gaXMNCj4gKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0
aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQo+ICsgKg0KPiArICogVGhlIGFib3ZlIGNvcHlyaWdo
dCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4N
Cj4gKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJl
Lg0KPiArICoNCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VU
IFdBUlJBTlRZIE9GIEFOWSBLSU5ELA0KPiBFWFBSRVNTIE9SDQo+ICsgKiBJTVBMSUVELCBJTkNM
VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GDQo+IE1FUkNIQU5UQUJJ
TElUWSwNCj4gKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZS
SU5HRU1FTlQuIElOIE5PDQo+IEVWRU5UIFNIQUxMIFRIRQ0KPiArICogQVVUSE9SUyBPUiBDT1BZ
UklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUw0KPiBPUiBPVEhF
Ug0KPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9S
VCBPUiBPVEhFUldJU0UsDQo+IEFSSVNJTkcNCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05O
RUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1INCj4gT1RIRVINCj4gKyAqIERF
QUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4NCj4gKyAqDQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMDUs
IE5ndXllbiBBbmggUXV5bmggPGFxdXluaEBnbWFpbC5jb20+DQo+ICsgKiBDb3B5cmlnaHQgKGMp
IDIwMDUsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+DQo+ICsgKi8NCj4gKw0KPiAr
I2lmbmRlZiBfX1hFTl9QVUJMSUNfVkVSU0lPTl9IX18NCj4gKyNkZWZpbmUgX19YRU5fUFVCTElD
X1ZFUlNJT05fSF9fDQo+ICsNCj4gKyNpbmNsdWRlICJ4ZW4uaCINCj4gKw0KPiArLyogTkIuIEFs
bCBvcHMgcmV0dXJuIHplcm8gb24gc3VjY2VzcywgZXhjZXB0IFhFTlZFUl97dmVyc2lvbixwYWdl
c2l6ZX0gKi8NCj4gKw0KPiArLyogYXJnID09IE5VTEw7IHJldHVybnMgbWFqb3I6bWlub3IgKDE2
OjE2KS4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX3ZlcnNpb24gICAgICAwDQo+ICsNCj4gKy8qIGFy
ZyA9PSB4ZW5fZXh0cmF2ZXJzaW9uX3QuICovDQo+ICsjZGVmaW5lIFhFTlZFUl9leHRyYXZlcnNp
b24gMQ0KPiArdHlwZWRlZiBjaGFyIHhlbl9leHRyYXZlcnNpb25fdFsxNl07DQo+ICsjZGVmaW5l
IFhFTl9FWFRSQVZFUlNJT05fTEVOIChzaXplb2YoeGVuX2V4dHJhdmVyc2lvbl90KSkNCj4gKw0K
PiArLyogYXJnID09IHhlbl9jb21waWxlX2luZm9fdC4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX2Nv
bXBpbGVfaW5mbyAyDQo+ICtzdHJ1Y3QgeGVuX2NvbXBpbGVfaW5mbyB7DQo+ICsgICAgY2hhciBj
b21waWxlcls2NF07DQo+ICsgICAgY2hhciBjb21waWxlX2J5WzE2XTsNCj4gKyAgICBjaGFyIGNv
bXBpbGVfZG9tYWluWzMyXTsNCj4gKyAgICBjaGFyIGNvbXBpbGVfZGF0ZVszMl07DQo+ICt9Ow0K
PiArdHlwZWRlZiBzdHJ1Y3QgeGVuX2NvbXBpbGVfaW5mbyB4ZW5fY29tcGlsZV9pbmZvX3Q7DQo+
ICsNCj4gKyNkZWZpbmUgWEVOVkVSX2NhcGFiaWxpdGllcyAzDQo+ICt0eXBlZGVmIGNoYXIgeGVu
X2NhcGFiaWxpdGllc19pbmZvX3RbMTAyNF07DQo+ICsjZGVmaW5lIFhFTl9DQVBBQklMSVRJRVNf
SU5GT19MRU4gKHNpemVvZih4ZW5fY2FwYWJpbGl0aWVzX2luZm9fdCkpDQo+ICsNCj4gKyNkZWZp
bmUgWEVOVkVSX2NoYW5nZXNldCA0DQo+ICt0eXBlZGVmIGNoYXIgeGVuX2NoYW5nZXNldF9pbmZv
X3RbNjRdOw0KPiArI2RlZmluZSBYRU5fQ0hBTkdFU0VUX0lORk9fTEVOIChzaXplb2YoeGVuX2No
YW5nZXNldF9pbmZvX3QpKQ0KPiArDQo+ICsjZGVmaW5lIFhFTlZFUl9wbGF0Zm9ybV9wYXJhbWV0
ZXJzIDUNCj4gK3N0cnVjdCB4ZW5fcGxhdGZvcm1fcGFyYW1ldGVycyB7DQo+ICsgICAgeGVuX3Vs
b25nX3QgdmlydF9zdGFydDsNCj4gK307DQo+ICt0eXBlZGVmIHN0cnVjdCB4ZW5fcGxhdGZvcm1f
cGFyYW1ldGVycyB4ZW5fcGxhdGZvcm1fcGFyYW1ldGVyc190Ow0KPiArDQo+ICsjZGVmaW5lIFhF
TlZFUl9nZXRfZmVhdHVyZXMgNg0KPiArc3RydWN0IHhlbl9mZWF0dXJlX2luZm8gew0KPiArICAg
IHVuc2lnbmVkIGludCBzdWJtYXBfaWR4OyAgICAvKiBJTjogd2hpY2ggMzItYml0IHN1Ym1hcCB0
byByZXR1cm4gKi8NCj4gKyAgICB1aW50MzJfdCAgICAgc3VibWFwOyAgICAgICAgLyogT1VUOiAz
Mi1iaXQgc3VibWFwICovDQo+ICt9Ow0KPiArdHlwZWRlZiBzdHJ1Y3QgeGVuX2ZlYXR1cmVfaW5m
byB4ZW5fZmVhdHVyZV9pbmZvX3Q7DQo+ICsNCj4gKy8qIERlY2xhcmVzIHRoZSBmZWF0dXJlcyBy
ZXBvcnRlZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLiAqLw0KPiArI2luY2x1ZGUgImZlYXR1cmVz
LmgiDQo+ICsNCj4gKy8qIGFyZyA9PSBOVUxMOyByZXR1cm5zIGhvc3QgbWVtb3J5IHBhZ2Ugc2l6
ZS4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX3BhZ2VzaXplIDcNCj4gKw0KPiArLyogYXJnID09IHhl
bl9kb21haW5faGFuZGxlX3QuICovDQo+ICsjZGVmaW5lIFhFTlZFUl9ndWVzdF9oYW5kbGUgOA0K
PiArDQo+ICsjZGVmaW5lIFhFTlZFUl9jb21tYW5kbGluZSA5DQo+ICt0eXBlZGVmIGNoYXIgeGVu
X2NvbW1hbmRsaW5lX3RbMTAyNF07DQo+ICsNCj4gKyNlbmRpZiAvKiBfX1hFTl9QVUJMSUNfVkVS
U0lPTl9IX18gKi8NCj4gKw0KPiArLyoNCj4gKyAqIExvY2FsIHZhcmlhYmxlczoNCj4gKyAqIG1v
ZGU6IEMNCj4gKyAqIGMtZmlsZS1zdHlsZTogIkJTRCINCj4gKyAqIGMtYmFzaWMtb2Zmc2V0OiA0
DQo+ICsgKiB0YWItd2lkdGg6IDQNCj4gKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbA0KPiArICog
RW5kOg0KPiArICovDQo+IGRpZmYgLS1naXQgYS9zcmMveGVuL2RyaXZlci5jIGIvc3JjL3hlbi9k
cml2ZXIuYw0KPiBpbmRleCBiYTU0MWI0Li5mY2U3NWFhIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVu
L2RyaXZlci5jDQo+ICsrKyBiL3NyYy94ZW4vZHJpdmVyLmMNCj4gQEAgLTU5LDYgKzU5LDI2IEBA
IFhlblRvdWNoKA0KPiAgICAgIFZPSUQNCj4gICAgICApDQo+ICB7DQo+ICsgICAgc3RhdGljIFVM
T05HICAgIFJlZmVyZW5jZTsNCj4gKyAgICBVTE9ORyAgICAgICAgICAgTWFqb3I7DQo+ICsgICAg
VUxPTkcgICAgICAgICAgIE1pbm9yOw0KPiArICAgIENIQVIgICAgICAgICAgICBFeHRyYVtYRU5f
RVhUUkFWRVJTSU9OX0xFTl07DQo+ICsgICAgTlRTVEFUVVMgICAgICAgIHN0YXR1czsNCj4gKw0K
PiArICAgIGlmIChSZWZlcmVuY2UrKyAhPSAwKQ0KPiArICAgICAgICByZXR1cm47DQo+ICsNCj4g
KyAgICBzdGF0dXMgPSBYZW5WZXJzaW9uKCZNYWpvciwgJk1pbm9yKTsNCj4gKyAgICBBU1NFUlQo
TlRfU1VDQ0VTUyhzdGF0dXMpKTsNCj4gKw0KPiArICAgIHN0YXR1cyA9IFhlblZlcnNpb25FeHRy
YShFeHRyYSk7DQo+ICsgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7DQo+ICsNCj4gKyAg
ICBMb2dQcmludGYoTE9HX0xFVkVMX0lORk8sDQo+ICsgICAgICAgICAgICAgICJYRU46ICV1LiV1
JXNcbiIsDQo+ICsgICAgICAgICAgICAgIE1ham9yLA0KPiArICAgICAgICAgICAgICBNaW5vciwN
Cj4gKyAgICAgICAgICAgICAgRXh0cmEpOw0KPiAgfQ0KPiANCj4gIHN0YXRpYyBWT0lEDQo+IGRp
ZmYgLS1naXQgYS9zcmMveGVuL2h5cGVyY2FsbC5jIGIvc3JjL3hlbi9oeXBlcmNhbGwuYw0KPiBp
bmRleCAwN2ViNDFhLi43MTdiOGMyIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuL2h5cGVyY2FsbC5j
DQo+ICsrKyBiL3NyYy94ZW4vaHlwZXJjYWxsLmMNCj4gQEAgLTI5LDYgKzI5LDkgQEANCj4gICAq
IFNVQ0ggREFNQUdFLg0KPiAgICovDQo+IA0KPiArI3VuZGVmICBYRU5fQVBJDQo+ICsjZGVmaW5l
IFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpDQo+ICsNCj4gICNpbmNsdWRlIDxudGRkay5o
Pg0KPiAgI2luY2x1ZGUgPHhlbi5oPg0KPiAgI2luY2x1ZGUgPHV0aWwuaD4NCj4gQEAgLTM3LDI0
ICs0MCw0MSBAQA0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUgImFzc2Vy
dC5oIg0KPiANCj4gLSNkZWZpbmUgTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UIDINCj4gKyNk
ZWZpbmUgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVCAyDQo+IA0KPiAgI3ByYWdtYSBjb2Rl
X3NlZygiaHlwZXJjYWxsIikNCj4gIF9fZGVjbHNwZWMoYWxsb2NhdGUoImh5cGVyY2FsbCIpKQ0K
PiAtc3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BGTl9D
T1VOVCArIDEpICoNCj4gUEFHRV9TSVpFXTsNCj4gK3N0YXRpYyBVQ0hBUiAgICAgICAgX19TZWN0
aW9uWyhNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UICsgMSkgKg0KPiBQQUdFX1NJWkVdOw0K
PiANCj4gIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYgPSAweDQwMDAwMDAwOw0KPiAN
Cj4gLXN0YXRpYyBVU0hPUlQgICAgICAgWGVuTWFqb3JWZXJzaW9uOw0KPiAtc3RhdGljIFVTSE9S
VCAgICAgICBYZW5NaW5vclZlcnNpb247DQo+IC0NCj4gLXN0YXRpYyBQRk5fTlVNQkVSICAgSHlw
ZXJjYWxsUGZuW01BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVF07DQo+IC1zdGF0aWMgVUxPTkcg
ICAgICAgIEh5cGVyY2FsbFBmbkNvdW50Ow0KPiArc3RhdGljIFBIWVNJQ0FMX0FERFJFU1MNCj4g
SHlwZXJjYWxsUGFnZVtNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UXTsNCj4gK3N0YXRpYyBV
TE9ORyAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VDb3VudDsNCj4gDQo+ICB0eXBlZGVmIFVDSEFS
ICAgICAgICAgICBIWVBFUkNBTExfR0FURVszMl07DQo+ICB0eXBlZGVmIEhZUEVSQ0FMTF9HQVRF
ICAqUEhZUEVSQ0FMTF9HQVRFOw0KPiANCj4gIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxs
Ow0KPiArVUxPTkcgICAgICAgICAgICAgICBIeXBlcmNhbGxNc3I7DQo+ICsNCj4gK1hFTl9BUEkN
Cj4gK1ZPSUQNCj4gK0h5cGVyY2FsbFBvcHVsYXRlKA0KPiArICAgIFZPSUQNCj4gKyAgICApDQo+
ICt7DQo+ICsgICAgVUxPTkcgICAgICAgSW5kZXg7DQo+ICsNCj4gKyAgICBmb3IgKEluZGV4ID0g
MDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsNCj4gKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLA0KPiArICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJD
QUxMIFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsDQo+ICsgICAgICAgICAgICAgICAgICBJbmRleCwN
Cj4gKyAgICAgICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LA0KPiAr
ICAgICAgICAgICAgICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7DQo+ICsNCj4g
KyAgICAgICAgX193cml0ZW1zcihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1
YWRQYXJ0KTsNCj4gKyAgICB9DQo+ICt9DQo+IA0KPiAgTlRTVEFUVVMNCj4gIEh5cGVyY2FsbElu
aXRpYWxpemUoDQo+IEBAIC02Niw3ICs4Niw2IEBAIEh5cGVyY2FsbEluaXRpYWxpemUoDQo+ICAg
ICAgVUxPTkcgICAgICAgRUNYID0gJ0RFQUQnOw0KPiAgICAgIFVMT05HICAgICAgIEVEWCA9ICdE
RUFEJzsNCj4gICAgICBVTE9ORyAgICAgICBJbmRleDsNCj4gLSAgICBVTE9ORyAgICAgICBIeXBl
cmNhbGxNc3I7DQo+ICAgICAgTlRTVEFUVVMgICAgc3RhdHVzOw0KPiANCj4gICAgICBzdGF0dXMg
PSBTVEFUVVNfVU5TVUNDRVNTRlVMOw0KPiBAQCAtODgsMTMgKzEwNyw2IEBAIEh5cGVyY2FsbElu
aXRpYWxpemUoDQo+ICAgICAgICAgICAgICBnb3RvIGZhaWwxOw0KPiAgICAgIH0NCj4gDQo+IC0g
ICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOw0KPiAt
ICAgIFhlbk1ham9yVmVyc2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7DQo+IC0gICAgWGVuTWlu
b3JWZXJzaW9uID0gKFVTSE9SVCkoRUFYICYgMHhGRkZGKTsNCj4gLQ0KPiAtICAgIEluZm8oIlhF
TiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJzaW9uLCBYZW5NaW5vclZlcnNpb24pOw0KPiAtICAgIElu
Zm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9fWEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOw0KPiAt
DQo+ICAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9uICYgKFBBR0VfU0laRSAtIDEpKQ0KPiAg
ICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdfUFRSKV9fU2VjdGlvbiArIFBBR0Vf
U0laRSAtIDEpICYNCj4gfihQQUdFX1NJWkUgLSAxKSk7DQo+ICAgICAgZWxzZQ0KPiBAQCAtMTAy
LDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgNCj4gDQo+ICAgICAgQVNTRVJUM1Uo
KChVTE9OR19QVFIpSHlwZXJjYWxsICYgKFBBR0VfU0laRSAtIDEpKSwgPT0sIDApOw0KPiANCj4g
LSAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7
IEluZGV4KyspIHsNCj4gLSAgICAgICAgUEhZU0lDQUxfQUREUkVTUyAgICBQaHlzaWNhbEFkZHJl
c3M7DQo+IC0NCj4gLSAgICAgICAgUGh5c2ljYWxBZGRyZXNzID0gTW1HZXRQaHlzaWNhbEFkZHJl
c3MoKFBVQ0hBUilIeXBlcmNhbGwgKyAoSW5kZXgNCj4gPDwgUEFHRV9TSElGVCkpOw0KPiAtICAg
ICAgICBIeXBlcmNhbGxQZm5bSW5kZXhdID0gKFBGTl9OVU1CRVIpKFBoeXNpY2FsQWRkcmVzcy5R
dWFkUGFydCA+Pg0KPiBQQUdFX1NISUZUKTsNCj4gLSAgICB9DQo+ICsgICAgZm9yIChJbmRleCA9
IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykNCj4gKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0gPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVDSEFS
KUh5cGVyY2FsbCArDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgKEluZGV4IDw8IFBBR0VfU0hJRlQpKTsNCj4gDQo+ICAgICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEwsIE5VTEwpOw0KPiAtICAgIEh5cGVyY2Fs
bFBmbkNvdW50ID0gRUFYOw0KPiAtICAgIEFTU0VSVChIeXBlcmNhbGxQZm5Db3VudCA8PSBNQVhJ
TVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOw0KPiArICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IEVB
WDsNCj4gKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElNVU1fSFlQRVJDQUxM
X1BBR0VfQ09VTlQpOw0KPiAgICAgIEh5cGVyY2FsbE1zciA9IEVCWDsNCj4gDQo+IC0gICAgZm9y
IChJbmRleCA9IDA7IEluZGV4IDwgSHlwZXJjYWxsUGZuQ291bnQ7IEluZGV4KyspIHsNCj4gLSAg
ICAgICAgSW5mbygiSHlwZXJjYWxsUGZuWyVkXTogJXBcbiIsIEluZGV4LCAoUFZPSUQpSHlwZXJj
YWxsUGZuW0luZGV4XSk7DQo+IC0gICAgICAgIF9fd3JpdGVtc3IoSHlwZXJjYWxsTXNyLCAoVUxP
Tkc2NClIeXBlcmNhbGxQZm5bSW5kZXhdIDw8DQo+IFBBR0VfU0hJRlQpOw0KPiAtICAgIH0NCj4g
KyAgICBIeXBlcmNhbGxQb3B1bGF0ZSgpOw0KPiANCj4gICAgICByZXR1cm4gU1RBVFVTX1NVQ0NF
U1M7DQo+IA0KPiBAQCAtMTc3LDggKzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKA0KPiANCj4g
ICAgICBIeXBlcmNhbGwgPSBOVUxMOw0KPiANCj4gLSAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXgg
PCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IEluZGV4KyspDQo+IC0gICAgICAgIEh5cGVy
Y2FsbFBmbltJbmRleF0gPSAwOw0KPiArICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQ7IEluZGV4KyspDQo+ICsgICAgICAgIEh5cGVyY2FsbFBh
Z2VbSW5kZXhdLlF1YWRQYXJ0ID0gMDsNCj4gDQo+IC0gICAgSHlwZXJjYWxsUGZuQ291bnQgPSAw
Ow0KPiArICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7DQo+ICB9DQo+IGRpZmYgLS1naXQgYS9z
cmMveGVuYnVzL2Zkby5jIGIvc3JjL3hlbmJ1cy9mZG8uYw0KPiBpbmRleCA1OTQ0MmJkLi4yMTVj
OTk3IDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuYnVzL2Zkby5jDQo+ICsrKyBiL3NyYy94ZW5idXMv
ZmRvLmMNCj4gQEAgLTIxODYsNiArMjE4Niw4IEBAIEZkb1M0VG9TMygNCj4gDQo+ICAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsNCj4gDQo+ICsgICAgSHlwZXJjYWxsUG9w
dWxhdGUoKTsNCj4gKw0KPiAgICAgIGlmIChGZG8tPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2Uu
Q29udGV4dCAhPSBOVUxMKQ0KPiAgICAgICAgICBYRU5GSUxUX1VOUExVRyhSZXBsYXksICZGZG8t
PlVucGx1Z0ludGVyZmFjZSk7DQo+IA0KPiBkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9zdXNwZW5k
LmMgYi9zcmMveGVuYnVzL3N1c3BlbmQuYw0KPiBpbmRleCA2YWIyYmQyLi5kZTcwZTQyIDEwMDY0
NA0KPiAtLS0gYS9zcmMveGVuYnVzL3N1c3BlbmQuYw0KPiArKysgYi9zcmMveGVuYnVzL3N1c3Bl
bmQuYw0KPiBAQCAtMTczLDYgKzE3Myw4IEBAIFN1c3BlbmRUcmlnZ2VyKA0KPiANCj4gICAgICAg
ICAgQ29udGV4dC0+Q291bnQrKzsNCj4gDQo+ICsgICAgICAgIEh5cGVyY2FsbFBvcHVsYXRlKCk7
DQo+ICsNCj4gICAgICAgICAgaWYgKENvbnRleHQtPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2Uu
Q29udGV4dCAhPSBOVUxMKQ0KPiAgICAgICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAm
Q29udGV4dC0+VW5wbHVnSW50ZXJmYWNlKTsNCj4gDQo+IGRpZmYgLS1naXQgYS92czIwMTIveGVu
L3hlbi52Y3hwcm9qIGIvdnMyMDEyL3hlbi94ZW4udmN4cHJvag0KPiBpbmRleCBlYjU0NjkyLi4y
ZjRkOTU4IDEwMDY0NA0KPiAtLS0gYS92czIwMTIveGVuL3hlbi52Y3hwcm9qDQo+ICsrKyBiL3Zz
MjAxMi94ZW4veGVuLnZjeHByb2oNCj4gQEAgLTg4LDYgKzg4LDcgQEANCj4gIAkJPENsQ29tcGls
ZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIgLz4NCj4gIAkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGdyYW50X3RhYmxlLmMiIC8+DQo+ICAJCTxDbENv
bXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxodm0uYyIgLz4NCj4gKwkJPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+DQo+ICAJCTxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxoeXBlcmNhbGwuYyIgLz4NCj4gIAkJPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuXG1lbW9yeS5jIiAvPg0KPiAgCQk8Q2xDb21waWxlIEluY2x1
ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4NCj4gZGlmZiAtLWdpdCBhL3ZzMjAxMy94ZW4v
eGVuLnZjeHByb2ogYi92czIwMTMveGVuL3hlbi52Y3hwcm9qDQo+IGluZGV4IDQ5MDI5NGMuLjgx
ZDUwZWEgMTAwNjQ0DQo+IC0tLSBhL3ZzMjAxMy94ZW4veGVuLnZjeHByb2oNCj4gKysrIGIvdnMy
MDEzL3hlbi94ZW4udmN4cHJvag0KPiBAQCAtMSw0ICsxLDQgQEANCj4gLe+7vzw/eG1sIHZlcnNp
b249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+ICs8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29k
aW5nPSJ1dGYtOCI/Pg0KPiAgPFByb2plY3QgRGVmYXVsdFRhcmdldHM9IkJ1aWxkIiBUb29sc1Zl
cnNpb249IjEyLjAiDQo+IHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2RldmVs
b3Blci9tc2J1aWxkLzIwMDMiPg0KPiAgICA8SW1wb3J0IFByb2plY3Q9Ii4uXGNvbmZpZ3MucHJv
cHMiIC8+DQo+ICAgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJHbG9iYWxzIj4NCj4gQEAgLTEyOCw2
ICsxMjgsNyBAQA0KPiAgICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxldmVu
dF9jaGFubmVsLmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVu
XGdyYW50X3RhYmxlLmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNc
eGVuXGh2bS5jIiAvPg0KPiArICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblx4
ZW5fdmVyc2lvbi5jIiAvPg0KPiAgICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhl
blxoeXBlcmNhbGwuYyIgLz4NCj4gICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4
ZW5cbWVtb3J5LmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVu
XHNjaGVkLmMiIC8+DQo+IC0tDQo+IDIuMS4xDQoNCl9fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fCndpbi1wdi1kZXZlbCBtYWlsaW5nIGxpc3QKd2luLXB2LWRl
dmVsQGxpc3RzLnhlbnByb2plY3Qub3JnCmh0dHA6Ly9saXN0cy54ZW5wcm9qZWN0Lm9yZy9jZ2kt
YmluL21haWxtYW4vbGlzdGluZm8vd2luLXB2LWRldmVs

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 14:19:40 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:19: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 1XmkO4-00067T-2B; Fri, 07 Nov 2014 14:19:40 +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 1XmkO2-00067M-CH
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:19:38 +0000
Received: from [193.109.254.147] by server-2.bemta-14.messagelabs.com id
	91/8C-02984-9F4DC545; Fri, 07 Nov 2014 14:19:37 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-7.tower-27.messagelabs.com!1415369973!12042606!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16630 invoked from network); 7 Nov 2014 14:19:33 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:19:33 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26637410"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 1/4] Re-populate hypercall page on resume from
	suspend/hibernate
Thread-Index: AQHP+o9WzyEiWYuQq0ybrkk/X/DY3pxVNnJA
Date: Fri, 7 Nov 2014 14:19:33 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114844E@AMSPEX01CL01.citrite.net>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
	<1415367162-28444-2-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415367162-28444-2-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 1/4] Re-populate hypercall page on resume
 from suspend/hibernate
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

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBQYXVsIER1cnJhbnQgW21haWx0
bzpwYXVsLmR1cnJhbnRAY2l0cml4LmNvbV0NCj4gU2VudDogMDcgTm92ZW1iZXIgMjAxNCAxMzoz
Mw0KPiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQo+IENjOiBQYXVsIER1
cnJhbnQNCj4gU3ViamVjdDogW1BBVENIIDEvNF0gUmUtcG9wdWxhdGUgaHlwZXJjYWxsIHBhZ2Ug
b24gcmVzdW1lIGZyb20NCj4gc3VzcGVuZC9oaWJlcm5hdGUNCj4gDQo+IERvaW5nIHRoaXMgaGFz
IHRoZSBzaWRlIGVmZmVjdCBvZiBsYXRjaGluZyB0aGUgc2hhcmVkIGluZm8gcGFnZSB3aWR0aCwN
Cj4gd2hpY2ggaXMgY3VycmVudGx5IGRvbmUgd2hlbiB0aGUgY2FsbGJhY2sgdmlhIGlzIHNldC4g
V2hlbiB3ZSBtb3ZlIHRvIGENCj4gcGVyLWNwdSBldmVudCBjaGFubmVsIHVwY2FsbCB0aGVuIHRo
aXMgc2lkZSBlZmZlY3Qgd2lsbCBiZSBsb3N0LCBzbw0KPiBkb2luZyB0aGlzIG1ha2VzIHN1cmUg
dGhhdCB0aGUgc2hhcmVkIGluZm8gaXMgc3RpbGwgb2YgdGhlIGNvcnJlY3Qgd2lkdGguDQo+IA0K
PiBBZGRpdGlvbmFsbHkgaW4gdGhpcyBwYXRjaCB0aGUgcmVwb3J0aW5nIG9mIHRoZSBYZW4gdmVy
c2lvbiBpcyBpbXByb3ZlZA0KPiBieSB1c2luZyB0aGUgWEVOVkVSIGh5cGVyY2FsbHMgdG8gZ2V0
IG1ham9yLCBtaW5vciBhbmQgZXh0cmEgdmVyc2lvbg0KPiBpbmZvcm1hdHRpb24uIEFzIHBhcnQg
b2YgdGhhdCBjaGFuZ2UsIG1vcmUgaGVhZGVycyBoYXZlIGJlZW4gY29waWVkIGluDQo+IGZyb20g
WGVuLg0KPiANCj4gU2lnbmVkLW9mZi1ieTogUGF1bCBEdXJyYW50IDxwYXVsLmR1cnJhbnRAY2l0
cml4LmNvbT4NCg0KVGhpcyBwYXRjaCBpcyBtaXNzaW5nIGEgZmlsZSB0aGF0IEkgZm9yZ290IHRv
IGdpdCBhZGQuIEknbGwgcmUtcG9zdC4NCg0KICBQYXVsDQoNCj4gLS0tDQo+ICBnZXRfeGVuX2hl
YWRlcnMucHkgICAgIHwgICAyICsNCj4gIGluY2x1ZGUveGVuLmggICAgICAgICAgfCAgMjYgKysr
KysrKysrKysrDQo+ICBpbmNsdWRlL3hlbi9mZWF0dXJlcy5oIHwgMTEyDQo+ICsrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gIGluY2x1ZGUveGVuL3Zl
cnNpb24uaCAgfCAgOTYNCj4gKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrDQo+ICBzcmMveGVuL2RyaXZlci5jICAgICAgIHwgIDIwICsrKysrKysrKw0KPiAgc3JjL3hl
bi9oeXBlcmNhbGwuYyAgICB8ICA2NiArKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLQ0KPiAg
c3JjL3hlbmJ1cy9mZG8uYyAgICAgICB8ICAgMiArDQo+ICBzcmMveGVuYnVzL3N1c3BlbmQuYyAg
IHwgICAyICsNCj4gIHZzMjAxMi94ZW4veGVuLnZjeHByb2ogfCAgIDEgKw0KPiAgdnMyMDEzL3hl
bi94ZW4udmN4cHJvaiB8ICAgMyArLQ0KPiAgMTAgZmlsZXMgY2hhbmdlZCwgMjk5IGluc2VydGlv
bnMoKyksIDMxIGRlbGV0aW9ucygtKQ0KPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUveGVu
L2ZlYXR1cmVzLmgNCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi92ZXJzaW9uLmgN
Cj4gDQo+IGRpZmYgLS1naXQgYS9nZXRfeGVuX2hlYWRlcnMucHkgYi9nZXRfeGVuX2hlYWRlcnMu
cHkNCj4gaW5kZXggNWNhNWM5My4uZWYxYTJjOCAxMDA2NDQNCj4gLS0tIGEvZ2V0X3hlbl9oZWFk
ZXJzLnB5DQo+ICsrKyBiL2dldF94ZW5faGVhZGVycy5weQ0KPiBAQCAtNjEsNiArNjEsOCBAQCBp
ZiBfX25hbWVfXyA9PSAnX19tYWluX18nOg0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnc2NoZWQuaCcpDQo+ICAgICAgY29weV9maWxlKHdvcmtpbmcsICdwdWJsaWMn
LCAnLicsICdldmVudF9jaGFubmVsLmgnKQ0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZ3JhbnRfdGFibGUuaCcpDQo+ICsgICAgY29weV9maWxlKHdvcmtpbmcsICdw
dWJsaWMnLCAnLicsICd2ZXJzaW9uLmgnKQ0KPiArICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZmVhdHVyZXMuaCcpDQo+IA0KPiAgICAgIGNvcHlfZmlsZSh3b3JraW5nLCAn
eGVuJywgJy4nLCAnZXJybm8uaCcpDQo+IA0KPiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBi
L2luY2x1ZGUveGVuLmgNCj4gaW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQNCj4gLS0tIGEv
aW5jbHVkZS94ZW4uaA0KPiArKysgYi9pbmNsdWRlL3hlbi5oDQo+IEBAIC00NCw2ICs0NCw3IEBA
DQo+ICAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+DQo+ICAjaW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMu
aD4NCj4gICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPg0KPiArI2luY2x1ZGUgPHhlbi92ZXJz
aW9uLmg+DQo+IA0KPiAgI2lmbmRlZiBYRU5fQVBJDQo+ICAjZGVmaW5lIFhFTl9BUEkgX19kZWNs
c3BlYyhkbGxpbXBvcnQpDQo+IEBAIC01Niw2ICs1NywxNCBAQCBYZW5Ub3VjaCgNCj4gICAgICBW
T0lEDQo+ICAgICAgKTsNCj4gDQo+ICsvLyBIWVBFUkNBTEwNCj4gKw0KPiArWEVOX0FQSQ0KPiAr
Vk9JRA0KPiArSHlwZXJjYWxsUG9wdWxhdGUoDQo+ICsgICAgVk9JRA0KPiArICAgICk7DQo+ICsN
Cj4gIC8vIEhWTQ0KPiANCj4gIF9fY2hlY2tSZXR1cm4NCj4gQEAgLTIzMyw2ICsyNDIsMjMgQEAg
U2NoZWRZaWVsZCgNCj4gICAgICBWT0lEDQo+ICAgICAgKTsNCj4gDQo+ICsvLyBYRU4gVkVSU0lP
Tg0KPiArDQo+ICtfX2NoZWNrUmV0dXJuDQo+ICtYRU5fQVBJDQo+ICtOVFNUQVRVUw0KPiArWGVu
VmVyc2lvbigNCj4gKyAgICBPVVQgUFVMT05HICBNYWpvciwNCj4gKyAgICBPVVQgUFVMT05HICBN
aW5vcg0KPiArICAgICk7DQo+ICsNCj4gK19fY2hlY2tSZXR1cm4NCj4gK1hFTl9BUEkNCj4gK05U
U1RBVFVTDQo+ICtYZW5WZXJzaW9uRXh0cmEoDQo+ICsgICAgT1VUIFBDSEFSICAgRXh0cmENCj4g
KyAgICApOw0KPiArDQo+ICAvLyBNT0RVTEUNCj4gDQo+ICBYRU5fQVBJDQo+IGRpZmYgLS1naXQg
YS9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaA0KPiBuZXcg
ZmlsZSBtb2RlIDEwMDY0NA0KPiBpbmRleCAwMDAwMDAwLi5iN2JmODNmDQo+IC0tLSAvZGV2L251
bGwNCj4gKysrIGIvaW5jbHVkZS94ZW4vZmVhdHVyZXMuaA0KPiBAQCAtMCwwICsxLDExMiBAQA0K
PiArLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKg0KPiAqKioqKioqKioqKioqKioqKioqKioNCj4gKyAqIGZlYXR1cmVzLmgNCj4gKyAqDQo+
ICsgKiBGZWF0dXJlIGZsYWdzLCByZXBvcnRlZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLg0KPiAr
ICoNCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0
byBhbnkgcGVyc29uIG9idGFpbmluZyBhDQo+IGNvcHkNCj4gKyAqIG9mIHRoaXMgc29mdHdhcmUg
YW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0bw0K
PiArICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5n
IHdpdGhvdXQgbGltaXRhdGlvbiB0aGUNCj4gKyAqIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlm
eSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vcg0KPiArICog
c2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hv
bSB0aGUgU29mdHdhcmUNCj4gaXMNCj4gKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0
byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQo+ICsgKg0KPiArICogVGhlIGFib3ZlIGNvcHly
aWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQg
aW4NCj4gKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLg0KPiArICoNCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRI
T1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELA0KPiBFWFBSRVNTIE9SDQo+ICsgKiBJTVBMSUVELCBJ
TkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GDQo+IE1FUkNIQU5U
QUJJTElUWSwNCj4gKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05J
TkZSSU5HRU1FTlQuIElOIE5PDQo+IEVWRU5UIFNIQUxMIFRIRQ0KPiArICogQVVUSE9SUyBPUiBD
T1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUw0KPiBPUiBP
VEhFUg0KPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwg
VE9SVCBPUiBPVEhFUldJU0UsDQo+IEFSSVNJTkcNCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBD
T05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1INCj4gT1RIRVINCj4gKyAq
IERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4NCj4gKyAqDQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIw
MDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+DQo+ICsgKi8NCj4gKw0KPiArI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fDQo+ICsjZGVmaW5lIF9fWEVOX1BVQkxJQ19G
RUFUVVJFU19IX18NCj4gKw0KPiArLyoNCj4gKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19m
ZWF0dXJlcyBYRU5fRUxGTk9URV9GRUFUVVJFUw0KPiArICoNCj4gKyAqIFRoZSBsaXN0IG9mIGFs
bCB0aGUgZmVhdHVyZXMgdGhlIGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkNCj4gKyAq
IHBhcnNpbmcgdGhlIFhFTl9FTEZOT1RFX0ZFQVRVUkVTIGFuZA0KPiBYRU5fRUxGTk9URV9TVVBQ
T1JURURfRkVBVFVSRVMNCj4gKyAqIHN0cmluZy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUg
bmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91dCB0aGUNCj4gKyAqICJYRU5GRUFUXyIgcHJlZml4
KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMuDQo+ICsgKiBJZiBhIGZlYXR1cmUgaXMgcmVx
dWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24gdGhlbiB0aGUgZmVhdHVyZSBuYW1lDQo+
ICsgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJhY3Rlci4NCj4gKyAqDQo+ICsgKiBO
b3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVTIGlzIHVzZWQsIHRoZW4g
aW4gdGhlDQo+ICsgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhlIGd1ZXN0IGlzIHRv
IGJlIGJvb3RlZCBhcyBkb20wLA0KPiArICovDQo+ICsNCj4gKy8qDQo+ICsgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4NCj4gKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLg0KPiArICovDQo+ICsj
ZGVmaW5lIFhFTkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMA0KPiArDQo+ICsvKg0K
PiArICogSWYgc2V0LCB0aGUgZ3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0
cyBzZWdtZW50IGRlc2NyaXB0b3INCj4gKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2
aWEgZGlyZWN0IHdyaXRlcy4NCj4gKyAqLw0KPiArI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rl
c2NyaXB0b3JfdGFibGVzIDENCj4gKw0KPiArLyoNCj4gKyAqIElmIHNldCwgdHJhbnNsYXRpb24g
YmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2FsJyBhZGRyZXNzIHNwYWNlDQo+ICsg
KiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2UgYXJlIGhhbmRsZWQgYnkgdGhl
IGh5cGVydmlzb3IuIEluDQo+IHRoaXMNCj4gKyAqIG1vZGUgdGhlIGd1ZXN0IGRvZXMgbm90IG5l
ZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZQ0KPiB0cmFuc2xhdGlvbnMNCj4gKyAq
IHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuDQo+ICsgKi8NCj4gKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyDQo+ICsNCj4gKy8qIElmIHNl
dCwgdGhlIGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmlu
ZyAwKS4gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAz
DQo+ICsNCj4gKy8qDQo+ICsgKiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFs
bG9jYXRlIHg4NiBQQUUgcGFnZSBkaXJlY3Rvcmllcw0KPiArICogYmVsb3cgNEdCLiBUaGlzIGZs
YWcgaXMgdXN1YWxseSBpbXBsaWVkIGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLg0KPiArICov
DQo+ICsjZGVmaW5lIFhFTkZFQVRfcGFlX3BnZGlyX2Fib3ZlXzRnYiAgICAgICAgNA0KPiArDQo+
ICsvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBwb3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BS
RVNFUlZFX0FEDQo+IGh5cGVyY2FsbD8gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9tbXVfcHRfdXBk
YXRlX3ByZXNlcnZlX2FkICA1DQo+ICsNCj4gKy8qIHg4NjogRG9lcyB0aGlzIFhlbiBob3N0IHN1
cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRQ0KPiBoeXBlcmNhbGw/ICovDQo+ICsjZGVm
aW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNg0KPiArDQo+ICsvKg0KPiAr
ICogSWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFj
ZWQgaW50byBndWVzdA0KPiBrZXJuZWwNCj4gKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4NCj4gKyAq
Lw0KPiArI2RlZmluZSBYRU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcNCj4gKw0K
PiArLyogeDg2OiBEb2VzIHRoaXMgWGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZl
Y3RvciB0eXBlPyAqLw0KPiArI2RlZmluZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAg
ICAgIDgNCj4gKw0KPiArLyogeDg2OiBwdmNsb2NrIGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBv
biBIVk0gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9odm1fc2FmZV9wdmNsb2NrICAgICAgICAgICA5
DQo+ICsNCj4gKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBIVk0gZ3Vlc3RzICovDQo+ICsj
ZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAxMA0KPiArDQo+ICsvKiBv
cGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9kb20w
ICAgICAgICAgICAgICAgICAgICAgIDExDQo+ICsNCj4gKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8NCj4gKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBf
aWRlbnRpdHkgICAgICAgIDEyDQo+ICsNCj4gKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEN
Cj4gKw0KPiArI2VuZGlmIC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8NCj4gKw0KPiAr
LyoNCj4gKyAqIExvY2FsIHZhcmlhYmxlczoNCj4gKyAqIG1vZGU6IEMNCj4gKyAqIGMtZmlsZS1z
dHlsZTogIkJTRCINCj4gKyAqIGMtYmFzaWMtb2Zmc2V0OiA0DQo+ICsgKiB0YWItd2lkdGg6IDQN
Cj4gKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbA0KPiArICogRW5kOg0KPiArICovDQo+IGRpZmYg
LS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJzaW9uLmgNCj4g
bmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gaW5kZXggMDAwMDAwMC4uNDRmMjZiMA0KPiAtLS0gL2Rl
di9udWxsDQo+ICsrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaA0KPiBAQCAtMCwwICsxLDk2IEBA
DQo+ICsvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqDQo+ICoqKioqKioqKioqKioqKioqKioqKg0KPiArICogdmVyc2lvbi5oDQo+ICsgKg0K
PiArICogWGVuIHZlcnNpb24sIHR5cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLg0KPiArICoN
Cj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBh
bnkgcGVyc29uIG9idGFpbmluZyBhDQo+IGNvcHkNCj4gKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5k
IGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJTb2Z0d2FyZSIpLCB0bw0KPiAr
ICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdp
dGhvdXQgbGltaXRhdGlvbiB0aGUNCj4gKyAqIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwg
bWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vcg0KPiArICogc2Vs
bCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0
aGUgU29mdHdhcmUNCj4gaXMNCj4gKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0
aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQo+ICsgKg0KPiArICogVGhlIGFib3ZlIGNvcHlyaWdo
dCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4N
Cj4gKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJl
Lg0KPiArICoNCj4gKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VU
IFdBUlJBTlRZIE9GIEFOWSBLSU5ELA0KPiBFWFBSRVNTIE9SDQo+ICsgKiBJTVBMSUVELCBJTkNM
VURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GDQo+IE1FUkNIQU5UQUJJ
TElUWSwNCj4gKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZS
SU5HRU1FTlQuIElOIE5PDQo+IEVWRU5UIFNIQUxMIFRIRQ0KPiArICogQVVUSE9SUyBPUiBDT1BZ
UklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUw0KPiBPUiBPVEhF
Ug0KPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9S
VCBPUiBPVEhFUldJU0UsDQo+IEFSSVNJTkcNCj4gKyAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05O
RUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1INCj4gT1RIRVINCj4gKyAqIERF
QUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4NCj4gKyAqDQo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMDUs
IE5ndXllbiBBbmggUXV5bmggPGFxdXluaEBnbWFpbC5jb20+DQo+ICsgKiBDb3B5cmlnaHQgKGMp
IDIwMDUsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+DQo+ICsgKi8NCj4gKw0KPiAr
I2lmbmRlZiBfX1hFTl9QVUJMSUNfVkVSU0lPTl9IX18NCj4gKyNkZWZpbmUgX19YRU5fUFVCTElD
X1ZFUlNJT05fSF9fDQo+ICsNCj4gKyNpbmNsdWRlICJ4ZW4uaCINCj4gKw0KPiArLyogTkIuIEFs
bCBvcHMgcmV0dXJuIHplcm8gb24gc3VjY2VzcywgZXhjZXB0IFhFTlZFUl97dmVyc2lvbixwYWdl
c2l6ZX0gKi8NCj4gKw0KPiArLyogYXJnID09IE5VTEw7IHJldHVybnMgbWFqb3I6bWlub3IgKDE2
OjE2KS4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX3ZlcnNpb24gICAgICAwDQo+ICsNCj4gKy8qIGFy
ZyA9PSB4ZW5fZXh0cmF2ZXJzaW9uX3QuICovDQo+ICsjZGVmaW5lIFhFTlZFUl9leHRyYXZlcnNp
b24gMQ0KPiArdHlwZWRlZiBjaGFyIHhlbl9leHRyYXZlcnNpb25fdFsxNl07DQo+ICsjZGVmaW5l
IFhFTl9FWFRSQVZFUlNJT05fTEVOIChzaXplb2YoeGVuX2V4dHJhdmVyc2lvbl90KSkNCj4gKw0K
PiArLyogYXJnID09IHhlbl9jb21waWxlX2luZm9fdC4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX2Nv
bXBpbGVfaW5mbyAyDQo+ICtzdHJ1Y3QgeGVuX2NvbXBpbGVfaW5mbyB7DQo+ICsgICAgY2hhciBj
b21waWxlcls2NF07DQo+ICsgICAgY2hhciBjb21waWxlX2J5WzE2XTsNCj4gKyAgICBjaGFyIGNv
bXBpbGVfZG9tYWluWzMyXTsNCj4gKyAgICBjaGFyIGNvbXBpbGVfZGF0ZVszMl07DQo+ICt9Ow0K
PiArdHlwZWRlZiBzdHJ1Y3QgeGVuX2NvbXBpbGVfaW5mbyB4ZW5fY29tcGlsZV9pbmZvX3Q7DQo+
ICsNCj4gKyNkZWZpbmUgWEVOVkVSX2NhcGFiaWxpdGllcyAzDQo+ICt0eXBlZGVmIGNoYXIgeGVu
X2NhcGFiaWxpdGllc19pbmZvX3RbMTAyNF07DQo+ICsjZGVmaW5lIFhFTl9DQVBBQklMSVRJRVNf
SU5GT19MRU4gKHNpemVvZih4ZW5fY2FwYWJpbGl0aWVzX2luZm9fdCkpDQo+ICsNCj4gKyNkZWZp
bmUgWEVOVkVSX2NoYW5nZXNldCA0DQo+ICt0eXBlZGVmIGNoYXIgeGVuX2NoYW5nZXNldF9pbmZv
X3RbNjRdOw0KPiArI2RlZmluZSBYRU5fQ0hBTkdFU0VUX0lORk9fTEVOIChzaXplb2YoeGVuX2No
YW5nZXNldF9pbmZvX3QpKQ0KPiArDQo+ICsjZGVmaW5lIFhFTlZFUl9wbGF0Zm9ybV9wYXJhbWV0
ZXJzIDUNCj4gK3N0cnVjdCB4ZW5fcGxhdGZvcm1fcGFyYW1ldGVycyB7DQo+ICsgICAgeGVuX3Vs
b25nX3QgdmlydF9zdGFydDsNCj4gK307DQo+ICt0eXBlZGVmIHN0cnVjdCB4ZW5fcGxhdGZvcm1f
cGFyYW1ldGVycyB4ZW5fcGxhdGZvcm1fcGFyYW1ldGVyc190Ow0KPiArDQo+ICsjZGVmaW5lIFhF
TlZFUl9nZXRfZmVhdHVyZXMgNg0KPiArc3RydWN0IHhlbl9mZWF0dXJlX2luZm8gew0KPiArICAg
IHVuc2lnbmVkIGludCBzdWJtYXBfaWR4OyAgICAvKiBJTjogd2hpY2ggMzItYml0IHN1Ym1hcCB0
byByZXR1cm4gKi8NCj4gKyAgICB1aW50MzJfdCAgICAgc3VibWFwOyAgICAgICAgLyogT1VUOiAz
Mi1iaXQgc3VibWFwICovDQo+ICt9Ow0KPiArdHlwZWRlZiBzdHJ1Y3QgeGVuX2ZlYXR1cmVfaW5m
byB4ZW5fZmVhdHVyZV9pbmZvX3Q7DQo+ICsNCj4gKy8qIERlY2xhcmVzIHRoZSBmZWF0dXJlcyBy
ZXBvcnRlZCBieSBYRU5WRVJfZ2V0X2ZlYXR1cmVzLiAqLw0KPiArI2luY2x1ZGUgImZlYXR1cmVz
LmgiDQo+ICsNCj4gKy8qIGFyZyA9PSBOVUxMOyByZXR1cm5zIGhvc3QgbWVtb3J5IHBhZ2Ugc2l6
ZS4gKi8NCj4gKyNkZWZpbmUgWEVOVkVSX3BhZ2VzaXplIDcNCj4gKw0KPiArLyogYXJnID09IHhl
bl9kb21haW5faGFuZGxlX3QuICovDQo+ICsjZGVmaW5lIFhFTlZFUl9ndWVzdF9oYW5kbGUgOA0K
PiArDQo+ICsjZGVmaW5lIFhFTlZFUl9jb21tYW5kbGluZSA5DQo+ICt0eXBlZGVmIGNoYXIgeGVu
X2NvbW1hbmRsaW5lX3RbMTAyNF07DQo+ICsNCj4gKyNlbmRpZiAvKiBfX1hFTl9QVUJMSUNfVkVS
U0lPTl9IX18gKi8NCj4gKw0KPiArLyoNCj4gKyAqIExvY2FsIHZhcmlhYmxlczoNCj4gKyAqIG1v
ZGU6IEMNCj4gKyAqIGMtZmlsZS1zdHlsZTogIkJTRCINCj4gKyAqIGMtYmFzaWMtb2Zmc2V0OiA0
DQo+ICsgKiB0YWItd2lkdGg6IDQNCj4gKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbA0KPiArICog
RW5kOg0KPiArICovDQo+IGRpZmYgLS1naXQgYS9zcmMveGVuL2RyaXZlci5jIGIvc3JjL3hlbi9k
cml2ZXIuYw0KPiBpbmRleCBiYTU0MWI0Li5mY2U3NWFhIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVu
L2RyaXZlci5jDQo+ICsrKyBiL3NyYy94ZW4vZHJpdmVyLmMNCj4gQEAgLTU5LDYgKzU5LDI2IEBA
IFhlblRvdWNoKA0KPiAgICAgIFZPSUQNCj4gICAgICApDQo+ICB7DQo+ICsgICAgc3RhdGljIFVM
T05HICAgIFJlZmVyZW5jZTsNCj4gKyAgICBVTE9ORyAgICAgICAgICAgTWFqb3I7DQo+ICsgICAg
VUxPTkcgICAgICAgICAgIE1pbm9yOw0KPiArICAgIENIQVIgICAgICAgICAgICBFeHRyYVtYRU5f
RVhUUkFWRVJTSU9OX0xFTl07DQo+ICsgICAgTlRTVEFUVVMgICAgICAgIHN0YXR1czsNCj4gKw0K
PiArICAgIGlmIChSZWZlcmVuY2UrKyAhPSAwKQ0KPiArICAgICAgICByZXR1cm47DQo+ICsNCj4g
KyAgICBzdGF0dXMgPSBYZW5WZXJzaW9uKCZNYWpvciwgJk1pbm9yKTsNCj4gKyAgICBBU1NFUlQo
TlRfU1VDQ0VTUyhzdGF0dXMpKTsNCj4gKw0KPiArICAgIHN0YXR1cyA9IFhlblZlcnNpb25FeHRy
YShFeHRyYSk7DQo+ICsgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7DQo+ICsNCj4gKyAg
ICBMb2dQcmludGYoTE9HX0xFVkVMX0lORk8sDQo+ICsgICAgICAgICAgICAgICJYRU46ICV1LiV1
JXNcbiIsDQo+ICsgICAgICAgICAgICAgIE1ham9yLA0KPiArICAgICAgICAgICAgICBNaW5vciwN
Cj4gKyAgICAgICAgICAgICAgRXh0cmEpOw0KPiAgfQ0KPiANCj4gIHN0YXRpYyBWT0lEDQo+IGRp
ZmYgLS1naXQgYS9zcmMveGVuL2h5cGVyY2FsbC5jIGIvc3JjL3hlbi9oeXBlcmNhbGwuYw0KPiBp
bmRleCAwN2ViNDFhLi43MTdiOGMyIDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuL2h5cGVyY2FsbC5j
DQo+ICsrKyBiL3NyYy94ZW4vaHlwZXJjYWxsLmMNCj4gQEAgLTI5LDYgKzI5LDkgQEANCj4gICAq
IFNVQ0ggREFNQUdFLg0KPiAgICovDQo+IA0KPiArI3VuZGVmICBYRU5fQVBJDQo+ICsjZGVmaW5l
IFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpDQo+ICsNCj4gICNpbmNsdWRlIDxudGRkay5o
Pg0KPiAgI2luY2x1ZGUgPHhlbi5oPg0KPiAgI2luY2x1ZGUgPHV0aWwuaD4NCj4gQEAgLTM3LDI0
ICs0MCw0MSBAQA0KPiAgI2luY2x1ZGUgImRiZ19wcmludC5oIg0KPiAgI2luY2x1ZGUgImFzc2Vy
dC5oIg0KPiANCj4gLSNkZWZpbmUgTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UIDINCj4gKyNk
ZWZpbmUgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVCAyDQo+IA0KPiAgI3ByYWdtYSBjb2Rl
X3NlZygiaHlwZXJjYWxsIikNCj4gIF9fZGVjbHNwZWMoYWxsb2NhdGUoImh5cGVyY2FsbCIpKQ0K
PiAtc3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BGTl9D
T1VOVCArIDEpICoNCj4gUEFHRV9TSVpFXTsNCj4gK3N0YXRpYyBVQ0hBUiAgICAgICAgX19TZWN0
aW9uWyhNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UICsgMSkgKg0KPiBQQUdFX1NJWkVdOw0K
PiANCj4gIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYgPSAweDQwMDAwMDAwOw0KPiAN
Cj4gLXN0YXRpYyBVU0hPUlQgICAgICAgWGVuTWFqb3JWZXJzaW9uOw0KPiAtc3RhdGljIFVTSE9S
VCAgICAgICBYZW5NaW5vclZlcnNpb247DQo+IC0NCj4gLXN0YXRpYyBQRk5fTlVNQkVSICAgSHlw
ZXJjYWxsUGZuW01BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVF07DQo+IC1zdGF0aWMgVUxPTkcg
ICAgICAgIEh5cGVyY2FsbFBmbkNvdW50Ow0KPiArc3RhdGljIFBIWVNJQ0FMX0FERFJFU1MNCj4g
SHlwZXJjYWxsUGFnZVtNQVhJTVVNX0hZUEVSQ0FMTF9QQUdFX0NPVU5UXTsNCj4gK3N0YXRpYyBV
TE9ORyAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VDb3VudDsNCj4gDQo+ICB0eXBlZGVmIFVDSEFS
ICAgICAgICAgICBIWVBFUkNBTExfR0FURVszMl07DQo+ICB0eXBlZGVmIEhZUEVSQ0FMTF9HQVRF
ICAqUEhZUEVSQ0FMTF9HQVRFOw0KPiANCj4gIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxs
Ow0KPiArVUxPTkcgICAgICAgICAgICAgICBIeXBlcmNhbGxNc3I7DQo+ICsNCj4gK1hFTl9BUEkN
Cj4gK1ZPSUQNCj4gK0h5cGVyY2FsbFBvcHVsYXRlKA0KPiArICAgIFZPSUQNCj4gKyAgICApDQo+
ICt7DQo+ICsgICAgVUxPTkcgICAgICAgSW5kZXg7DQo+ICsNCj4gKyAgICBmb3IgKEluZGV4ID0g
MDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsNCj4gKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLA0KPiArICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJD
QUxMIFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsDQo+ICsgICAgICAgICAgICAgICAgICBJbmRleCwN
Cj4gKyAgICAgICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LA0KPiAr
ICAgICAgICAgICAgICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7DQo+ICsNCj4g
KyAgICAgICAgX193cml0ZW1zcihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1
YWRQYXJ0KTsNCj4gKyAgICB9DQo+ICt9DQo+IA0KPiAgTlRTVEFUVVMNCj4gIEh5cGVyY2FsbElu
aXRpYWxpemUoDQo+IEBAIC02Niw3ICs4Niw2IEBAIEh5cGVyY2FsbEluaXRpYWxpemUoDQo+ICAg
ICAgVUxPTkcgICAgICAgRUNYID0gJ0RFQUQnOw0KPiAgICAgIFVMT05HICAgICAgIEVEWCA9ICdE
RUFEJzsNCj4gICAgICBVTE9ORyAgICAgICBJbmRleDsNCj4gLSAgICBVTE9ORyAgICAgICBIeXBl
cmNhbGxNc3I7DQo+ICAgICAgTlRTVEFUVVMgICAgc3RhdHVzOw0KPiANCj4gICAgICBzdGF0dXMg
PSBTVEFUVVNfVU5TVUNDRVNTRlVMOw0KPiBAQCAtODgsMTMgKzEwNyw2IEBAIEh5cGVyY2FsbElu
aXRpYWxpemUoDQo+ICAgICAgICAgICAgICBnb3RvIGZhaWwxOw0KPiAgICAgIH0NCj4gDQo+IC0g
ICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOw0KPiAt
ICAgIFhlbk1ham9yVmVyc2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7DQo+IC0gICAgWGVuTWlu
b3JWZXJzaW9uID0gKFVTSE9SVCkoRUFYICYgMHhGRkZGKTsNCj4gLQ0KPiAtICAgIEluZm8oIlhF
TiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJzaW9uLCBYZW5NaW5vclZlcnNpb24pOw0KPiAtICAgIElu
Zm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9fWEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOw0KPiAt
DQo+ICAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9uICYgKFBBR0VfU0laRSAtIDEpKQ0KPiAg
ICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdfUFRSKV9fU2VjdGlvbiArIFBBR0Vf
U0laRSAtIDEpICYNCj4gfihQQUdFX1NJWkUgLSAxKSk7DQo+ICAgICAgZWxzZQ0KPiBAQCAtMTAy
LDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgNCj4gDQo+ICAgICAgQVNTRVJUM1Uo
KChVTE9OR19QVFIpSHlwZXJjYWxsICYgKFBBR0VfU0laRSAtIDEpKSwgPT0sIDApOw0KPiANCj4g
LSAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7
IEluZGV4KyspIHsNCj4gLSAgICAgICAgUEhZU0lDQUxfQUREUkVTUyAgICBQaHlzaWNhbEFkZHJl
c3M7DQo+IC0NCj4gLSAgICAgICAgUGh5c2ljYWxBZGRyZXNzID0gTW1HZXRQaHlzaWNhbEFkZHJl
c3MoKFBVQ0hBUilIeXBlcmNhbGwgKyAoSW5kZXgNCj4gPDwgUEFHRV9TSElGVCkpOw0KPiAtICAg
ICAgICBIeXBlcmNhbGxQZm5bSW5kZXhdID0gKFBGTl9OVU1CRVIpKFBoeXNpY2FsQWRkcmVzcy5R
dWFkUGFydCA+Pg0KPiBQQUdFX1NISUZUKTsNCj4gLSAgICB9DQo+ICsgICAgZm9yIChJbmRleCA9
IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykNCj4gKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0gPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVDSEFS
KUh5cGVyY2FsbCArDQo+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgKEluZGV4IDw8IFBBR0VfU0hJRlQpKTsNCj4gDQo+ICAgICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEwsIE5VTEwpOw0KPiAtICAgIEh5cGVyY2Fs
bFBmbkNvdW50ID0gRUFYOw0KPiAtICAgIEFTU0VSVChIeXBlcmNhbGxQZm5Db3VudCA8PSBNQVhJ
TVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOw0KPiArICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IEVB
WDsNCj4gKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElNVU1fSFlQRVJDQUxM
X1BBR0VfQ09VTlQpOw0KPiAgICAgIEh5cGVyY2FsbE1zciA9IEVCWDsNCj4gDQo+IC0gICAgZm9y
IChJbmRleCA9IDA7IEluZGV4IDwgSHlwZXJjYWxsUGZuQ291bnQ7IEluZGV4KyspIHsNCj4gLSAg
ICAgICAgSW5mbygiSHlwZXJjYWxsUGZuWyVkXTogJXBcbiIsIEluZGV4LCAoUFZPSUQpSHlwZXJj
YWxsUGZuW0luZGV4XSk7DQo+IC0gICAgICAgIF9fd3JpdGVtc3IoSHlwZXJjYWxsTXNyLCAoVUxP
Tkc2NClIeXBlcmNhbGxQZm5bSW5kZXhdIDw8DQo+IFBBR0VfU0hJRlQpOw0KPiAtICAgIH0NCj4g
KyAgICBIeXBlcmNhbGxQb3B1bGF0ZSgpOw0KPiANCj4gICAgICByZXR1cm4gU1RBVFVTX1NVQ0NF
U1M7DQo+IA0KPiBAQCAtMTc3LDggKzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKA0KPiANCj4g
ICAgICBIeXBlcmNhbGwgPSBOVUxMOw0KPiANCj4gLSAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXgg
PCBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQ7IEluZGV4KyspDQo+IC0gICAgICAgIEh5cGVy
Y2FsbFBmbltJbmRleF0gPSAwOw0KPiArICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQ7IEluZGV4KyspDQo+ICsgICAgICAgIEh5cGVyY2FsbFBh
Z2VbSW5kZXhdLlF1YWRQYXJ0ID0gMDsNCj4gDQo+IC0gICAgSHlwZXJjYWxsUGZuQ291bnQgPSAw
Ow0KPiArICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7DQo+ICB9DQo+IGRpZmYgLS1naXQgYS9z
cmMveGVuYnVzL2Zkby5jIGIvc3JjL3hlbmJ1cy9mZG8uYw0KPiBpbmRleCA1OTQ0MmJkLi4yMTVj
OTk3IDEwMDY0NA0KPiAtLS0gYS9zcmMveGVuYnVzL2Zkby5jDQo+ICsrKyBiL3NyYy94ZW5idXMv
ZmRvLmMNCj4gQEAgLTIxODYsNiArMjE4Niw4IEBAIEZkb1M0VG9TMygNCj4gDQo+ICAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsNCj4gDQo+ICsgICAgSHlwZXJjYWxsUG9w
dWxhdGUoKTsNCj4gKw0KPiAgICAgIGlmIChGZG8tPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2Uu
Q29udGV4dCAhPSBOVUxMKQ0KPiAgICAgICAgICBYRU5GSUxUX1VOUExVRyhSZXBsYXksICZGZG8t
PlVucGx1Z0ludGVyZmFjZSk7DQo+IA0KPiBkaWZmIC0tZ2l0IGEvc3JjL3hlbmJ1cy9zdXNwZW5k
LmMgYi9zcmMveGVuYnVzL3N1c3BlbmQuYw0KPiBpbmRleCA2YWIyYmQyLi5kZTcwZTQyIDEwMDY0
NA0KPiAtLS0gYS9zcmMveGVuYnVzL3N1c3BlbmQuYw0KPiArKysgYi9zcmMveGVuYnVzL3N1c3Bl
bmQuYw0KPiBAQCAtMTczLDYgKzE3Myw4IEBAIFN1c3BlbmRUcmlnZ2VyKA0KPiANCj4gICAgICAg
ICAgQ29udGV4dC0+Q291bnQrKzsNCj4gDQo+ICsgICAgICAgIEh5cGVyY2FsbFBvcHVsYXRlKCk7
DQo+ICsNCj4gICAgICAgICAgaWYgKENvbnRleHQtPlVucGx1Z0ludGVyZmFjZS5JbnRlcmZhY2Uu
Q29udGV4dCAhPSBOVUxMKQ0KPiAgICAgICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAm
Q29udGV4dC0+VW5wbHVnSW50ZXJmYWNlKTsNCj4gDQo+IGRpZmYgLS1naXQgYS92czIwMTIveGVu
L3hlbi52Y3hwcm9qIGIvdnMyMDEyL3hlbi94ZW4udmN4cHJvag0KPiBpbmRleCBlYjU0NjkyLi4y
ZjRkOTU4IDEwMDY0NA0KPiAtLS0gYS92czIwMTIveGVuL3hlbi52Y3hwcm9qDQo+ICsrKyBiL3Zz
MjAxMi94ZW4veGVuLnZjeHByb2oNCj4gQEAgLTg4LDYgKzg4LDcgQEANCj4gIAkJPENsQ29tcGls
ZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIgLz4NCj4gIAkJPENsQ29t
cGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGdyYW50X3RhYmxlLmMiIC8+DQo+ICAJCTxDbENv
bXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxodm0uYyIgLz4NCj4gKwkJPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+DQo+ICAJCTxDbENvbXBpbGUg
SW5jbHVkZT0iLi5cLi5cc3JjXHhlblxoeXBlcmNhbGwuYyIgLz4NCj4gIAkJPENsQ29tcGlsZSBJ
bmNsdWRlPSIuLlwuLlxzcmNceGVuXG1lbW9yeS5jIiAvPg0KPiAgCQk8Q2xDb21waWxlIEluY2x1
ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4NCj4gZGlmZiAtLWdpdCBhL3ZzMjAxMy94ZW4v
eGVuLnZjeHByb2ogYi92czIwMTMveGVuL3hlbi52Y3hwcm9qDQo+IGluZGV4IDQ5MDI5NGMuLjgx
ZDUwZWEgMTAwNjQ0DQo+IC0tLSBhL3ZzMjAxMy94ZW4veGVuLnZjeHByb2oNCj4gKysrIGIvdnMy
MDEzL3hlbi94ZW4udmN4cHJvag0KPiBAQCAtMSw0ICsxLDQgQEANCj4gLe+7vzw/eG1sIHZlcnNp
b249IjEuMCIgZW5jb2Rpbmc9InV0Zi04Ij8+DQo+ICs8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29k
aW5nPSJ1dGYtOCI/Pg0KPiAgPFByb2plY3QgRGVmYXVsdFRhcmdldHM9IkJ1aWxkIiBUb29sc1Zl
cnNpb249IjEyLjAiDQo+IHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2RldmVs
b3Blci9tc2J1aWxkLzIwMDMiPg0KPiAgICA8SW1wb3J0IFByb2plY3Q9Ii4uXGNvbmZpZ3MucHJv
cHMiIC8+DQo+ICAgIDxQcm9wZXJ0eUdyb3VwIExhYmVsPSJHbG9iYWxzIj4NCj4gQEAgLTEyOCw2
ICsxMjgsNyBAQA0KPiAgICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxldmVu
dF9jaGFubmVsLmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVu
XGdyYW50X3RhYmxlLmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNc
eGVuXGh2bS5jIiAvPg0KPiArICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblx4
ZW5fdmVyc2lvbi5jIiAvPg0KPiAgICAgIDxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhl
blxoeXBlcmNhbGwuYyIgLz4NCj4gICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4
ZW5cbWVtb3J5LmMiIC8+DQo+ICAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVu
XHNjaGVkLmMiIC8+DQo+IC0tDQo+IDIuMS4xDQoNCl9fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fCndpbi1wdi1kZXZlbCBtYWlsaW5nIGxpc3QKd2luLXB2LWRl
dmVsQGxpc3RzLnhlbnByb2plY3Qub3JnCmh0dHA6Ly9saXN0cy54ZW5wcm9qZWN0Lm9yZy9jZ2kt
YmluL21haWxtYW4vbGlzdGluZm8vd2luLXB2LWRldmVs

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 14:20:34 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:20:34 +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 1XmkOw-00068v-5O; Fri, 07 Nov 2014 14:20:34 +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 1XmkOu-00068q-0z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:20:32 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	69/86-25547-F25DC545; Fri, 07 Nov 2014 14:20:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-31.messagelabs.com!1415370028!11007438!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20452 invoked from network); 7 Nov 2014 14:20:28 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:20:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26637460"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 2/4] Re-work interrupt code in FDO
Thread-Index: AQHP+o9ZSNJdB2wtMUq336G/gASJgpxVNqjQ
Date: Fri, 7 Nov 2014 14:20:28 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114846A@AMSPEX01CL01.citrite.net>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
	<1415367162-28444-3-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415367162-28444-3-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 07 November 2014 13:33
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH 2/4] Re-work interrupt code in FDO
> 
> This patch adds code to the FDO handler to acquire extra message signaled
> (i.e. edge triggered) interrupt vectors that can be used for per-CPU event
> channel upcalls (with extra support in Xen).
> The existing callback via is also limited to upcall on CPU 0 meaning the
> interrupt callback in the EVTCHN code can pass the current CPU value
> through
> to the ABI.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  src/common/names.h  | 122 ++++++-
>  src/xenbus.inf      |  10 +-
>  src/xenbus/evtchn.c |  55 +++-
>  src/xenbus/fdo.c    | 894
> +++++++++++++++++++++++++++++++++++++++++-----------
>  src/xenbus/fdo.h    |  39 ++-
>  src/xenbus/pdo.c    |   2 +-
>  6 files changed, 897 insertions(+), 225 deletions(-)
> 
> diff --git a/src/common/names.h b/src/common/names.h
> index 89894b9..f4a8bd0 100644
> --- a/src/common/names.h
> +++ b/src/common/names.h
> @@ -196,32 +196,124 @@ PnpMinorFunctionName(
>  }
> 
>  static FORCEINLINE const CHAR *
> -PartialResourceDescriptorTypeName(
> +ResourceDescriptorTypeName(
>      IN  UCHAR   Type
>      )
>  {
> -#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> -    case CmResourceType ## _Type:                       \
> +#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> +    case CmResourceType ## _Type:               \
>          return #_Type;
> 
>      switch (Type) {
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
>      default:
>          break;
>      }
> 
>      return "UNKNOWN";
> 
> -#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
> +#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +ResourceDescriptorShareDispositionName(
> +    IN  UCHAR   Disposition
> +    )
> +{
> +#define
> _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
> +    case CmResourceShare ## _Disposition:                           \
> +        return #_Disposition;
> +
> +    switch (Disposition) {
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqDevicePolicyName(
> +    IN  IRQ_DEVICE_POLICY   Policy
> +    )
> +{
> +#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
> +    case IrqPolicy ## _Policy:              \
> +        return #_Policy;
> +
> +    switch (Policy) {
> +    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
> +    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
> +    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
> +    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_DEVICE_POLICY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqPriorityName(
> +    IN  IRQ_PRIORITY    Priority
> +    )
> +{
> +#define _IRQ_PRIORITY_NAME(_Priority)   \
> +    case IrqPriority ## _Priority:      \
> +        return #_Priority;
> +
> +    switch (Priority) {
> +    _IRQ_PRIORITY_NAME(Undefined);
> +    _IRQ_PRIORITY_NAME(Low);
> +    _IRQ_PRIORITY_NAME(Normal);
> +    _IRQ_PRIORITY_NAME(High);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_PRIORITY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +InterruptModeName(
> +    IN  KINTERRUPT_MODE Mode
> +    )
> +{
> +#define _INTERRUPT_MODE_NAME(_Mode) \
> +    case _Mode:                     \
> +        return #_Mode;
> +
> +    switch (Mode) {
> +    _INTERRUPT_MODE_NAME(LevelSensitive);
> +    _INTERRUPT_MODE_NAME(Latched);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _INTERRUPT_MODE_NAME
>  }
> 
>  static FORCEINLINE const CHAR *
> @@ -358,4 +450,6 @@ BusQueryIdTypeName(
>  #undef  _BUS_QUERY_ID_TYPE_NAME
>  }
> 
> +
> +
>  #endif // _COMMON_NAMES_H_
> diff --git a/src/xenbus.inf b/src/xenbus.inf
> index 544bb2c..b2c17c3 100644
> --- a/src/xenbus.inf
> +++ b/src/xenbus.inf
> @@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service,
>  [XenBus_Service]
>  DisplayName=%XenBusDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> -StartType=%SERVICE_BOOT_START%
> +StartType=%SERVICE_DEMAND_START%

This change was meant to be only for the sake of my own debugging. I'll remove it and re-post.

  Paul

>  ErrorControl=%SERVICE_ERROR_NORMAL%
>  ServiceBinary=%12%\xenbus.sys
>  LoadOrderGroup="Boot Bus Extender"
> -AddReg = XenBus_Parameters, XenBus_Interfaces
> +AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
> 
>  [XenBus_Parameters]
>  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
> 
> +[XenBus_Interrupts]
> +HKR,"Interrupt Management",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties","MSISupported",0x000
> 10001,1
> +
>  [XenFilt_Service]
>  DisplayName=%XenFiltDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
> index 1bd5e5f..44043d4 100644
> --- a/src/xenbus/evtchn.c
> +++ b/src/xenbus/evtchn.c
> @@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
>      PXENBUS_FDO                     Fdo;
>      KSPIN_LOCK                      Lock;
>      LONG                            References;
> -    ULONG                           Vector;
> +    PXENBUS_INTERRUPT               Interrupt;
>      BOOLEAN                         Enabled;
>      XENBUS_SUSPEND_INTERFACE        SuspendInterface;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
> @@ -127,11 +127,14 @@ EvtchnInterruptEnable(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> +    ULONG                       Line;
>      NTSTATUS                    status;
> 
>      Trace("<===>\n");
> 
> -    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
> +    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
> +
> +    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
>      ASSERT(NT_SUCCESS(status));
>  }
> 
> @@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> -    return FdoAcquireInterruptLock(Context->Fdo);
> +    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
>  }
> 
>  static FORCEINLINE
> @@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
>      IN  __drv_restoresIRQL KIRQL    Irql
>      )
>  {
> -    FdoReleaseInterruptLock(Context->Fdo, Irql);
> +    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
>  }
> 
>  static NTSTATUS
> @@ -644,21 +647,32 @@ done:
>      return DoneSomething;
>  }
> 
> +static
> +_Function_class_(KSERVICE_ROUTINE)
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -EvtchnInterrupt(
> -    IN  PXENBUS_EVTCHN_CONTEXT  Context
> +EvtchnInterruptCallback(
> +    IN  PKINTERRUPT         InterruptObject,
> +    IN  PVOID               Argument
>      )
>  {
> -    BOOLEAN                     DoneSomething;
> +    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
> +    ULONG                   Cpu;
> +    BOOLEAN                 DoneSomething;
> +
> +    UNREFERENCED_PARAMETER(InterruptObject);
> +
> +    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
> +    Cpu = KeGetCurrentProcessorNumber();
> 
>      DoneSomething = FALSE;
> 
>      while (XENBUS_SHARED_INFO(UpcallPending,
>                                &Context->SharedInfoInterface,
> -                              0))
> +                              Cpu))
>          DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
>                                             &Context->EvtchnAbi,
> -                                           0,
> +                                           Cpu,
>                                             EvtchnPollCallback,
>                                             Context);
> 
> @@ -857,8 +871,6 @@ EvtchnAcquire(
> 
>      Trace("====>\n");
> 
> -    Context->Vector = FdoGetInterruptVector(Fdo);
> -
>      status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
>      if (!NT_SUCCESS(status))
>          goto fail1;
> @@ -902,6 +914,15 @@ EvtchnAcquire(
>      if (!NT_SUCCESS(status))
>          goto fail7;
> 
> +    status = FdoAllocateInterrupt(Fdo,
> +                                  LevelSensitive,
> +                                  0,
> +                                  EvtchnInterruptCallback,
> +                                  Context,
> +                                  &Context->Interrupt);
> +    if (!NT_SUCCESS(status))
> +        goto fail8;
> +
>      Trace("<====\n");
> 
>  done:
> @@ -909,6 +930,11 @@ done:
> 
>      return STATUS_SUCCESS;
> 
> +fail8:
> +    Error("fail8\n");
> +
> +    EvtchnAbiRelease(Context);
> +
>  fail7:
>      Error("fail7\n");
> 
> @@ -948,8 +974,6 @@ fail2:
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -978,6 +1002,9 @@ EvtchnRelease(
>      if (!IsListEmpty(&Context->List))
>          BUG("OUTSTANDING EVENT CHANNELS");
> 
> +    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
> +    Context->Interrupt = NULL;
> +
>      EvtchnAbiRelease(Context);
> 
>      XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
> @@ -1001,8 +1028,6 @@ EvtchnRelease(
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>      Trace("<====\n");
> 
>  done:
> diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
> index 215c997..cc0c775 100644
> --- a/src/xenbus/fdo.c
> +++ b/src/xenbus/fdo.c
> @@ -45,6 +45,7 @@
>  #include "fdo.h"
>  #include "pdo.h"
>  #include "thread.h"
> +#include "high.h"
>  #include "mutex.h"
>  #include "shared_info.h"
>  #include "evtchn.h"
> @@ -64,16 +65,17 @@
> 
>  #define MAXNAMELEN  128
> 
> -typedef enum _XENBUS_RESOURCE_TYPE {
> -    MEMORY_RESOURCE = 0,
> -    INTERRUPT_RESOURCE,
> -    RESOURCE_COUNT
> -} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
> -
> -typedef struct _XENBUS_RESOURCE {
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> -} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
> +struct _XENBUS_INTERRUPT {
> +    PXENBUS_FDO         Fdo;
> +    LIST_ENTRY          ListEntry;
> +    KINTERRUPT_MODE     InterruptMode;
> +    PKINTERRUPT         InterruptObject;
> +    ULONG               Cpu;
> +    UCHAR               Vector;
> +    ULONG               Line;
> +    PKSERVICE_ROUTINE   Callback;
> +    PVOID               Argument;
> +};
> 
>  struct _XENBUS_FDO {
>      PXENBUS_DX                      Dx;
> @@ -108,8 +110,8 @@ struct _XENBUS_FDO {
>      PXENBUS_STORE_WATCH             BalloonWatch;
>      MUTEX                           BalloonSuspendMutex;
> 
> -    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
> -    PKINTERRUPT                     InterruptObject;
> +    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
> +    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
> 
>      PXENBUS_SUSPEND_CONTEXT         SuspendContext;
>      PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
> @@ -129,9 +131,11 @@ struct _XENBUS_FDO {
>      XENBUS_BALLOON_INTERFACE        BalloonInterface;
>      XENFILT_UNPLUG_INTERFACE        UnplugInterface;
> 
> +    PXENBUS_RANGE_SET               RangeSet;
> +    LIST_ENTRY                      List;
> +
>      PXENBUS_EVTCHN_CHANNEL          Channel;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
> -    PXENBUS_RANGE_SET               RangeSet;
>  };
> 
>  static FORCEINLINE PVOID
> @@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
>      return Dx->DevicePnpState;
>  }
> 
> +static FORCEINLINE DEVICE_PNP_STATE
> +__FdoGetPreviousDevicePnpState(
> +    IN  PXENBUS_FDO Fdo
> +    )
> +{
> +    PXENBUS_DX      Dx = Fdo->Dx;
> +
> +    return Dx->PreviousDevicePnpState;
> +}
> +
>  static FORCEINLINE VOID
>  __FdoSetDevicePowerState(
>      IN  PXENBUS_FDO         Fdo,
> @@ -1383,219 +1397,595 @@ loop:
>  }
> 
>  static VOID
> -FdoParseResources(
> +FdoDumpIoResourceDescriptor(
>      IN  PXENBUS_FDO             Fdo,
> -    IN  PCM_RESOURCE_LIST       RawResourceList,
> -    IN  PCM_RESOURCE_LIST       TranslatedResourceList
> +    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
>      )
>  {
> -    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
> -    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
> -    ULONG                       Index;
> +    Trace("%s: %s\n",
> +          __FdoGetName(Fdo),
> +          ResourceDescriptorTypeName(Descriptor->Type));
> +
> +    if (Descriptor->Option == 0)
> +        Trace("Required\n");
> +    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
> +        Trace("Alternative\n");
> +    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
> +        Trace("Preferred\n");
> +    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE |
> IO_RESOURCE_PREFERRED))
> +        Trace("Preferred Alternative\n");
> +
> +    Trace("ShareDisposition=%s Flags=%04x\n",
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("Length = %08x Alignment = %08x\n MinimumAddress =
> %08x.%08x MaximumAddress = %08x.%08x\n",
> +              Descriptor->u.Memory.Length,
> +              Descriptor->u.Memory.Alignment,
> +              Descriptor->u.Memory.MinimumAddress.HighPart,
> +              Descriptor->u.Memory.MinimumAddress.LowPart,
> +              Descriptor->u.Memory.MaximumAddress.HighPart,
> +              Descriptor->u.Memory.MaximumAddress.LowPart);
> +        break;
> 
> -    ASSERT3U(RawResourceList->Count, ==, 1);
> -    RawPartialList = &RawResourceList->List[0].PartialResourceList;
> +    case CmResourceTypeInterrupt:
> +        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s
> PriorityPolicy=%s TargettedProcessors = %p\n",
> +              Descriptor->u.Interrupt.MinimumVector,
> +              Descriptor->u.Interrupt.MaximumVector,
> +              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
> +              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
> +              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
> +        break;
> 
> -    ASSERT3U(RawPartialList->Version, ==, 1);
> -    ASSERT3U(RawPartialList->Revision, ==, 1);
> +    default:
> +        break;
> +    }
> +}
> 
> -    ASSERT3U(TranslatedResourceList->Count, ==, 1);
> -    TranslatedPartialList = &TranslatedResourceList-
> >List[0].PartialResourceList;
> +static VOID
> +FdoDumpIoResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PIO_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                   Index;
> 
> -    ASSERT3U(TranslatedPartialList->Version, ==, 1);
> -    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> 
> -    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
> +        Trace("%s: %d\n",
> +              __FdoGetName(Fdo),
> +              Index);
> 
> -        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
> -        TranslatedPartialDescriptor = &TranslatedPartialList-
> >PartialDescriptors[Index];
> +        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
> +    }
> +}
> 
> -        Trace("%s: [%d] %02x:%s\n",
> -              __FdoGetName(Fdo),
> -              Index,
> -              TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> -
> -        switch (TranslatedPartialDescriptor->Type) {
> -        case CmResourceTypeMemory:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x
> Length = %08x\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Memory.Start.HighPart,
> -                  RawPartialDescriptor->u.Memory.Start.LowPart,
> -                  RawPartialDescriptor->u.Memory.Length);
> -
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start =
> %08x.%08x Length = %08x\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
> -                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
> -                  TranslatedPartialDescriptor->u.Memory.Length);
> -
> -            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[MEMORY_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +static NTSTATUS
> +FdoFilterResourceRequirements(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
> +    )
> +{
> +    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
> +    ULONG                           Size;
> +    PIO_RESOURCE_REQUIREMENTS_LIST  New;
> +    IO_RESOURCE_DESCRIPTOR          Interrupt;
> +    PIO_RESOURCE_LIST               List;
> +    ULONG                           Index;
> +    NTSTATUS                        status;
> 
> -            break;
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> 
> -        case CmResourceTypeInterrupt:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector
> = %08x Affinity = %p\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Interrupt.Level,
> -                  RawPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
> +    if (!__FdoIsActive(Fdo))
> +        goto not_active;
> 
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level =
> %08x Vector = %08x Affinity = %p\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Interrupt.Level,
> -                  TranslatedPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
> +    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
> +    ASSERT3U(Old->AlternativeLists, ==, 1);
> 
> -            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[INTERRUPT_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +    Size = Old->ListSize +
> +        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
> 
> -            break;
> +    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
> 
> -        default:
> -            break;
> +    status = STATUS_NO_MEMORY;
> +    if (New == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(New, Old, Old->ListSize);
> +    New->ListSize = Size;
> +
> +    List = &New->List[0];
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> +
> +        if (Descriptor->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
> +        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
> +    }
> +
> +    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
> +    Interrupt.Option = 0; // Required
> +    Interrupt.Type = CmResourceTypeInterrupt;
> +    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
> +    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
> +                      CM_RESOURCE_INTERRUPT_MESSAGE |
> +                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +
> +    Interrupt.u.Interrupt.MinimumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.MaximumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
> +    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
> +
> +    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
> +        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
> +        List->Descriptors[List->Count++] = Interrupt;
> +    }
> +
> +    FdoDumpIoResourceList(Fdo, List);
> +
> +    Irp->IoStatus.Information = (ULONG_PTR)New;
> +    status = STATUS_SUCCESS;
> +
> +    ExFreePool(Old);
> +
> +not_active:
> +    status = Irp->IoStatus.Status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    Irp->IoStatus.Status = status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +}
> +
> +static VOID
> +FdoDumpCmPartialResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
> +    )
> +{
> +    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          ResourceDescriptorTypeName(Descriptor->Type),
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Descriptor->u.Memory.Start.HighPart,
> +              Descriptor->u.Memory.Start.LowPart,
> +              Descriptor->u.Memory.Length);
> +        break;
> +
> +    case CmResourceTypeInterrupt:
> +        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +            if (Translated)
> +                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Translated.Level,
> +                      Descriptor->u.MessageInterrupt.Translated.Vector,
> +                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
> +            else
> +                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
> +                      Descriptor->u.MessageInterrupt.Raw.Vector,
> +                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
> +        } else {
> +            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
> +                  __FdoGetName(Fdo),
> +                  (Translated) ? "TRANSLATED" : "RAW",
> +                  Descriptor->u.Interrupt.Level,
> +                  Descriptor->u.Interrupt.Vector,
> +                  (PVOID)Descriptor->u.Interrupt.Affinity);
>          }
> +        break;
> +    default:
> +        break;
>      }
> +}
> 
> -    Trace("<====\n");
> +static VOID
> +FdoDumpCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  BOOLEAN                     Translated,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          List->Version,
> +          List->Revision,
> +          List->Count);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        Trace("%s: %s: %d\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Index);
> +
> +        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
> +    }
>  }
> 
> -static FORCEINLINE PXENBUS_RESOURCE
> -__FdoGetResource(
> -    IN  PXENBUS_FDO             Fdo,
> -    IN  XENBUS_RESOURCE_TYPE    Type
> +static VOID
> +FdoDumpCmFullResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
>      )
>  {
> -    ASSERT3U(Type, <, RESOURCE_COUNT);
> +    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          InterfaceTypeName(Descriptor->InterfaceType),
> +          Descriptor->BusNumber);
> 
> -    return &Fdo->Resource[Type];
> +    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor-
> >PartialResourceList);
> +}
> +
> +static VOID
> +FdoDumpCmResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  BOOLEAN             Translated,
> +    IN  PCM_RESOURCE_LIST   List
> +    )
> +{
> +    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
> +}
> +
> +_IRQL_requires_max_(HIGH_LEVEL)
> +_IRQL_saves_
> +_IRQL_raises_(HIGH_LEVEL)
> +KIRQL
> +FdoAcquireInterruptLock(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
> +}
> +
> +_IRQL_requires_(HIGH_LEVEL)
> +VOID
> +FdoReleaseInterruptLock(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
> +    IN  __drv_restoresIRQL KIRQL    Irql
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
>  }
> 
>  static
>  _Function_class_(KSERVICE_ROUTINE)
> -_IRQL_requires_(HIGH_LEVEL)
> -_IRQL_requires_same_
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -FdoInterrupt(
> +FdoInterruptCallback(
>      IN  PKINTERRUPT             InterruptObject,
>      IN  PVOID                   Context
>      )
>  {
> -    PXENBUS_FDO                 Fdo = Context;
> +    PXENBUS_INTERRUPT           Interrupt = Context;
> 
> -    UNREFERENCED_PARAMETER(InterruptObject);
> +    if (Interrupt->Callback == NULL)
> +        return FALSE;
> 
> -    ASSERT(Fdo != NULL);
> -
> -    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
> +    return Interrupt->Callback(InterruptObject,
> +                               Interrupt->Argument);
>  }
> 
>  static NTSTATUS
>  FdoConnectInterrupt(
> -    IN  PXENBUS_FDO                 Fdo
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
> +    OUT PXENBUS_INTERRUPT               *Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE                Interrupt;
> -    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
> -    NTSTATUS                        status;
> +    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
> +    ULONG                               Cpu;
> +    NTSTATUS                            status;
> 
>      Trace("====>\n");
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Interrupt == NULL)
> +        goto fail1;
> +
> +    (*Interrupt)->Fdo = Fdo;
> +    (*Interrupt)->InterruptMode = (Translated->Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> +                                  Latched :
> +                                  LevelSensitive;
> +
> +    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
> +        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
> 
>      RtlZeroMemory(&Connect, sizeof
> (IO_CONNECT_INTERRUPT_PARAMETERS));
>      Connect.Version = CONNECT_FULLY_SPECIFIED;
>      Connect.FullySpecified.PhysicalDeviceObject =
> __FdoGetPhysicalDeviceObject(Fdo);
> -    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt-
> >Translated.ShareDisposition == CmResourceShareShared);
> -    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
> -    Connect.FullySpecified.Irql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> -                                           Latched :
> -                                           LevelSensitive;
> -    Connect.FullySpecified.ProcessorEnableMask = Interrupt-
> >Translated.u.Interrupt.Affinity;
> -    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
> -    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
> -    Connect.FullySpecified.ServiceContext = Fdo;
> +    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated-
> >ShareDisposition == CmResourceShareShared);
> +    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
> +    Connect.FullySpecified.InterruptObject = &(*Interrupt)-
> >InterruptObject;
> +    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
> +    Connect.FullySpecified.ServiceContext = *Interrupt;
> +
> +    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +        Connect.FullySpecified.Vector = Translated-
> >u.MessageInterrupt.Translated.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.MessageInterrupt.Translated.Affinity;
> +    } else {
> +        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.Interrupt.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.Interrupt.Affinity;
> +    }
> 
>      status = IoConnectInterruptEx(&Connect);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> +
> +    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
> +
> +#if defined(__i386__)
> +    (VOID)_BitScanReverse(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#elif defined(__x86_64__)
> +    (VOID)_BitScanReverse64(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#else
> +#error 'Unrecognised architecture'
> +#endif
> +
> +    (*Interrupt)->Cpu = Cpu;
> +
> +    Info("%p: %s %s CPU %u VECTOR %02x\n",
> +         (*Interrupt)->InterruptObject,
> +         ResourceDescriptorShareDispositionName(Translated-
> >ShareDisposition),
> +         InterruptModeName((*Interrupt)->InterruptMode),
> +         (*Interrupt)->Cpu,
> +         (*Interrupt)->Vector);
> 
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    __FdoFree(*Interrupt);
> +    *Interrupt = NULL;
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
>      return status;
>  }
> 
> -_IRQL_requires_max_(HIGH_LEVEL)
> -_IRQL_saves_
> -_IRQL_raises_(HIGH_LEVEL)
> -KIRQL
> -FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +static VOID
> +FdoDisconnectInterrupt(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PXENBUS_INTERRUPT               Interrupt
>      )
>  {
> -    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
> +    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    Trace("====>\n");
> +
> +    Info("%p: CPU %u VECTOR %02x\n",
> +         Interrupt->InterruptObject,
> +         Interrupt->Cpu,
> +         Interrupt->Vector);
> +
> +    Interrupt->Cpu = 0;
> +    Interrupt->Vector = 0;
> +
> +    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> +    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> +    Disconnect.ConnectionContext.InterruptObject = Interrupt-
> >InterruptObject;
> 
> -    return KeAcquireInterruptSpinLock(InterruptObject);
> +    IoDisconnectInterruptEx(&Disconnect);
> +
> +    Interrupt->Line = 0;
> +    Interrupt->InterruptObject = NULL;
> +    Interrupt->InterruptMode = 0;
> +    Interrupt->Fdo = NULL;
> +
> +    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
> +    __FdoFree(Interrupt);
> +
> +    Trace("<====\n");
>  }
> -
> -_IRQL_requires_(HIGH_LEVEL)
> -VOID
> -FdoReleaseInterruptLock(
> -    IN  PXENBUS_FDO                 Fdo,
> -    IN  __drv_restoresIRQL KIRQL    Irql
> +
> +static NTSTATUS
> +FdoCreateInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
> +    ULONG               Index;
> +    PXENBUS_INTERRUPT   Interrupt;
> +    NTSTATUS            status;
> +
> +    InitializeListHead(&Fdo->List);
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo-
> >RawResourceList->PartialDescriptors[Index];
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo-
> >TranslatedResourceList->PartialDescriptors[Index];
> +
> +        if (Translated->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> +
> +        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY ListEntry;
> +
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
> 
> -    KeReleaseInterruptSpinLock(InterruptObject, Irql);
> +    return status;
>  }
> 
> -ULONG
> +NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    )
> +{
> +    PLIST_ENTRY             ListEntry;
> +    KIRQL                   Irql;
> +    NTSTATUS                status;
> +
> +    for (ListEntry = Fdo->List.Flink;
> +         ListEntry != &Fdo->List;
> +         ListEntry = ListEntry->Flink) {
> +        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        if ((*Interrupt)->Callback == NULL &&
> +            (*Interrupt)->InterruptMode == InterruptMode &&
> +            (*Interrupt)->Cpu == Cpu)
> +            goto found;
> +    }
> +
> +    *Interrupt = NULL;
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> +
> +found:
> +    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
> +    (*Interrupt)->Callback = Callback;
> +    (*Interrupt)->Argument = Argument;
> +    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +UCHAR
>  FdoGetInterruptVector(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Vector;
> +}
> +
> +ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE    Interrupt;
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Line;
> +}
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    KIRQL                   Irql;
> 
> -    return Interrupt->Raw.u.Interrupt.Vector;
> +    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
> +    Interrupt->Callback = NULL;
> +    Interrupt->Argument = NULL;
> +    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
>  }
> 
>  static VOID
> -FdoDisconnectInterrupt(
> -    IN  PXENBUS_FDO                     Fdo
> +FdoDestroyInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                         InterruptObject;
> -    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY         ListEntry;
> +        PXENBUS_INTERRUPT   Interrupt;
> 
> -    Trace("====>\n");
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> 
> -    InterruptObject = Fdo->InterruptObject;
> -    Fdo->InterruptObject = NULL;
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> 
> -    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> -    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> -    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> 
> -    IoDisconnectInterruptEx(&Disconnect);
> +#pragma warning(push)
> +#pragma warning(disable:4054)   // 'type cast' : from function pointer to
> data pointer
> +        ASSERT3P(Interrupt->Callback, ==, NULL);
> +#pragma warning(pop)
> 
> -    Trace("<====\n");
> +        ASSERT3P(Interrupt->Argument, ==, NULL);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
>  }
> 
>  static
> @@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
> 
>  static NTSTATUS
>  FdoCreateIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    PHYSICAL_ADDRESS                End;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> 
> +found:
>      status = XENBUS_RANGE_SET(Create,
>                                &Fdo->RangeSetInterface,
>                                "io_space",
>                                &Fdo->RangeSet);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> 
>      status = XENBUS_RANGE_SET(Put,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail3;
> +
> +    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated-
> >u.Memory.Length - 1;
> +
> +    Info("%08x.%08x - %08x.%08x\n",
> +         Translated->u.Memory.Start.HighPart,
> +         Translated->u.Memory.Start.LowPart,
> +         End.HighPart,
> +         End.LowPart);
> 
>      return STATUS_SUCCESS;
> 
> -fail2:
> -    Error("fail2\n");
> +fail3:
> +    Error("fail3\n");
> 
>      XENBUS_RANGE_SET(Destroy,
>                       &Fdo->RangeSetInterface,
>                       Fdo->RangeSet);
>      Fdo->RangeSet = NULL;
> 
> +fail2:
> +    Error("fail2\n");
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
> 
>  static VOID
>  FdoDestroyIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    ASSERT(FALSE);
> +    return;
> 
> +found:
>      status = XENBUS_RANGE_SET(Get,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      ASSERT(NT_SUCCESS(status));
> 
>      XENBUS_RANGE_SET(Destroy,
> @@ -2214,39 +2636,111 @@ FdoS3ToS4(
>      Trace("<====\n");
>  }
> 
> +static VOID
> +FdoFilterCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        //
> +        // These are additional resources that XENBUS requested, so they must
> +        // be filtered out before the underlying PCI bus driver sees them.
> Happily
> +        // it appears that swapping the type to DevicePrivate causes PCI.SYS to
> ignore
> +        // them.
> +        //
> +        if (Descriptor->Type == CmResourceTypeInterrupt &&
> +            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
> +            Descriptor->Type = CmResourceTypeDevicePrivate;
> +    }
> +}
> +
>  static NTSTATUS
>  FdoStartDevice(
> -    IN  PXENBUS_FDO     Fdo,
> -    IN  PIRP            Irp
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
>      )
>  {
> -    PIO_STACK_LOCATION  StackLocation;
> -    NTSTATUS            status;
> +    PIO_STACK_LOCATION              StackLocation;
> +    PCM_RESOURCE_LIST               ResourceList;
> +    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
> +    ULONG                           Size;
> +    NTSTATUS                        status;
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> -    status = FdoForwardIrpSynchronously(Fdo, Irp);
> -    if (!NT_SUCCESS(status))
> +    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +
> +    // Raw
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResources;
> +    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->RawResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->RawResourceList == NULL)
>          goto fail1;
> 
> -    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +    RtlCopyMemory(Fdo->RawResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> +
> +    // Translated
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated;
> +    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->TranslatedResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->TranslatedResourceList == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> 
> -    FdoParseResources(Fdo,
> -                      StackLocation->Parameters.StartDevice.AllocatedResources,
> -                      StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated);
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
>      if (!__FdoIsActive(Fdo))
>          goto not_active;
> 
> -    status = FdoConnectInterrupt(Fdo);
> +    status = FdoCreateInterrupt(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail4;
> 
>      KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
> 
>      status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
>      if (!NT_SUCCESS(status))
> -        goto fail3;
> +        goto fail5;
> 
>      InitializeMutex(&Fdo->BalloonSuspendMutex);
> 
> @@ -2254,20 +2748,20 @@ FdoStartDevice(
> 
>      status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
>      if (!NT_SUCCESS(status))
> -        goto fail4;
> +        goto fail6;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
> 
>          status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
>          if (!NT_SUCCESS(status))
> -            goto fail5;
> +            goto fail7;
>      }
> 
>  not_active:
>      status = FdoD3ToD0(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail6;
> +        goto fail8;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          BOOLEAN Warned;
> @@ -2306,11 +2800,11 @@ not_active:
> 
>      return status;
> 
> -fail6:
> -    Error("fail6\n");
> +fail8:
> +    Error("fail8\n");
> 
>      if (!__FdoIsActive(Fdo))
> -        goto fail2;
> +        goto fail4;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          ThreadAlert(Fdo->BalloonThread);
> @@ -2318,8 +2812,8 @@ fail6:
>          Fdo->BalloonThread = NULL;
>      }
> 
> -fail5:
> -    Error("fail5\n");
> +fail7:
> +    Error("fail7\n");
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL)
>          RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
> @@ -2328,8 +2822,8 @@ fail5:
>      ThreadJoin(Fdo->SuspendThread);
>      Fdo->SuspendThread = NULL;
> 
> -fail4:
> -    Error("fail4\n");
> +fail6:
> +    Error("fail6\n");
> 
>      RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
> 
> @@ -2339,17 +2833,27 @@ fail4:
>      ThreadJoin(Fdo->ScanThread);
>      Fdo->ScanThread = NULL;
> 
> -fail3:
> -    Error("fail3\n");
> +fail5:
> +    Error("fail5\n");
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> +
> +fail4:
> +    Error("fail4\n");
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> 
>  fail2:
>      Error("fail2\n");
> 
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>  fail1:
>      Error("fail1 (%08x)\n", status);
> @@ -2445,10 +2949,14 @@ FdoStopDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>      __FdoSetDevicePnpState(Fdo, Stopped);
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2554,6 +3062,9 @@ FdoRemoveDevice(
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> +    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
> +        goto done;
> +
>      if (__FdoIsActive(Fdo)) {
>          Trace("waiting for scan thread...\n");
> 
> @@ -2621,11 +3132,16 @@ FdoRemoveDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
> +done:
>      __FdoSetDevicePnpState(Fdo, Deleted);
> 
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2937,6 +3453,10 @@ FdoDispatchPnp(
>            PnpMinorFunctionName(MinorFunction));
> 
>      switch (StackLocation->MinorFunction) {
> +    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
> +        status = FdoFilterResourceRequirements(Fdo, Irp);
> +        break;
> +
>      case IRP_MN_START_DEVICE:
>          status = FdoStartDevice(Fdo, Irp);
>          break;
> diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
> index fdb6f79..4916be4 100644
> --- a/src/xenbus/fdo.h
> +++ b/src/xenbus/fdo.h
> @@ -38,6 +38,8 @@
>  #include "driver.h"
>  #include "types.h"
> 
> +typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT,
> *PXENBUS_INTERRUPT;
> +
>  extern NTSTATUS
>  FdoCreate(
>      IN  PDEVICE_OBJECT  PhysicalDeviceObject,
> @@ -140,11 +142,6 @@ FdoFreeIoSpace(
>      IN  ULONG               Size
>      );
> 
> -extern ULONG
> -FdoGetInterruptVector(
> -    IN  PXENBUS_FDO Fdo
> -    );
> -
>  // Disable erroneous SAL warnings around use of interrupt locks
>  #pragma warning(disable:28230)
>  #pragma warning(disable:28285)
> @@ -155,7 +152,8 @@ _IRQL_saves_
>  _IRQL_raises_(HIGH_LEVEL)
>  KIRQL
>  FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      );
> 
>  extern
> @@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
>  VOID
>  FdoReleaseInterruptLock(
>      IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
>      IN  __drv_restoresIRQL KIRQL    Irql
>      );
> 
> +extern NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    );
> +
> +extern UCHAR
> +FdoGetInterruptVector(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
>  #include "suspend.h"
> 
>  extern PXENBUS_SUSPEND_CONTEXT
> diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
> index 650e84d..ad0d4de 100644
> --- a/src/xenbus/pdo.c
> +++ b/src/xenbus/pdo.c
> @@ -682,7 +682,7 @@ PdoParseResources(
>                __PdoGetName(Pdo),
>                Index,
>                TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> +              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
> 
>          switch (TranslatedPartialDescriptor->Type) {
>          case CmResourceTypeMemory:
> --
> 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 Nov 07 14:20:34 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:20:34 +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 1XmkOw-00068v-5O; Fri, 07 Nov 2014 14:20:34 +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 1XmkOu-00068q-0z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:20:32 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	69/86-25547-F25DC545; Fri, 07 Nov 2014 14:20:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-31.messagelabs.com!1415370028!11007438!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20452 invoked from network); 7 Nov 2014 14:20:28 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:20:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26637460"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 2/4] Re-work interrupt code in FDO
Thread-Index: AQHP+o9ZSNJdB2wtMUq336G/gASJgpxVNqjQ
Date: Fri, 7 Nov 2014 14:20:28 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114846A@AMSPEX01CL01.citrite.net>
References: <1415367162-28444-1-git-send-email-paul.durrant@citrix.com>
	<1415367162-28444-3-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415367162-28444-3-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH 2/4] Re-work interrupt code in FDO
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 07 November 2014 13:33
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH 2/4] Re-work interrupt code in FDO
> 
> This patch adds code to the FDO handler to acquire extra message signaled
> (i.e. edge triggered) interrupt vectors that can be used for per-CPU event
> channel upcalls (with extra support in Xen).
> The existing callback via is also limited to upcall on CPU 0 meaning the
> interrupt callback in the EVTCHN code can pass the current CPU value
> through
> to the ABI.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  src/common/names.h  | 122 ++++++-
>  src/xenbus.inf      |  10 +-
>  src/xenbus/evtchn.c |  55 +++-
>  src/xenbus/fdo.c    | 894
> +++++++++++++++++++++++++++++++++++++++++-----------
>  src/xenbus/fdo.h    |  39 ++-
>  src/xenbus/pdo.c    |   2 +-
>  6 files changed, 897 insertions(+), 225 deletions(-)
> 
> diff --git a/src/common/names.h b/src/common/names.h
> index 89894b9..f4a8bd0 100644
> --- a/src/common/names.h
> +++ b/src/common/names.h
> @@ -196,32 +196,124 @@ PnpMinorFunctionName(
>  }
> 
>  static FORCEINLINE const CHAR *
> -PartialResourceDescriptorTypeName(
> +ResourceDescriptorTypeName(
>      IN  UCHAR   Type
>      )
>  {
> -#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> -    case CmResourceType ## _Type:                       \
> +#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
> +    case CmResourceType ## _Type:               \
>          return #_Type;
> 
>      switch (Type) {
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> -    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
> +    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
>      default:
>          break;
>      }
> 
>      return "UNKNOWN";
> 
> -#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
> +#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +ResourceDescriptorShareDispositionName(
> +    IN  UCHAR   Disposition
> +    )
> +{
> +#define
> _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
> +    case CmResourceShare ## _Disposition:                           \
> +        return #_Disposition;
> +
> +    switch (Disposition) {
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
> +    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqDevicePolicyName(
> +    IN  IRQ_DEVICE_POLICY   Policy
> +    )
> +{
> +#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
> +    case IrqPolicy ## _Policy:              \
> +        return #_Policy;
> +
> +    switch (Policy) {
> +    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
> +    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
> +    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
> +    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
> +    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_DEVICE_POLICY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +IrqPriorityName(
> +    IN  IRQ_PRIORITY    Priority
> +    )
> +{
> +#define _IRQ_PRIORITY_NAME(_Priority)   \
> +    case IrqPriority ## _Priority:      \
> +        return #_Priority;
> +
> +    switch (Priority) {
> +    _IRQ_PRIORITY_NAME(Undefined);
> +    _IRQ_PRIORITY_NAME(Low);
> +    _IRQ_PRIORITY_NAME(Normal);
> +    _IRQ_PRIORITY_NAME(High);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _IRQ_PRIORITY_NAME
> +}
> +
> +static FORCEINLINE const CHAR *
> +InterruptModeName(
> +    IN  KINTERRUPT_MODE Mode
> +    )
> +{
> +#define _INTERRUPT_MODE_NAME(_Mode) \
> +    case _Mode:                     \
> +        return #_Mode;
> +
> +    switch (Mode) {
> +    _INTERRUPT_MODE_NAME(LevelSensitive);
> +    _INTERRUPT_MODE_NAME(Latched);
> +    default:
> +        break;
> +    }
> +
> +    return "UNKNOWN";
> +
> +#undef  _INTERRUPT_MODE_NAME
>  }
> 
>  static FORCEINLINE const CHAR *
> @@ -358,4 +450,6 @@ BusQueryIdTypeName(
>  #undef  _BUS_QUERY_ID_TYPE_NAME
>  }
> 
> +
> +
>  #endif // _COMMON_NAMES_H_
> diff --git a/src/xenbus.inf b/src/xenbus.inf
> index 544bb2c..b2c17c3 100644
> --- a/src/xenbus.inf
> +++ b/src/xenbus.inf
> @@ -78,20 +78,26 @@ AddService=xenfilt,,XenFilt_Service,
>  [XenBus_Service]
>  DisplayName=%XenBusDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> -StartType=%SERVICE_BOOT_START%
> +StartType=%SERVICE_DEMAND_START%

This change was meant to be only for the sake of my own debugging. I'll remove it and re-post.

  Paul

>  ErrorControl=%SERVICE_ERROR_NORMAL%
>  ServiceBinary=%12%\xenbus.sys
>  LoadOrderGroup="Boot Bus Extender"
> -AddReg = XenBus_Parameters, XenBus_Interfaces
> +AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
> 
>  [XenBus_Parameters]
>  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
> 
> +[XenBus_Interrupts]
> +HKR,"Interrupt Management",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties",,0x00000010
> +HKR,"Interrupt
> Management\MessageSignaledInterruptProperties","MSISupported",0x000
> 10001,1
> +
>  [XenFilt_Service]
>  DisplayName=%XenFiltDesc%
>  ServiceType=%SERVICE_KERNEL_DRIVER%
> diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
> index 1bd5e5f..44043d4 100644
> --- a/src/xenbus/evtchn.c
> +++ b/src/xenbus/evtchn.c
> @@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
>      PXENBUS_FDO                     Fdo;
>      KSPIN_LOCK                      Lock;
>      LONG                            References;
> -    ULONG                           Vector;
> +    PXENBUS_INTERRUPT               Interrupt;
>      BOOLEAN                         Enabled;
>      XENBUS_SUSPEND_INTERFACE        SuspendInterface;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
> @@ -127,11 +127,14 @@ EvtchnInterruptEnable(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> +    ULONG                       Line;
>      NTSTATUS                    status;
> 
>      Trace("<===>\n");
> 
> -    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
> +    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
> +
> +    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
>      ASSERT(NT_SUCCESS(status));
>  }
> 
> @@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
>      IN  PXENBUS_EVTCHN_CONTEXT  Context
>      )
>  {
> -    return FdoAcquireInterruptLock(Context->Fdo);
> +    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
>  }
> 
>  static FORCEINLINE
> @@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
>      IN  __drv_restoresIRQL KIRQL    Irql
>      )
>  {
> -    FdoReleaseInterruptLock(Context->Fdo, Irql);
> +    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
>  }
> 
>  static NTSTATUS
> @@ -644,21 +647,32 @@ done:
>      return DoneSomething;
>  }
> 
> +static
> +_Function_class_(KSERVICE_ROUTINE)
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -EvtchnInterrupt(
> -    IN  PXENBUS_EVTCHN_CONTEXT  Context
> +EvtchnInterruptCallback(
> +    IN  PKINTERRUPT         InterruptObject,
> +    IN  PVOID               Argument
>      )
>  {
> -    BOOLEAN                     DoneSomething;
> +    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
> +    ULONG                   Cpu;
> +    BOOLEAN                 DoneSomething;
> +
> +    UNREFERENCED_PARAMETER(InterruptObject);
> +
> +    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
> +    Cpu = KeGetCurrentProcessorNumber();
> 
>      DoneSomething = FALSE;
> 
>      while (XENBUS_SHARED_INFO(UpcallPending,
>                                &Context->SharedInfoInterface,
> -                              0))
> +                              Cpu))
>          DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
>                                             &Context->EvtchnAbi,
> -                                           0,
> +                                           Cpu,
>                                             EvtchnPollCallback,
>                                             Context);
> 
> @@ -857,8 +871,6 @@ EvtchnAcquire(
> 
>      Trace("====>\n");
> 
> -    Context->Vector = FdoGetInterruptVector(Fdo);
> -
>      status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
>      if (!NT_SUCCESS(status))
>          goto fail1;
> @@ -902,6 +914,15 @@ EvtchnAcquire(
>      if (!NT_SUCCESS(status))
>          goto fail7;
> 
> +    status = FdoAllocateInterrupt(Fdo,
> +                                  LevelSensitive,
> +                                  0,
> +                                  EvtchnInterruptCallback,
> +                                  Context,
> +                                  &Context->Interrupt);
> +    if (!NT_SUCCESS(status))
> +        goto fail8;
> +
>      Trace("<====\n");
> 
>  done:
> @@ -909,6 +930,11 @@ done:
> 
>      return STATUS_SUCCESS;
> 
> +fail8:
> +    Error("fail8\n");
> +
> +    EvtchnAbiRelease(Context);
> +
>  fail7:
>      Error("fail7\n");
> 
> @@ -948,8 +974,6 @@ fail2:
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -978,6 +1002,9 @@ EvtchnRelease(
>      if (!IsListEmpty(&Context->List))
>          BUG("OUTSTANDING EVENT CHANNELS");
> 
> +    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
> +    Context->Interrupt = NULL;
> +
>      EvtchnAbiRelease(Context);
> 
>      XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
> @@ -1001,8 +1028,6 @@ EvtchnRelease(
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Context->Vector = 0;
> -
>      Trace("<====\n");
> 
>  done:
> diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
> index 215c997..cc0c775 100644
> --- a/src/xenbus/fdo.c
> +++ b/src/xenbus/fdo.c
> @@ -45,6 +45,7 @@
>  #include "fdo.h"
>  #include "pdo.h"
>  #include "thread.h"
> +#include "high.h"
>  #include "mutex.h"
>  #include "shared_info.h"
>  #include "evtchn.h"
> @@ -64,16 +65,17 @@
> 
>  #define MAXNAMELEN  128
> 
> -typedef enum _XENBUS_RESOURCE_TYPE {
> -    MEMORY_RESOURCE = 0,
> -    INTERRUPT_RESOURCE,
> -    RESOURCE_COUNT
> -} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
> -
> -typedef struct _XENBUS_RESOURCE {
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
> -    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> -} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
> +struct _XENBUS_INTERRUPT {
> +    PXENBUS_FDO         Fdo;
> +    LIST_ENTRY          ListEntry;
> +    KINTERRUPT_MODE     InterruptMode;
> +    PKINTERRUPT         InterruptObject;
> +    ULONG               Cpu;
> +    UCHAR               Vector;
> +    ULONG               Line;
> +    PKSERVICE_ROUTINE   Callback;
> +    PVOID               Argument;
> +};
> 
>  struct _XENBUS_FDO {
>      PXENBUS_DX                      Dx;
> @@ -108,8 +110,8 @@ struct _XENBUS_FDO {
>      PXENBUS_STORE_WATCH             BalloonWatch;
>      MUTEX                           BalloonSuspendMutex;
> 
> -    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
> -    PKINTERRUPT                     InterruptObject;
> +    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
> +    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
> 
>      PXENBUS_SUSPEND_CONTEXT         SuspendContext;
>      PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
> @@ -129,9 +131,11 @@ struct _XENBUS_FDO {
>      XENBUS_BALLOON_INTERFACE        BalloonInterface;
>      XENFILT_UNPLUG_INTERFACE        UnplugInterface;
> 
> +    PXENBUS_RANGE_SET               RangeSet;
> +    LIST_ENTRY                      List;
> +
>      PXENBUS_EVTCHN_CHANNEL          Channel;
>      PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
> -    PXENBUS_RANGE_SET               RangeSet;
>  };
> 
>  static FORCEINLINE PVOID
> @@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
>      return Dx->DevicePnpState;
>  }
> 
> +static FORCEINLINE DEVICE_PNP_STATE
> +__FdoGetPreviousDevicePnpState(
> +    IN  PXENBUS_FDO Fdo
> +    )
> +{
> +    PXENBUS_DX      Dx = Fdo->Dx;
> +
> +    return Dx->PreviousDevicePnpState;
> +}
> +
>  static FORCEINLINE VOID
>  __FdoSetDevicePowerState(
>      IN  PXENBUS_FDO         Fdo,
> @@ -1383,219 +1397,595 @@ loop:
>  }
> 
>  static VOID
> -FdoParseResources(
> +FdoDumpIoResourceDescriptor(
>      IN  PXENBUS_FDO             Fdo,
> -    IN  PCM_RESOURCE_LIST       RawResourceList,
> -    IN  PCM_RESOURCE_LIST       TranslatedResourceList
> +    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
>      )
>  {
> -    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
> -    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
> -    ULONG                       Index;
> +    Trace("%s: %s\n",
> +          __FdoGetName(Fdo),
> +          ResourceDescriptorTypeName(Descriptor->Type));
> +
> +    if (Descriptor->Option == 0)
> +        Trace("Required\n");
> +    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
> +        Trace("Alternative\n");
> +    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
> +        Trace("Preferred\n");
> +    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE |
> IO_RESOURCE_PREFERRED))
> +        Trace("Preferred Alternative\n");
> +
> +    Trace("ShareDisposition=%s Flags=%04x\n",
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("Length = %08x Alignment = %08x\n MinimumAddress =
> %08x.%08x MaximumAddress = %08x.%08x\n",
> +              Descriptor->u.Memory.Length,
> +              Descriptor->u.Memory.Alignment,
> +              Descriptor->u.Memory.MinimumAddress.HighPart,
> +              Descriptor->u.Memory.MinimumAddress.LowPart,
> +              Descriptor->u.Memory.MaximumAddress.HighPart,
> +              Descriptor->u.Memory.MaximumAddress.LowPart);
> +        break;
> 
> -    ASSERT3U(RawResourceList->Count, ==, 1);
> -    RawPartialList = &RawResourceList->List[0].PartialResourceList;
> +    case CmResourceTypeInterrupt:
> +        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s
> PriorityPolicy=%s TargettedProcessors = %p\n",
> +              Descriptor->u.Interrupt.MinimumVector,
> +              Descriptor->u.Interrupt.MaximumVector,
> +              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
> +              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
> +              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
> +        break;
> 
> -    ASSERT3U(RawPartialList->Version, ==, 1);
> -    ASSERT3U(RawPartialList->Revision, ==, 1);
> +    default:
> +        break;
> +    }
> +}
> 
> -    ASSERT3U(TranslatedResourceList->Count, ==, 1);
> -    TranslatedPartialList = &TranslatedResourceList-
> >List[0].PartialResourceList;
> +static VOID
> +FdoDumpIoResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PIO_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                   Index;
> 
> -    ASSERT3U(TranslatedPartialList->Version, ==, 1);
> -    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> 
> -    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
> -        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
> +        Trace("%s: %d\n",
> +              __FdoGetName(Fdo),
> +              Index);
> 
> -        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
> -        TranslatedPartialDescriptor = &TranslatedPartialList-
> >PartialDescriptors[Index];
> +        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
> +    }
> +}
> 
> -        Trace("%s: [%d] %02x:%s\n",
> -              __FdoGetName(Fdo),
> -              Index,
> -              TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> -
> -        switch (TranslatedPartialDescriptor->Type) {
> -        case CmResourceTypeMemory:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x
> Length = %08x\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Memory.Start.HighPart,
> -                  RawPartialDescriptor->u.Memory.Start.LowPart,
> -                  RawPartialDescriptor->u.Memory.Length);
> -
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start =
> %08x.%08x Length = %08x\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
> -                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
> -                  TranslatedPartialDescriptor->u.Memory.Length);
> -
> -            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[MEMORY_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +static NTSTATUS
> +FdoFilterResourceRequirements(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
> +    )
> +{
> +    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
> +    ULONG                           Size;
> +    PIO_RESOURCE_REQUIREMENTS_LIST  New;
> +    IO_RESOURCE_DESCRIPTOR          Interrupt;
> +    PIO_RESOURCE_LIST               List;
> +    ULONG                           Index;
> +    NTSTATUS                        status;
> 
> -            break;
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> 
> -        case CmResourceTypeInterrupt:
> -            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector
> = %08x Affinity = %p\n",
> -                  RawPartialDescriptor->ShareDisposition,
> -                  RawPartialDescriptor->Flags,
> -                  RawPartialDescriptor->u.Interrupt.Level,
> -                  RawPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
> +    if (!__FdoIsActive(Fdo))
> +        goto not_active;
> 
> -            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level =
> %08x Vector = %08x Affinity = %p\n",
> -                  TranslatedPartialDescriptor->ShareDisposition,
> -                  TranslatedPartialDescriptor->Flags,
> -                  TranslatedPartialDescriptor->u.Interrupt.Level,
> -                  TranslatedPartialDescriptor->u.Interrupt.Vector,
> -                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
> +    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
> +    ASSERT3U(Old->AlternativeLists, ==, 1);
> 
> -            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
> -            Fdo->Resource[INTERRUPT_RESOURCE].Translated =
> *TranslatedPartialDescriptor;
> +    Size = Old->ListSize +
> +        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
> 
> -            break;
> +    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
> 
> -        default:
> -            break;
> +    status = STATUS_NO_MEMORY;
> +    if (New == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(New, Old, Old->ListSize);
> +    New->ListSize = Size;
> +
> +    List = &New->List[0];
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
> +
> +        if (Descriptor->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
> +        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
> +    }
> +
> +    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
> +    Interrupt.Option = 0; // Required
> +    Interrupt.Type = CmResourceTypeInterrupt;
> +    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
> +    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
> +                      CM_RESOURCE_INTERRUPT_MESSAGE |
> +                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
> +
> +    Interrupt.u.Interrupt.MinimumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.MaximumVector =
> CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
> +    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
> +    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
> +
> +    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
> +        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
> +        List->Descriptors[List->Count++] = Interrupt;
> +    }
> +
> +    FdoDumpIoResourceList(Fdo, List);
> +
> +    Irp->IoStatus.Information = (ULONG_PTR)New;
> +    status = STATUS_SUCCESS;
> +
> +    ExFreePool(Old);
> +
> +not_active:
> +    status = Irp->IoStatus.Status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    Irp->IoStatus.Status = status;
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +
> +    return status;
> +}
> +
> +static VOID
> +FdoDumpCmPartialResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
> +    )
> +{
> +    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          ResourceDescriptorTypeName(Descriptor->Type),
> +          ResourceDescriptorShareDispositionName(Descriptor-
> >ShareDisposition),
> +          Descriptor->Flags);
> +
> +    switch (Descriptor->Type) {
> +    case CmResourceTypeMemory:
> +        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Descriptor->u.Memory.Start.HighPart,
> +              Descriptor->u.Memory.Start.LowPart,
> +              Descriptor->u.Memory.Length);
> +        break;
> +
> +    case CmResourceTypeInterrupt:
> +        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +            if (Translated)
> +                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Translated.Level,
> +                      Descriptor->u.MessageInterrupt.Translated.Vector,
> +                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
> +            else
> +                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity =
> %p\n",
> +                      __FdoGetName(Fdo),
> +                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
> +                      Descriptor->u.MessageInterrupt.Raw.Vector,
> +                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
> +        } else {
> +            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
> +                  __FdoGetName(Fdo),
> +                  (Translated) ? "TRANSLATED" : "RAW",
> +                  Descriptor->u.Interrupt.Level,
> +                  Descriptor->u.Interrupt.Vector,
> +                  (PVOID)Descriptor->u.Interrupt.Affinity);
>          }
> +        break;
> +    default:
> +        break;
>      }
> +}
> 
> -    Trace("<====\n");
> +static VOID
> +FdoDumpCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  BOOLEAN                     Translated,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          List->Version,
> +          List->Revision,
> +          List->Count);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        Trace("%s: %s: %d\n",
> +              __FdoGetName(Fdo),
> +              (Translated) ? "TRANSLATED" : "RAW",
> +              Index);
> +
> +        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
> +    }
>  }
> 
> -static FORCEINLINE PXENBUS_RESOURCE
> -__FdoGetResource(
> -    IN  PXENBUS_FDO             Fdo,
> -    IN  XENBUS_RESOURCE_TYPE    Type
> +static VOID
> +FdoDumpCmFullResourceDescriptor(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  BOOLEAN                         Translated,
> +    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
>      )
>  {
> -    ASSERT3U(Type, <, RESOURCE_COUNT);
> +    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
> +          __FdoGetName(Fdo),
> +          (Translated) ? "TRANSLATED" : "RAW",
> +          InterfaceTypeName(Descriptor->InterfaceType),
> +          Descriptor->BusNumber);
> 
> -    return &Fdo->Resource[Type];
> +    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor-
> >PartialResourceList);
> +}
> +
> +static VOID
> +FdoDumpCmResourceList(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  BOOLEAN             Translated,
> +    IN  PCM_RESOURCE_LIST   List
> +    )
> +{
> +    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
> +}
> +
> +_IRQL_requires_max_(HIGH_LEVEL)
> +_IRQL_saves_
> +_IRQL_raises_(HIGH_LEVEL)
> +KIRQL
> +FdoAcquireInterruptLock(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
> +}
> +
> +_IRQL_requires_(HIGH_LEVEL)
> +VOID
> +FdoReleaseInterruptLock(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
> +    IN  __drv_restoresIRQL KIRQL    Irql
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
>  }
> 
>  static
>  _Function_class_(KSERVICE_ROUTINE)
> -_IRQL_requires_(HIGH_LEVEL)
> -_IRQL_requires_same_
> +__drv_requiresIRQL(HIGH_LEVEL)
>  BOOLEAN
> -FdoInterrupt(
> +FdoInterruptCallback(
>      IN  PKINTERRUPT             InterruptObject,
>      IN  PVOID                   Context
>      )
>  {
> -    PXENBUS_FDO                 Fdo = Context;
> +    PXENBUS_INTERRUPT           Interrupt = Context;
> 
> -    UNREFERENCED_PARAMETER(InterruptObject);
> +    if (Interrupt->Callback == NULL)
> +        return FALSE;
> 
> -    ASSERT(Fdo != NULL);
> -
> -    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
> +    return Interrupt->Callback(InterruptObject,
> +                               Interrupt->Argument);
>  }
> 
>  static NTSTATUS
>  FdoConnectInterrupt(
> -    IN  PXENBUS_FDO                 Fdo
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
> +    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
> +    OUT PXENBUS_INTERRUPT               *Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE                Interrupt;
> -    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
> -    NTSTATUS                        status;
> +    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
> +    ULONG                               Cpu;
> +    NTSTATUS                            status;
> 
>      Trace("====>\n");
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Interrupt == NULL)
> +        goto fail1;
> +
> +    (*Interrupt)->Fdo = Fdo;
> +    (*Interrupt)->InterruptMode = (Translated->Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> +                                  Latched :
> +                                  LevelSensitive;
> +
> +    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
> +        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
> 
>      RtlZeroMemory(&Connect, sizeof
> (IO_CONNECT_INTERRUPT_PARAMETERS));
>      Connect.Version = CONNECT_FULLY_SPECIFIED;
>      Connect.FullySpecified.PhysicalDeviceObject =
> __FdoGetPhysicalDeviceObject(Fdo);
> -    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt-
> >Translated.ShareDisposition == CmResourceShareShared);
> -    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
> -    Connect.FullySpecified.Irql = (KIRQL)Interrupt-
> >Translated.u.Interrupt.Level;
> -    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags &
> CM_RESOURCE_INTERRUPT_LATCHED) ?
> -                                           Latched :
> -                                           LevelSensitive;
> -    Connect.FullySpecified.ProcessorEnableMask = Interrupt-
> >Translated.u.Interrupt.Affinity;
> -    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
> -    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
> -    Connect.FullySpecified.ServiceContext = Fdo;
> +    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated-
> >ShareDisposition == CmResourceShareShared);
> +    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
> +    Connect.FullySpecified.InterruptObject = &(*Interrupt)-
> >InterruptObject;
> +    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
> +    Connect.FullySpecified.ServiceContext = *Interrupt;
> +
> +    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
> +        Connect.FullySpecified.Vector = Translated-
> >u.MessageInterrupt.Translated.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.MessageInterrupt.Translated.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.MessageInterrupt.Translated.Affinity;
> +    } else {
> +        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
> +        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
> +        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated-
> >u.Interrupt.Level;
> +        Connect.FullySpecified.ProcessorEnableMask = Translated-
> >u.Interrupt.Affinity;
> +    }
> 
>      status = IoConnectInterruptEx(&Connect);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> +
> +    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
> +
> +#if defined(__i386__)
> +    (VOID)_BitScanReverse(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#elif defined(__x86_64__)
> +    (VOID)_BitScanReverse64(&Cpu,
> Connect.FullySpecified.ProcessorEnableMask);
> +#else
> +#error 'Unrecognised architecture'
> +#endif
> +
> +    (*Interrupt)->Cpu = Cpu;
> +
> +    Info("%p: %s %s CPU %u VECTOR %02x\n",
> +         (*Interrupt)->InterruptObject,
> +         ResourceDescriptorShareDispositionName(Translated-
> >ShareDisposition),
> +         InterruptModeName((*Interrupt)->InterruptMode),
> +         (*Interrupt)->Cpu,
> +         (*Interrupt)->Vector);
> 
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    __FdoFree(*Interrupt);
> +    *Interrupt = NULL;
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
>      return status;
>  }
> 
> -_IRQL_requires_max_(HIGH_LEVEL)
> -_IRQL_saves_
> -_IRQL_raises_(HIGH_LEVEL)
> -KIRQL
> -FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +static VOID
> +FdoDisconnectInterrupt(
> +    IN  PXENBUS_FDO                     Fdo,
> +    IN  PXENBUS_INTERRUPT               Interrupt
>      )
>  {
> -    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
> +    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    Trace("====>\n");
> +
> +    Info("%p: CPU %u VECTOR %02x\n",
> +         Interrupt->InterruptObject,
> +         Interrupt->Cpu,
> +         Interrupt->Vector);
> +
> +    Interrupt->Cpu = 0;
> +    Interrupt->Vector = 0;
> +
> +    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> +    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> +    Disconnect.ConnectionContext.InterruptObject = Interrupt-
> >InterruptObject;
> 
> -    return KeAcquireInterruptSpinLock(InterruptObject);
> +    IoDisconnectInterruptEx(&Disconnect);
> +
> +    Interrupt->Line = 0;
> +    Interrupt->InterruptObject = NULL;
> +    Interrupt->InterruptMode = 0;
> +    Interrupt->Fdo = NULL;
> +
> +    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
> +    __FdoFree(Interrupt);
> +
> +    Trace("<====\n");
>  }
> -
> -_IRQL_requires_(HIGH_LEVEL)
> -VOID
> -FdoReleaseInterruptLock(
> -    IN  PXENBUS_FDO                 Fdo,
> -    IN  __drv_restoresIRQL KIRQL    Irql
> +
> +static NTSTATUS
> +FdoCreateInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
> +    ULONG               Index;
> +    PXENBUS_INTERRUPT   Interrupt;
> +    NTSTATUS            status;
> +
> +    InitializeListHead(&Fdo->List);
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo-
> >RawResourceList->PartialDescriptors[Index];
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo-
> >TranslatedResourceList->PartialDescriptors[Index];
> +
> +        if (Translated->Type != CmResourceTypeInterrupt)
> +            continue;
> +
> +        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> +
> +        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY ListEntry;
> +
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
> 
> -    KeReleaseInterruptSpinLock(InterruptObject, Irql);
> +    return status;
>  }
> 
> -ULONG
> +NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    )
> +{
> +    PLIST_ENTRY             ListEntry;
> +    KIRQL                   Irql;
> +    NTSTATUS                status;
> +
> +    for (ListEntry = Fdo->List.Flink;
> +         ListEntry != &Fdo->List;
> +         ListEntry = ListEntry->Flink) {
> +        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> +
> +        if ((*Interrupt)->Callback == NULL &&
> +            (*Interrupt)->InterruptMode == InterruptMode &&
> +            (*Interrupt)->Cpu == Cpu)
> +            goto found;
> +    }
> +
> +    *Interrupt = NULL;
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> +
> +found:
> +    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
> +    (*Interrupt)->Callback = Callback;
> +    (*Interrupt)->Argument = Argument;
> +    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +UCHAR
>  FdoGetInterruptVector(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Vector;
> +}
> +
> +ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      )
>  {
> -    PXENBUS_RESOURCE    Interrupt;
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    return Interrupt->Line;
> +}
> 
> -    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
> +VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    )
> +{
> +    KIRQL                   Irql;
> 
> -    return Interrupt->Raw.u.Interrupt.Vector;
> +    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
> +    Interrupt->Callback = NULL;
> +    Interrupt->Argument = NULL;
> +    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
>  }
> 
>  static VOID
> -FdoDisconnectInterrupt(
> -    IN  PXENBUS_FDO                     Fdo
> +FdoDestroyInterrupt(
> +    IN  PXENBUS_FDO     Fdo
>      )
>  {
> -    PKINTERRUPT                         InterruptObject;
> -    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
> +    while (!IsListEmpty(&Fdo->List)) {
> +        PLIST_ENTRY         ListEntry;
> +        PXENBUS_INTERRUPT   Interrupt;
> 
> -    Trace("====>\n");
> +        ListEntry = RemoveHeadList(&Fdo->List);
> +        ASSERT(ListEntry != &Fdo->List);
> 
> -    InterruptObject = Fdo->InterruptObject;
> -    Fdo->InterruptObject = NULL;
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> 
> -    RtlZeroMemory(&Disconnect, sizeof
> (IO_DISCONNECT_INTERRUPT_PARAMETERS));
> -    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
> -    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
> +        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT,
> ListEntry);
> 
> -    IoDisconnectInterruptEx(&Disconnect);
> +#pragma warning(push)
> +#pragma warning(disable:4054)   // 'type cast' : from function pointer to
> data pointer
> +        ASSERT3P(Interrupt->Callback, ==, NULL);
> +#pragma warning(pop)
> 
> -    Trace("<====\n");
> +        ASSERT3P(Interrupt->Argument, ==, NULL);
> +
> +        FdoDisconnectInterrupt(Fdo, Interrupt);
> +    }
> +
> +    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
>  }
> 
>  static
> @@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
> 
>  static NTSTATUS
>  FdoCreateIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    PHYSICAL_ADDRESS                End;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    status = STATUS_OBJECT_NAME_NOT_FOUND;
> +    goto fail1;
> 
> +found:
>      status = XENBUS_RANGE_SET(Create,
>                                &Fdo->RangeSetInterface,
>                                "io_space",
>                                &Fdo->RangeSet);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> 
>      status = XENBUS_RANGE_SET(Put,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail3;
> +
> +    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated-
> >u.Memory.Length - 1;
> +
> +    Info("%08x.%08x - %08x.%08x\n",
> +         Translated->u.Memory.Start.HighPart,
> +         Translated->u.Memory.Start.LowPart,
> +         End.HighPart,
> +         End.LowPart);
> 
>      return STATUS_SUCCESS;
> 
> -fail2:
> -    Error("fail2\n");
> +fail3:
> +    Error("fail3\n");
> 
>      XENBUS_RANGE_SET(Destroy,
>                       &Fdo->RangeSetInterface,
>                       Fdo->RangeSet);
>      Fdo->RangeSet = NULL;
> 
> +fail2:
> +    Error("fail2\n");
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
> 
>  static VOID
>  FdoDestroyIoSpace(
> -    IN  PXENBUS_FDO     Fdo
> +    IN  PXENBUS_FDO                 Fdo
>      )
>  {
> -    PXENBUS_RESOURCE    Memory;
> -    NTSTATUS            status;
> +    ULONG                           Index;
> +    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
> +    NTSTATUS                        status;
> +
> +    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
> +        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
> 
> -    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
> +        if (Translated->Type == CmResourceTypeMemory)
> +            goto found;
> +    }
> +
> +    ASSERT(FALSE);
> +    return;
> 
> +found:
>      status = XENBUS_RANGE_SET(Get,
>                                &Fdo->RangeSetInterface,
>                                Fdo->RangeSet,
> -                              Memory->Translated.u.Memory.Start.QuadPart,
> -                              Memory->Translated.u.Memory.Length);
> +                              Translated->u.Memory.Start.QuadPart,
> +                              Translated->u.Memory.Length);
>      ASSERT(NT_SUCCESS(status));
> 
>      XENBUS_RANGE_SET(Destroy,
> @@ -2214,39 +2636,111 @@ FdoS3ToS4(
>      Trace("<====\n");
>  }
> 
> +static VOID
> +FdoFilterCmPartialResourceList(
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PCM_PARTIAL_RESOURCE_LIST   List
> +    )
> +{
> +    ULONG                           Index;
> +
> +    UNREFERENCED_PARAMETER(Fdo);
> +
> +    for (Index = 0; Index < List->Count; Index++) {
> +        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List-
> >PartialDescriptors[Index];
> +
> +        //
> +        // These are additional resources that XENBUS requested, so they must
> +        // be filtered out before the underlying PCI bus driver sees them.
> Happily
> +        // it appears that swapping the type to DevicePrivate causes PCI.SYS to
> ignore
> +        // them.
> +        //
> +        if (Descriptor->Type == CmResourceTypeInterrupt &&
> +            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
> +            Descriptor->Type = CmResourceTypeDevicePrivate;
> +    }
> +}
> +
>  static NTSTATUS
>  FdoStartDevice(
> -    IN  PXENBUS_FDO     Fdo,
> -    IN  PIRP            Irp
> +    IN  PXENBUS_FDO                 Fdo,
> +    IN  PIRP                        Irp
>      )
>  {
> -    PIO_STACK_LOCATION  StackLocation;
> -    NTSTATUS            status;
> +    PIO_STACK_LOCATION              StackLocation;
> +    PCM_RESOURCE_LIST               ResourceList;
> +    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
> +    ULONG                           Size;
> +    NTSTATUS                        status;
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> -    status = FdoForwardIrpSynchronously(Fdo, Irp);
> -    if (!NT_SUCCESS(status))
> +    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +
> +    // Raw
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResources;
> +    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->RawResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->RawResourceList == NULL)
>          goto fail1;
> 
> -    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +    RtlCopyMemory(Fdo->RawResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> +
> +    // Translated
> +
> +    ResourceList = StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated;
> +    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
> +
> +    ASSERT3U(ResourceList->Count, ==, 1);
> +    Descriptor = &ResourceList->List[0];
> +
> +    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
> +    ASSERT3U(Descriptor->BusNumber, ==, 0);
> +
> +    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
> +           (Descriptor->PartialResourceList.Count) * sizeof
> (CM_PARTIAL_RESOURCE_DESCRIPTOR);
> +
> +    Fdo->TranslatedResourceList = __FdoAllocate(Size);
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Fdo->TranslatedResourceList == NULL)
> +        goto fail2;
> +
> +    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor-
> >PartialResourceList, Size);
> +
> +    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
> 
> -    FdoParseResources(Fdo,
> -                      StackLocation->Parameters.StartDevice.AllocatedResources,
> -                      StackLocation-
> >Parameters.StartDevice.AllocatedResourcesTranslated);
> +    status = FdoForwardIrpSynchronously(Fdo, Irp);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
>      if (!__FdoIsActive(Fdo))
>          goto not_active;
> 
> -    status = FdoConnectInterrupt(Fdo);
> +    status = FdoCreateInterrupt(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail4;
> 
>      KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
> 
>      status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
>      if (!NT_SUCCESS(status))
> -        goto fail3;
> +        goto fail5;
> 
>      InitializeMutex(&Fdo->BalloonSuspendMutex);
> 
> @@ -2254,20 +2748,20 @@ FdoStartDevice(
> 
>      status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
>      if (!NT_SUCCESS(status))
> -        goto fail4;
> +        goto fail6;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
> 
>          status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
>          if (!NT_SUCCESS(status))
> -            goto fail5;
> +            goto fail7;
>      }
> 
>  not_active:
>      status = FdoD3ToD0(Fdo);
>      if (!NT_SUCCESS(status))
> -        goto fail6;
> +        goto fail8;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          BOOLEAN Warned;
> @@ -2306,11 +2800,11 @@ not_active:
> 
>      return status;
> 
> -fail6:
> -    Error("fail6\n");
> +fail8:
> +    Error("fail8\n");
> 
>      if (!__FdoIsActive(Fdo))
> -        goto fail2;
> +        goto fail4;
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL) {
>          ThreadAlert(Fdo->BalloonThread);
> @@ -2318,8 +2812,8 @@ fail6:
>          Fdo->BalloonThread = NULL;
>      }
> 
> -fail5:
> -    Error("fail5\n");
> +fail7:
> +    Error("fail7\n");
> 
>      if (Fdo->BalloonInterface.Interface.Context != NULL)
>          RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
> @@ -2328,8 +2822,8 @@ fail5:
>      ThreadJoin(Fdo->SuspendThread);
>      Fdo->SuspendThread = NULL;
> 
> -fail4:
> -    Error("fail4\n");
> +fail6:
> +    Error("fail6\n");
> 
>      RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
> 
> @@ -2339,17 +2833,27 @@ fail4:
>      ThreadJoin(Fdo->ScanThread);
>      Fdo->ScanThread = NULL;
> 
> -fail3:
> -    Error("fail3\n");
> +fail5:
> +    Error("fail5\n");
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> +
> +fail4:
> +    Error("fail4\n");
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> 
>  fail2:
>      Error("fail2\n");
> 
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>  fail1:
>      Error("fail1 (%08x)\n", status);
> @@ -2445,10 +2949,14 @@ FdoStopDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
>      __FdoSetDevicePnpState(Fdo, Stopped);
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2554,6 +3062,9 @@ FdoRemoveDevice(
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
> 
> +    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
> +        goto done;
> +
>      if (__FdoIsActive(Fdo)) {
>          Trace("waiting for scan thread...\n");
> 
> @@ -2621,11 +3132,16 @@ FdoRemoveDevice(
> 
>      RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
> 
> -    FdoDisconnectInterrupt(Fdo);
> +    FdoDestroyInterrupt(Fdo);
> 
>  not_active:
> -    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) *
> RESOURCE_COUNT);
> +    __FdoFree(Fdo->TranslatedResourceList);
> +    Fdo->TranslatedResourceList = NULL;
> +
> +    __FdoFree(Fdo->RawResourceList);
> +    Fdo->RawResourceList = NULL;
> 
> +done:
>      __FdoSetDevicePnpState(Fdo, Deleted);
> 
>      Irp->IoStatus.Status = STATUS_SUCCESS;
> @@ -2937,6 +3453,10 @@ FdoDispatchPnp(
>            PnpMinorFunctionName(MinorFunction));
> 
>      switch (StackLocation->MinorFunction) {
> +    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
> +        status = FdoFilterResourceRequirements(Fdo, Irp);
> +        break;
> +
>      case IRP_MN_START_DEVICE:
>          status = FdoStartDevice(Fdo, Irp);
>          break;
> diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
> index fdb6f79..4916be4 100644
> --- a/src/xenbus/fdo.h
> +++ b/src/xenbus/fdo.h
> @@ -38,6 +38,8 @@
>  #include "driver.h"
>  #include "types.h"
> 
> +typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT,
> *PXENBUS_INTERRUPT;
> +
>  extern NTSTATUS
>  FdoCreate(
>      IN  PDEVICE_OBJECT  PhysicalDeviceObject,
> @@ -140,11 +142,6 @@ FdoFreeIoSpace(
>      IN  ULONG               Size
>      );
> 
> -extern ULONG
> -FdoGetInterruptVector(
> -    IN  PXENBUS_FDO Fdo
> -    );
> -
>  // Disable erroneous SAL warnings around use of interrupt locks
>  #pragma warning(disable:28230)
>  #pragma warning(disable:28285)
> @@ -155,7 +152,8 @@ _IRQL_saves_
>  _IRQL_raises_(HIGH_LEVEL)
>  KIRQL
>  FdoAcquireInterruptLock(
> -    IN  PXENBUS_FDO Fdo
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
>      );
> 
>  extern
> @@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
>  VOID
>  FdoReleaseInterruptLock(
>      IN  PXENBUS_FDO                 Fdo,
> +    IN  PXENBUS_INTERRUPT           Interrupt,
>      IN  __drv_restoresIRQL KIRQL    Irql
>      );
> 
> +extern NTSTATUS
> +FdoAllocateInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  KINTERRUPT_MODE     InterruptMode,
> +    IN  ULONG               Cpu,
> +    IN  KSERVICE_ROUTINE    Callback,
> +    IN  PVOID               Argument OPTIONAL,
> +    OUT PXENBUS_INTERRUPT   *Interrupt
> +    );
> +
> +extern UCHAR
> +FdoGetInterruptVector(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern ULONG
> +FdoGetInterruptLine(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
> +extern VOID
> +FdoFreeInterrupt(
> +    IN  PXENBUS_FDO         Fdo,
> +    IN  PXENBUS_INTERRUPT   Interrupt
> +    );
> +
>  #include "suspend.h"
> 
>  extern PXENBUS_SUSPEND_CONTEXT
> diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
> index 650e84d..ad0d4de 100644
> --- a/src/xenbus/pdo.c
> +++ b/src/xenbus/pdo.c
> @@ -682,7 +682,7 @@ PdoParseResources(
>                __PdoGetName(Pdo),
>                Index,
>                TranslatedPartialDescriptor->Type,
> -              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor-
> >Type));
> +              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
> 
>          switch (TranslatedPartialDescriptor->Type) {
>          case CmResourceTypeMemory:
> --
> 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 Nov 07 14:31:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:04 +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 1XmkZ5-0006Ue-Ts; Fri, 07 Nov 2014 14:31:03 +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 1XmkZ5-0006UQ-0H
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:03 +0000
Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id
	14/0D-26740-6A7DC545; Fri, 07 Nov 2014 14:31:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16340 invoked from network); 7 Nov 2014 14:31:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143112"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-5P;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:35 +0000
Message-ID: <1415370635-26884-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 ++++++-
 include/xen.h              |  16 +++
 src/xen/event_channel.c    |  30 ++++++
 src/xen/hvm.c              |  28 ++++++
 src/xenbus/evtchn.c        | 239 ++++++++++++++++++++++++++++++++++++++++++---
 src/xenbus/store.c         |   9 ++
 6 files changed, 341 insertions(+), 16 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..aa26a31 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -82,13 +82,16 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,15 +130,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +170,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +201,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +213,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +402,10 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -422,6 +470,89 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto done;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -516,7 +647,7 @@ EvtchnTrigger(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
@@ -527,7 +658,7 @@ EvtchnTrigger(
         DoneSomething = FALSE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
 
     return DoneSomething;
 }
@@ -575,6 +706,8 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +750,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +763,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -767,8 +912,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1009,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1067,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1092,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1163,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1177,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1227,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1171,6 +1365,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 14:31:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:04 +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 1XmkZ5-0006Ua-Sn; Fri, 07 Nov 2014 14:31:03 +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 1XmkZ4-0006UP-8Q
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:02 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	69/D3-28296-5A7DC545; Fri, 07 Nov 2014 14:31:01 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16146 invoked from network); 7 Nov 2014 14:31:00 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:00 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143109"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-3Z;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:32 +0000
Message-ID: <1415370635-26884-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 27023
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuL3hlbl92ZXJz
aW9uLmMgIHwgMTA3ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysKIHNyYy94ZW5idXMvZmRvLmMgICAgICAgfCAgIDIgKwogc3JjL3hlbmJ1cy9zdXNwZW5kLmMg
ICB8ICAgMiArCiB2czIwMTIveGVuL3hlbi52Y3hwcm9qIHwgICAxICsKIHZzMjAxMy94ZW4veGVu
LnZjeHByb2ogfCAgIDMgKy0KIDExIGZpbGVzIGNoYW5nZWQsIDQwNiBpbnNlcnRpb25zKCspLCAz
MSBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi9mZWF0dXJlcy5o
CiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vdmVyc2lvbi5oCiBjcmVhdGUgbW9kZSAx
MDA2NDQgc3JjL3hlbi94ZW5fdmVyc2lvbi5jCgpkaWZmIC0tZ2l0IGEvZ2V0X3hlbl9oZWFkZXJz
LnB5IGIvZ2V0X3hlbl9oZWFkZXJzLnB5CmluZGV4IDVjYTVjOTMuLmVmMWEyYzggMTAwNjQ0Ci0t
LSBhL2dldF94ZW5faGVhZGVycy5weQorKysgYi9nZXRfeGVuX2hlYWRlcnMucHkKQEAgLTYxLDYg
KzYxLDggQEAgaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgICBjb3B5X2ZpbGUod29ya2lu
ZywgJ3B1YmxpYycsICcuJywgJ3NjaGVkLmgnKQogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZXZlbnRfY2hhbm5lbC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1
YmxpYycsICcuJywgJ2dyYW50X3RhYmxlLmgnKQorICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAndmVyc2lvbi5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2ZlYXR1cmVzLmgnKQogCiAgICAgY29weV9maWxlKHdvcmtpbmcsICd4ZW4nLCAnLics
ICdlcnJuby5oJykKIApkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBiL2luY2x1ZGUveGVuLmgK
aW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQKLS0tIGEvaW5jbHVkZS94ZW4uaAorKysgYi9p
bmNsdWRlL3hlbi5oCkBAIC00NCw2ICs0NCw3IEBACiAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+CiAj
aW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMuaD4KICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPgor
I2luY2x1ZGUgPHhlbi92ZXJzaW9uLmg+CiAKICNpZm5kZWYgWEVOX0FQSQogI2RlZmluZSBYRU5f
QVBJIF9fZGVjbHNwZWMoZGxsaW1wb3J0KQpAQCAtNTYsNiArNTcsMTQgQEAgWGVuVG91Y2goCiAg
ICAgVk9JRAogICAgICk7CiAKKy8vIEhZUEVSQ0FMTAorCitYRU5fQVBJCitWT0lECitIeXBlcmNh
bGxQb3B1bGF0ZSgKKyAgICBWT0lECisgICAgKTsKKwogLy8gSFZNCiAKIF9fY2hlY2tSZXR1cm4K
QEAgLTIzMyw2ICsyNDIsMjMgQEAgU2NoZWRZaWVsZCgKICAgICBWT0lECiAgICAgKTsKIAorLy8g
WEVOIFZFUlNJT04KKworX19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNp
b24oCisgICAgT1VUIFBVTE9ORyAgTWFqb3IsCisgICAgT1VUIFBVTE9ORyAgTWlub3IKKyAgICAp
OworCitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbkV4dHJhKAor
ICAgIE9VVCBQQ0hBUiAgIEV4dHJhCisgICAgKTsKKwogLy8gTU9EVUxFCiAKIFhFTl9BUEkKZGlm
ZiAtLWdpdCBhL2luY2x1ZGUveGVuL2ZlYXR1cmVzLmggYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmI3YmY4M2YKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oCkBAIC0wLDAgKzEsMTEyIEBACisvKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqCisgKiBmZWF0dXJlcy5oCisgKiAKKyAqIEZlYXR1cmUgZmxhZ3MsIHJl
cG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMuCisgKiAKKyAqIFBlcm1pc3Npb24gaXMgaGVy
ZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNv
cHkKKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxl
cyAodGhlICJTb2Z0d2FyZSIpLCB0bworICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCBy
ZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUKKyAqIHJpZ2h0cyB0
byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vu
c2UsIGFuZC9vcgorICogc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0
IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywg
c3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNv
cHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVk
ZWQgaW4KKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdB
UlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVU
IE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJ
VE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5P
IEVWRU5UIFNIQUxMIFRIRQorICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFC
TEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBXSEVUSEVS
IElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKKyAq
IEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBV
U0UgT1IgT1RIRVIKKyAqIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBDb3B5cmln
aHQgKGMpIDIwMDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+CisgKi8KKworI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19GRUFU
VVJFU19IX18KKworLyoKKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19mZWF0dXJlcyBYRU5f
RUxGTk9URV9GRUFUVVJFUworICoKKyAqIFRoZSBsaXN0IG9mIGFsbCB0aGUgZmVhdHVyZXMgdGhl
IGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkKKyAqIHBhcnNpbmcgdGhlIFhFTl9FTEZO
T1RFX0ZFQVRVUkVTIGFuZCBYRU5fRUxGTk9URV9TVVBQT1JURURfRkVBVFVSRVMKKyAqIHN0cmlu
Zy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUgbmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91
dCB0aGUKKyAqICJYRU5GRUFUXyIgcHJlZml4KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMu
CisgKiBJZiBhIGZlYXR1cmUgaXMgcmVxdWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24g
dGhlbiB0aGUgZmVhdHVyZSBuYW1lCisgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJh
Y3Rlci4KKyAqCisgKiBOb3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVT
IGlzIHVzZWQsIHRoZW4gaW4gdGhlCisgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhl
IGd1ZXN0IGlzIHRvIGJlIGJvb3RlZCBhcyBkb20wLAorICovCisKKy8qCisgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4KKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLgorICovCisjZGVmaW5lIFhF
TkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMAorCisvKgorICogSWYgc2V0LCB0aGUg
Z3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBzZWdtZW50IGRlc2NyaXB0
b3IKKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAq
LworI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rlc2NyaXB0b3JfdGFibGVzIDEKKworLyoKKyAq
IElmIHNldCwgdHJhbnNsYXRpb24gYmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2Fs
JyBhZGRyZXNzIHNwYWNlCisgKiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2Ug
YXJlIGhhbmRsZWQgYnkgdGhlIGh5cGVydmlzb3IuIEluIHRoaXMKKyAqIG1vZGUgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZSB0cmFuc2xhdGlv
bnMKKyAqIHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuCisgKi8KKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyCisKKy8qIElmIHNldCwgdGhl
IGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmluZyAwKS4g
Ki8KKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAzCisKKy8qCisg
KiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFsbG9jYXRlIHg4NiBQQUUgcGFn
ZSBkaXJlY3RvcmllcworICogYmVsb3cgNEdCLiBUaGlzIGZsYWcgaXMgdXN1YWxseSBpbXBsaWVk
IGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLgorICovCisjZGVmaW5lIFhFTkZFQVRfcGFlX3Bn
ZGlyX2Fib3ZlXzRnYiAgICAgICAgNAorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBw
b3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BSRVNFUlZFX0FEIGh5cGVyY2FsbD8gKi8KKyNkZWZpbmUg
WEVORkVBVF9tbXVfcHRfdXBkYXRlX3ByZXNlcnZlX2FkICA1CisKKy8qIHg4NjogRG9lcyB0aGlz
IFhlbiBob3N0IHN1cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRSBoeXBlcmNhbGw/ICov
CisjZGVmaW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNgorCisvKgorICog
SWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFjZWQg
aW50byBndWVzdCBrZXJuZWwKKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4KKyAqLworI2RlZmluZSBY
RU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcKKworLyogeDg2OiBEb2VzIHRoaXMg
WGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZlY3RvciB0eXBlPyAqLworI2RlZmlu
ZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAgICAgIDgKKworLyogeDg2OiBwdmNsb2Nr
IGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBvbiBIVk0gKi8KKyNkZWZpbmUgWEVORkVBVF9odm1f
c2FmZV9wdmNsb2NrICAgICAgICAgICA5CisKKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBI
Vk0gZ3Vlc3RzICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAx
MAorCisvKiBvcGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8KKyNkZWZpbmUgWEVORkVB
VF9kb20wICAgICAgICAgICAgICAgICAgICAgIDExCisKKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8KKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBfaWRl
bnRpdHkgICAgICAgIDEyCisKKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEKKworI2VuZGlm
IC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8KKworLyoKKyAqIExvY2FsIHZhcmlhYmxl
czoKKyAqIG1vZGU6IEMKKyAqIGMtZmlsZS1zdHlsZTogIkJTRCIKKyAqIGMtYmFzaWMtb2Zmc2V0
OiA0CisgKiB0YWItd2lkdGg6IDQKKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbAorICogRW5kOgor
ICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJz
aW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNDRmMjZiMAotLS0gL2Rl
di9udWxsCisrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaApAQCAtMCwwICsxLDk2IEBACisvKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqCisgKiB2ZXJzaW9uLmgKKyAqIAorICogWGVuIHZlcnNpb24sIHR5
cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVi
eSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5
CisgKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMg
KHRoZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVz
dHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8g
dXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNl
LCBhbmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBw
ZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1
YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5
cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVk
IGluCisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2Fy
ZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJS
QU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBO
T1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRO
RVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBF
VkVOVCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxF
IEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJ
TiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBG
Uk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNF
IE9SIE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0
IChjKSAyMDA1LCBOZ3V5ZW4gQW5oIFF1eW5oIDxhcXV5bmhAZ21haWwuY29tPgorICogQ29weXJp
Z2h0IChjKSAyMDA1LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNp
Zm5kZWYgX19YRU5fUFVCTElDX1ZFUlNJT05fSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19WRVJT
SU9OX0hfXworCisjaW5jbHVkZSAieGVuLmgiCisKKy8qIE5CLiBBbGwgb3BzIHJldHVybiB6ZXJv
IG9uIHN1Y2Nlc3MsIGV4Y2VwdCBYRU5WRVJfe3ZlcnNpb24scGFnZXNpemV9ICovCisKKy8qIGFy
ZyA9PSBOVUxMOyByZXR1cm5zIG1ham9yOm1pbm9yICgxNjoxNikuICovCisjZGVmaW5lIFhFTlZF
Ul92ZXJzaW9uICAgICAgMAorCisvKiBhcmcgPT0geGVuX2V4dHJhdmVyc2lvbl90LiAqLworI2Rl
ZmluZSBYRU5WRVJfZXh0cmF2ZXJzaW9uIDEKK3R5cGVkZWYgY2hhciB4ZW5fZXh0cmF2ZXJzaW9u
X3RbMTZdOworI2RlZmluZSBYRU5fRVhUUkFWRVJTSU9OX0xFTiAoc2l6ZW9mKHhlbl9leHRyYXZl
cnNpb25fdCkpCisKKy8qIGFyZyA9PSB4ZW5fY29tcGlsZV9pbmZvX3QuICovCisjZGVmaW5lIFhF
TlZFUl9jb21waWxlX2luZm8gMgorc3RydWN0IHhlbl9jb21waWxlX2luZm8geworICAgIGNoYXIg
Y29tcGlsZXJbNjRdOworICAgIGNoYXIgY29tcGlsZV9ieVsxNl07CisgICAgY2hhciBjb21waWxl
X2RvbWFpblszMl07CisgICAgY2hhciBjb21waWxlX2RhdGVbMzJdOworfTsKK3R5cGVkZWYgc3Ry
dWN0IHhlbl9jb21waWxlX2luZm8geGVuX2NvbXBpbGVfaW5mb190OworCisjZGVmaW5lIFhFTlZF
Ul9jYXBhYmlsaXRpZXMgMwordHlwZWRlZiBjaGFyIHhlbl9jYXBhYmlsaXRpZXNfaW5mb190WzEw
MjRdOworI2RlZmluZSBYRU5fQ0FQQUJJTElUSUVTX0lORk9fTEVOIChzaXplb2YoeGVuX2NhcGFi
aWxpdGllc19pbmZvX3QpKQorCisjZGVmaW5lIFhFTlZFUl9jaGFuZ2VzZXQgNAordHlwZWRlZiBj
aGFyIHhlbl9jaGFuZ2VzZXRfaW5mb190WzY0XTsKKyNkZWZpbmUgWEVOX0NIQU5HRVNFVF9JTkZP
X0xFTiAoc2l6ZW9mKHhlbl9jaGFuZ2VzZXRfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfcGxh
dGZvcm1fcGFyYW1ldGVycyA1CitzdHJ1Y3QgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnMgeworICAg
IHhlbl91bG9uZ190IHZpcnRfc3RhcnQ7Cit9OwordHlwZWRlZiBzdHJ1Y3QgeGVuX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnNfdDsKKworI2RlZmluZSBYRU5WRVJf
Z2V0X2ZlYXR1cmVzIDYKK3N0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHsKKyAgICB1bnNpZ25lZCBp
bnQgc3VibWFwX2lkeDsgICAgLyogSU46IHdoaWNoIDMyLWJpdCBzdWJtYXAgdG8gcmV0dXJuICov
CisgICAgdWludDMyX3QgICAgIHN1Ym1hcDsgICAgICAgIC8qIE9VVDogMzItYml0IHN1Ym1hcCAq
LworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9mZWF0dXJlX2luZm8geGVuX2ZlYXR1cmVfaW5mb190
OworCisvKiBEZWNsYXJlcyB0aGUgZmVhdHVyZXMgcmVwb3J0ZWQgYnkgWEVOVkVSX2dldF9mZWF0
dXJlcy4gKi8KKyNpbmNsdWRlICJmZWF0dXJlcy5oIgorCisvKiBhcmcgPT0gTlVMTDsgcmV0dXJu
cyBob3N0IG1lbW9yeSBwYWdlIHNpemUuICovCisjZGVmaW5lIFhFTlZFUl9wYWdlc2l6ZSA3CisK
Ky8qIGFyZyA9PSB4ZW5fZG9tYWluX2hhbmRsZV90LiAqLworI2RlZmluZSBYRU5WRVJfZ3Vlc3Rf
aGFuZGxlIDgKKworI2RlZmluZSBYRU5WRVJfY29tbWFuZGxpbmUgOQordHlwZWRlZiBjaGFyIHhl
bl9jb21tYW5kbGluZV90WzEwMjRdOworCisjZW5kaWYgLyogX19YRU5fUFVCTElDX1ZFUlNJT05f
SF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6CisgKiBtb2RlOiBDCisgKiBjLWZpbGUt
c3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAorICogdGFiLXdpZHRoOiA0CisgKiBp
bmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpkaWZmIC0tZ2l0IGEvc3JjL3hlbi9k
cml2ZXIuYyBiL3NyYy94ZW4vZHJpdmVyLmMKaW5kZXggYmE1NDFiNC4uZmNlNzVhYSAxMDA2NDQK
LS0tIGEvc3JjL3hlbi9kcml2ZXIuYworKysgYi9zcmMveGVuL2RyaXZlci5jCkBAIC01OSw2ICs1
OSwyNiBAQCBYZW5Ub3VjaCgKICAgICBWT0lECiAgICAgKQogeworICAgIHN0YXRpYyBVTE9ORyAg
ICBSZWZlcmVuY2U7CisgICAgVUxPTkcgICAgICAgICAgIE1ham9yOworICAgIFVMT05HICAgICAg
ICAgICBNaW5vcjsKKyAgICBDSEFSICAgICAgICAgICAgRXh0cmFbWEVOX0VYVFJBVkVSU0lPTl9M
RU5dOworICAgIE5UU1RBVFVTICAgICAgICBzdGF0dXM7CisKKyAgICBpZiAoUmVmZXJlbmNlKysg
IT0gMCkKKyAgICAgICAgcmV0dXJuOworCisgICAgc3RhdHVzID0gWGVuVmVyc2lvbigmTWFqb3Is
ICZNaW5vcik7CisgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7CisKKyAgICBzdGF0dXMg
PSBYZW5WZXJzaW9uRXh0cmEoRXh0cmEpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykp
OworCisgICAgTG9nUHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAiWEVOOiAl
dS4ldSVzXG4iLAorICAgICAgICAgICAgICBNYWpvciwKKyAgICAgICAgICAgICAgTWlub3IsCisg
ICAgICAgICAgICAgIEV4dHJhKTsKIH0KIAogc3RhdGljIFZPSUQKZGlmZiAtLWdpdCBhL3NyYy94
ZW4vaHlwZXJjYWxsLmMgYi9zcmMveGVuL2h5cGVyY2FsbC5jCmluZGV4IDA3ZWI0MWEuLjcxN2I4
YzIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW4vaHlwZXJjYWxsLmMKKysrIGIvc3JjL3hlbi9oeXBlcmNh
bGwuYwpAQCAtMjksNiArMjksOSBAQAogICogU1VDSCBEQU1BR0UuCiAgKi8KIAorI3VuZGVmICBY
RU5fQVBJCisjZGVmaW5lIFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpCisKICNpbmNsdWRl
IDxudGRkay5oPgogI2luY2x1ZGUgPHhlbi5oPgogI2luY2x1ZGUgPHV0aWwuaD4KQEAgLTM3LDI0
ICs0MCw0MSBAQAogI2luY2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgog
Ci0jZGVmaW5lIE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCAyCisjZGVmaW5lIE1BWElNVU1f
SFlQRVJDQUxMX1BBR0VfQ09VTlQgMgogCiAjcHJhZ21hIGNvZGVfc2VnKCJoeXBlcmNhbGwiKQog
X19kZWNsc3BlYyhhbGxvY2F0ZSgiaHlwZXJjYWxsIikpCi1zdGF0aWMgVUNIQVIgICAgICAgIF9f
U2VjdGlvblsoTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UICsgMSkgKiBQQUdFX1NJWkVdOwor
c3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09V
TlQgKyAxKSAqIFBBR0VfU0laRV07CiAKIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYg
PSAweDQwMDAwMDAwOwogCi1zdGF0aWMgVVNIT1JUICAgICAgIFhlbk1ham9yVmVyc2lvbjsKLXN0
YXRpYyBVU0hPUlQgICAgICAgWGVuTWlub3JWZXJzaW9uOwotCi1zdGF0aWMgUEZOX05VTUJFUiAg
IEh5cGVyY2FsbFBmbltNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlRdOwotc3RhdGljIFVMT05H
ICAgICAgICBIeXBlcmNhbGxQZm5Db3VudDsKK3N0YXRpYyBQSFlTSUNBTF9BRERSRVNTIEh5cGVy
Y2FsbFBhZ2VbTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVF07CitzdGF0aWMgVUxPTkcgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlQ291bnQ7CiAKIHR5cGVkZWYgVUNIQVIgICAgICAgICAgIEhZ
UEVSQ0FMTF9HQVRFWzMyXTsKIHR5cGVkZWYgSFlQRVJDQUxMX0dBVEUgICpQSFlQRVJDQUxMX0dB
VEU7CiAKIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxsOworVUxPTkcgICAgICAgICAgICAg
ICBIeXBlcmNhbGxNc3I7CisKK1hFTl9BUEkKK1ZPSUQKK0h5cGVyY2FsbFBvcHVsYXRlKAorICAg
IFZPSUQKKyAgICApCit7CisgICAgVUxPTkcgICAgICAgSW5kZXg7CisKKyAgICBmb3IgKEluZGV4
ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsKKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJDQUxM
IFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsCisgICAgICAgICAgICAgICAgICBJbmRleCwKKyAgICAg
ICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LAorICAgICAgICAgICAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7CisKKyAgICAgICAgX193cml0ZW1z
cihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0KTsKKyAgICB9Cit9
CiAKIE5UU1RBVFVTCiBIeXBlcmNhbGxJbml0aWFsaXplKApAQCAtNjYsNyArODYsNiBAQCBIeXBl
cmNhbGxJbml0aWFsaXplKAogICAgIFVMT05HICAgICAgIEVDWCA9ICdERUFEJzsKICAgICBVTE9O
RyAgICAgICBFRFggPSAnREVBRCc7CiAgICAgVUxPTkcgICAgICAgSW5kZXg7Ci0gICAgVUxPTkcg
ICAgICAgSHlwZXJjYWxsTXNyOwogICAgIE5UU1RBVFVTICAgIHN0YXR1czsKIAogICAgIHN0YXR1
cyA9IFNUQVRVU19VTlNVQ0NFU1NGVUw7CkBAIC04OCwxMyArMTA3LDYgQEAgSHlwZXJjYWxsSW5p
dGlhbGl6ZSgKICAgICAgICAgICAgIGdvdG8gZmFpbDE7CiAgICAgfQogCi0gICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOwotICAgIFhlbk1ham9yVmVy
c2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7Ci0gICAgWGVuTWlub3JWZXJzaW9uID0gKFVTSE9S
VCkoRUFYICYgMHhGRkZGKTsKLQotICAgIEluZm8oIlhFTiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJz
aW9uLCBYZW5NaW5vclZlcnNpb24pOwotICAgIEluZm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9f
WEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOwotCiAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9u
ICYgKFBBR0VfU0laRSAtIDEpKQogICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdf
UFRSKV9fU2VjdGlvbiArIFBBR0VfU0laRSAtIDEpICYgfihQQUdFX1NJWkUgLSAxKSk7CiAgICAg
ZWxzZQpAQCAtMTAyLDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgKIAogICAgIEFT
U0VSVDNVKCgoVUxPTkdfUFRSKUh5cGVyY2FsbCAmIChQQUdFX1NJWkUgLSAxKSksID09LCAwKTsK
IAotICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VO
VDsgSW5kZXgrKykgewotICAgICAgICBQSFlTSUNBTF9BRERSRVNTICAgIFBoeXNpY2FsQWRkcmVz
czsKLQotICAgICAgICBQaHlzaWNhbEFkZHJlc3MgPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVD
SEFSKUh5cGVyY2FsbCArIChJbmRleCA8PCBQQUdFX1NISUZUKSk7Ci0gICAgICAgIEh5cGVyY2Fs
bFBmbltJbmRleF0gPSAoUEZOX05VTUJFUikoUGh5c2ljYWxBZGRyZXNzLlF1YWRQYXJ0ID4+IFBB
R0VfU0hJRlQpOwotICAgIH0KKyAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UOyBJbmRleCsrKQorICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4
XSA9IE1tR2V0UGh5c2ljYWxBZGRyZXNzKChQVUNIQVIpSHlwZXJjYWxsICsKKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoSW5kZXggPDwgUEFHRV9T
SElGVCkpOwogCiAgICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEws
IE5VTEwpOwotICAgIEh5cGVyY2FsbFBmbkNvdW50ID0gRUFYOwotICAgIEFTU0VSVChIeXBlcmNh
bGxQZm5Db3VudCA8PSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOworICAgIEh5cGVyY2Fs
bFBhZ2VDb3VudCA9IEVBWDsKKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQpOwogICAgIEh5cGVyY2FsbE1zciA9IEVCWDsKIAotICAg
IGZvciAoSW5kZXggPSAwOyBJbmRleCA8IEh5cGVyY2FsbFBmbkNvdW50OyBJbmRleCsrKSB7Ci0g
ICAgICAgIEluZm8oIkh5cGVyY2FsbFBmblslZF06ICVwXG4iLCBJbmRleCwgKFBWT0lEKUh5cGVy
Y2FsbFBmbltJbmRleF0pOwotICAgICAgICBfX3dyaXRlbXNyKEh5cGVyY2FsbE1zciwgKFVMT05H
NjQpSHlwZXJjYWxsUGZuW0luZGV4XSA8PCBQQUdFX1NISUZUKTsKLSAgICB9CisgICAgSHlwZXJj
YWxsUG9wdWxhdGUoKTsKIAogICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsKIApAQCAtMTc3LDgg
KzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKAogCiAgICAgSHlwZXJjYWxsID0gTlVMTDsKIAot
ICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVDsg
SW5kZXgrKykKLSAgICAgICAgSHlwZXJjYWxsUGZuW0luZGV4XSA9IDA7CisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uUXVhZFBhcnQgPSAwOwogCi0gICAgSHlwZXJjYWxs
UGZuQ291bnQgPSAwOworICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7CiB9CmRpZmYgLS1naXQg
YS9zcmMveGVuL3hlbl92ZXJzaW9uLmMgYi9zcmMveGVuL3hlbl92ZXJzaW9uLmMKbmV3IGZpbGUg
bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNmVmMDYxZgotLS0gL2Rldi9udWxsCisrKyBiL3Ny
Yy94ZW4veGVuX3ZlcnNpb24uYwpAQCAtMCwwICsxLDEwNyBAQAorLyogQ29weXJpZ2h0IChjKSBD
aXRyaXggU3lzdGVtcyBJbmMuCisgKiBBbGwgcmlnaHRzIHJlc2VydmVkLgorICogCisgKiBSZWRp
c3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCAKKyAqIHdpdGgg
b3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgCisgKiB0aGF0
IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OgorICogCisgKiAqICAgUmVkaXN0cmli
dXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5
cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZv
bGxvd2luZyBkaXNjbGFpbWVyLgorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9y
bSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhp
cyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1l
ciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgCisgKiAgICAgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqIAorICogVEhJUyBTT0ZUV0FSRSBJUyBQ
Uk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIAorICogQ09OVFJJQlVUT1JTICJB
UyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgCisgKiBJTkNMVURJ
TkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiAKKyAqIE1F
UkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIAor
ICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1Ig
CisgKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D
SURFTlRBTCwgCisgKiBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdF
UyAoSU5DTFVESU5HLCAKKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VC
U1RJVFVURSBHT09EUyBPUiAKKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJP
RklUUzsgT1IgQlVTSU5FU1MgCisgKiBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBP
TiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgCisgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgCisgKiBORUdMSUdFTkNFIE9SIE9USEVS
V0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIAorICogT0YgVEhJUyBTT0ZU
V0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiAKKyAqIFNVQ0ggREFN
QUdFLgorICovCisKKyNkZWZpbmUgWEVOX0FQSSBfX2RlY2xzcGVjKGRsbGV4cG9ydCkKKworI2lu
Y2x1ZGUgPG50ZGRrLmg+CisjaW5jbHVkZSA8eGVuLmg+CisKKyNpbmNsdWRlICJoeXBlcmNhbGwu
aCIKKyNpbmNsdWRlICJkYmdfcHJpbnQuaCIKKyNpbmNsdWRlICJhc3NlcnQuaCIKKworc3RhdGlj
IEZPUkNFSU5MSU5FIExPTkdfUFRSCitYZW5WZXJzaW9uT3AoCisgICAgSU4gIFVMT05HICAgQ29t
bWFuZCwKKyAgICBJTiAgUFZPSUQgICBBcmd1bWVudAorICAgICkKK3sKKyAgICByZXR1cm4gSFlQ
RVJDQUxMKExPTkdfUFRSLCB4ZW5fdmVyc2lvbiwgMiwgQ29tbWFuZCwgQXJndW1lbnQpOworfQor
CitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbigKKyAgICBPVVQg
UFVMT05HICBNYWpvciwKKyAgICBPVVQgUFVMT05HICBNaW5vcgorICAgICkKK3sKKyAgICBMT05H
X1BUUiAgICAgICAgICAgICAgICAgICAgcmM7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIHJjID0gWGVuVmVyc2lvbk9wKFhFTlZFUl92ZXJzaW9uLCBOVUxM
KTsKKworICAgIGlmIChyYyA8IDApIHsKKyAgICAgICAgRVJSTk9fVE9fU1RBVFVTKC1yYywgc3Rh
dHVzKTsKKyAgICAgICAgZ290byBmYWlsMTsKKyAgICB9CisKKyAgICAqTWFqb3IgPSAoVUxPTkcp
KChyYyA+PiAxNikgJiAweEZGRkYpOworICAgICpNaW5vciA9IChVTE9ORykocmMgJiAweEZGRkYp
OworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAgICBFcnJvcigiZmFp
bDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsKK30KKworX19jaGVj
a1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBPVVQgUENI
QVIgICAgICAgICAgIEV4dHJhCisgICAgKQoreworICAgIHhlbl9leHRyYXZlcnNpb25fdCAgb3A7
CisgICAgTE9OR19QVFIgICAgICAgICAgICByYzsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgIHN0
YXR1czsKKworICAgIFJ0bFplcm9NZW1vcnkoJm9wLCBzaXplb2YgKG9wKSk7CisKKyAgICByYyA9
IFhlblZlcnNpb25PcChYRU5WRVJfZXh0cmF2ZXJzaW9uLCAmb3ApOworCisgICAgaWYgKHJjIDwg
MCkgeworICAgICAgICBFUlJOT19UT19TVEFUVVMoLXJjLCBzdGF0dXMpOworICAgICAgICBnb3Rv
IGZhaWwxOworICAgIH0KKworICAgIFJ0bENvcHlNZW1vcnkoRXh0cmEsICZvcCwgWEVOX0VYVFJB
VkVSU0lPTl9MRU4pOworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAg
ICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsK
K30KZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZmRvLmMgYi9zcmMveGVuYnVzL2Zkby5jCmluZGV4
IDU5NDQyYmQuLjIxNWM5OTcgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZmRvLmMKKysrIGIvc3Jj
L3hlbmJ1cy9mZG8uYwpAQCAtMjE4Niw2ICsyMTg2LDggQEAgRmRvUzRUb1MzKAogCiAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsKIAorICAgIEh5cGVyY2FsbFBvcHVsYXRl
KCk7CisKICAgICBpZiAoRmRvLT5VbnBsdWdJbnRlcmZhY2UuSW50ZXJmYWNlLkNvbnRleHQgIT0g
TlVMTCkKICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmRmRvLT5VbnBsdWdJbnRlcmZh
Y2UpOwogCmRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3N1c3BlbmQuYyBiL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCmluZGV4IDZhYjJiZDIuLmRlNzBlNDIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCisrKyBiL3NyYy94ZW5idXMvc3VzcGVuZC5jCkBAIC0xNzMsNiArMTczLDggQEAgU3Vz
cGVuZFRyaWdnZXIoCiAKICAgICAgICAgQ29udGV4dC0+Q291bnQrKzsKIAorICAgICAgICBIeXBl
cmNhbGxQb3B1bGF0ZSgpOworCiAgICAgICAgIGlmIChDb250ZXh0LT5VbnBsdWdJbnRlcmZhY2Uu
SW50ZXJmYWNlLkNvbnRleHQgIT0gTlVMTCkKICAgICAgICAgICAgIFhFTkZJTFRfVU5QTFVHKFJl
cGxheSwgJkNvbnRleHQtPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBhL3ZzMjAxMi94
ZW4veGVuLnZjeHByb2ogYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCmluZGV4IGViNTQ2OTIuLjJm
NGQ5NTggMTAwNjQ0Ci0tLSBhL3ZzMjAxMi94ZW4veGVuLnZjeHByb2oKKysrIGIvdnMyMDEyL3hl
bi94ZW4udmN4cHJvagpAQCAtODgsNiArODgsNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuXGh2bS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5c
eGVuX3ZlcnNpb24uYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5
cGVyY2FsbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cbWVtb3J5
LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxzY2hlZC5jIiAvPgpk
aWZmIC0tZ2l0IGEvdnMyMDEzL3hlbi94ZW4udmN4cHJvaiBiL3ZzMjAxMy94ZW4veGVuLnZjeHBy
b2oKaW5kZXggNDkwMjk0Yy4uODFkNTBlYSAxMDA2NDQKLS0tIGEvdnMyMDEzL3hlbi94ZW4udmN4
cHJvagorKysgYi92czIwMTMveGVuL3hlbi52Y3hwcm9qCkBAIC0xLDQgKzEsNCBAQAot77u/PD94
bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KKzw/eG1sIHZlcnNpb249IjEuMCIg
ZW5jb2Rpbmc9InV0Zi04Ij8+CiA8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xz
VmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxv
cGVyL21zYnVpbGQvMjAwMyI+CiAgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIg
Lz4KICAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgpAQCAtMTI4LDYgKzEyOCw3IEBA
CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+CisgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+CiAgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5cGVyY2FsbC5jIiAvPgogICAgIDxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KICAgICA8Q2xDb21w
aWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4KLS0gCjIuMS4xCgoKX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1h
aWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3Rz
LnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 14:31:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:04 +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 1XmkZ5-0006Ue-Ts; Fri, 07 Nov 2014 14:31:03 +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 1XmkZ5-0006UQ-0H
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:03 +0000
Received: from [85.158.137.68] by server-12.bemta-3.messagelabs.com id
	14/0D-26740-6A7DC545; Fri, 07 Nov 2014 14:31:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16340 invoked from network); 7 Nov 2014 14:31:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143112"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-5P;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:35 +0000
Message-ID: <1415370635-26884-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 ++++++-
 include/xen.h              |  16 +++
 src/xen/event_channel.c    |  30 ++++++
 src/xen/hvm.c              |  28 ++++++
 src/xenbus/evtchn.c        | 239 ++++++++++++++++++++++++++++++++++++++++++---
 src/xenbus/store.c         |   9 ++
 6 files changed, 341 insertions(+), 16 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..aa26a31 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -82,13 +82,16 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,15 +130,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +170,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +201,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +213,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +402,10 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -422,6 +470,89 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto done;
+
+    KeRaiseIrql(HIGH_LEVEL, &Irql);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+    KeLowerIrql(Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -516,7 +647,7 @@ EvtchnTrigger(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    Irql = __EvtchnAcquireInterruptLock(Context);
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
@@ -527,7 +658,7 @@ EvtchnTrigger(
         DoneSomething = FALSE;
     }
 
-    __EvtchnReleaseInterruptLock(Context, Irql);
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
 
     return DoneSomething;
 }
@@ -575,6 +706,8 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +750,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +763,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -767,8 +912,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1009,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1067,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1092,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1163,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1177,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1227,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1171,6 +1365,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 14:31:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:04 +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 1XmkZ5-0006Ua-Sn; Fri, 07 Nov 2014 14:31:03 +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 1XmkZ4-0006UP-8Q
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:02 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	69/D3-28296-5A7DC545; Fri, 07 Nov 2014 14:31:01 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16146 invoked from network); 7 Nov 2014 14:31:00 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:00 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143109"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-3Z;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:32 +0000
Message-ID: <1415370635-26884-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 27023
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuL3hlbl92ZXJz
aW9uLmMgIHwgMTA3ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysKIHNyYy94ZW5idXMvZmRvLmMgICAgICAgfCAgIDIgKwogc3JjL3hlbmJ1cy9zdXNwZW5kLmMg
ICB8ICAgMiArCiB2czIwMTIveGVuL3hlbi52Y3hwcm9qIHwgICAxICsKIHZzMjAxMy94ZW4veGVu
LnZjeHByb2ogfCAgIDMgKy0KIDExIGZpbGVzIGNoYW5nZWQsIDQwNiBpbnNlcnRpb25zKCspLCAz
MSBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi9mZWF0dXJlcy5o
CiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vdmVyc2lvbi5oCiBjcmVhdGUgbW9kZSAx
MDA2NDQgc3JjL3hlbi94ZW5fdmVyc2lvbi5jCgpkaWZmIC0tZ2l0IGEvZ2V0X3hlbl9oZWFkZXJz
LnB5IGIvZ2V0X3hlbl9oZWFkZXJzLnB5CmluZGV4IDVjYTVjOTMuLmVmMWEyYzggMTAwNjQ0Ci0t
LSBhL2dldF94ZW5faGVhZGVycy5weQorKysgYi9nZXRfeGVuX2hlYWRlcnMucHkKQEAgLTYxLDYg
KzYxLDggQEAgaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgICBjb3B5X2ZpbGUod29ya2lu
ZywgJ3B1YmxpYycsICcuJywgJ3NjaGVkLmgnKQogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZXZlbnRfY2hhbm5lbC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1
YmxpYycsICcuJywgJ2dyYW50X3RhYmxlLmgnKQorICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAndmVyc2lvbi5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2ZlYXR1cmVzLmgnKQogCiAgICAgY29weV9maWxlKHdvcmtpbmcsICd4ZW4nLCAnLics
ICdlcnJuby5oJykKIApkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBiL2luY2x1ZGUveGVuLmgK
aW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQKLS0tIGEvaW5jbHVkZS94ZW4uaAorKysgYi9p
bmNsdWRlL3hlbi5oCkBAIC00NCw2ICs0NCw3IEBACiAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+CiAj
aW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMuaD4KICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPgor
I2luY2x1ZGUgPHhlbi92ZXJzaW9uLmg+CiAKICNpZm5kZWYgWEVOX0FQSQogI2RlZmluZSBYRU5f
QVBJIF9fZGVjbHNwZWMoZGxsaW1wb3J0KQpAQCAtNTYsNiArNTcsMTQgQEAgWGVuVG91Y2goCiAg
ICAgVk9JRAogICAgICk7CiAKKy8vIEhZUEVSQ0FMTAorCitYRU5fQVBJCitWT0lECitIeXBlcmNh
bGxQb3B1bGF0ZSgKKyAgICBWT0lECisgICAgKTsKKwogLy8gSFZNCiAKIF9fY2hlY2tSZXR1cm4K
QEAgLTIzMyw2ICsyNDIsMjMgQEAgU2NoZWRZaWVsZCgKICAgICBWT0lECiAgICAgKTsKIAorLy8g
WEVOIFZFUlNJT04KKworX19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNp
b24oCisgICAgT1VUIFBVTE9ORyAgTWFqb3IsCisgICAgT1VUIFBVTE9ORyAgTWlub3IKKyAgICAp
OworCitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbkV4dHJhKAor
ICAgIE9VVCBQQ0hBUiAgIEV4dHJhCisgICAgKTsKKwogLy8gTU9EVUxFCiAKIFhFTl9BUEkKZGlm
ZiAtLWdpdCBhL2luY2x1ZGUveGVuL2ZlYXR1cmVzLmggYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmI3YmY4M2YKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oCkBAIC0wLDAgKzEsMTEyIEBACisvKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqCisgKiBmZWF0dXJlcy5oCisgKiAKKyAqIEZlYXR1cmUgZmxhZ3MsIHJl
cG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMuCisgKiAKKyAqIFBlcm1pc3Npb24gaXMgaGVy
ZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNv
cHkKKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxl
cyAodGhlICJTb2Z0d2FyZSIpLCB0bworICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCBy
ZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUKKyAqIHJpZ2h0cyB0
byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vu
c2UsIGFuZC9vcgorICogc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0
IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywg
c3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNv
cHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVk
ZWQgaW4KKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdB
UlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVU
IE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJ
VE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5P
IEVWRU5UIFNIQUxMIFRIRQorICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFC
TEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBXSEVUSEVS
IElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKKyAq
IEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBV
U0UgT1IgT1RIRVIKKyAqIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBDb3B5cmln
aHQgKGMpIDIwMDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+CisgKi8KKworI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19GRUFU
VVJFU19IX18KKworLyoKKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19mZWF0dXJlcyBYRU5f
RUxGTk9URV9GRUFUVVJFUworICoKKyAqIFRoZSBsaXN0IG9mIGFsbCB0aGUgZmVhdHVyZXMgdGhl
IGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkKKyAqIHBhcnNpbmcgdGhlIFhFTl9FTEZO
T1RFX0ZFQVRVUkVTIGFuZCBYRU5fRUxGTk9URV9TVVBQT1JURURfRkVBVFVSRVMKKyAqIHN0cmlu
Zy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUgbmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91
dCB0aGUKKyAqICJYRU5GRUFUXyIgcHJlZml4KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMu
CisgKiBJZiBhIGZlYXR1cmUgaXMgcmVxdWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24g
dGhlbiB0aGUgZmVhdHVyZSBuYW1lCisgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJh
Y3Rlci4KKyAqCisgKiBOb3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVT
IGlzIHVzZWQsIHRoZW4gaW4gdGhlCisgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhl
IGd1ZXN0IGlzIHRvIGJlIGJvb3RlZCBhcyBkb20wLAorICovCisKKy8qCisgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4KKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLgorICovCisjZGVmaW5lIFhF
TkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMAorCisvKgorICogSWYgc2V0LCB0aGUg
Z3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBzZWdtZW50IGRlc2NyaXB0
b3IKKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAq
LworI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rlc2NyaXB0b3JfdGFibGVzIDEKKworLyoKKyAq
IElmIHNldCwgdHJhbnNsYXRpb24gYmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2Fs
JyBhZGRyZXNzIHNwYWNlCisgKiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2Ug
YXJlIGhhbmRsZWQgYnkgdGhlIGh5cGVydmlzb3IuIEluIHRoaXMKKyAqIG1vZGUgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZSB0cmFuc2xhdGlv
bnMKKyAqIHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuCisgKi8KKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyCisKKy8qIElmIHNldCwgdGhl
IGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmluZyAwKS4g
Ki8KKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAzCisKKy8qCisg
KiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFsbG9jYXRlIHg4NiBQQUUgcGFn
ZSBkaXJlY3RvcmllcworICogYmVsb3cgNEdCLiBUaGlzIGZsYWcgaXMgdXN1YWxseSBpbXBsaWVk
IGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLgorICovCisjZGVmaW5lIFhFTkZFQVRfcGFlX3Bn
ZGlyX2Fib3ZlXzRnYiAgICAgICAgNAorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBw
b3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BSRVNFUlZFX0FEIGh5cGVyY2FsbD8gKi8KKyNkZWZpbmUg
WEVORkVBVF9tbXVfcHRfdXBkYXRlX3ByZXNlcnZlX2FkICA1CisKKy8qIHg4NjogRG9lcyB0aGlz
IFhlbiBob3N0IHN1cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRSBoeXBlcmNhbGw/ICov
CisjZGVmaW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNgorCisvKgorICog
SWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFjZWQg
aW50byBndWVzdCBrZXJuZWwKKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4KKyAqLworI2RlZmluZSBY
RU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcKKworLyogeDg2OiBEb2VzIHRoaXMg
WGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZlY3RvciB0eXBlPyAqLworI2RlZmlu
ZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAgICAgIDgKKworLyogeDg2OiBwdmNsb2Nr
IGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBvbiBIVk0gKi8KKyNkZWZpbmUgWEVORkVBVF9odm1f
c2FmZV9wdmNsb2NrICAgICAgICAgICA5CisKKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBI
Vk0gZ3Vlc3RzICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAx
MAorCisvKiBvcGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8KKyNkZWZpbmUgWEVORkVB
VF9kb20wICAgICAgICAgICAgICAgICAgICAgIDExCisKKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8KKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBfaWRl
bnRpdHkgICAgICAgIDEyCisKKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEKKworI2VuZGlm
IC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8KKworLyoKKyAqIExvY2FsIHZhcmlhYmxl
czoKKyAqIG1vZGU6IEMKKyAqIGMtZmlsZS1zdHlsZTogIkJTRCIKKyAqIGMtYmFzaWMtb2Zmc2V0
OiA0CisgKiB0YWItd2lkdGg6IDQKKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbAorICogRW5kOgor
ICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJz
aW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNDRmMjZiMAotLS0gL2Rl
di9udWxsCisrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaApAQCAtMCwwICsxLDk2IEBACisvKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqCisgKiB2ZXJzaW9uLmgKKyAqIAorICogWGVuIHZlcnNpb24sIHR5
cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVi
eSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5
CisgKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMg
KHRoZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVz
dHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8g
dXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNl
LCBhbmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBw
ZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1
YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5
cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVk
IGluCisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2Fy
ZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJS
QU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBO
T1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRO
RVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBF
VkVOVCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxF
IEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJ
TiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBG
Uk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNF
IE9SIE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0
IChjKSAyMDA1LCBOZ3V5ZW4gQW5oIFF1eW5oIDxhcXV5bmhAZ21haWwuY29tPgorICogQ29weXJp
Z2h0IChjKSAyMDA1LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNp
Zm5kZWYgX19YRU5fUFVCTElDX1ZFUlNJT05fSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19WRVJT
SU9OX0hfXworCisjaW5jbHVkZSAieGVuLmgiCisKKy8qIE5CLiBBbGwgb3BzIHJldHVybiB6ZXJv
IG9uIHN1Y2Nlc3MsIGV4Y2VwdCBYRU5WRVJfe3ZlcnNpb24scGFnZXNpemV9ICovCisKKy8qIGFy
ZyA9PSBOVUxMOyByZXR1cm5zIG1ham9yOm1pbm9yICgxNjoxNikuICovCisjZGVmaW5lIFhFTlZF
Ul92ZXJzaW9uICAgICAgMAorCisvKiBhcmcgPT0geGVuX2V4dHJhdmVyc2lvbl90LiAqLworI2Rl
ZmluZSBYRU5WRVJfZXh0cmF2ZXJzaW9uIDEKK3R5cGVkZWYgY2hhciB4ZW5fZXh0cmF2ZXJzaW9u
X3RbMTZdOworI2RlZmluZSBYRU5fRVhUUkFWRVJTSU9OX0xFTiAoc2l6ZW9mKHhlbl9leHRyYXZl
cnNpb25fdCkpCisKKy8qIGFyZyA9PSB4ZW5fY29tcGlsZV9pbmZvX3QuICovCisjZGVmaW5lIFhF
TlZFUl9jb21waWxlX2luZm8gMgorc3RydWN0IHhlbl9jb21waWxlX2luZm8geworICAgIGNoYXIg
Y29tcGlsZXJbNjRdOworICAgIGNoYXIgY29tcGlsZV9ieVsxNl07CisgICAgY2hhciBjb21waWxl
X2RvbWFpblszMl07CisgICAgY2hhciBjb21waWxlX2RhdGVbMzJdOworfTsKK3R5cGVkZWYgc3Ry
dWN0IHhlbl9jb21waWxlX2luZm8geGVuX2NvbXBpbGVfaW5mb190OworCisjZGVmaW5lIFhFTlZF
Ul9jYXBhYmlsaXRpZXMgMwordHlwZWRlZiBjaGFyIHhlbl9jYXBhYmlsaXRpZXNfaW5mb190WzEw
MjRdOworI2RlZmluZSBYRU5fQ0FQQUJJTElUSUVTX0lORk9fTEVOIChzaXplb2YoeGVuX2NhcGFi
aWxpdGllc19pbmZvX3QpKQorCisjZGVmaW5lIFhFTlZFUl9jaGFuZ2VzZXQgNAordHlwZWRlZiBj
aGFyIHhlbl9jaGFuZ2VzZXRfaW5mb190WzY0XTsKKyNkZWZpbmUgWEVOX0NIQU5HRVNFVF9JTkZP
X0xFTiAoc2l6ZW9mKHhlbl9jaGFuZ2VzZXRfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfcGxh
dGZvcm1fcGFyYW1ldGVycyA1CitzdHJ1Y3QgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnMgeworICAg
IHhlbl91bG9uZ190IHZpcnRfc3RhcnQ7Cit9OwordHlwZWRlZiBzdHJ1Y3QgeGVuX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnNfdDsKKworI2RlZmluZSBYRU5WRVJf
Z2V0X2ZlYXR1cmVzIDYKK3N0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHsKKyAgICB1bnNpZ25lZCBp
bnQgc3VibWFwX2lkeDsgICAgLyogSU46IHdoaWNoIDMyLWJpdCBzdWJtYXAgdG8gcmV0dXJuICov
CisgICAgdWludDMyX3QgICAgIHN1Ym1hcDsgICAgICAgIC8qIE9VVDogMzItYml0IHN1Ym1hcCAq
LworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9mZWF0dXJlX2luZm8geGVuX2ZlYXR1cmVfaW5mb190
OworCisvKiBEZWNsYXJlcyB0aGUgZmVhdHVyZXMgcmVwb3J0ZWQgYnkgWEVOVkVSX2dldF9mZWF0
dXJlcy4gKi8KKyNpbmNsdWRlICJmZWF0dXJlcy5oIgorCisvKiBhcmcgPT0gTlVMTDsgcmV0dXJu
cyBob3N0IG1lbW9yeSBwYWdlIHNpemUuICovCisjZGVmaW5lIFhFTlZFUl9wYWdlc2l6ZSA3CisK
Ky8qIGFyZyA9PSB4ZW5fZG9tYWluX2hhbmRsZV90LiAqLworI2RlZmluZSBYRU5WRVJfZ3Vlc3Rf
aGFuZGxlIDgKKworI2RlZmluZSBYRU5WRVJfY29tbWFuZGxpbmUgOQordHlwZWRlZiBjaGFyIHhl
bl9jb21tYW5kbGluZV90WzEwMjRdOworCisjZW5kaWYgLyogX19YRU5fUFVCTElDX1ZFUlNJT05f
SF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6CisgKiBtb2RlOiBDCisgKiBjLWZpbGUt
c3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAorICogdGFiLXdpZHRoOiA0CisgKiBp
bmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpkaWZmIC0tZ2l0IGEvc3JjL3hlbi9k
cml2ZXIuYyBiL3NyYy94ZW4vZHJpdmVyLmMKaW5kZXggYmE1NDFiNC4uZmNlNzVhYSAxMDA2NDQK
LS0tIGEvc3JjL3hlbi9kcml2ZXIuYworKysgYi9zcmMveGVuL2RyaXZlci5jCkBAIC01OSw2ICs1
OSwyNiBAQCBYZW5Ub3VjaCgKICAgICBWT0lECiAgICAgKQogeworICAgIHN0YXRpYyBVTE9ORyAg
ICBSZWZlcmVuY2U7CisgICAgVUxPTkcgICAgICAgICAgIE1ham9yOworICAgIFVMT05HICAgICAg
ICAgICBNaW5vcjsKKyAgICBDSEFSICAgICAgICAgICAgRXh0cmFbWEVOX0VYVFJBVkVSU0lPTl9M
RU5dOworICAgIE5UU1RBVFVTICAgICAgICBzdGF0dXM7CisKKyAgICBpZiAoUmVmZXJlbmNlKysg
IT0gMCkKKyAgICAgICAgcmV0dXJuOworCisgICAgc3RhdHVzID0gWGVuVmVyc2lvbigmTWFqb3Is
ICZNaW5vcik7CisgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7CisKKyAgICBzdGF0dXMg
PSBYZW5WZXJzaW9uRXh0cmEoRXh0cmEpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykp
OworCisgICAgTG9nUHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAiWEVOOiAl
dS4ldSVzXG4iLAorICAgICAgICAgICAgICBNYWpvciwKKyAgICAgICAgICAgICAgTWlub3IsCisg
ICAgICAgICAgICAgIEV4dHJhKTsKIH0KIAogc3RhdGljIFZPSUQKZGlmZiAtLWdpdCBhL3NyYy94
ZW4vaHlwZXJjYWxsLmMgYi9zcmMveGVuL2h5cGVyY2FsbC5jCmluZGV4IDA3ZWI0MWEuLjcxN2I4
YzIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW4vaHlwZXJjYWxsLmMKKysrIGIvc3JjL3hlbi9oeXBlcmNh
bGwuYwpAQCAtMjksNiArMjksOSBAQAogICogU1VDSCBEQU1BR0UuCiAgKi8KIAorI3VuZGVmICBY
RU5fQVBJCisjZGVmaW5lIFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpCisKICNpbmNsdWRl
IDxudGRkay5oPgogI2luY2x1ZGUgPHhlbi5oPgogI2luY2x1ZGUgPHV0aWwuaD4KQEAgLTM3LDI0
ICs0MCw0MSBAQAogI2luY2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgog
Ci0jZGVmaW5lIE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCAyCisjZGVmaW5lIE1BWElNVU1f
SFlQRVJDQUxMX1BBR0VfQ09VTlQgMgogCiAjcHJhZ21hIGNvZGVfc2VnKCJoeXBlcmNhbGwiKQog
X19kZWNsc3BlYyhhbGxvY2F0ZSgiaHlwZXJjYWxsIikpCi1zdGF0aWMgVUNIQVIgICAgICAgIF9f
U2VjdGlvblsoTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UICsgMSkgKiBQQUdFX1NJWkVdOwor
c3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09V
TlQgKyAxKSAqIFBBR0VfU0laRV07CiAKIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYg
PSAweDQwMDAwMDAwOwogCi1zdGF0aWMgVVNIT1JUICAgICAgIFhlbk1ham9yVmVyc2lvbjsKLXN0
YXRpYyBVU0hPUlQgICAgICAgWGVuTWlub3JWZXJzaW9uOwotCi1zdGF0aWMgUEZOX05VTUJFUiAg
IEh5cGVyY2FsbFBmbltNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlRdOwotc3RhdGljIFVMT05H
ICAgICAgICBIeXBlcmNhbGxQZm5Db3VudDsKK3N0YXRpYyBQSFlTSUNBTF9BRERSRVNTIEh5cGVy
Y2FsbFBhZ2VbTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVF07CitzdGF0aWMgVUxPTkcgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlQ291bnQ7CiAKIHR5cGVkZWYgVUNIQVIgICAgICAgICAgIEhZ
UEVSQ0FMTF9HQVRFWzMyXTsKIHR5cGVkZWYgSFlQRVJDQUxMX0dBVEUgICpQSFlQRVJDQUxMX0dB
VEU7CiAKIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxsOworVUxPTkcgICAgICAgICAgICAg
ICBIeXBlcmNhbGxNc3I7CisKK1hFTl9BUEkKK1ZPSUQKK0h5cGVyY2FsbFBvcHVsYXRlKAorICAg
IFZPSUQKKyAgICApCit7CisgICAgVUxPTkcgICAgICAgSW5kZXg7CisKKyAgICBmb3IgKEluZGV4
ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsKKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJDQUxM
IFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsCisgICAgICAgICAgICAgICAgICBJbmRleCwKKyAgICAg
ICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LAorICAgICAgICAgICAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7CisKKyAgICAgICAgX193cml0ZW1z
cihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0KTsKKyAgICB9Cit9
CiAKIE5UU1RBVFVTCiBIeXBlcmNhbGxJbml0aWFsaXplKApAQCAtNjYsNyArODYsNiBAQCBIeXBl
cmNhbGxJbml0aWFsaXplKAogICAgIFVMT05HICAgICAgIEVDWCA9ICdERUFEJzsKICAgICBVTE9O
RyAgICAgICBFRFggPSAnREVBRCc7CiAgICAgVUxPTkcgICAgICAgSW5kZXg7Ci0gICAgVUxPTkcg
ICAgICAgSHlwZXJjYWxsTXNyOwogICAgIE5UU1RBVFVTICAgIHN0YXR1czsKIAogICAgIHN0YXR1
cyA9IFNUQVRVU19VTlNVQ0NFU1NGVUw7CkBAIC04OCwxMyArMTA3LDYgQEAgSHlwZXJjYWxsSW5p
dGlhbGl6ZSgKICAgICAgICAgICAgIGdvdG8gZmFpbDE7CiAgICAgfQogCi0gICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOwotICAgIFhlbk1ham9yVmVy
c2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7Ci0gICAgWGVuTWlub3JWZXJzaW9uID0gKFVTSE9S
VCkoRUFYICYgMHhGRkZGKTsKLQotICAgIEluZm8oIlhFTiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJz
aW9uLCBYZW5NaW5vclZlcnNpb24pOwotICAgIEluZm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9f
WEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOwotCiAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9u
ICYgKFBBR0VfU0laRSAtIDEpKQogICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdf
UFRSKV9fU2VjdGlvbiArIFBBR0VfU0laRSAtIDEpICYgfihQQUdFX1NJWkUgLSAxKSk7CiAgICAg
ZWxzZQpAQCAtMTAyLDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgKIAogICAgIEFT
U0VSVDNVKCgoVUxPTkdfUFRSKUh5cGVyY2FsbCAmIChQQUdFX1NJWkUgLSAxKSksID09LCAwKTsK
IAotICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VO
VDsgSW5kZXgrKykgewotICAgICAgICBQSFlTSUNBTF9BRERSRVNTICAgIFBoeXNpY2FsQWRkcmVz
czsKLQotICAgICAgICBQaHlzaWNhbEFkZHJlc3MgPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVD
SEFSKUh5cGVyY2FsbCArIChJbmRleCA8PCBQQUdFX1NISUZUKSk7Ci0gICAgICAgIEh5cGVyY2Fs
bFBmbltJbmRleF0gPSAoUEZOX05VTUJFUikoUGh5c2ljYWxBZGRyZXNzLlF1YWRQYXJ0ID4+IFBB
R0VfU0hJRlQpOwotICAgIH0KKyAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UOyBJbmRleCsrKQorICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4
XSA9IE1tR2V0UGh5c2ljYWxBZGRyZXNzKChQVUNIQVIpSHlwZXJjYWxsICsKKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoSW5kZXggPDwgUEFHRV9T
SElGVCkpOwogCiAgICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEws
IE5VTEwpOwotICAgIEh5cGVyY2FsbFBmbkNvdW50ID0gRUFYOwotICAgIEFTU0VSVChIeXBlcmNh
bGxQZm5Db3VudCA8PSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOworICAgIEh5cGVyY2Fs
bFBhZ2VDb3VudCA9IEVBWDsKKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQpOwogICAgIEh5cGVyY2FsbE1zciA9IEVCWDsKIAotICAg
IGZvciAoSW5kZXggPSAwOyBJbmRleCA8IEh5cGVyY2FsbFBmbkNvdW50OyBJbmRleCsrKSB7Ci0g
ICAgICAgIEluZm8oIkh5cGVyY2FsbFBmblslZF06ICVwXG4iLCBJbmRleCwgKFBWT0lEKUh5cGVy
Y2FsbFBmbltJbmRleF0pOwotICAgICAgICBfX3dyaXRlbXNyKEh5cGVyY2FsbE1zciwgKFVMT05H
NjQpSHlwZXJjYWxsUGZuW0luZGV4XSA8PCBQQUdFX1NISUZUKTsKLSAgICB9CisgICAgSHlwZXJj
YWxsUG9wdWxhdGUoKTsKIAogICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsKIApAQCAtMTc3LDgg
KzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKAogCiAgICAgSHlwZXJjYWxsID0gTlVMTDsKIAot
ICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVDsg
SW5kZXgrKykKLSAgICAgICAgSHlwZXJjYWxsUGZuW0luZGV4XSA9IDA7CisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uUXVhZFBhcnQgPSAwOwogCi0gICAgSHlwZXJjYWxs
UGZuQ291bnQgPSAwOworICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7CiB9CmRpZmYgLS1naXQg
YS9zcmMveGVuL3hlbl92ZXJzaW9uLmMgYi9zcmMveGVuL3hlbl92ZXJzaW9uLmMKbmV3IGZpbGUg
bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNmVmMDYxZgotLS0gL2Rldi9udWxsCisrKyBiL3Ny
Yy94ZW4veGVuX3ZlcnNpb24uYwpAQCAtMCwwICsxLDEwNyBAQAorLyogQ29weXJpZ2h0IChjKSBD
aXRyaXggU3lzdGVtcyBJbmMuCisgKiBBbGwgcmlnaHRzIHJlc2VydmVkLgorICogCisgKiBSZWRp
c3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCAKKyAqIHdpdGgg
b3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgCisgKiB0aGF0
IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OgorICogCisgKiAqICAgUmVkaXN0cmli
dXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5
cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZv
bGxvd2luZyBkaXNjbGFpbWVyLgorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9y
bSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhp
cyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1l
ciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgCisgKiAgICAgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqIAorICogVEhJUyBTT0ZUV0FSRSBJUyBQ
Uk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIAorICogQ09OVFJJQlVUT1JTICJB
UyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgCisgKiBJTkNMVURJ
TkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiAKKyAqIE1F
UkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIAor
ICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1Ig
CisgKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D
SURFTlRBTCwgCisgKiBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdF
UyAoSU5DTFVESU5HLCAKKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VC
U1RJVFVURSBHT09EUyBPUiAKKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJP
RklUUzsgT1IgQlVTSU5FU1MgCisgKiBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBP
TiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgCisgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgCisgKiBORUdMSUdFTkNFIE9SIE9USEVS
V0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIAorICogT0YgVEhJUyBTT0ZU
V0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiAKKyAqIFNVQ0ggREFN
QUdFLgorICovCisKKyNkZWZpbmUgWEVOX0FQSSBfX2RlY2xzcGVjKGRsbGV4cG9ydCkKKworI2lu
Y2x1ZGUgPG50ZGRrLmg+CisjaW5jbHVkZSA8eGVuLmg+CisKKyNpbmNsdWRlICJoeXBlcmNhbGwu
aCIKKyNpbmNsdWRlICJkYmdfcHJpbnQuaCIKKyNpbmNsdWRlICJhc3NlcnQuaCIKKworc3RhdGlj
IEZPUkNFSU5MSU5FIExPTkdfUFRSCitYZW5WZXJzaW9uT3AoCisgICAgSU4gIFVMT05HICAgQ29t
bWFuZCwKKyAgICBJTiAgUFZPSUQgICBBcmd1bWVudAorICAgICkKK3sKKyAgICByZXR1cm4gSFlQ
RVJDQUxMKExPTkdfUFRSLCB4ZW5fdmVyc2lvbiwgMiwgQ29tbWFuZCwgQXJndW1lbnQpOworfQor
CitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbigKKyAgICBPVVQg
UFVMT05HICBNYWpvciwKKyAgICBPVVQgUFVMT05HICBNaW5vcgorICAgICkKK3sKKyAgICBMT05H
X1BUUiAgICAgICAgICAgICAgICAgICAgcmM7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIHJjID0gWGVuVmVyc2lvbk9wKFhFTlZFUl92ZXJzaW9uLCBOVUxM
KTsKKworICAgIGlmIChyYyA8IDApIHsKKyAgICAgICAgRVJSTk9fVE9fU1RBVFVTKC1yYywgc3Rh
dHVzKTsKKyAgICAgICAgZ290byBmYWlsMTsKKyAgICB9CisKKyAgICAqTWFqb3IgPSAoVUxPTkcp
KChyYyA+PiAxNikgJiAweEZGRkYpOworICAgICpNaW5vciA9IChVTE9ORykocmMgJiAweEZGRkYp
OworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAgICBFcnJvcigiZmFp
bDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsKK30KKworX19jaGVj
a1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBPVVQgUENI
QVIgICAgICAgICAgIEV4dHJhCisgICAgKQoreworICAgIHhlbl9leHRyYXZlcnNpb25fdCAgb3A7
CisgICAgTE9OR19QVFIgICAgICAgICAgICByYzsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgIHN0
YXR1czsKKworICAgIFJ0bFplcm9NZW1vcnkoJm9wLCBzaXplb2YgKG9wKSk7CisKKyAgICByYyA9
IFhlblZlcnNpb25PcChYRU5WRVJfZXh0cmF2ZXJzaW9uLCAmb3ApOworCisgICAgaWYgKHJjIDwg
MCkgeworICAgICAgICBFUlJOT19UT19TVEFUVVMoLXJjLCBzdGF0dXMpOworICAgICAgICBnb3Rv
IGZhaWwxOworICAgIH0KKworICAgIFJ0bENvcHlNZW1vcnkoRXh0cmEsICZvcCwgWEVOX0VYVFJB
VkVSU0lPTl9MRU4pOworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAg
ICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsK
K30KZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZmRvLmMgYi9zcmMveGVuYnVzL2Zkby5jCmluZGV4
IDU5NDQyYmQuLjIxNWM5OTcgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZmRvLmMKKysrIGIvc3Jj
L3hlbmJ1cy9mZG8uYwpAQCAtMjE4Niw2ICsyMTg2LDggQEAgRmRvUzRUb1MzKAogCiAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsKIAorICAgIEh5cGVyY2FsbFBvcHVsYXRl
KCk7CisKICAgICBpZiAoRmRvLT5VbnBsdWdJbnRlcmZhY2UuSW50ZXJmYWNlLkNvbnRleHQgIT0g
TlVMTCkKICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmRmRvLT5VbnBsdWdJbnRlcmZh
Y2UpOwogCmRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3N1c3BlbmQuYyBiL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCmluZGV4IDZhYjJiZDIuLmRlNzBlNDIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCisrKyBiL3NyYy94ZW5idXMvc3VzcGVuZC5jCkBAIC0xNzMsNiArMTczLDggQEAgU3Vz
cGVuZFRyaWdnZXIoCiAKICAgICAgICAgQ29udGV4dC0+Q291bnQrKzsKIAorICAgICAgICBIeXBl
cmNhbGxQb3B1bGF0ZSgpOworCiAgICAgICAgIGlmIChDb250ZXh0LT5VbnBsdWdJbnRlcmZhY2Uu
SW50ZXJmYWNlLkNvbnRleHQgIT0gTlVMTCkKICAgICAgICAgICAgIFhFTkZJTFRfVU5QTFVHKFJl
cGxheSwgJkNvbnRleHQtPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBhL3ZzMjAxMi94
ZW4veGVuLnZjeHByb2ogYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCmluZGV4IGViNTQ2OTIuLjJm
NGQ5NTggMTAwNjQ0Ci0tLSBhL3ZzMjAxMi94ZW4veGVuLnZjeHByb2oKKysrIGIvdnMyMDEyL3hl
bi94ZW4udmN4cHJvagpAQCAtODgsNiArODgsNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuXGh2bS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5c
eGVuX3ZlcnNpb24uYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5
cGVyY2FsbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cbWVtb3J5
LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxzY2hlZC5jIiAvPgpk
aWZmIC0tZ2l0IGEvdnMyMDEzL3hlbi94ZW4udmN4cHJvaiBiL3ZzMjAxMy94ZW4veGVuLnZjeHBy
b2oKaW5kZXggNDkwMjk0Yy4uODFkNTBlYSAxMDA2NDQKLS0tIGEvdnMyMDEzL3hlbi94ZW4udmN4
cHJvagorKysgYi92czIwMTMveGVuL3hlbi52Y3hwcm9qCkBAIC0xLDQgKzEsNCBAQAot77u/PD94
bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KKzw/eG1sIHZlcnNpb249IjEuMCIg
ZW5jb2Rpbmc9InV0Zi04Ij8+CiA8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xz
VmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxv
cGVyL21zYnVpbGQvMjAwMyI+CiAgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIg
Lz4KICAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgpAQCAtMTI4LDYgKzEyOCw3IEBA
CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+CisgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+CiAgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5cGVyY2FsbC5jIiAvPgogICAgIDxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KICAgICA8Q2xDb21w
aWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4KLS0gCjIuMS4xCgoKX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1h
aWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3Rz
LnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 14:31:06 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:06 +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 1XmkZ7-0006VP-Vo; Fri, 07 Nov 2014 14:31:05 +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 1XmkZ6-0006UZ-2W
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:04 +0000
Received: from [85.158.137.68] by server-2.bemta-3.messagelabs.com id
	6A/63-05632-7A7DC545; Fri, 07 Nov 2014 14:31:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16562 invoked from network); 7 Nov 2014 14:31:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143122"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-4L;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:33 +0000
Message-ID: <1415370635-26884-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |   8 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 896 insertions(+), 224 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..669e866 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -82,16 +82,22 @@ StartType=%SERVICE_BOOT_START%
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 14:31:06 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:06 +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 1XmkZ7-0006VP-Vo; Fri, 07 Nov 2014 14:31:05 +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 1XmkZ6-0006UZ-2W
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:04 +0000
Received: from [85.158.137.68] by server-2.bemta-3.messagelabs.com id
	6A/63-05632-7A7DC545; Fri, 07 Nov 2014 14:31:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1415370658!11143341!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16562 invoked from network); 7 Nov 2014 14:31:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189143122"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-4L;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:33 +0000
Message-ID: <1415370635-26884-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |   8 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 896 insertions(+), 224 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..669e866 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -82,16 +82,22 @@ StartType=%SERVICE_BOOT_START%
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 14:31:39 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:39 +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 1XmkZf-0006WH-35; Fri, 07 Nov 2014 14:31:39 +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 1XmkZd-0006Vr-DO
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:37 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	4A/FC-02954-8C7DC545; Fri, 07 Nov 2014 14:31:36 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415370694!8746124!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23538 invoked from network); 7 Nov 2014 14:31:35 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190571558"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-31	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:31 +0000
Message-ID: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Subject: [win-pv-devel] [PATCH v2 0/4] Use per-vcpu event channel upcalls if
	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be
allocated, one per CPU.

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.

v2:
 - Added missing file to patch #1
 - Removed spurious INF file change from patch #2


_______________________________________________
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 Nov 07 14:31:39 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:39 +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 1XmkZf-0006WH-35; Fri, 07 Nov 2014 14:31:39 +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 1XmkZd-0006Vr-DO
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:37 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	4A/FC-02954-8C7DC545; Fri, 07 Nov 2014 14:31:36 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415370694!8746124!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23538 invoked from network); 7 Nov 2014 14:31:35 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190571558"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-31	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:31 +0000
Message-ID: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA1
Subject: [win-pv-devel] [PATCH v2 0/4] Use per-vcpu event channel upcalls if
	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be
allocated, one per CPU.

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.

v2:
 - Added missing file to patch #1
 - Removed spurious INF file change from patch #2


_______________________________________________
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 Nov 07 14:31:39 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:39 +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 1XmkZf-0006WL-48; Fri, 07 Nov 2014 14:31:39 +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 1XmkZd-0006Vt-W1
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:38 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	91/14-27785-9C7DC545; Fri, 07 Nov 2014 14:31:37 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415370694!8746124!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23662 invoked from network); 7 Nov 2014 14:31:36 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:36 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190571559"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-51;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:34 +0000
Message-ID: <1415370635-26884-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 3/4] Update Xen headers to master (4.5-rc0
	+ HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 14:31:39 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:31:39 +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 1XmkZf-0006WL-48; Fri, 07 Nov 2014 14:31:39 +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 1XmkZd-0006Vt-W1
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:31:38 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	91/14-27785-9C7DC545; Fri, 07 Nov 2014 14:31:37 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415370694!8746124!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23662 invoked from network); 7 Nov 2014 14:31:36 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:31:36 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="190571559"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Fri, 7 Nov 2014 09:30: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 1XmkYn-000589-51;
	Fri, 07 Nov 2014 14:30:45 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 14:30:34 +0000
Message-ID: <1415370635-26884-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
References: <1415370635-26884-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v2 3/4] Update Xen headers to master (4.5-rc0
	+ HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 14:48:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:48: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 1Xmkpf-00070f-Em; Fri, 07 Nov 2014 14:48:11 +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 1Xmkpe-00070a-1x
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:48:10 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	50/65-09842-9ABDC545; Fri, 07 Nov 2014 14:48:09 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-21.messagelabs.com!1415371688!12244379!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26608 invoked from network); 7 Nov 2014 14:48:08 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:48:08 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26638492"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: David Vrabel <david.vrabel@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ///4+ACAABDwgA==
Date: Fri, 7 Nov 2014 14:47:50 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
In-Reply-To: <545CD91E.5090504@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
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: David Vrabel
> Sent: 07 November 2014 14:37
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> On 07/11/14 14:02, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> >> Sent: 06 November 2014 14:31
> >> To: win-pv-devel@lists.xenproject.org
> >> Cc: Paul Durrant
> >> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
> >>
> >> If it is available then the fifo ABI will be used. If it is not then the
> >> two-level ABI will be used instead.
> >> The ABI is released and re-acquired across suspend/resume so this should
> >> allow moving between hosts with different capabilities.
> 
> Moving from FIFO to 2-level is only safe if you use fewer than 4095 (or
> 1023 on 32-bit) events, but this shouldn't be a problem for a Windows guest
> 

That's a good point. All event channels are essentially lost across a suspend/resume. The data structures are retained so that the clients can go through close/open cycle to re-establish their channels and if the open fails (because there are no longer as many ports as there were before) then the client needs to deal with that. As you say, such a high limit should never be hit in practice.

> >> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> >> new file mode 100644
> >> index 0000000..d37b1cd
> >> --- /dev/null
> >> +++ b/src/xenbus/evtchn_fifo.c
> >> @@ -0,0 +1,702 @@
> 
> >> +static event_word_t *
> >> +EvtchnFifoEventWord(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> >> +    IN  ULONG                       Port
> >> +    )
> >> +{
> >> +    ULONG                           Index;
> >> +    PMDL                            Mdl;
> >> +    event_word_t                    *EventWord;
> >> +
> >> +    Index = Port / EVENT_WORDS_PER_PAGE;
> >> +    ASSERT3U(Index, <, Context->EventPageCount);
> >> +
> >> +    Mdl = Context->EventPageMdl[Index];
> >> +
> >> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> >> NormalPagePriority);
> >> +    ASSERT(EventWord != NULL);
> >> +
> >> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
> >> +    Port -= Index * EVENT_WORDS_PER_PAGE;
> >> +
> >> +    return &EventWord[Port];
> >> +}
> 
> I'm not at all familiar with Windows kernel memory management but is all
> this MDL stuff expensive?  Can you not store the VA instead of looking
> it up every time?
> 

It's actually a macro that pulls a field from the MDL if it's non-NULL and sets up a new PTE if its NULL, thus it's only costly on the first invocation.

> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> Do you need this barrier?  The doc has a section describing the minimum
> number of barriers needed.
> 
> >> +
> >> +    return !!(*EventWord & (1 << Flag));
> >> +}
> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestAndSetFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> Or this one?  The Interlocked*() functions are also already barriers.
> 

Yes, this me being too liberal with the barriers.

> >> +
> >> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> >> +}
> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestAndClearFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> ditto.
> 
> >> +
> >> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> >> +}
> >> +
> >> +static FORCEINLINE VOID
> >> +__EvtchnFifoSetFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    *EventWord |= (1 << Flag);
> 
> This must be atomic.  Remember that Xen may be simultaneously writing to
> this word from a different PCPU.
> 

Yes. Good point.

> You need an InterlockedBitSet() (which doesn't seem to exist.  Perhaps
> make one with InterlockedOr()?)
> 

Or just a TestAndSet, ignoring the result.

> >> +    KeMemoryBarrier();
> >> +}
> >> +
> >> +static FORCEINLINE VOID
> >> +__EvtchnFifoClearFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    *EventWord &= ~(1 << Flag);
> 
> This must be atomic as well.
> 

Ok.

> >> +static VOID
> >> +EvtchnFifoContract(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> >> +    )
> >> +{
> 
> You can't shrink the event array if it is in use.  I assume this is only
> called after an EVTCHNOP_reset hypercall?
> 

Yes. It's not a shrink in practice, it's a 'bin it and start again' :-)

> >> +static BOOLEAN
> >> +EvtchnFifoPortUnmask(
> >> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> >> +    IN  ULONG                       Port
> >> +    )
> >> +{
> >> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> >> +    event_word_t                    *EventWord;
> >> +    LONG                            Old;
> >> +    LONG                            New;
> >> +
> >> +    EventWord = EvtchnFifoEventWord(Context, Port);
> >> +
> >> +    // Clear masked bit, spinning if busy
> >> +    do {
> >> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> >> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> >> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
> Old) !=
> >> Old);
> >> +
> >> +    // Check whether the port was masked
> >> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> >> +        return FALSE;
> >> +
> >> +    // If we cleared the mask then check whether something is pending
> >> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
> EVTCHN_FIFO_PENDING))
> >> +        return FALSE;
> 
> The doc says you should do an EVTCHNOP_unmask hypercall here, but
> picking up any pending event here is fine.
> 
> You may want to be more careful if you unmask an event while running on
> a VCPU that is not the one the event is bound to.
> 

Yes - I do need to allow for that. It won't happen at the moment but nothing in the API prevents it.

> >> +static VOID
> >> +EvtchnFifoReset(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> >> +    )
> >> +{
> >> +    ULONGLONG                       Value;
> >> +    ULONG                           LocalPort;
> >> +    ULONG                           RemotePort;
> >> +    USHORT                          RemoteDomain;
> >> +    NTSTATUS                        status;
> >> +
> >> +    UNREFERENCED_PARAMETER(Context);
> >> +
> >> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
> >> +    ASSERT(NT_SUCCESS(status));
> >> +
> >> +    LocalPort = (LONG)Value;
> 
> You may wish to consider the console event channel as well.  But if you
> don't use it, it's ok to leave it unbound.
> 

I think I may add it in. I do eventually want to use the console for debug output.

Thanks very much for the review,

  Paul

> David

_______________________________________________
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 Nov 07 14:48:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:48: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 1Xmkpf-00070f-Em; Fri, 07 Nov 2014 14:48:11 +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 1Xmkpe-00070a-1x
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:48:10 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	50/65-09842-9ABDC545; Fri, 07 Nov 2014 14:48:09 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-21.messagelabs.com!1415371688!12244379!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26608 invoked from network); 7 Nov 2014 14:48:08 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:48:08 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="26638492"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: David Vrabel <david.vrabel@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ///4+ACAABDwgA==
Date: Fri, 7 Nov 2014 14:47:50 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
In-Reply-To: <545CD91E.5090504@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
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: David Vrabel
> Sent: 07 November 2014 14:37
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> On 07/11/14 14:02, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> >> Sent: 06 November 2014 14:31
> >> To: win-pv-devel@lists.xenproject.org
> >> Cc: Paul Durrant
> >> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
> >>
> >> If it is available then the fifo ABI will be used. If it is not then the
> >> two-level ABI will be used instead.
> >> The ABI is released and re-acquired across suspend/resume so this should
> >> allow moving between hosts with different capabilities.
> 
> Moving from FIFO to 2-level is only safe if you use fewer than 4095 (or
> 1023 on 32-bit) events, but this shouldn't be a problem for a Windows guest
> 

That's a good point. All event channels are essentially lost across a suspend/resume. The data structures are retained so that the clients can go through close/open cycle to re-establish their channels and if the open fails (because there are no longer as many ports as there were before) then the client needs to deal with that. As you say, such a high limit should never be hit in practice.

> >> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> >> new file mode 100644
> >> index 0000000..d37b1cd
> >> --- /dev/null
> >> +++ b/src/xenbus/evtchn_fifo.c
> >> @@ -0,0 +1,702 @@
> 
> >> +static event_word_t *
> >> +EvtchnFifoEventWord(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
> >> +    IN  ULONG                       Port
> >> +    )
> >> +{
> >> +    ULONG                           Index;
> >> +    PMDL                            Mdl;
> >> +    event_word_t                    *EventWord;
> >> +
> >> +    Index = Port / EVENT_WORDS_PER_PAGE;
> >> +    ASSERT3U(Index, <, Context->EventPageCount);
> >> +
> >> +    Mdl = Context->EventPageMdl[Index];
> >> +
> >> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
> >> NormalPagePriority);
> >> +    ASSERT(EventWord != NULL);
> >> +
> >> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
> >> +    Port -= Index * EVENT_WORDS_PER_PAGE;
> >> +
> >> +    return &EventWord[Port];
> >> +}
> 
> I'm not at all familiar with Windows kernel memory management but is all
> this MDL stuff expensive?  Can you not store the VA instead of looking
> it up every time?
> 

It's actually a macro that pulls a field from the MDL if it's non-NULL and sets up a new PTE if its NULL, thus it's only costly on the first invocation.

> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> Do you need this barrier?  The doc has a section describing the minimum
> number of barriers needed.
> 
> >> +
> >> +    return !!(*EventWord & (1 << Flag));
> >> +}
> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestAndSetFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> Or this one?  The Interlocked*() functions are also already barriers.
> 

Yes, this me being too liberal with the barriers.

> >> +
> >> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> >> +}
> >> +
> >> +static FORCEINLINE BOOLEAN
> >> +__EvtchnFifoTestAndClearFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    KeMemoryBarrier();
> 
> ditto.
> 
> >> +
> >> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> >> +}
> >> +
> >> +static FORCEINLINE VOID
> >> +__EvtchnFifoSetFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    *EventWord |= (1 << Flag);
> 
> This must be atomic.  Remember that Xen may be simultaneously writing to
> this word from a different PCPU.
> 

Yes. Good point.

> You need an InterlockedBitSet() (which doesn't seem to exist.  Perhaps
> make one with InterlockedOr()?)
> 

Or just a TestAndSet, ignoring the result.

> >> +    KeMemoryBarrier();
> >> +}
> >> +
> >> +static FORCEINLINE VOID
> >> +__EvtchnFifoClearFlag(
> >> +    IN  event_word_t    *EventWord,
> >> +    IN  ULONG           Flag
> >> +    )
> >> +{
> >> +    *EventWord &= ~(1 << Flag);
> 
> This must be atomic as well.
> 

Ok.

> >> +static VOID
> >> +EvtchnFifoContract(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> >> +    )
> >> +{
> 
> You can't shrink the event array if it is in use.  I assume this is only
> called after an EVTCHNOP_reset hypercall?
> 

Yes. It's not a shrink in practice, it's a 'bin it and start again' :-)

> >> +static BOOLEAN
> >> +EvtchnFifoPortUnmask(
> >> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> >> +    IN  ULONG                       Port
> >> +    )
> >> +{
> >> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> >> +    event_word_t                    *EventWord;
> >> +    LONG                            Old;
> >> +    LONG                            New;
> >> +
> >> +    EventWord = EvtchnFifoEventWord(Context, Port);
> >> +
> >> +    // Clear masked bit, spinning if busy
> >> +    do {
> >> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> >> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> >> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
> Old) !=
> >> Old);
> >> +
> >> +    // Check whether the port was masked
> >> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> >> +        return FALSE;
> >> +
> >> +    // If we cleared the mask then check whether something is pending
> >> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
> EVTCHN_FIFO_PENDING))
> >> +        return FALSE;
> 
> The doc says you should do an EVTCHNOP_unmask hypercall here, but
> picking up any pending event here is fine.
> 
> You may want to be more careful if you unmask an event while running on
> a VCPU that is not the one the event is bound to.
> 

Yes - I do need to allow for that. It won't happen at the moment but nothing in the API prevents it.

> >> +static VOID
> >> +EvtchnFifoReset(
> >> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
> >> +    )
> >> +{
> >> +    ULONGLONG                       Value;
> >> +    ULONG                           LocalPort;
> >> +    ULONG                           RemotePort;
> >> +    USHORT                          RemoteDomain;
> >> +    NTSTATUS                        status;
> >> +
> >> +    UNREFERENCED_PARAMETER(Context);
> >> +
> >> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
> >> +    ASSERT(NT_SUCCESS(status));
> >> +
> >> +    LocalPort = (LONG)Value;
> 
> You may wish to consider the console event channel as well.  But if you
> don't use it, it's ok to leave it unbound.
> 

I think I may add it in. I do eventually want to use the console for debug output.

Thanks very much for the review,

  Paul

> David

_______________________________________________
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 Nov 07 14:48:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:48:31 +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 1Xmkpz-000712-GW; Fri, 07 Nov 2014 14:48:31 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <david.vrabel@citrix.com>) id 1Xmkfz-0006h7-LH
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:38:11 +0000
Received: from [85.158.139.211] by server-3.bemta-5.messagelabs.com id
	95/7F-14727-259DC545; Fri, 07 Nov 2014 14:38:10 +0000
X-Env-Sender: david.vrabel@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415371088!11125814!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21743 invoked from network); 7 Nov 2014 14:38:10 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:38:10 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189145271"
Message-ID: <545CD91E.5090504@citrix.com>
Date: Fri, 7 Nov 2014 14:37:18 +0000
From: David Vrabel <david.vrabel@citrix.com>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
	rv:24.0) Gecko/20100101 Icedove/24.5.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
X-DLP: MIA1
X-Mailman-Approved-At: Fri, 07 Nov 2014 14:48:31 +0000
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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 07/11/14 14:02, Paul Durrant wrote:
>> -----Original Message-----
>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
>> Sent: 06 November 2014 14:31
>> To: win-pv-devel@lists.xenproject.org
>> Cc: Paul Durrant
>> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
>>
>> If it is available then the fifo ABI will be used. If it is not then the
>> two-level ABI will be used instead.
>> The ABI is released and re-acquired across suspend/resume so this should
>> allow moving between hosts with different capabilities.

Moving from FIFO to 2-level is only safe if you use fewer than 4095 (or
1023 on 32-bit) events, but this shouldn't be a problem for a Windows guest

>> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
>> new file mode 100644
>> index 0000000..d37b1cd
>> --- /dev/null
>> +++ b/src/xenbus/evtchn_fifo.c
>> @@ -0,0 +1,702 @@

>> +static event_word_t *
>> +EvtchnFifoEventWord(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
>> +    IN  ULONG                       Port
>> +    )
>> +{
>> +    ULONG                           Index;
>> +    PMDL                            Mdl;
>> +    event_word_t                    *EventWord;
>> +
>> +    Index = Port / EVENT_WORDS_PER_PAGE;
>> +    ASSERT3U(Index, <, Context->EventPageCount);
>> +
>> +    Mdl = Context->EventPageMdl[Index];
>> +
>> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
>> NormalPagePriority);
>> +    ASSERT(EventWord != NULL);
>> +
>> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
>> +    Port -= Index * EVENT_WORDS_PER_PAGE;
>> +
>> +    return &EventWord[Port];
>> +}

I'm not at all familiar with Windows kernel memory management but is all
this MDL stuff expensive?  Can you not store the VA instead of looking
it up every time?

>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

Do you need this barrier?  The doc has a section describing the minimum
number of barriers needed.

>> +
>> +    return !!(*EventWord & (1 << Flag));
>> +}
>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestAndSetFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

Or this one?  The Interlocked*() functions are also already barriers.

>> +
>> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
>> +}
>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestAndClearFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

ditto.

>> +
>> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
>> +}
>> +
>> +static FORCEINLINE VOID
>> +__EvtchnFifoSetFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    *EventWord |= (1 << Flag);

This must be atomic.  Remember that Xen may be simultaneously writing to
this word from a different PCPU.

You need an InterlockedBitSet() (which doesn't seem to exist.  Perhaps
make one with InterlockedOr()?)

>> +    KeMemoryBarrier();
>> +}
>> +
>> +static FORCEINLINE VOID
>> +__EvtchnFifoClearFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    *EventWord &= ~(1 << Flag);

This must be atomic as well.

>> +static VOID
>> +EvtchnFifoContract(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
>> +    )
>> +{

You can't shrink the event array if it is in use.  I assume this is only
called after an EVTCHNOP_reset hypercall?

>> +static BOOLEAN
>> +EvtchnFifoPortUnmask(
>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
>> +    IN  ULONG                       Port
>> +    )
>> +{
>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
>> +    event_word_t                    *EventWord;
>> +    LONG                            Old;
>> +    LONG                            New;
>> +
>> +    EventWord = EvtchnFifoEventWord(Context, Port);
>> +
>> +    // Clear masked bit, spinning if busy
>> +    do {
>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
>> Old);
>> +
>> +    // Check whether the port was masked
>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
>> +        return FALSE;
>> +
>> +    // If we cleared the mask then check whether something is pending
>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
>> +        return FALSE;

The doc says you should do an EVTCHNOP_unmask hypercall here, but
picking up any pending event here is fine.

You may want to be more careful if you unmask an event while running on
a VCPU that is not the one the event is bound to.

>> +static VOID
>> +EvtchnFifoReset(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
>> +    )
>> +{
>> +    ULONGLONG                       Value;
>> +    ULONG                           LocalPort;
>> +    ULONG                           RemotePort;
>> +    USHORT                          RemoteDomain;
>> +    NTSTATUS                        status;
>> +
>> +    UNREFERENCED_PARAMETER(Context);
>> +
>> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
>> +    ASSERT(NT_SUCCESS(status));
>> +
>> +    LocalPort = (LONG)Value;

You may wish to consider the console event channel as well.  But if you
don't use it, it's ok to leave it unbound.

David

_______________________________________________
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 Nov 07 14:48:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 14:48:31 +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 1Xmkpz-000712-GW; Fri, 07 Nov 2014 14:48:31 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <david.vrabel@citrix.com>) id 1Xmkfz-0006h7-LH
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 14:38:11 +0000
Received: from [85.158.139.211] by server-3.bemta-5.messagelabs.com id
	95/7F-14727-259DC545; Fri, 07 Nov 2014 14:38:10 +0000
X-Env-Sender: david.vrabel@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415371088!11125814!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21743 invoked from network); 7 Nov 2014 14:38:10 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 14:38:10 -0000
X-IronPort-AV: E=Sophos;i="5.07,332,1413244800"; d="scan'208";a="189145271"
Message-ID: <545CD91E.5090504@citrix.com>
Date: Fri, 7 Nov 2014 14:37:18 +0000
From: David Vrabel <david.vrabel@citrix.com>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
	rv:24.0) Gecko/20100101 Icedove/24.5.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
X-DLP: MIA1
X-Mailman-Approved-At: Fri, 07 Nov 2014 14:48:31 +0000
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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 07/11/14 14:02, Paul Durrant wrote:
>> -----Original Message-----
>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
>> Sent: 06 November 2014 14:31
>> To: win-pv-devel@lists.xenproject.org
>> Cc: Paul Durrant
>> Subject: [PATCH 10/10] Add support for the FIFO event channel ABI
>>
>> If it is available then the fifo ABI will be used. If it is not then the
>> two-level ABI will be used instead.
>> The ABI is released and re-acquired across suspend/resume so this should
>> allow moving between hosts with different capabilities.

Moving from FIFO to 2-level is only safe if you use fewer than 4095 (or
1023 on 32-bit) events, but this shouldn't be a problem for a Windows guest

>> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
>> new file mode 100644
>> index 0000000..d37b1cd
>> --- /dev/null
>> +++ b/src/xenbus/evtchn_fifo.c
>> @@ -0,0 +1,702 @@

>> +static event_word_t *
>> +EvtchnFifoEventWord(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context,
>> +    IN  ULONG                       Port
>> +    )
>> +{
>> +    ULONG                           Index;
>> +    PMDL                            Mdl;
>> +    event_word_t                    *EventWord;
>> +
>> +    Index = Port / EVENT_WORDS_PER_PAGE;
>> +    ASSERT3U(Index, <, Context->EventPageCount);
>> +
>> +    Mdl = Context->EventPageMdl[Index];
>> +
>> +    EventWord = MmGetSystemAddressForMdlSafe(Mdl,
>> NormalPagePriority);
>> +    ASSERT(EventWord != NULL);
>> +
>> +    ASSERT3U(Port, >=, Index * EVENT_WORDS_PER_PAGE);
>> +    Port -= Index * EVENT_WORDS_PER_PAGE;
>> +
>> +    return &EventWord[Port];
>> +}

I'm not at all familiar with Windows kernel memory management but is all
this MDL stuff expensive?  Can you not store the VA instead of looking
it up every time?

>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

Do you need this barrier?  The doc has a section describing the minimum
number of barriers needed.

>> +
>> +    return !!(*EventWord & (1 << Flag));
>> +}
>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestAndSetFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

Or this one?  The Interlocked*() functions are also already barriers.

>> +
>> +    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
>> +}
>> +
>> +static FORCEINLINE BOOLEAN
>> +__EvtchnFifoTestAndClearFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    KeMemoryBarrier();

ditto.

>> +
>> +    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
>> +}
>> +
>> +static FORCEINLINE VOID
>> +__EvtchnFifoSetFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    *EventWord |= (1 << Flag);

This must be atomic.  Remember that Xen may be simultaneously writing to
this word from a different PCPU.

You need an InterlockedBitSet() (which doesn't seem to exist.  Perhaps
make one with InterlockedOr()?)

>> +    KeMemoryBarrier();
>> +}
>> +
>> +static FORCEINLINE VOID
>> +__EvtchnFifoClearFlag(
>> +    IN  event_word_t    *EventWord,
>> +    IN  ULONG           Flag
>> +    )
>> +{
>> +    *EventWord &= ~(1 << Flag);

This must be atomic as well.

>> +static VOID
>> +EvtchnFifoContract(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
>> +    )
>> +{

You can't shrink the event array if it is in use.  I assume this is only
called after an EVTCHNOP_reset hypercall?

>> +static BOOLEAN
>> +EvtchnFifoPortUnmask(
>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
>> +    IN  ULONG                       Port
>> +    )
>> +{
>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
>> +    event_word_t                    *EventWord;
>> +    LONG                            Old;
>> +    LONG                            New;
>> +
>> +    EventWord = EvtchnFifoEventWord(Context, Port);
>> +
>> +    // Clear masked bit, spinning if busy
>> +    do {
>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New, Old) !=
>> Old);
>> +
>> +    // Check whether the port was masked
>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
>> +        return FALSE;
>> +
>> +    // If we cleared the mask then check whether something is pending
>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
>> +        return FALSE;

The doc says you should do an EVTCHNOP_unmask hypercall here, but
picking up any pending event here is fine.

You may want to be more careful if you unmask an event while running on
a VCPU that is not the one the event is bound to.

>> +static VOID
>> +EvtchnFifoReset(
>> +    IN  PXENBUS_EVTCHN_FIFO_CONTEXT Context
>> +    )
>> +{
>> +    ULONGLONG                       Value;
>> +    ULONG                           LocalPort;
>> +    ULONG                           RemotePort;
>> +    USHORT                          RemoteDomain;
>> +    NTSTATUS                        status;
>> +
>> +    UNREFERENCED_PARAMETER(Context);
>> +
>> +    status = HvmGetParam(HVM_PARAM_STORE_EVTCHN, &Value);
>> +    ASSERT(NT_SUCCESS(status));
>> +
>> +    LocalPort = (LONG)Value;

You may wish to consider the console event channel as well.  But if you
don't use it, it's ok to leave it unbound.

David

_______________________________________________
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 Nov 07 15:14:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:14: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 1XmlEx-0007V3-5V; Fri, 07 Nov 2014 15:14:19 +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 1XmlEv-0007Uy-90
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:14:17 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	6F/DF-25727-8C1EC545; Fri, 07 Nov 2014 15:14:16 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-31.messagelabs.com!1415373253!11167283!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12447 invoked from network); 7 Nov 2014 15:14:15 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:14:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="190588226"
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.181.6;
	Fri, 7 Nov 2014 10:14:10 -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 1XmlBZ-0005mW-3V;
	Fri, 07 Nov 2014 15:10:49 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 15:10:38 +0000
Message-ID: <1415373038-11304-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 v2] Update EVTCHN FIFO ABI
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

This patch is in response to review comments by David Vrabel.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn_fifo.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index d37b1cd..f65cc1b 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!(*EventWord & (1 << Flag));
+    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE VOID
@@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord |= (1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE VOID
@@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord &= ~(1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE ULONG
-- 
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 Nov 07 15:14:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:14: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 1XmlEx-0007V3-5V; Fri, 07 Nov 2014 15:14:19 +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 1XmlEv-0007Uy-90
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:14:17 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	6F/DF-25727-8C1EC545; Fri, 07 Nov 2014 15:14:16 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-31.messagelabs.com!1415373253!11167283!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12447 invoked from network); 7 Nov 2014 15:14:15 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-8.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:14:15 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="190588226"
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.181.6;
	Fri, 7 Nov 2014 10:14:10 -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 1XmlBZ-0005mW-3V;
	Fri, 07 Nov 2014 15:10:49 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 15:10:38 +0000
Message-ID: <1415373038-11304-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 v2] Update EVTCHN FIFO ABI
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

This patch is in response to review comments by David Vrabel.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn_fifo.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index d37b1cd..f65cc1b 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!(*EventWord & (1 << Flag));
+    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE VOID
@@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord |= (1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE VOID
@@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord &= ~(1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE ULONG
-- 
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 Nov 07 15:15:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:15: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 1XmlG1-0007Vd-9U; Fri, 07 Nov 2014 15:15:25 +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 1XmlG0-0007VY-JM
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:15:24 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	15/48-17958-B02EC545; Fri, 07 Nov 2014 15:15:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415373319!11160510!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30303 invoked from network); 7 Nov 2014 15:15:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:15:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="190588677"
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.181.6;
	Fri, 7 Nov 2014 10:15:16 -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 1Xml6w-0005iJ-JK;
	Fri, 07 Nov 2014 15:06:02 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 15:05:52 +0000
Message-ID: <1415372752-27652-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] Update EVTCHN FIFO ABI
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

This patch is in response to review comments by David Vrabel.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn_fifo.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index d37b1cd..2dd9597 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!(*EventWord & (1 << Flag));
+    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE
 }
 
 static FORCEINLINE BOOLEAN
@@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE VOID
@@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord |= (1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE VOID
@@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord &= ~(1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE ULONG
-- 
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 Nov 07 15:15:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:15: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 1XmlG1-0007Vd-9U; Fri, 07 Nov 2014 15:15:25 +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 1XmlG0-0007VY-JM
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:15:24 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	15/48-17958-B02EC545; Fri, 07 Nov 2014 15:15:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-31.messagelabs.com!1415373319!11160510!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30303 invoked from network); 7 Nov 2014 15:15:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:15:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="190588677"
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.181.6;
	Fri, 7 Nov 2014 10:15:16 -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 1Xml6w-0005iJ-JK;
	Fri, 07 Nov 2014 15:06:02 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 15:05:52 +0000
Message-ID: <1415372752-27652-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] Update EVTCHN FIFO ABI
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

This patch is in response to review comments by David Vrabel.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/evtchn_fifo.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index d37b1cd..2dd9597 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!(*EventWord & (1 << Flag));
+    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
 }
 
 static FORCEINLINE BOOLEAN
@@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE
 }
 
 static FORCEINLINE BOOLEAN
@@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
     IN  ULONG           Flag
     )
 {
-    KeMemoryBarrier();
-
-    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
+    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ? TRUE : FALSE;
 }
 
 static FORCEINLINE VOID
@@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord |= (1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE VOID
@@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
     IN  ULONG           Flag
     )
 {
-    *EventWord &= ~(1 << Flag);
-    KeMemoryBarrier();
+    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
 }
 
 static FORCEINLINE ULONG
-- 
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 Nov 07 15:17:00 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:17:00 +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 1XmlHY-0007WF-Dq; Fri, 07 Nov 2014 15:17:00 +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 1XmlHX-0007WA-5z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:16:59 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	A8/45-25727-A62EC545; Fri, 07 Nov 2014 15:16:58 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415373416!11124473!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7798 invoked from network); 7 Nov 2014 15:16:57 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:16:57 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="26639604"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH] Update EVTCHN FIFO ABI
Thread-Index: AQHP+p3CiLUPQiGnH0+9OO69WPOEzZxVRmJg
Date: Fri, 7 Nov 2014 15:16:55 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011148793@AMSPEX01CL01.citrite.net>
References: <1415372752-27652-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415372752-27652-1-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH] Update EVTCHN FIFO ABI
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 07 November 2014 15:06
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH] Update EVTCHN FIFO ABI
> 
> This patch is in response to review comments by David Vrabel.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  src/xenbus/evtchn_fifo.c | 18 +++++-------------
>  1 file changed, 5 insertions(+), 13 deletions(-)
> 
> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> index d37b1cd..2dd9597 100644
> --- a/src/xenbus/evtchn_fifo.c
> +++ b/src/xenbus/evtchn_fifo.c
> @@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!(*EventWord & (1 << Flag));
> +    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> +    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE
> : FALSE

This is a build failure. I posted prematurely.

  Paul

>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> +    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ?
> TRUE : FALSE;
>  }
> 
>  static FORCEINLINE VOID
> @@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    *EventWord |= (1 << Flag);
> -    KeMemoryBarrier();
> +    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
>  }
> 
>  static FORCEINLINE VOID
> @@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    *EventWord &= ~(1 << Flag);
> -    KeMemoryBarrier();
> +    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
>  }
> 
>  static FORCEINLINE ULONG
> --
> 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 Nov 07 15:17:00 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 15:17:00 +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 1XmlHY-0007WF-Dq; Fri, 07 Nov 2014 15:17:00 +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 1XmlHX-0007WA-5z
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 15:16:59 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	A8/45-25727-A62EC545; Fri, 07 Nov 2014 15:16:58 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415373416!11124473!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7798 invoked from network); 7 Nov 2014 15:16:57 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 15:16:57 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="26639604"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH] Update EVTCHN FIFO ABI
Thread-Index: AQHP+p3CiLUPQiGnH0+9OO69WPOEzZxVRmJg
Date: Fri, 7 Nov 2014 15:16:55 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011148793@AMSPEX01CL01.citrite.net>
References: <1415372752-27652-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1415372752-27652-1-git-send-email-paul.durrant@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
Subject: Re: [win-pv-devel] [PATCH] Update EVTCHN FIFO ABI
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: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 07 November 2014 15:06
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant
> Subject: [PATCH] Update EVTCHN FIFO ABI
> 
> This patch is in response to review comments by David Vrabel.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> ---
>  src/xenbus/evtchn_fifo.c | 18 +++++-------------
>  1 file changed, 5 insertions(+), 13 deletions(-)
> 
> diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
> index d37b1cd..2dd9597 100644
> --- a/src/xenbus/evtchn_fifo.c
> +++ b/src/xenbus/evtchn_fifo.c
> @@ -102,9 +102,7 @@ __EvtchnFifoTestFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!(*EventWord & (1 << Flag));
> +    return (*EventWord & (1 << Flag)) ? TRUE : FALSE;
>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -113,9 +111,7 @@ __EvtchnFifoTestAndSetFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!InterlockedBitTestAndSet((LONG *)EventWord, Flag);
> +    return (InterlockedBitTestAndSet((LONG *)EventWord, Flag) != 0) ? TRUE
> : FALSE

This is a build failure. I posted prematurely.

  Paul

>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -124,9 +120,7 @@ __EvtchnFifoTestAndClearFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    KeMemoryBarrier();
> -
> -    return !!InterlockedBitTestAndReset((LONG *)EventWord, Flag);
> +    return (InterlockedBitTestAndReset((LONG *)EventWord, Flag) != 0) ?
> TRUE : FALSE;
>  }
> 
>  static FORCEINLINE VOID
> @@ -135,8 +129,7 @@ __EvtchnFifoSetFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    *EventWord |= (1 << Flag);
> -    KeMemoryBarrier();
> +    (VOID) InterlockedBitTestAndSet((LONG *)EventWord, Flag);
>  }
> 
>  static FORCEINLINE VOID
> @@ -145,8 +138,7 @@ __EvtchnFifoClearFlag(
>      IN  ULONG           Flag
>      )
>  {
> -    *EventWord &= ~(1 << Flag);
> -    KeMemoryBarrier();
> +    (VOID) InterlockedBitTestAndReset((LONG *)EventWord, Flag);
>  }
> 
>  static FORCEINLINE ULONG
> --
> 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 Nov 07 16:37:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:22 +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 1XmmXK-0000kq-2U; Fri, 07 Nov 2014 16:37:22 +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 1XmmXI-0000kg-Ux
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:21 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	36/72-07724-045FC545; Fri, 07 Nov 2014 16:37:20 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19909 invoked from network); 7 Nov 2014 16:37:19 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196327"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-Si;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:46 +0000
Message-ID: <1415378147-17816-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 3/4] Update Xen headers to master (4.5-rc0
	+ HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 16:37:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:22 +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 1XmmXK-0000kq-2U; Fri, 07 Nov 2014 16:37:22 +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 1XmmXI-0000kg-Ux
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:21 +0000
Received: from [85.158.137.68] by server-14.bemta-3.messagelabs.com id
	36/72-07724-045FC545; Fri, 07 Nov 2014 16:37:20 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19909 invoked from network); 7 Nov 2014 16:37:19 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196327"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-Si;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:46 +0000
Message-ID: <1415378147-17816-4-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 3/4] Update Xen headers to master (4.5-rc0
	+ HVMOP_set_evtchn_upcall_vector)
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>
---
 include/xen/features.h    |  4 +++-
 include/xen/grant_table.h | 20 ++++++++++++++++++++
 include/xen/hvm/hvm_op.h  | 20 ++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/xen/features.h b/include/xen/features.h
index b7bf83f..16d92aa 100644
--- a/include/xen/features.h
+++ b/include/xen/features.h
@@ -94,8 +94,10 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
-/* Xen also maps grant references at pfn = mfn */
+/* Xen also maps grant references at pfn = mfn.
+ * This feature flag is deprecated and should not be used.
 #define XENFEAT_grant_map_identity        12
+ */
 
 #define XENFEAT_NR_SUBMAPS 1
 
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
index 6bff379..05b29bb 100644
--- a/include/xen/grant_table.h
+++ b/include/xen/grant_table.h
@@ -309,6 +309,7 @@ typedef uint16_t grant_status_t;
 #define GNTTABOP_get_status_frames    9
 #define GNTTABOP_get_version          10
 #define GNTTABOP_swap_grant_ref	      11
+#define GNTTABOP_cache_flush	      12
 #endif /* __XEN_INTERFACE_VERSION__ */
 /* ` } */
 
@@ -574,6 +575,25 @@ struct gnttab_swap_grant_ref {
 typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
 DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
 
+/*
+ * Issue one or more cache maintenance operations on a portion of a
+ * page granted to the calling domain by a foreign domain.
+ */
+struct gnttab_cache_flush {
+    union {
+        uint64_t dev_bus_addr;
+        grant_ref_t ref;
+    } a;
+    uint16_t offset; /* offset from start of grant */
+    uint16_t length; /* size within the grant */
+#define GNTTAB_CACHE_CLEAN          (1<<0)
+#define GNTTAB_CACHE_INVAL          (1<<1)
+#define GNTTAB_CACHE_SOURCE_GREF    (1<<31)
+    uint32_t op;
+};
+typedef struct gnttab_cache_flush gnttab_cache_flush_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_cache_flush_t);
+
 #endif /* __XEN_INTERFACE_VERSION__ */
 
 /*
diff --git a/include/xen/hvm/hvm_op.h b/include/xen/hvm/hvm_op.h
index eeb0a60..cfbf85d 100644
--- a/include/xen/hvm/hvm_op.h
+++ b/include/xen/hvm/hvm_op.h
@@ -369,6 +369,26 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
 
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
+#if defined(__i386__) || defined(__x86_64__)
+
+/*
+ * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event
+ *                                 channel upcalls on the specified <vcpu>. If set,
+ *                                 this vector will be used in preference to the
+ *                                 domain callback via (see HVM_PARAM_CALLBACK_IRQ)
+ *                                 and hence allows HVM guests to bind event
+ *                                 event channels to a vcpu other than 0.
+ */
+#define HVMOP_set_evtchn_upcall_vector 23
+struct xen_hvm_set_evtchn_upcall_vector {
+    uint32_t vcpu;
+    uint8_t vector;
+};
+typedef struct xen_hvm_set_evtchn_upcall_vector xen_hvm_set_evtchn_upcall_vector_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_evtchn_upcall_vector_t);
+
+#endif /* defined(__i386__) || defined(__x86_64__) */
+
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
 
 /*
-- 
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 Nov 07 16:37:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:22 +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 1XmmXK-0000kw-3Y; Fri, 07 Nov 2014 16:37:22 +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 1XmmXJ-0000kl-Lv
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:21 +0000
Received: from [85.158.137.68] by server-15.bemta-3.messagelabs.com id
	98/8A-17735-045FC545; Fri, 07 Nov 2014 16:37:20 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20015 invoked from network); 7 Nov 2014 16:37:20 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196315"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-RF	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:43 +0000
Message-ID: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Subject: [win-pv-devel] [PATCH v3 0/4] Use per-vcpu event channel upcalls
	if	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be
allocated, one per CPU.

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.

v2:
 - Added missing file to patch #1
 - Removed spurious INF file change from patch #2

v3:
 - Modified trigger code to use affinitized DPC so that it is done on
   the correct CPU
 - Modified the unmask code to use trigger if it is not on the correct
   CPU
 

_______________________________________________
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 Nov 07 16:37:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:22 +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 1XmmXK-0000kw-3Y; Fri, 07 Nov 2014 16:37:22 +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 1XmmXJ-0000kl-Lv
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:21 +0000
Received: from [85.158.137.68] by server-15.bemta-3.messagelabs.com id
	98/8A-17735-045FC545; Fri, 07 Nov 2014 16:37:20 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20015 invoked from network); 7 Nov 2014 16:37:20 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196315"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-RF	for
	win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:43 +0000
Message-ID: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
MIME-Version: 1.0
X-DLP: MIA2
Subject: [win-pv-devel] [PATCH v3 0/4] Use per-vcpu event channel upcalls
	if	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

My recent patch posted to xen-devel provides a new hypercall to register an
upcall vector per-vcpu for event channels. This series supplies the in-guest
code to make use of that.

Patch #1 adds code to re-populate the hypercall page on resume. This needs to
be done because the guest currently relies on a set effect of setting the
callback via to latch the shared info width in Xen. Re-populating the
hypercall page does the same thing so if use of the callback via is
dropped in future, in favour of just using the per-vcpu upcall, then the
shared info width will still get latched.

Patch #2 modifies the FDO handling code to intercept
IRP_MN_FILTER_RESOURCE_REQUIREMENTS so that extra interrupts can be
allocated, one per CPU.

Patch #3 updates to the latest Xen headers, including the new HVM op.

Patch #4 switches over to using the new per-vcpu upcalls, if the hypervisor
supports the new hypercall, and allows event channels to be bound to a vcpu
other than 0 if there is an upcall registered for that vcpu. The STORE
event channel is bound to the highest numbered vcpu as an example.

v2:
 - Added missing file to patch #1
 - Removed spurious INF file change from patch #2

v3:
 - Modified trigger code to use affinitized DPC so that it is done on
   the correct CPU
 - Modified the unmask code to use trigger if it is not on the correct
   CPU
 

_______________________________________________
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 Nov 07 16:37:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37: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 1XmmXN-0000lg-4y; Fri, 07 Nov 2014 16:37:25 +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 1XmmXM-0000lY-3c
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:24 +0000
Received: from [85.158.137.68] by server-16.bemta-3.messagelabs.com id
	E0/07-09284-345FC545; Fri, 07 Nov 2014 16:37:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20188 invoked from network); 7 Nov 2014 16:37:21 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:21 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196332"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-Rh;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:44 +0000
Message-ID: <1415378147-17816-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 27023
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v3 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuL3hlbl92ZXJz
aW9uLmMgIHwgMTA3ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysKIHNyYy94ZW5idXMvZmRvLmMgICAgICAgfCAgIDIgKwogc3JjL3hlbmJ1cy9zdXNwZW5kLmMg
ICB8ICAgMiArCiB2czIwMTIveGVuL3hlbi52Y3hwcm9qIHwgICAxICsKIHZzMjAxMy94ZW4veGVu
LnZjeHByb2ogfCAgIDMgKy0KIDExIGZpbGVzIGNoYW5nZWQsIDQwNiBpbnNlcnRpb25zKCspLCAz
MSBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi9mZWF0dXJlcy5o
CiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vdmVyc2lvbi5oCiBjcmVhdGUgbW9kZSAx
MDA2NDQgc3JjL3hlbi94ZW5fdmVyc2lvbi5jCgpkaWZmIC0tZ2l0IGEvZ2V0X3hlbl9oZWFkZXJz
LnB5IGIvZ2V0X3hlbl9oZWFkZXJzLnB5CmluZGV4IDVjYTVjOTMuLmVmMWEyYzggMTAwNjQ0Ci0t
LSBhL2dldF94ZW5faGVhZGVycy5weQorKysgYi9nZXRfeGVuX2hlYWRlcnMucHkKQEAgLTYxLDYg
KzYxLDggQEAgaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgICBjb3B5X2ZpbGUod29ya2lu
ZywgJ3B1YmxpYycsICcuJywgJ3NjaGVkLmgnKQogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZXZlbnRfY2hhbm5lbC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1
YmxpYycsICcuJywgJ2dyYW50X3RhYmxlLmgnKQorICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAndmVyc2lvbi5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2ZlYXR1cmVzLmgnKQogCiAgICAgY29weV9maWxlKHdvcmtpbmcsICd4ZW4nLCAnLics
ICdlcnJuby5oJykKIApkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBiL2luY2x1ZGUveGVuLmgK
aW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQKLS0tIGEvaW5jbHVkZS94ZW4uaAorKysgYi9p
bmNsdWRlL3hlbi5oCkBAIC00NCw2ICs0NCw3IEBACiAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+CiAj
aW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMuaD4KICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPgor
I2luY2x1ZGUgPHhlbi92ZXJzaW9uLmg+CiAKICNpZm5kZWYgWEVOX0FQSQogI2RlZmluZSBYRU5f
QVBJIF9fZGVjbHNwZWMoZGxsaW1wb3J0KQpAQCAtNTYsNiArNTcsMTQgQEAgWGVuVG91Y2goCiAg
ICAgVk9JRAogICAgICk7CiAKKy8vIEhZUEVSQ0FMTAorCitYRU5fQVBJCitWT0lECitIeXBlcmNh
bGxQb3B1bGF0ZSgKKyAgICBWT0lECisgICAgKTsKKwogLy8gSFZNCiAKIF9fY2hlY2tSZXR1cm4K
QEAgLTIzMyw2ICsyNDIsMjMgQEAgU2NoZWRZaWVsZCgKICAgICBWT0lECiAgICAgKTsKIAorLy8g
WEVOIFZFUlNJT04KKworX19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNp
b24oCisgICAgT1VUIFBVTE9ORyAgTWFqb3IsCisgICAgT1VUIFBVTE9ORyAgTWlub3IKKyAgICAp
OworCitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbkV4dHJhKAor
ICAgIE9VVCBQQ0hBUiAgIEV4dHJhCisgICAgKTsKKwogLy8gTU9EVUxFCiAKIFhFTl9BUEkKZGlm
ZiAtLWdpdCBhL2luY2x1ZGUveGVuL2ZlYXR1cmVzLmggYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmI3YmY4M2YKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oCkBAIC0wLDAgKzEsMTEyIEBACisvKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqCisgKiBmZWF0dXJlcy5oCisgKiAKKyAqIEZlYXR1cmUgZmxhZ3MsIHJl
cG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMuCisgKiAKKyAqIFBlcm1pc3Npb24gaXMgaGVy
ZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNv
cHkKKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxl
cyAodGhlICJTb2Z0d2FyZSIpLCB0bworICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCBy
ZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUKKyAqIHJpZ2h0cyB0
byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vu
c2UsIGFuZC9vcgorICogc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0
IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywg
c3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNv
cHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVk
ZWQgaW4KKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdB
UlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVU
IE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJ
VE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5P
IEVWRU5UIFNIQUxMIFRIRQorICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFC
TEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBXSEVUSEVS
IElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKKyAq
IEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBV
U0UgT1IgT1RIRVIKKyAqIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBDb3B5cmln
aHQgKGMpIDIwMDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+CisgKi8KKworI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19GRUFU
VVJFU19IX18KKworLyoKKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19mZWF0dXJlcyBYRU5f
RUxGTk9URV9GRUFUVVJFUworICoKKyAqIFRoZSBsaXN0IG9mIGFsbCB0aGUgZmVhdHVyZXMgdGhl
IGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkKKyAqIHBhcnNpbmcgdGhlIFhFTl9FTEZO
T1RFX0ZFQVRVUkVTIGFuZCBYRU5fRUxGTk9URV9TVVBQT1JURURfRkVBVFVSRVMKKyAqIHN0cmlu
Zy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUgbmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91
dCB0aGUKKyAqICJYRU5GRUFUXyIgcHJlZml4KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMu
CisgKiBJZiBhIGZlYXR1cmUgaXMgcmVxdWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24g
dGhlbiB0aGUgZmVhdHVyZSBuYW1lCisgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJh
Y3Rlci4KKyAqCisgKiBOb3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVT
IGlzIHVzZWQsIHRoZW4gaW4gdGhlCisgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhl
IGd1ZXN0IGlzIHRvIGJlIGJvb3RlZCBhcyBkb20wLAorICovCisKKy8qCisgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4KKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLgorICovCisjZGVmaW5lIFhF
TkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMAorCisvKgorICogSWYgc2V0LCB0aGUg
Z3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBzZWdtZW50IGRlc2NyaXB0
b3IKKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAq
LworI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rlc2NyaXB0b3JfdGFibGVzIDEKKworLyoKKyAq
IElmIHNldCwgdHJhbnNsYXRpb24gYmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2Fs
JyBhZGRyZXNzIHNwYWNlCisgKiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2Ug
YXJlIGhhbmRsZWQgYnkgdGhlIGh5cGVydmlzb3IuIEluIHRoaXMKKyAqIG1vZGUgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZSB0cmFuc2xhdGlv
bnMKKyAqIHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuCisgKi8KKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyCisKKy8qIElmIHNldCwgdGhl
IGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmluZyAwKS4g
Ki8KKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAzCisKKy8qCisg
KiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFsbG9jYXRlIHg4NiBQQUUgcGFn
ZSBkaXJlY3RvcmllcworICogYmVsb3cgNEdCLiBUaGlzIGZsYWcgaXMgdXN1YWxseSBpbXBsaWVk
IGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLgorICovCisjZGVmaW5lIFhFTkZFQVRfcGFlX3Bn
ZGlyX2Fib3ZlXzRnYiAgICAgICAgNAorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBw
b3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BSRVNFUlZFX0FEIGh5cGVyY2FsbD8gKi8KKyNkZWZpbmUg
WEVORkVBVF9tbXVfcHRfdXBkYXRlX3ByZXNlcnZlX2FkICA1CisKKy8qIHg4NjogRG9lcyB0aGlz
IFhlbiBob3N0IHN1cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRSBoeXBlcmNhbGw/ICov
CisjZGVmaW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNgorCisvKgorICog
SWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFjZWQg
aW50byBndWVzdCBrZXJuZWwKKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4KKyAqLworI2RlZmluZSBY
RU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcKKworLyogeDg2OiBEb2VzIHRoaXMg
WGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZlY3RvciB0eXBlPyAqLworI2RlZmlu
ZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAgICAgIDgKKworLyogeDg2OiBwdmNsb2Nr
IGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBvbiBIVk0gKi8KKyNkZWZpbmUgWEVORkVBVF9odm1f
c2FmZV9wdmNsb2NrICAgICAgICAgICA5CisKKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBI
Vk0gZ3Vlc3RzICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAx
MAorCisvKiBvcGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8KKyNkZWZpbmUgWEVORkVB
VF9kb20wICAgICAgICAgICAgICAgICAgICAgIDExCisKKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8KKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBfaWRl
bnRpdHkgICAgICAgIDEyCisKKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEKKworI2VuZGlm
IC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8KKworLyoKKyAqIExvY2FsIHZhcmlhYmxl
czoKKyAqIG1vZGU6IEMKKyAqIGMtZmlsZS1zdHlsZTogIkJTRCIKKyAqIGMtYmFzaWMtb2Zmc2V0
OiA0CisgKiB0YWItd2lkdGg6IDQKKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbAorICogRW5kOgor
ICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJz
aW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNDRmMjZiMAotLS0gL2Rl
di9udWxsCisrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaApAQCAtMCwwICsxLDk2IEBACisvKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqCisgKiB2ZXJzaW9uLmgKKyAqIAorICogWGVuIHZlcnNpb24sIHR5
cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVi
eSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5
CisgKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMg
KHRoZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVz
dHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8g
dXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNl
LCBhbmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBw
ZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1
YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5
cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVk
IGluCisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2Fy
ZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJS
QU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBO
T1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRO
RVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBF
VkVOVCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxF
IEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJ
TiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBG
Uk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNF
IE9SIE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0
IChjKSAyMDA1LCBOZ3V5ZW4gQW5oIFF1eW5oIDxhcXV5bmhAZ21haWwuY29tPgorICogQ29weXJp
Z2h0IChjKSAyMDA1LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNp
Zm5kZWYgX19YRU5fUFVCTElDX1ZFUlNJT05fSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19WRVJT
SU9OX0hfXworCisjaW5jbHVkZSAieGVuLmgiCisKKy8qIE5CLiBBbGwgb3BzIHJldHVybiB6ZXJv
IG9uIHN1Y2Nlc3MsIGV4Y2VwdCBYRU5WRVJfe3ZlcnNpb24scGFnZXNpemV9ICovCisKKy8qIGFy
ZyA9PSBOVUxMOyByZXR1cm5zIG1ham9yOm1pbm9yICgxNjoxNikuICovCisjZGVmaW5lIFhFTlZF
Ul92ZXJzaW9uICAgICAgMAorCisvKiBhcmcgPT0geGVuX2V4dHJhdmVyc2lvbl90LiAqLworI2Rl
ZmluZSBYRU5WRVJfZXh0cmF2ZXJzaW9uIDEKK3R5cGVkZWYgY2hhciB4ZW5fZXh0cmF2ZXJzaW9u
X3RbMTZdOworI2RlZmluZSBYRU5fRVhUUkFWRVJTSU9OX0xFTiAoc2l6ZW9mKHhlbl9leHRyYXZl
cnNpb25fdCkpCisKKy8qIGFyZyA9PSB4ZW5fY29tcGlsZV9pbmZvX3QuICovCisjZGVmaW5lIFhF
TlZFUl9jb21waWxlX2luZm8gMgorc3RydWN0IHhlbl9jb21waWxlX2luZm8geworICAgIGNoYXIg
Y29tcGlsZXJbNjRdOworICAgIGNoYXIgY29tcGlsZV9ieVsxNl07CisgICAgY2hhciBjb21waWxl
X2RvbWFpblszMl07CisgICAgY2hhciBjb21waWxlX2RhdGVbMzJdOworfTsKK3R5cGVkZWYgc3Ry
dWN0IHhlbl9jb21waWxlX2luZm8geGVuX2NvbXBpbGVfaW5mb190OworCisjZGVmaW5lIFhFTlZF
Ul9jYXBhYmlsaXRpZXMgMwordHlwZWRlZiBjaGFyIHhlbl9jYXBhYmlsaXRpZXNfaW5mb190WzEw
MjRdOworI2RlZmluZSBYRU5fQ0FQQUJJTElUSUVTX0lORk9fTEVOIChzaXplb2YoeGVuX2NhcGFi
aWxpdGllc19pbmZvX3QpKQorCisjZGVmaW5lIFhFTlZFUl9jaGFuZ2VzZXQgNAordHlwZWRlZiBj
aGFyIHhlbl9jaGFuZ2VzZXRfaW5mb190WzY0XTsKKyNkZWZpbmUgWEVOX0NIQU5HRVNFVF9JTkZP
X0xFTiAoc2l6ZW9mKHhlbl9jaGFuZ2VzZXRfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfcGxh
dGZvcm1fcGFyYW1ldGVycyA1CitzdHJ1Y3QgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnMgeworICAg
IHhlbl91bG9uZ190IHZpcnRfc3RhcnQ7Cit9OwordHlwZWRlZiBzdHJ1Y3QgeGVuX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnNfdDsKKworI2RlZmluZSBYRU5WRVJf
Z2V0X2ZlYXR1cmVzIDYKK3N0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHsKKyAgICB1bnNpZ25lZCBp
bnQgc3VibWFwX2lkeDsgICAgLyogSU46IHdoaWNoIDMyLWJpdCBzdWJtYXAgdG8gcmV0dXJuICov
CisgICAgdWludDMyX3QgICAgIHN1Ym1hcDsgICAgICAgIC8qIE9VVDogMzItYml0IHN1Ym1hcCAq
LworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9mZWF0dXJlX2luZm8geGVuX2ZlYXR1cmVfaW5mb190
OworCisvKiBEZWNsYXJlcyB0aGUgZmVhdHVyZXMgcmVwb3J0ZWQgYnkgWEVOVkVSX2dldF9mZWF0
dXJlcy4gKi8KKyNpbmNsdWRlICJmZWF0dXJlcy5oIgorCisvKiBhcmcgPT0gTlVMTDsgcmV0dXJu
cyBob3N0IG1lbW9yeSBwYWdlIHNpemUuICovCisjZGVmaW5lIFhFTlZFUl9wYWdlc2l6ZSA3CisK
Ky8qIGFyZyA9PSB4ZW5fZG9tYWluX2hhbmRsZV90LiAqLworI2RlZmluZSBYRU5WRVJfZ3Vlc3Rf
aGFuZGxlIDgKKworI2RlZmluZSBYRU5WRVJfY29tbWFuZGxpbmUgOQordHlwZWRlZiBjaGFyIHhl
bl9jb21tYW5kbGluZV90WzEwMjRdOworCisjZW5kaWYgLyogX19YRU5fUFVCTElDX1ZFUlNJT05f
SF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6CisgKiBtb2RlOiBDCisgKiBjLWZpbGUt
c3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAorICogdGFiLXdpZHRoOiA0CisgKiBp
bmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpkaWZmIC0tZ2l0IGEvc3JjL3hlbi9k
cml2ZXIuYyBiL3NyYy94ZW4vZHJpdmVyLmMKaW5kZXggYmE1NDFiNC4uZmNlNzVhYSAxMDA2NDQK
LS0tIGEvc3JjL3hlbi9kcml2ZXIuYworKysgYi9zcmMveGVuL2RyaXZlci5jCkBAIC01OSw2ICs1
OSwyNiBAQCBYZW5Ub3VjaCgKICAgICBWT0lECiAgICAgKQogeworICAgIHN0YXRpYyBVTE9ORyAg
ICBSZWZlcmVuY2U7CisgICAgVUxPTkcgICAgICAgICAgIE1ham9yOworICAgIFVMT05HICAgICAg
ICAgICBNaW5vcjsKKyAgICBDSEFSICAgICAgICAgICAgRXh0cmFbWEVOX0VYVFJBVkVSU0lPTl9M
RU5dOworICAgIE5UU1RBVFVTICAgICAgICBzdGF0dXM7CisKKyAgICBpZiAoUmVmZXJlbmNlKysg
IT0gMCkKKyAgICAgICAgcmV0dXJuOworCisgICAgc3RhdHVzID0gWGVuVmVyc2lvbigmTWFqb3Is
ICZNaW5vcik7CisgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7CisKKyAgICBzdGF0dXMg
PSBYZW5WZXJzaW9uRXh0cmEoRXh0cmEpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykp
OworCisgICAgTG9nUHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAiWEVOOiAl
dS4ldSVzXG4iLAorICAgICAgICAgICAgICBNYWpvciwKKyAgICAgICAgICAgICAgTWlub3IsCisg
ICAgICAgICAgICAgIEV4dHJhKTsKIH0KIAogc3RhdGljIFZPSUQKZGlmZiAtLWdpdCBhL3NyYy94
ZW4vaHlwZXJjYWxsLmMgYi9zcmMveGVuL2h5cGVyY2FsbC5jCmluZGV4IDA3ZWI0MWEuLjcxN2I4
YzIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW4vaHlwZXJjYWxsLmMKKysrIGIvc3JjL3hlbi9oeXBlcmNh
bGwuYwpAQCAtMjksNiArMjksOSBAQAogICogU1VDSCBEQU1BR0UuCiAgKi8KIAorI3VuZGVmICBY
RU5fQVBJCisjZGVmaW5lIFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpCisKICNpbmNsdWRl
IDxudGRkay5oPgogI2luY2x1ZGUgPHhlbi5oPgogI2luY2x1ZGUgPHV0aWwuaD4KQEAgLTM3LDI0
ICs0MCw0MSBAQAogI2luY2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgog
Ci0jZGVmaW5lIE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCAyCisjZGVmaW5lIE1BWElNVU1f
SFlQRVJDQUxMX1BBR0VfQ09VTlQgMgogCiAjcHJhZ21hIGNvZGVfc2VnKCJoeXBlcmNhbGwiKQog
X19kZWNsc3BlYyhhbGxvY2F0ZSgiaHlwZXJjYWxsIikpCi1zdGF0aWMgVUNIQVIgICAgICAgIF9f
U2VjdGlvblsoTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UICsgMSkgKiBQQUdFX1NJWkVdOwor
c3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09V
TlQgKyAxKSAqIFBBR0VfU0laRV07CiAKIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYg
PSAweDQwMDAwMDAwOwogCi1zdGF0aWMgVVNIT1JUICAgICAgIFhlbk1ham9yVmVyc2lvbjsKLXN0
YXRpYyBVU0hPUlQgICAgICAgWGVuTWlub3JWZXJzaW9uOwotCi1zdGF0aWMgUEZOX05VTUJFUiAg
IEh5cGVyY2FsbFBmbltNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlRdOwotc3RhdGljIFVMT05H
ICAgICAgICBIeXBlcmNhbGxQZm5Db3VudDsKK3N0YXRpYyBQSFlTSUNBTF9BRERSRVNTIEh5cGVy
Y2FsbFBhZ2VbTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVF07CitzdGF0aWMgVUxPTkcgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlQ291bnQ7CiAKIHR5cGVkZWYgVUNIQVIgICAgICAgICAgIEhZ
UEVSQ0FMTF9HQVRFWzMyXTsKIHR5cGVkZWYgSFlQRVJDQUxMX0dBVEUgICpQSFlQRVJDQUxMX0dB
VEU7CiAKIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxsOworVUxPTkcgICAgICAgICAgICAg
ICBIeXBlcmNhbGxNc3I7CisKK1hFTl9BUEkKK1ZPSUQKK0h5cGVyY2FsbFBvcHVsYXRlKAorICAg
IFZPSUQKKyAgICApCit7CisgICAgVUxPTkcgICAgICAgSW5kZXg7CisKKyAgICBmb3IgKEluZGV4
ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsKKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJDQUxM
IFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsCisgICAgICAgICAgICAgICAgICBJbmRleCwKKyAgICAg
ICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LAorICAgICAgICAgICAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7CisKKyAgICAgICAgX193cml0ZW1z
cihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0KTsKKyAgICB9Cit9
CiAKIE5UU1RBVFVTCiBIeXBlcmNhbGxJbml0aWFsaXplKApAQCAtNjYsNyArODYsNiBAQCBIeXBl
cmNhbGxJbml0aWFsaXplKAogICAgIFVMT05HICAgICAgIEVDWCA9ICdERUFEJzsKICAgICBVTE9O
RyAgICAgICBFRFggPSAnREVBRCc7CiAgICAgVUxPTkcgICAgICAgSW5kZXg7Ci0gICAgVUxPTkcg
ICAgICAgSHlwZXJjYWxsTXNyOwogICAgIE5UU1RBVFVTICAgIHN0YXR1czsKIAogICAgIHN0YXR1
cyA9IFNUQVRVU19VTlNVQ0NFU1NGVUw7CkBAIC04OCwxMyArMTA3LDYgQEAgSHlwZXJjYWxsSW5p
dGlhbGl6ZSgKICAgICAgICAgICAgIGdvdG8gZmFpbDE7CiAgICAgfQogCi0gICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOwotICAgIFhlbk1ham9yVmVy
c2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7Ci0gICAgWGVuTWlub3JWZXJzaW9uID0gKFVTSE9S
VCkoRUFYICYgMHhGRkZGKTsKLQotICAgIEluZm8oIlhFTiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJz
aW9uLCBYZW5NaW5vclZlcnNpb24pOwotICAgIEluZm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9f
WEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOwotCiAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9u
ICYgKFBBR0VfU0laRSAtIDEpKQogICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdf
UFRSKV9fU2VjdGlvbiArIFBBR0VfU0laRSAtIDEpICYgfihQQUdFX1NJWkUgLSAxKSk7CiAgICAg
ZWxzZQpAQCAtMTAyLDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgKIAogICAgIEFT
U0VSVDNVKCgoVUxPTkdfUFRSKUh5cGVyY2FsbCAmIChQQUdFX1NJWkUgLSAxKSksID09LCAwKTsK
IAotICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VO
VDsgSW5kZXgrKykgewotICAgICAgICBQSFlTSUNBTF9BRERSRVNTICAgIFBoeXNpY2FsQWRkcmVz
czsKLQotICAgICAgICBQaHlzaWNhbEFkZHJlc3MgPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVD
SEFSKUh5cGVyY2FsbCArIChJbmRleCA8PCBQQUdFX1NISUZUKSk7Ci0gICAgICAgIEh5cGVyY2Fs
bFBmbltJbmRleF0gPSAoUEZOX05VTUJFUikoUGh5c2ljYWxBZGRyZXNzLlF1YWRQYXJ0ID4+IFBB
R0VfU0hJRlQpOwotICAgIH0KKyAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UOyBJbmRleCsrKQorICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4
XSA9IE1tR2V0UGh5c2ljYWxBZGRyZXNzKChQVUNIQVIpSHlwZXJjYWxsICsKKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoSW5kZXggPDwgUEFHRV9T
SElGVCkpOwogCiAgICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEws
IE5VTEwpOwotICAgIEh5cGVyY2FsbFBmbkNvdW50ID0gRUFYOwotICAgIEFTU0VSVChIeXBlcmNh
bGxQZm5Db3VudCA8PSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOworICAgIEh5cGVyY2Fs
bFBhZ2VDb3VudCA9IEVBWDsKKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQpOwogICAgIEh5cGVyY2FsbE1zciA9IEVCWDsKIAotICAg
IGZvciAoSW5kZXggPSAwOyBJbmRleCA8IEh5cGVyY2FsbFBmbkNvdW50OyBJbmRleCsrKSB7Ci0g
ICAgICAgIEluZm8oIkh5cGVyY2FsbFBmblslZF06ICVwXG4iLCBJbmRleCwgKFBWT0lEKUh5cGVy
Y2FsbFBmbltJbmRleF0pOwotICAgICAgICBfX3dyaXRlbXNyKEh5cGVyY2FsbE1zciwgKFVMT05H
NjQpSHlwZXJjYWxsUGZuW0luZGV4XSA8PCBQQUdFX1NISUZUKTsKLSAgICB9CisgICAgSHlwZXJj
YWxsUG9wdWxhdGUoKTsKIAogICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsKIApAQCAtMTc3LDgg
KzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKAogCiAgICAgSHlwZXJjYWxsID0gTlVMTDsKIAot
ICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVDsg
SW5kZXgrKykKLSAgICAgICAgSHlwZXJjYWxsUGZuW0luZGV4XSA9IDA7CisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uUXVhZFBhcnQgPSAwOwogCi0gICAgSHlwZXJjYWxs
UGZuQ291bnQgPSAwOworICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7CiB9CmRpZmYgLS1naXQg
YS9zcmMveGVuL3hlbl92ZXJzaW9uLmMgYi9zcmMveGVuL3hlbl92ZXJzaW9uLmMKbmV3IGZpbGUg
bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNmVmMDYxZgotLS0gL2Rldi9udWxsCisrKyBiL3Ny
Yy94ZW4veGVuX3ZlcnNpb24uYwpAQCAtMCwwICsxLDEwNyBAQAorLyogQ29weXJpZ2h0IChjKSBD
aXRyaXggU3lzdGVtcyBJbmMuCisgKiBBbGwgcmlnaHRzIHJlc2VydmVkLgorICogCisgKiBSZWRp
c3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCAKKyAqIHdpdGgg
b3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgCisgKiB0aGF0
IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OgorICogCisgKiAqICAgUmVkaXN0cmli
dXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5
cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZv
bGxvd2luZyBkaXNjbGFpbWVyLgorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9y
bSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhp
cyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1l
ciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgCisgKiAgICAgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqIAorICogVEhJUyBTT0ZUV0FSRSBJUyBQ
Uk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIAorICogQ09OVFJJQlVUT1JTICJB
UyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgCisgKiBJTkNMVURJ
TkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiAKKyAqIE1F
UkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIAor
ICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1Ig
CisgKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D
SURFTlRBTCwgCisgKiBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdF
UyAoSU5DTFVESU5HLCAKKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VC
U1RJVFVURSBHT09EUyBPUiAKKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJP
RklUUzsgT1IgQlVTSU5FU1MgCisgKiBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBP
TiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgCisgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgCisgKiBORUdMSUdFTkNFIE9SIE9USEVS
V0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIAorICogT0YgVEhJUyBTT0ZU
V0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiAKKyAqIFNVQ0ggREFN
QUdFLgorICovCisKKyNkZWZpbmUgWEVOX0FQSSBfX2RlY2xzcGVjKGRsbGV4cG9ydCkKKworI2lu
Y2x1ZGUgPG50ZGRrLmg+CisjaW5jbHVkZSA8eGVuLmg+CisKKyNpbmNsdWRlICJoeXBlcmNhbGwu
aCIKKyNpbmNsdWRlICJkYmdfcHJpbnQuaCIKKyNpbmNsdWRlICJhc3NlcnQuaCIKKworc3RhdGlj
IEZPUkNFSU5MSU5FIExPTkdfUFRSCitYZW5WZXJzaW9uT3AoCisgICAgSU4gIFVMT05HICAgQ29t
bWFuZCwKKyAgICBJTiAgUFZPSUQgICBBcmd1bWVudAorICAgICkKK3sKKyAgICByZXR1cm4gSFlQ
RVJDQUxMKExPTkdfUFRSLCB4ZW5fdmVyc2lvbiwgMiwgQ29tbWFuZCwgQXJndW1lbnQpOworfQor
CitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbigKKyAgICBPVVQg
UFVMT05HICBNYWpvciwKKyAgICBPVVQgUFVMT05HICBNaW5vcgorICAgICkKK3sKKyAgICBMT05H
X1BUUiAgICAgICAgICAgICAgICAgICAgcmM7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIHJjID0gWGVuVmVyc2lvbk9wKFhFTlZFUl92ZXJzaW9uLCBOVUxM
KTsKKworICAgIGlmIChyYyA8IDApIHsKKyAgICAgICAgRVJSTk9fVE9fU1RBVFVTKC1yYywgc3Rh
dHVzKTsKKyAgICAgICAgZ290byBmYWlsMTsKKyAgICB9CisKKyAgICAqTWFqb3IgPSAoVUxPTkcp
KChyYyA+PiAxNikgJiAweEZGRkYpOworICAgICpNaW5vciA9IChVTE9ORykocmMgJiAweEZGRkYp
OworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAgICBFcnJvcigiZmFp
bDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsKK30KKworX19jaGVj
a1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBPVVQgUENI
QVIgICAgICAgICAgIEV4dHJhCisgICAgKQoreworICAgIHhlbl9leHRyYXZlcnNpb25fdCAgb3A7
CisgICAgTE9OR19QVFIgICAgICAgICAgICByYzsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgIHN0
YXR1czsKKworICAgIFJ0bFplcm9NZW1vcnkoJm9wLCBzaXplb2YgKG9wKSk7CisKKyAgICByYyA9
IFhlblZlcnNpb25PcChYRU5WRVJfZXh0cmF2ZXJzaW9uLCAmb3ApOworCisgICAgaWYgKHJjIDwg
MCkgeworICAgICAgICBFUlJOT19UT19TVEFUVVMoLXJjLCBzdGF0dXMpOworICAgICAgICBnb3Rv
IGZhaWwxOworICAgIH0KKworICAgIFJ0bENvcHlNZW1vcnkoRXh0cmEsICZvcCwgWEVOX0VYVFJB
VkVSU0lPTl9MRU4pOworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAg
ICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsK
K30KZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZmRvLmMgYi9zcmMveGVuYnVzL2Zkby5jCmluZGV4
IDU5NDQyYmQuLjIxNWM5OTcgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZmRvLmMKKysrIGIvc3Jj
L3hlbmJ1cy9mZG8uYwpAQCAtMjE4Niw2ICsyMTg2LDggQEAgRmRvUzRUb1MzKAogCiAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsKIAorICAgIEh5cGVyY2FsbFBvcHVsYXRl
KCk7CisKICAgICBpZiAoRmRvLT5VbnBsdWdJbnRlcmZhY2UuSW50ZXJmYWNlLkNvbnRleHQgIT0g
TlVMTCkKICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmRmRvLT5VbnBsdWdJbnRlcmZh
Y2UpOwogCmRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3N1c3BlbmQuYyBiL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCmluZGV4IDZhYjJiZDIuLmRlNzBlNDIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCisrKyBiL3NyYy94ZW5idXMvc3VzcGVuZC5jCkBAIC0xNzMsNiArMTczLDggQEAgU3Vz
cGVuZFRyaWdnZXIoCiAKICAgICAgICAgQ29udGV4dC0+Q291bnQrKzsKIAorICAgICAgICBIeXBl
cmNhbGxQb3B1bGF0ZSgpOworCiAgICAgICAgIGlmIChDb250ZXh0LT5VbnBsdWdJbnRlcmZhY2Uu
SW50ZXJmYWNlLkNvbnRleHQgIT0gTlVMTCkKICAgICAgICAgICAgIFhFTkZJTFRfVU5QTFVHKFJl
cGxheSwgJkNvbnRleHQtPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBhL3ZzMjAxMi94
ZW4veGVuLnZjeHByb2ogYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCmluZGV4IGViNTQ2OTIuLjJm
NGQ5NTggMTAwNjQ0Ci0tLSBhL3ZzMjAxMi94ZW4veGVuLnZjeHByb2oKKysrIGIvdnMyMDEyL3hl
bi94ZW4udmN4cHJvagpAQCAtODgsNiArODgsNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuXGh2bS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5c
eGVuX3ZlcnNpb24uYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5
cGVyY2FsbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cbWVtb3J5
LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxzY2hlZC5jIiAvPgpk
aWZmIC0tZ2l0IGEvdnMyMDEzL3hlbi94ZW4udmN4cHJvaiBiL3ZzMjAxMy94ZW4veGVuLnZjeHBy
b2oKaW5kZXggNDkwMjk0Yy4uODFkNTBlYSAxMDA2NDQKLS0tIGEvdnMyMDEzL3hlbi94ZW4udmN4
cHJvagorKysgYi92czIwMTMveGVuL3hlbi52Y3hwcm9qCkBAIC0xLDQgKzEsNCBAQAot77u/PD94
bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KKzw/eG1sIHZlcnNpb249IjEuMCIg
ZW5jb2Rpbmc9InV0Zi04Ij8+CiA8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xz
VmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxv
cGVyL21zYnVpbGQvMjAwMyI+CiAgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIg
Lz4KICAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgpAQCAtMTI4LDYgKzEyOCw3IEBA
CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+CisgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+CiAgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5cGVyY2FsbC5jIiAvPgogICAgIDxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KICAgICA8Q2xDb21w
aWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4KLS0gCjIuMS4xCgoKX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1h
aWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3Rz
LnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 16:37:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37: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 1XmmXN-0000lg-4y; Fri, 07 Nov 2014 16:37:25 +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 1XmmXM-0000lY-3c
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:24 +0000
Received: from [85.158.137.68] by server-16.bemta-3.messagelabs.com id
	E0/07-09284-345FC545; Fri, 07 Nov 2014 16:37:23 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20188 invoked from network); 7 Nov 2014 16:37:21 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:21 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196332"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-Rh;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:44 +0000
Message-ID: <1415378147-17816-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
Content-Length: 27023
X-DLP: MIA2
Cc: Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH v3 1/4] Re-populate hypercall page on resume
	from suspend/hibernate
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

RG9pbmcgdGhpcyBoYXMgdGhlIHNpZGUgZWZmZWN0IG9mIGxhdGNoaW5nIHRoZSBzaGFyZWQgaW5m
byBwYWdlIHdpZHRoLAp3aGljaCBpcyBjdXJyZW50bHkgZG9uZSB3aGVuIHRoZSBjYWxsYmFjayB2
aWEgaXMgc2V0LiBXaGVuIHdlIG1vdmUgdG8gYQpwZXItY3B1IGV2ZW50IGNoYW5uZWwgdXBjYWxs
IHRoZW4gdGhpcyBzaWRlIGVmZmVjdCB3aWxsIGJlIGxvc3QsIHNvCmRvaW5nIHRoaXMgbWFrZXMg
c3VyZSB0aGF0IHRoZSBzaGFyZWQgaW5mbyBpcyBzdGlsbCBvZiB0aGUgY29ycmVjdCB3aWR0aC4K
CkFkZGl0aW9uYWxseSBpbiB0aGlzIHBhdGNoIHRoZSByZXBvcnRpbmcgb2YgdGhlIFhlbiB2ZXJz
aW9uIGlzIGltcHJvdmVkCmJ5IHVzaW5nIHRoZSBYRU5WRVIgaHlwZXJjYWxscyB0byBnZXQgbWFq
b3IsIG1pbm9yIGFuZCBleHRyYSB2ZXJzaW9uCmluZm9ybWF0dGlvbi4gQXMgcGFydCBvZiB0aGF0
IGNoYW5nZSwgbW9yZSBoZWFkZXJzIGhhdmUgYmVlbiBjb3BpZWQgaW4KZnJvbSBYZW4uCgpTaWdu
ZWQtb2ZmLWJ5OiBQYXVsIER1cnJhbnQgPHBhdWwuZHVycmFudEBjaXRyaXguY29tPgotLS0KIGdl
dF94ZW5faGVhZGVycy5weSAgICAgfCAgIDIgKwogaW5jbHVkZS94ZW4uaCAgICAgICAgICB8ICAy
NiArKysrKysrKysrKysKIGluY2x1ZGUveGVuL2ZlYXR1cmVzLmggfCAxMTIgKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS94ZW4vdmVyc2lv
bi5oICB8ICA5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIHNy
Yy94ZW4vZHJpdmVyLmMgICAgICAgfCAgMjAgKysrKysrKysrCiBzcmMveGVuL2h5cGVyY2FsbC5j
ICAgIHwgIDY2ICsrKysrKysrKysrKysrKystLS0tLS0tLS0tLS0tCiBzcmMveGVuL3hlbl92ZXJz
aW9uLmMgIHwgMTA3ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysKIHNyYy94ZW5idXMvZmRvLmMgICAgICAgfCAgIDIgKwogc3JjL3hlbmJ1cy9zdXNwZW5kLmMg
ICB8ICAgMiArCiB2czIwMTIveGVuL3hlbi52Y3hwcm9qIHwgICAxICsKIHZzMjAxMy94ZW4veGVu
LnZjeHByb2ogfCAgIDMgKy0KIDExIGZpbGVzIGNoYW5nZWQsIDQwNiBpbnNlcnRpb25zKCspLCAz
MSBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3hlbi9mZWF0dXJlcy5o
CiBjcmVhdGUgbW9kZSAxMDA2NDQgaW5jbHVkZS94ZW4vdmVyc2lvbi5oCiBjcmVhdGUgbW9kZSAx
MDA2NDQgc3JjL3hlbi94ZW5fdmVyc2lvbi5jCgpkaWZmIC0tZ2l0IGEvZ2V0X3hlbl9oZWFkZXJz
LnB5IGIvZ2V0X3hlbl9oZWFkZXJzLnB5CmluZGV4IDVjYTVjOTMuLmVmMWEyYzggMTAwNjQ0Ci0t
LSBhL2dldF94ZW5faGVhZGVycy5weQorKysgYi9nZXRfeGVuX2hlYWRlcnMucHkKQEAgLTYxLDYg
KzYxLDggQEAgaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgICBjb3B5X2ZpbGUod29ya2lu
ZywgJ3B1YmxpYycsICcuJywgJ3NjaGVkLmgnKQogICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAnZXZlbnRfY2hhbm5lbC5oJykKICAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1
YmxpYycsICcuJywgJ2dyYW50X3RhYmxlLmgnKQorICAgIGNvcHlfZmlsZSh3b3JraW5nLCAncHVi
bGljJywgJy4nLCAndmVyc2lvbi5oJykKKyAgICBjb3B5X2ZpbGUod29ya2luZywgJ3B1YmxpYycs
ICcuJywgJ2ZlYXR1cmVzLmgnKQogCiAgICAgY29weV9maWxlKHdvcmtpbmcsICd4ZW4nLCAnLics
ICdlcnJuby5oJykKIApkaWZmIC0tZ2l0IGEvaW5jbHVkZS94ZW4uaCBiL2luY2x1ZGUveGVuLmgK
aW5kZXggMDAzOWQ3YS4uMGRhYmM3NCAxMDA2NDQKLS0tIGEvaW5jbHVkZS94ZW4uaAorKysgYi9p
bmNsdWRlL3hlbi5oCkBAIC00NCw2ICs0NCw3IEBACiAjaW5jbHVkZSA8eGVuL3NjaGVkLmg+CiAj
aW5jbHVkZSA8eGVuL2h2bS9wYXJhbXMuaD4KICNpbmNsdWRlIDx4ZW4vaW8veHNfd2lyZS5oPgor
I2luY2x1ZGUgPHhlbi92ZXJzaW9uLmg+CiAKICNpZm5kZWYgWEVOX0FQSQogI2RlZmluZSBYRU5f
QVBJIF9fZGVjbHNwZWMoZGxsaW1wb3J0KQpAQCAtNTYsNiArNTcsMTQgQEAgWGVuVG91Y2goCiAg
ICAgVk9JRAogICAgICk7CiAKKy8vIEhZUEVSQ0FMTAorCitYRU5fQVBJCitWT0lECitIeXBlcmNh
bGxQb3B1bGF0ZSgKKyAgICBWT0lECisgICAgKTsKKwogLy8gSFZNCiAKIF9fY2hlY2tSZXR1cm4K
QEAgLTIzMyw2ICsyNDIsMjMgQEAgU2NoZWRZaWVsZCgKICAgICBWT0lECiAgICAgKTsKIAorLy8g
WEVOIFZFUlNJT04KKworX19jaGVja1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNp
b24oCisgICAgT1VUIFBVTE9ORyAgTWFqb3IsCisgICAgT1VUIFBVTE9ORyAgTWlub3IKKyAgICAp
OworCitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbkV4dHJhKAor
ICAgIE9VVCBQQ0hBUiAgIEV4dHJhCisgICAgKTsKKwogLy8gTU9EVUxFCiAKIFhFTl9BUEkKZGlm
ZiAtLWdpdCBhL2luY2x1ZGUveGVuL2ZlYXR1cmVzLmggYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5o
Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmI3YmY4M2YKLS0tIC9kZXYvbnVs
bAorKysgYi9pbmNsdWRlL3hlbi9mZWF0dXJlcy5oCkBAIC0wLDAgKzEsMTEyIEBACisvKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqCisgKiBmZWF0dXJlcy5oCisgKiAKKyAqIEZlYXR1cmUgZmxhZ3MsIHJl
cG9ydGVkIGJ5IFhFTlZFUl9nZXRfZmVhdHVyZXMuCisgKiAKKyAqIFBlcm1pc3Npb24gaXMgaGVy
ZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNv
cHkKKyAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxl
cyAodGhlICJTb2Z0d2FyZSIpLCB0bworICogZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCBy
ZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUKKyAqIHJpZ2h0cyB0
byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vu
c2UsIGFuZC9vcgorICogc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0
IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMKKyAqIGZ1cm5pc2hlZCB0byBkbyBzbywg
c3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6CisgKgorICogVGhlIGFib3ZlIGNv
cHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVk
ZWQgaW4KKyAqIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3
YXJlLgorICoKKyAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdB
UlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SCisgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVU
IE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKKyAqIEZJ
VE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5P
IEVWRU5UIFNIQUxMIFRIRQorICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFC
TEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUgorICogTElBQklMSVRZLCBXSEVUSEVS
IElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcKKyAq
IEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBV
U0UgT1IgT1RIRVIKKyAqIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS4KKyAqCisgKiBDb3B5cmln
aHQgKGMpIDIwMDYsIEtlaXIgRnJhc2VyIDxrZWlyQHhlbnNvdXJjZS5jb20+CisgKi8KKworI2lm
bmRlZiBfX1hFTl9QVUJMSUNfRkVBVFVSRVNfSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19GRUFU
VVJFU19IX18KKworLyoKKyAqIGBpbmNvbnRlbnRzIDIwMCBlbGZub3Rlc19mZWF0dXJlcyBYRU5f
RUxGTk9URV9GRUFUVVJFUworICoKKyAqIFRoZSBsaXN0IG9mIGFsbCB0aGUgZmVhdHVyZXMgdGhl
IGd1ZXN0IHN1cHBvcnRzLiBUaGV5IGFyZSBzZXQgYnkKKyAqIHBhcnNpbmcgdGhlIFhFTl9FTEZO
T1RFX0ZFQVRVUkVTIGFuZCBYRU5fRUxGTk9URV9TVVBQT1JURURfRkVBVFVSRVMKKyAqIHN0cmlu
Zy4gVGhlIGZvcm1hdCBpcyB0aGUgIGZlYXR1cmUgbmFtZXMgKGFzIGdpdmVuIGhlcmUgd2l0aG91
dCB0aGUKKyAqICJYRU5GRUFUXyIgcHJlZml4KSBzZXBhcmF0ZWQgYnkgJ3wnIGNoYXJhY3RlcnMu
CisgKiBJZiBhIGZlYXR1cmUgaXMgcmVxdWlyZWQgZm9yIHRoZSBrZXJuZWwgdG8gZnVuY3Rpb24g
dGhlbiB0aGUgZmVhdHVyZSBuYW1lCisgKiBtdXN0IGJlIHByZWNlZGVkIGJ5IGEgJyEnIGNoYXJh
Y3Rlci4KKyAqCisgKiBOb3RlIHRoYXQgaWYgWEVOX0VMRk5PVEVfU1VQUE9SVEVEX0ZFQVRVUkVT
IGlzIHVzZWQsIHRoZW4gaW4gdGhlCisgKiBYRU5GRUFUX2RvbTAgTVVTVCBiZSBzZXQgaWYgdGhl
IGd1ZXN0IGlzIHRvIGJlIGJvb3RlZCBhcyBkb20wLAorICovCisKKy8qCisgKiBJZiBzZXQsIHRo
ZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIHdyaXRlLXByb3RlY3QgaXRzIHBhZ2V0YWJsZXMsIGFu
ZCBjYW4KKyAqIHVwZGF0ZSB0aGVtIHZpYSBkaXJlY3Qgd3JpdGVzLgorICovCisjZGVmaW5lIFhF
TkZFQVRfd3JpdGFibGVfcGFnZV90YWJsZXMgICAgICAgMAorCisvKgorICogSWYgc2V0LCB0aGUg
Z3Vlc3QgZG9lcyBub3QgbmVlZCB0byB3cml0ZS1wcm90ZWN0IGl0cyBzZWdtZW50IGRlc2NyaXB0
b3IKKyAqIHRhYmxlcywgYW5kIGNhbiB1cGRhdGUgdGhlbSB2aWEgZGlyZWN0IHdyaXRlcy4KKyAq
LworI2RlZmluZSBYRU5GRUFUX3dyaXRhYmxlX2Rlc2NyaXB0b3JfdGFibGVzIDEKKworLyoKKyAq
IElmIHNldCwgdHJhbnNsYXRpb24gYmV0d2VlbiB0aGUgZ3Vlc3QncyAncHNldWRvLXBoeXNpY2Fs
JyBhZGRyZXNzIHNwYWNlCisgKiBhbmQgdGhlIGhvc3QncyBtYWNoaW5lIGFkZHJlc3Mgc3BhY2Ug
YXJlIGhhbmRsZWQgYnkgdGhlIGh5cGVydmlzb3IuIEluIHRoaXMKKyAqIG1vZGUgdGhlIGd1ZXN0
IGRvZXMgbm90IG5lZWQgdG8gcGVyZm9ybSBwaHlzLXRvL2Zyb20tbWFjaGluZSB0cmFuc2xhdGlv
bnMKKyAqIHdoZW4gcGVyZm9ybWluZyBwYWdlIHRhYmxlIG9wZXJhdGlvbnMuCisgKi8KKyNkZWZp
bmUgWEVORkVBVF9hdXRvX3RyYW5zbGF0ZWRfcGh5c21hcCAgICAyCisKKy8qIElmIHNldCwgdGhl
IGd1ZXN0IGlzIHJ1bm5pbmcgaW4gc3VwZXJ2aXNvciBtb2RlIChlLmcuLCB4ODYgcmluZyAwKS4g
Ki8KKyNkZWZpbmUgWEVORkVBVF9zdXBlcnZpc29yX21vZGVfa2VybmVsICAgICAzCisKKy8qCisg
KiBJZiBzZXQsIHRoZSBndWVzdCBkb2VzIG5vdCBuZWVkIHRvIGFsbG9jYXRlIHg4NiBQQUUgcGFn
ZSBkaXJlY3RvcmllcworICogYmVsb3cgNEdCLiBUaGlzIGZsYWcgaXMgdXN1YWxseSBpbXBsaWVk
IGJ5IGF1dG9fdHJhbnNsYXRlZF9waHlzbWFwLgorICovCisjZGVmaW5lIFhFTkZFQVRfcGFlX3Bn
ZGlyX2Fib3ZlXzRnYiAgICAgICAgNAorCisvKiB4ODY6IERvZXMgdGhpcyBYZW4gaG9zdCBzdXBw
b3J0IHRoZSBNTVVfUFRfVVBEQVRFX1BSRVNFUlZFX0FEIGh5cGVyY2FsbD8gKi8KKyNkZWZpbmUg
WEVORkVBVF9tbXVfcHRfdXBkYXRlX3ByZXNlcnZlX2FkICA1CisKKy8qIHg4NjogRG9lcyB0aGlz
IFhlbiBob3N0IHN1cHBvcnQgdGhlIE1NVV97Q0xFQVIsQ09QWX1fUEFHRSBoeXBlcmNhbGw/ICov
CisjZGVmaW5lIFhFTkZFQVRfaGlnaG1lbV9hc3Npc3QgICAgICAgICAgICAgNgorCisvKgorICog
SWYgc2V0LCBHTlRUQUJPUF9tYXBfZ3JhbnRfcmVmIGhvbm9ycyBmbGFncyB0byBiZSBwbGFjZWQg
aW50byBndWVzdCBrZXJuZWwKKyAqIGF2YWlsYWJsZSBwdGUgYml0cy4KKyAqLworI2RlZmluZSBY
RU5GRUFUX2dudHRhYl9tYXBfYXZhaWxfYml0cyAgICAgIDcKKworLyogeDg2OiBEb2VzIHRoaXMg
WGVuIGhvc3Qgc3VwcG9ydCB0aGUgSFZNIGNhbGxiYWNrIHZlY3RvciB0eXBlPyAqLworI2RlZmlu
ZSBYRU5GRUFUX2h2bV9jYWxsYmFja192ZWN0b3IgICAgICAgIDgKKworLyogeDg2OiBwdmNsb2Nr
IGFsZ29yaXRobSBpcyBzYWZlIHRvIHVzZSBvbiBIVk0gKi8KKyNkZWZpbmUgWEVORkVBVF9odm1f
c2FmZV9wdmNsb2NrICAgICAgICAgICA5CisKKy8qIHg4NjogcGlycSBjYW4gYmUgdXNlZCBieSBI
Vk0gZ3Vlc3RzICovCisjZGVmaW5lIFhFTkZFQVRfaHZtX3BpcnFzICAgICAgICAgICAgICAgICAx
MAorCisvKiBvcGVyYXRpb24gYXMgRG9tMCBpcyBzdXBwb3J0ZWQgKi8KKyNkZWZpbmUgWEVORkVB
VF9kb20wICAgICAgICAgICAgICAgICAgICAgIDExCisKKy8qIFhlbiBhbHNvIG1hcHMgZ3JhbnQg
cmVmZXJlbmNlcyBhdCBwZm4gPSBtZm4gKi8KKyNkZWZpbmUgWEVORkVBVF9ncmFudF9tYXBfaWRl
bnRpdHkgICAgICAgIDEyCisKKyNkZWZpbmUgWEVORkVBVF9OUl9TVUJNQVBTIDEKKworI2VuZGlm
IC8qIF9fWEVOX1BVQkxJQ19GRUFUVVJFU19IX18gKi8KKworLyoKKyAqIExvY2FsIHZhcmlhYmxl
czoKKyAqIG1vZGU6IEMKKyAqIGMtZmlsZS1zdHlsZTogIkJTRCIKKyAqIGMtYmFzaWMtb2Zmc2V0
OiA0CisgKiB0YWItd2lkdGg6IDQKKyAqIGluZGVudC10YWJzLW1vZGU6IG5pbAorICogRW5kOgor
ICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3hlbi92ZXJzaW9uLmggYi9pbmNsdWRlL3hlbi92ZXJz
aW9uLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNDRmMjZiMAotLS0gL2Rl
di9udWxsCisrKyBiL2luY2x1ZGUveGVuL3ZlcnNpb24uaApAQCAtMCwwICsxLDk2IEBACisvKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqCisgKiB2ZXJzaW9uLmgKKyAqIAorICogWGVuIHZlcnNpb24sIHR5
cGUsIGFuZCBjb21waWxlIGluZm9ybWF0aW9uLgorICogCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVi
eSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5
CisgKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMg
KHRoZSAiU29mdHdhcmUiKSwgdG8KKyAqIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVz
dHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlCisgKiByaWdodHMgdG8g
dXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNl
LCBhbmQvb3IKKyAqIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBw
ZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1
YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5
cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVk
IGluCisgKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2Fy
ZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJS
QU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBO
T1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRO
RVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBF
VkVOVCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxF
IEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJ
TiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCisgKiBG
Uk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNF
IE9SIE9USEVSCisgKiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuCisgKgorICogQ29weXJpZ2h0
IChjKSAyMDA1LCBOZ3V5ZW4gQW5oIFF1eW5oIDxhcXV5bmhAZ21haWwuY29tPgorICogQ29weXJp
Z2h0IChjKSAyMDA1LCBLZWlyIEZyYXNlciA8a2VpckB4ZW5zb3VyY2UuY29tPgorICovCisKKyNp
Zm5kZWYgX19YRU5fUFVCTElDX1ZFUlNJT05fSF9fCisjZGVmaW5lIF9fWEVOX1BVQkxJQ19WRVJT
SU9OX0hfXworCisjaW5jbHVkZSAieGVuLmgiCisKKy8qIE5CLiBBbGwgb3BzIHJldHVybiB6ZXJv
IG9uIHN1Y2Nlc3MsIGV4Y2VwdCBYRU5WRVJfe3ZlcnNpb24scGFnZXNpemV9ICovCisKKy8qIGFy
ZyA9PSBOVUxMOyByZXR1cm5zIG1ham9yOm1pbm9yICgxNjoxNikuICovCisjZGVmaW5lIFhFTlZF
Ul92ZXJzaW9uICAgICAgMAorCisvKiBhcmcgPT0geGVuX2V4dHJhdmVyc2lvbl90LiAqLworI2Rl
ZmluZSBYRU5WRVJfZXh0cmF2ZXJzaW9uIDEKK3R5cGVkZWYgY2hhciB4ZW5fZXh0cmF2ZXJzaW9u
X3RbMTZdOworI2RlZmluZSBYRU5fRVhUUkFWRVJTSU9OX0xFTiAoc2l6ZW9mKHhlbl9leHRyYXZl
cnNpb25fdCkpCisKKy8qIGFyZyA9PSB4ZW5fY29tcGlsZV9pbmZvX3QuICovCisjZGVmaW5lIFhF
TlZFUl9jb21waWxlX2luZm8gMgorc3RydWN0IHhlbl9jb21waWxlX2luZm8geworICAgIGNoYXIg
Y29tcGlsZXJbNjRdOworICAgIGNoYXIgY29tcGlsZV9ieVsxNl07CisgICAgY2hhciBjb21waWxl
X2RvbWFpblszMl07CisgICAgY2hhciBjb21waWxlX2RhdGVbMzJdOworfTsKK3R5cGVkZWYgc3Ry
dWN0IHhlbl9jb21waWxlX2luZm8geGVuX2NvbXBpbGVfaW5mb190OworCisjZGVmaW5lIFhFTlZF
Ul9jYXBhYmlsaXRpZXMgMwordHlwZWRlZiBjaGFyIHhlbl9jYXBhYmlsaXRpZXNfaW5mb190WzEw
MjRdOworI2RlZmluZSBYRU5fQ0FQQUJJTElUSUVTX0lORk9fTEVOIChzaXplb2YoeGVuX2NhcGFi
aWxpdGllc19pbmZvX3QpKQorCisjZGVmaW5lIFhFTlZFUl9jaGFuZ2VzZXQgNAordHlwZWRlZiBj
aGFyIHhlbl9jaGFuZ2VzZXRfaW5mb190WzY0XTsKKyNkZWZpbmUgWEVOX0NIQU5HRVNFVF9JTkZP
X0xFTiAoc2l6ZW9mKHhlbl9jaGFuZ2VzZXRfaW5mb190KSkKKworI2RlZmluZSBYRU5WRVJfcGxh
dGZvcm1fcGFyYW1ldGVycyA1CitzdHJ1Y3QgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnMgeworICAg
IHhlbl91bG9uZ190IHZpcnRfc3RhcnQ7Cit9OwordHlwZWRlZiBzdHJ1Y3QgeGVuX3BsYXRmb3Jt
X3BhcmFtZXRlcnMgeGVuX3BsYXRmb3JtX3BhcmFtZXRlcnNfdDsKKworI2RlZmluZSBYRU5WRVJf
Z2V0X2ZlYXR1cmVzIDYKK3N0cnVjdCB4ZW5fZmVhdHVyZV9pbmZvIHsKKyAgICB1bnNpZ25lZCBp
bnQgc3VibWFwX2lkeDsgICAgLyogSU46IHdoaWNoIDMyLWJpdCBzdWJtYXAgdG8gcmV0dXJuICov
CisgICAgdWludDMyX3QgICAgIHN1Ym1hcDsgICAgICAgIC8qIE9VVDogMzItYml0IHN1Ym1hcCAq
LworfTsKK3R5cGVkZWYgc3RydWN0IHhlbl9mZWF0dXJlX2luZm8geGVuX2ZlYXR1cmVfaW5mb190
OworCisvKiBEZWNsYXJlcyB0aGUgZmVhdHVyZXMgcmVwb3J0ZWQgYnkgWEVOVkVSX2dldF9mZWF0
dXJlcy4gKi8KKyNpbmNsdWRlICJmZWF0dXJlcy5oIgorCisvKiBhcmcgPT0gTlVMTDsgcmV0dXJu
cyBob3N0IG1lbW9yeSBwYWdlIHNpemUuICovCisjZGVmaW5lIFhFTlZFUl9wYWdlc2l6ZSA3CisK
Ky8qIGFyZyA9PSB4ZW5fZG9tYWluX2hhbmRsZV90LiAqLworI2RlZmluZSBYRU5WRVJfZ3Vlc3Rf
aGFuZGxlIDgKKworI2RlZmluZSBYRU5WRVJfY29tbWFuZGxpbmUgOQordHlwZWRlZiBjaGFyIHhl
bl9jb21tYW5kbGluZV90WzEwMjRdOworCisjZW5kaWYgLyogX19YRU5fUFVCTElDX1ZFUlNJT05f
SF9fICovCisKKy8qCisgKiBMb2NhbCB2YXJpYWJsZXM6CisgKiBtb2RlOiBDCisgKiBjLWZpbGUt
c3R5bGU6ICJCU0QiCisgKiBjLWJhc2ljLW9mZnNldDogNAorICogdGFiLXdpZHRoOiA0CisgKiBp
bmRlbnQtdGFicy1tb2RlOiBuaWwKKyAqIEVuZDoKKyAqLwpkaWZmIC0tZ2l0IGEvc3JjL3hlbi9k
cml2ZXIuYyBiL3NyYy94ZW4vZHJpdmVyLmMKaW5kZXggYmE1NDFiNC4uZmNlNzVhYSAxMDA2NDQK
LS0tIGEvc3JjL3hlbi9kcml2ZXIuYworKysgYi9zcmMveGVuL2RyaXZlci5jCkBAIC01OSw2ICs1
OSwyNiBAQCBYZW5Ub3VjaCgKICAgICBWT0lECiAgICAgKQogeworICAgIHN0YXRpYyBVTE9ORyAg
ICBSZWZlcmVuY2U7CisgICAgVUxPTkcgICAgICAgICAgIE1ham9yOworICAgIFVMT05HICAgICAg
ICAgICBNaW5vcjsKKyAgICBDSEFSICAgICAgICAgICAgRXh0cmFbWEVOX0VYVFJBVkVSU0lPTl9M
RU5dOworICAgIE5UU1RBVFVTICAgICAgICBzdGF0dXM7CisKKyAgICBpZiAoUmVmZXJlbmNlKysg
IT0gMCkKKyAgICAgICAgcmV0dXJuOworCisgICAgc3RhdHVzID0gWGVuVmVyc2lvbigmTWFqb3Is
ICZNaW5vcik7CisgICAgQVNTRVJUKE5UX1NVQ0NFU1Moc3RhdHVzKSk7CisKKyAgICBzdGF0dXMg
PSBYZW5WZXJzaW9uRXh0cmEoRXh0cmEpOworICAgIEFTU0VSVChOVF9TVUNDRVNTKHN0YXR1cykp
OworCisgICAgTG9nUHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAiWEVOOiAl
dS4ldSVzXG4iLAorICAgICAgICAgICAgICBNYWpvciwKKyAgICAgICAgICAgICAgTWlub3IsCisg
ICAgICAgICAgICAgIEV4dHJhKTsKIH0KIAogc3RhdGljIFZPSUQKZGlmZiAtLWdpdCBhL3NyYy94
ZW4vaHlwZXJjYWxsLmMgYi9zcmMveGVuL2h5cGVyY2FsbC5jCmluZGV4IDA3ZWI0MWEuLjcxN2I4
YzIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW4vaHlwZXJjYWxsLmMKKysrIGIvc3JjL3hlbi9oeXBlcmNh
bGwuYwpAQCAtMjksNiArMjksOSBAQAogICogU1VDSCBEQU1BR0UuCiAgKi8KIAorI3VuZGVmICBY
RU5fQVBJCisjZGVmaW5lIFhFTl9BUEkgX19kZWNsc3BlYyhkbGxleHBvcnQpCisKICNpbmNsdWRl
IDxudGRkay5oPgogI2luY2x1ZGUgPHhlbi5oPgogI2luY2x1ZGUgPHV0aWwuaD4KQEAgLTM3LDI0
ICs0MCw0MSBAQAogI2luY2x1ZGUgImRiZ19wcmludC5oIgogI2luY2x1ZGUgImFzc2VydC5oIgog
Ci0jZGVmaW5lIE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVCAyCisjZGVmaW5lIE1BWElNVU1f
SFlQRVJDQUxMX1BBR0VfQ09VTlQgMgogCiAjcHJhZ21hIGNvZGVfc2VnKCJoeXBlcmNhbGwiKQog
X19kZWNsc3BlYyhhbGxvY2F0ZSgiaHlwZXJjYWxsIikpCi1zdGF0aWMgVUNIQVIgICAgICAgIF9f
U2VjdGlvblsoTUFYSU1VTV9IWVBFUkNBTExfUEZOX0NPVU5UICsgMSkgKiBQQUdFX1NJWkVdOwor
c3RhdGljIFVDSEFSICAgICAgICBfX1NlY3Rpb25bKE1BWElNVU1fSFlQRVJDQUxMX1BBR0VfQ09V
TlQgKyAxKSAqIFBBR0VfU0laRV07CiAKIHN0YXRpYyBVTE9ORyAgICAgICAgWGVuQmFzZUxlYWYg
PSAweDQwMDAwMDAwOwogCi1zdGF0aWMgVVNIT1JUICAgICAgIFhlbk1ham9yVmVyc2lvbjsKLXN0
YXRpYyBVU0hPUlQgICAgICAgWGVuTWlub3JWZXJzaW9uOwotCi1zdGF0aWMgUEZOX05VTUJFUiAg
IEh5cGVyY2FsbFBmbltNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlRdOwotc3RhdGljIFVMT05H
ICAgICAgICBIeXBlcmNhbGxQZm5Db3VudDsKK3N0YXRpYyBQSFlTSUNBTF9BRERSRVNTIEh5cGVy
Y2FsbFBhZ2VbTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVF07CitzdGF0aWMgVUxPTkcgICAg
ICAgICAgICBIeXBlcmNhbGxQYWdlQ291bnQ7CiAKIHR5cGVkZWYgVUNIQVIgICAgICAgICAgIEhZ
UEVSQ0FMTF9HQVRFWzMyXTsKIHR5cGVkZWYgSFlQRVJDQUxMX0dBVEUgICpQSFlQRVJDQUxMX0dB
VEU7CiAKIFBIWVBFUkNBTExfR0FURSAgICAgSHlwZXJjYWxsOworVUxPTkcgICAgICAgICAgICAg
ICBIeXBlcmNhbGxNc3I7CisKK1hFTl9BUEkKK1ZPSUQKK0h5cGVyY2FsbFBvcHVsYXRlKAorICAg
IFZPSUQKKyAgICApCit7CisgICAgVUxPTkcgICAgICAgSW5kZXg7CisKKyAgICBmb3IgKEluZGV4
ID0gMDsgSW5kZXggPCBIeXBlcmNhbGxQYWdlQ291bnQ7IEluZGV4KyspIHsKKyAgICAgICAgTG9n
UHJpbnRmKExPR19MRVZFTF9JTkZPLAorICAgICAgICAgICAgICAgICAgIlhFTjogSFlQRVJDQUxM
IFBBR0UgJWQgQCAlMDh4LiUwOHhcbiIsCisgICAgICAgICAgICAgICAgICBJbmRleCwKKyAgICAg
ICAgICAgICAgICAgIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLkhpZ2hQYXJ0LAorICAgICAgICAgICAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uTG93UGFydCk7CisKKyAgICAgICAgX193cml0ZW1z
cihIeXBlcmNhbGxNc3IsIEh5cGVyY2FsbFBhZ2VbSW5kZXhdLlF1YWRQYXJ0KTsKKyAgICB9Cit9
CiAKIE5UU1RBVFVTCiBIeXBlcmNhbGxJbml0aWFsaXplKApAQCAtNjYsNyArODYsNiBAQCBIeXBl
cmNhbGxJbml0aWFsaXplKAogICAgIFVMT05HICAgICAgIEVDWCA9ICdERUFEJzsKICAgICBVTE9O
RyAgICAgICBFRFggPSAnREVBRCc7CiAgICAgVUxPTkcgICAgICAgSW5kZXg7Ci0gICAgVUxPTkcg
ICAgICAgSHlwZXJjYWxsTXNyOwogICAgIE5UU1RBVFVTICAgIHN0YXR1czsKIAogICAgIHN0YXR1
cyA9IFNUQVRVU19VTlNVQ0NFU1NGVUw7CkBAIC04OCwxMyArMTA3LDYgQEAgSHlwZXJjYWxsSW5p
dGlhbGl6ZSgKICAgICAgICAgICAgIGdvdG8gZmFpbDE7CiAgICAgfQogCi0gICAgX19DcHVJZChY
ZW5CYXNlTGVhZiArIDEsICZFQVgsIE5VTEwsIE5VTEwsIE5VTEwpOwotICAgIFhlbk1ham9yVmVy
c2lvbiA9IChVU0hPUlQpKEVBWCA+PiAxNik7Ci0gICAgWGVuTWlub3JWZXJzaW9uID0gKFVTSE9S
VCkoRUFYICYgMHhGRkZGKTsKLQotICAgIEluZm8oIlhFTiAlZC4lZFxuIiwgWGVuTWFqb3JWZXJz
aW9uLCBYZW5NaW5vclZlcnNpb24pOwotICAgIEluZm8oIklOVEVSRkFDRSAweCUwOHhcbiIsIF9f
WEVOX0lOVEVSRkFDRV9WRVJTSU9OX18pOwotCiAgICAgaWYgKChVTE9OR19QVFIpX19TZWN0aW9u
ICYgKFBBR0VfU0laRSAtIDEpKQogICAgICAgICBIeXBlcmNhbGwgPSAoUFZPSUQpKCgoVUxPTkdf
UFRSKV9fU2VjdGlvbiArIFBBR0VfU0laRSAtIDEpICYgfihQQUdFX1NJWkUgLSAxKSk7CiAgICAg
ZWxzZQpAQCAtMTAyLDIyICsxMTQsMTYgQEAgSHlwZXJjYWxsSW5pdGlhbGl6ZSgKIAogICAgIEFT
U0VSVDNVKCgoVUxPTkdfUFRSKUh5cGVyY2FsbCAmIChQQUdFX1NJWkUgLSAxKSksID09LCAwKTsK
IAotICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VO
VDsgSW5kZXgrKykgewotICAgICAgICBQSFlTSUNBTF9BRERSRVNTICAgIFBoeXNpY2FsQWRkcmVz
czsKLQotICAgICAgICBQaHlzaWNhbEFkZHJlc3MgPSBNbUdldFBoeXNpY2FsQWRkcmVzcygoUFVD
SEFSKUh5cGVyY2FsbCArIChJbmRleCA8PCBQQUdFX1NISUZUKSk7Ci0gICAgICAgIEh5cGVyY2Fs
bFBmbltJbmRleF0gPSAoUEZOX05VTUJFUikoUGh5c2ljYWxBZGRyZXNzLlF1YWRQYXJ0ID4+IFBB
R0VfU0hJRlQpOwotICAgIH0KKyAgICBmb3IgKEluZGV4ID0gMDsgSW5kZXggPCBNQVhJTVVNX0hZ
UEVSQ0FMTF9QQUdFX0NPVU5UOyBJbmRleCsrKQorICAgICAgICBIeXBlcmNhbGxQYWdlW0luZGV4
XSA9IE1tR2V0UGh5c2ljYWxBZGRyZXNzKChQVUNIQVIpSHlwZXJjYWxsICsKKyAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoSW5kZXggPDwgUEFHRV9T
SElGVCkpOwogCiAgICAgX19DcHVJZChYZW5CYXNlTGVhZiArIDIsICZFQVgsICZFQlgsIE5VTEws
IE5VTEwpOwotICAgIEh5cGVyY2FsbFBmbkNvdW50ID0gRUFYOwotICAgIEFTU0VSVChIeXBlcmNh
bGxQZm5Db3VudCA8PSBNQVhJTVVNX0hZUEVSQ0FMTF9QRk5fQ09VTlQpOworICAgIEh5cGVyY2Fs
bFBhZ2VDb3VudCA9IEVBWDsKKyAgICBBU1NFUlQoSHlwZXJjYWxsUGFnZUNvdW50IDw9IE1BWElN
VU1fSFlQRVJDQUxMX1BBR0VfQ09VTlQpOwogICAgIEh5cGVyY2FsbE1zciA9IEVCWDsKIAotICAg
IGZvciAoSW5kZXggPSAwOyBJbmRleCA8IEh5cGVyY2FsbFBmbkNvdW50OyBJbmRleCsrKSB7Ci0g
ICAgICAgIEluZm8oIkh5cGVyY2FsbFBmblslZF06ICVwXG4iLCBJbmRleCwgKFBWT0lEKUh5cGVy
Y2FsbFBmbltJbmRleF0pOwotICAgICAgICBfX3dyaXRlbXNyKEh5cGVyY2FsbE1zciwgKFVMT05H
NjQpSHlwZXJjYWxsUGZuW0luZGV4XSA8PCBQQUdFX1NISUZUKTsKLSAgICB9CisgICAgSHlwZXJj
YWxsUG9wdWxhdGUoKTsKIAogICAgIHJldHVybiBTVEFUVVNfU1VDQ0VTUzsKIApAQCAtMTc3LDgg
KzE4Myw4IEBAIEh5cGVyY2FsbFRlYXJkb3duKAogCiAgICAgSHlwZXJjYWxsID0gTlVMTDsKIAot
ICAgIGZvciAoSW5kZXggPSAwOyBJbmRleCA8IE1BWElNVU1fSFlQRVJDQUxMX1BGTl9DT1VOVDsg
SW5kZXgrKykKLSAgICAgICAgSHlwZXJjYWxsUGZuW0luZGV4XSA9IDA7CisgICAgZm9yIChJbmRl
eCA9IDA7IEluZGV4IDwgTUFYSU1VTV9IWVBFUkNBTExfUEFHRV9DT1VOVDsgSW5kZXgrKykKKyAg
ICAgICAgSHlwZXJjYWxsUGFnZVtJbmRleF0uUXVhZFBhcnQgPSAwOwogCi0gICAgSHlwZXJjYWxs
UGZuQ291bnQgPSAwOworICAgIEh5cGVyY2FsbFBhZ2VDb3VudCA9IDA7CiB9CmRpZmYgLS1naXQg
YS9zcmMveGVuL3hlbl92ZXJzaW9uLmMgYi9zcmMveGVuL3hlbl92ZXJzaW9uLmMKbmV3IGZpbGUg
bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNmVmMDYxZgotLS0gL2Rldi9udWxsCisrKyBiL3Ny
Yy94ZW4veGVuX3ZlcnNpb24uYwpAQCAtMCwwICsxLDEwNyBAQAorLyogQ29weXJpZ2h0IChjKSBD
aXRyaXggU3lzdGVtcyBJbmMuCisgKiBBbGwgcmlnaHRzIHJlc2VydmVkLgorICogCisgKiBSZWRp
c3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCAKKyAqIHdpdGgg
b3Igd2l0aG91dCBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgCisgKiB0aGF0
IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OgorICogCisgKiAqICAgUmVkaXN0cmli
dXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSAKKyAqICAgICBjb3B5
cmlnaHQgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIAorICogICAgIGZv
bGxvd2luZyBkaXNjbGFpbWVyLgorICogKiAgIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9y
bSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgCisgKiAgICAgY29weXJpZ2h0IG5vdGljZSwgdGhp
cyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSAKKyAqICAgICBmb2xsb3dpbmcgZGlzY2xhaW1l
ciBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgCisgKiAgICAgbWF0ZXJpYWxzIHBy
b3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KKyAqIAorICogVEhJUyBTT0ZUV0FSRSBJUyBQ
Uk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIAorICogQ09OVFJJQlVUT1JTICJB
UyBJUyIgQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgCisgKiBJTkNMVURJ
TkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFUyBPRiAKKyAqIE1F
UkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIAor
ICogRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1Ig
CisgKiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5D
SURFTlRBTCwgCisgKiBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdF
UyAoSU5DTFVESU5HLCAKKyAqIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VC
U1RJVFVURSBHT09EUyBPUiAKKyAqIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJP
RklUUzsgT1IgQlVTSU5FU1MgCisgKiBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBP
TiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgCisgKiBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJ
Q1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgCisgKiBORUdMSUdFTkNFIE9SIE9USEVS
V0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIAorICogT0YgVEhJUyBTT0ZU
V0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiAKKyAqIFNVQ0ggREFN
QUdFLgorICovCisKKyNkZWZpbmUgWEVOX0FQSSBfX2RlY2xzcGVjKGRsbGV4cG9ydCkKKworI2lu
Y2x1ZGUgPG50ZGRrLmg+CisjaW5jbHVkZSA8eGVuLmg+CisKKyNpbmNsdWRlICJoeXBlcmNhbGwu
aCIKKyNpbmNsdWRlICJkYmdfcHJpbnQuaCIKKyNpbmNsdWRlICJhc3NlcnQuaCIKKworc3RhdGlj
IEZPUkNFSU5MSU5FIExPTkdfUFRSCitYZW5WZXJzaW9uT3AoCisgICAgSU4gIFVMT05HICAgQ29t
bWFuZCwKKyAgICBJTiAgUFZPSUQgICBBcmd1bWVudAorICAgICkKK3sKKyAgICByZXR1cm4gSFlQ
RVJDQUxMKExPTkdfUFRSLCB4ZW5fdmVyc2lvbiwgMiwgQ29tbWFuZCwgQXJndW1lbnQpOworfQor
CitfX2NoZWNrUmV0dXJuCitYRU5fQVBJCitOVFNUQVRVUworWGVuVmVyc2lvbigKKyAgICBPVVQg
UFVMT05HICBNYWpvciwKKyAgICBPVVQgUFVMT05HICBNaW5vcgorICAgICkKK3sKKyAgICBMT05H
X1BUUiAgICAgICAgICAgICAgICAgICAgcmM7CisgICAgTlRTVEFUVVMgICAgICAgICAgICAgICAg
ICAgIHN0YXR1czsKKworICAgIHJjID0gWGVuVmVyc2lvbk9wKFhFTlZFUl92ZXJzaW9uLCBOVUxM
KTsKKworICAgIGlmIChyYyA8IDApIHsKKyAgICAgICAgRVJSTk9fVE9fU1RBVFVTKC1yYywgc3Rh
dHVzKTsKKyAgICAgICAgZ290byBmYWlsMTsKKyAgICB9CisKKyAgICAqTWFqb3IgPSAoVUxPTkcp
KChyYyA+PiAxNikgJiAweEZGRkYpOworICAgICpNaW5vciA9IChVTE9ORykocmMgJiAweEZGRkYp
OworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAgICBFcnJvcigiZmFp
bDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsKK30KKworX19jaGVj
a1JldHVybgorWEVOX0FQSQorTlRTVEFUVVMKK1hlblZlcnNpb25FeHRyYSgKKyAgICBPVVQgUENI
QVIgICAgICAgICAgIEV4dHJhCisgICAgKQoreworICAgIHhlbl9leHRyYXZlcnNpb25fdCAgb3A7
CisgICAgTE9OR19QVFIgICAgICAgICAgICByYzsKKyAgICBOVFNUQVRVUyAgICAgICAgICAgIHN0
YXR1czsKKworICAgIFJ0bFplcm9NZW1vcnkoJm9wLCBzaXplb2YgKG9wKSk7CisKKyAgICByYyA9
IFhlblZlcnNpb25PcChYRU5WRVJfZXh0cmF2ZXJzaW9uLCAmb3ApOworCisgICAgaWYgKHJjIDwg
MCkgeworICAgICAgICBFUlJOT19UT19TVEFUVVMoLXJjLCBzdGF0dXMpOworICAgICAgICBnb3Rv
IGZhaWwxOworICAgIH0KKworICAgIFJ0bENvcHlNZW1vcnkoRXh0cmEsICZvcCwgWEVOX0VYVFJB
VkVSU0lPTl9MRU4pOworCisgICAgcmV0dXJuIFNUQVRVU19TVUNDRVNTOworCitmYWlsMToKKyAg
ICBFcnJvcigiZmFpbDEgKCUwOHgpXG4iLCBzdGF0dXMpOworCisgICAgcmV0dXJuIHN0YXR1czsK
K30KZGlmZiAtLWdpdCBhL3NyYy94ZW5idXMvZmRvLmMgYi9zcmMveGVuYnVzL2Zkby5jCmluZGV4
IDU5NDQyYmQuLjIxNWM5OTcgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvZmRvLmMKKysrIGIvc3Jj
L3hlbmJ1cy9mZG8uYwpAQCAtMjE4Niw2ICsyMTg2LDggQEAgRmRvUzRUb1MzKAogCiAgICAgS2VS
YWlzZUlycWwoRElTUEFUQ0hfTEVWRUwsICZJcnFsKTsKIAorICAgIEh5cGVyY2FsbFBvcHVsYXRl
KCk7CisKICAgICBpZiAoRmRvLT5VbnBsdWdJbnRlcmZhY2UuSW50ZXJmYWNlLkNvbnRleHQgIT0g
TlVMTCkKICAgICAgICAgWEVORklMVF9VTlBMVUcoUmVwbGF5LCAmRmRvLT5VbnBsdWdJbnRlcmZh
Y2UpOwogCmRpZmYgLS1naXQgYS9zcmMveGVuYnVzL3N1c3BlbmQuYyBiL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCmluZGV4IDZhYjJiZDIuLmRlNzBlNDIgMTAwNjQ0Ci0tLSBhL3NyYy94ZW5idXMvc3Vz
cGVuZC5jCisrKyBiL3NyYy94ZW5idXMvc3VzcGVuZC5jCkBAIC0xNzMsNiArMTczLDggQEAgU3Vz
cGVuZFRyaWdnZXIoCiAKICAgICAgICAgQ29udGV4dC0+Q291bnQrKzsKIAorICAgICAgICBIeXBl
cmNhbGxQb3B1bGF0ZSgpOworCiAgICAgICAgIGlmIChDb250ZXh0LT5VbnBsdWdJbnRlcmZhY2Uu
SW50ZXJmYWNlLkNvbnRleHQgIT0gTlVMTCkKICAgICAgICAgICAgIFhFTkZJTFRfVU5QTFVHKFJl
cGxheSwgJkNvbnRleHQtPlVucGx1Z0ludGVyZmFjZSk7CiAKZGlmZiAtLWdpdCBhL3ZzMjAxMi94
ZW4veGVuLnZjeHByb2ogYi92czIwMTIveGVuL3hlbi52Y3hwcm9qCmluZGV4IGViNTQ2OTIuLjJm
NGQ5NTggMTAwNjQ0Ci0tLSBhL3ZzMjAxMi94ZW4veGVuLnZjeHByb2oKKysrIGIvdnMyMDEyL3hl
bi94ZW4udmN4cHJvagpAQCAtODgsNiArODgsNyBAQAogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZXZlbnRfY2hhbm5lbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4u
XC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwu
LlxzcmNceGVuXGh2bS5jIiAvPgorCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5c
eGVuX3ZlcnNpb24uYyIgLz4KIAkJPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5
cGVyY2FsbC5jIiAvPgogCQk8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cbWVtb3J5
LmMiIC8+CiAJCTxDbENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxzY2hlZC5jIiAvPgpk
aWZmIC0tZ2l0IGEvdnMyMDEzL3hlbi94ZW4udmN4cHJvaiBiL3ZzMjAxMy94ZW4veGVuLnZjeHBy
b2oKaW5kZXggNDkwMjk0Yy4uODFkNTBlYSAxMDA2NDQKLS0tIGEvdnMyMDEzL3hlbi94ZW4udmN4
cHJvagorKysgYi92czIwMTMveGVuL3hlbi52Y3hwcm9qCkBAIC0xLDQgKzEsNCBAQAot77u/PD94
bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KKzw/eG1sIHZlcnNpb249IjEuMCIg
ZW5jb2Rpbmc9InV0Zi04Ij8+CiA8UHJvamVjdCBEZWZhdWx0VGFyZ2V0cz0iQnVpbGQiIFRvb2xz
VmVyc2lvbj0iMTIuMCIgeG1sbnM9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vZGV2ZWxv
cGVyL21zYnVpbGQvMjAwMyI+CiAgIDxJbXBvcnQgUHJvamVjdD0iLi5cY29uZmlncy5wcm9wcyIg
Lz4KICAgPFByb3BlcnR5R3JvdXAgTGFiZWw9Ikdsb2JhbHMiPgpAQCAtMTI4LDYgKzEyOCw3IEBA
CiAgICAgPENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGV2ZW50X2NoYW5uZWwuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cZ3JhbnRfdGFibGUuYyIg
Lz4KICAgICA8Q2xDb21waWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5caHZtLmMiIC8+CisgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXHhlbl92ZXJzaW9uLmMiIC8+CiAgICAg
PENsQ29tcGlsZSBJbmNsdWRlPSIuLlwuLlxzcmNceGVuXGh5cGVyY2FsbC5jIiAvPgogICAgIDxD
bENvbXBpbGUgSW5jbHVkZT0iLi5cLi5cc3JjXHhlblxtZW1vcnkuYyIgLz4KICAgICA8Q2xDb21w
aWxlIEluY2x1ZGU9Ii4uXC4uXHNyY1x4ZW5cc2NoZWQuYyIgLz4KLS0gCjIuMS4xCgoKX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1h
aWxpbmcgbGlzdAp3aW4tcHYtZGV2ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3Rz
LnhlbnByb2plY3Qub3JnL2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 07 16:37:26 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:26 +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 1XmmXO-0000mC-6n; Fri, 07 Nov 2014 16:37:26 +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 1XmmXN-0000lf-1b
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:25 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	6F/EB-28296-445FC545; Fri, 07 Nov 2014 16:37:24 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415378240!11141871!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21427 invoked from network); 7 Nov 2014 16:37:23 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196335"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-T6;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:47 +0000
Message-ID: <1415378147-17816-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 +++-
 include/xen.h              |  16 ++
 src/xen/event_channel.c    |  30 ++++
 src/xen/hvm.c              |  28 ++++
 src/xenbus/evtchn.c        | 409 +++++++++++++++++++++++++++++++++++++--------
 src/xenbus/store.c         |   9 +
 6 files changed, 453 insertions(+), 74 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..c6ac30d 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -73,6 +73,7 @@ typedef struct _XENBUS_EVTCHN_PARAMETERS {
 
 struct _XENBUS_EVTCHN_CHANNEL {
     ULONG                       Magic;
+    KSPIN_LOCK                  Lock;
     LIST_ENTRY                  ListEntry;
     PVOID                       Caller;
     PKSERVICE_ROUTINE           Callback;
@@ -82,13 +83,17 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    ULONG                       Cpu;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -102,6 +107,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     BOOLEAN                         UseEvtchnFifoAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
+    KDPC                            Dpc;
 };
 
 #define XENBUS_EVTCHN_TAG  'CTVE'
@@ -127,15 +133,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +173,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +204,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +216,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +405,11 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Cpu = 0;
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -385,6 +437,8 @@ EvtchnOpen(
 
     KeLowerIrql(Irql);
 
+    KeInitializeSpinLock(&Channel->Lock);
+
     return Channel;
 
 fail4:
@@ -422,6 +476,150 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    KeAcquireSpinLock(&Channel->Lock, &Irql);
+
+    if (Channel->Cpu == Cpu)
+        goto done;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    (VOID) KfRaiseIrql(HIGH_LEVEL);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+    Channel->Cpu = Cpu;
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+#pragma prefast(suppress:28138) // Use constant rather than variable
+    KeLowerIrql(DISPATCH_LEVEL);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+#pragma prefast(suppress:28138) // Use constant rather than variable
+    KeLowerIrql(DISPATCH_LEVEL);
+
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
+VOID
+EvtchnCallback(
+    IN  PKDPC               Dpc,
+    IN  PVOID               _Context,
+    IN  PVOID               Argument1,
+    IN  PVOID               Argument2
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT  Context = _Context;
+    PXENBUS_EVTCHN_CHANNEL  Channel = Argument1;
+    KIRQL                   Irql;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    if (!Channel->Active)
+        return;
+
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
+
+#pragma warning(suppress:6387)  // NULL argument
+    (VOID) Channel->Callback(NULL, Channel->Argument);
+
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
+}
+
+static VOID
+EvtchnTrigger(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PKDPC                       Dpc = &Context->Dpc;
+    KIRQL                       Irql;
+
+    ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
+
+    KeAcquireSpinLock(&Channel->Lock, &Irql);
+
+    KeSetTargetProcessorDpc(Dpc, (CCHAR)Channel->Cpu);
+    KeInsertQueueDpc(Dpc, Channel, NULL);
+
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -432,27 +630,55 @@ EvtchnUnmask(
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     KIRQL                       Irql = PASSIVE_LEVEL;
     BOOLEAN                     Pending = FALSE;
+    ULONG                       Cpu;
+    PXENBUS_INTERRUPT           Interrupt;
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
     if (!InCallback)
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+        KeAcquireSpinLock(&Channel->Lock, &Irql);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
-    if (Channel->Active) {
-        Pending = XENBUS_EVTCHN_ABI(PortUnmask,
-                                    &Context->EvtchnAbi,
-                                    Channel->LocalPort);
-
-        if (Pending && Channel->Mask)
-            XENBUS_EVTCHN_ABI(PortMask,
-                              &Context->EvtchnAbi,
-                              Channel->LocalPort);
-    }
+    if (!Channel->Active)
+        goto done;
+
+    Pending = XENBUS_EVTCHN_ABI(PortUnmask,
+                                &Context->EvtchnAbi,
+                                Channel->LocalPort);
+
+    if (!Pending)
+        goto done;
+
+    if (InCallback)
+        goto mask;
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto mask;
 
+    //
+    // We are not on the CPU to which the event is bound so
+    // we must trigger.
+    //
+    EvtchnTrigger(Interface, Channel);
+
+    Pending = FALSE;
+    goto done;
+
+mask:
+    if (Channel->Mask)
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          Channel->LocalPort);
+
+done:
     if (!InCallback)
-        KeLowerIrql(Irql);
+        KeReleaseSpinLock(&Channel->Lock, Irql);
 
     return Pending;
 }
@@ -485,53 +711,6 @@ done:
     return status;
 }
 
-static BOOLEAN
-EvtchnCallback(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context,
-    IN  PXENBUS_EVTCHN_CHANNEL  Channel
-    )
-{
-    BOOLEAN                     DoneSomething;
-
-    UNREFERENCED_PARAMETER(Context);
-
-    ASSERT(Channel != NULL);
-    ASSERT(Channel->Active);
-
-#pragma warning(suppress:6387)  // NULL argument
-    DoneSomething = Channel->Callback(NULL, Channel->Argument);
-
-    return DoneSomething;
-}
-
-static BOOLEAN
-EvtchnTrigger(
-    IN  PINTERFACE              Interface,
-    IN  PXENBUS_EVTCHN_CHANNEL  Channel
-    )
-{
-    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
-    KIRQL                       Irql;
-    BOOLEAN                     DoneSomething;
-
-    ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
-
-    Irql = __EvtchnAcquireInterruptLock(Context);
-
-    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
-
-    if (Channel->Active) {
-        DoneSomething = EvtchnCallback(Context, Channel);
-    } else {
-        Warning("[%d]: INVALID PORT\n", Channel->LocalPort);
-        DoneSomething = FALSE;
-    }
-
-    __EvtchnReleaseInterruptLock(Context, Irql);
-
-    return DoneSomething;
-}
-
 static VOID
 EvtchnClose(
     IN  PINTERFACE              Interface,
@@ -543,6 +722,8 @@ EvtchnClose(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
+    RtlZeroMemory(&Channel->Lock, sizeof (KSPIN_LOCK));
+
     KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
 
     KeAcquireSpinLockAtDpcLevel(&Context->Lock);
@@ -575,6 +756,9 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+    Channel->Cpu = 0;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +801,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +814,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -641,7 +837,8 @@ EvtchnPollCallback(
                       &Context->EvtchnAbi,
                       LocalPort);
 
-    DoneSomething = EvtchnCallback(Context, Channel);
+#pragma warning(suppress:6387)  // NULL argument
+    DoneSomething = Channel->Callback(NULL, Channel->Argument);
 
 done:
     return DoneSomething;
@@ -767,8 +964,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1061,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1119,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1144,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1215,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1229,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1279,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1110,6 +1356,7 @@ EvtchnInitialize(
 
     InitializeListHead(&(*Context)->List);
     KeInitializeSpinLock(&(*Context)->Lock);
+    KeInitializeDpc(&(*Context)->Dpc, EvtchnCallback, Context);
 
     (*Context)->Fdo = Fdo;
 
@@ -1171,6 +1418,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
@@ -1188,6 +1452,7 @@ EvtchnTeardown(
 
     Context->Fdo = NULL;
 
+    RtlZeroMemory(&Context->Dpc, sizeof (KDPC));
     RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY));
 
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 16:37:26 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37:26 +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 1XmmXO-0000mC-6n; Fri, 07 Nov 2014 16:37:26 +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 1XmmXN-0000lf-1b
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:25 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	6F/EB-28296-445FC545; Fri, 07 Nov 2014 16:37:24 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-31.messagelabs.com!1415378240!11141871!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 21427 invoked from network); 7 Nov 2014 16:37:23 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-10.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196335"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-T6;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:47 +0000
Message-ID: <1415378147-17816-5-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 4/4] Use per-CPU event channel upcalls if
	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

A recent patch to Xen introduced a new HVM op to set a per-vcpu event
channel upcall. This patch adds code to make use of the latched interrupts
allocated by the FDO code to enable per-vcpu upcalls and adds an extra
EvtchnBind operation to a new v2 EVTCHN interface so that events can be
steered to a specified CPU.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/evtchn_interface.h |  35 +++-
 include/xen.h              |  16 ++
 src/xen/event_channel.c    |  30 ++++
 src/xen/hvm.c              |  28 ++++
 src/xenbus/evtchn.c        | 409 +++++++++++++++++++++++++++++++++++++--------
 src/xenbus/store.c         |   9 +
 6 files changed, 453 insertions(+), 74 deletions(-)

diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 5898e08..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,6 +112,20 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
@@ -196,7 +210,24 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -207,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/xen.h b/include/xen.h
index 0dabc74..84197a5 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -97,6 +97,14 @@ HvmPagetableDying(
     IN  PHYSICAL_ADDRESS    Address
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int    vcpu_id,
+    IN  UCHAR           Vector
+    );
+
 // MEMORY
 
 __checkReturn
@@ -196,6 +204,14 @@ EventChannelReset(
     VOID
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index aa87fd4..94a6b82 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -327,3 +327,33 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelBindVirtualCpu(
+    IN  ULONG               LocalPort,
+    IN  unsigned int        vcpu_id
+    )
+{
+    struct evtchn_bind_vcpu op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+    op.vcpu = vcpu_id;
+
+    rc = EventChannelOp(EVTCHNOP_bind_vcpu, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xen/hvm.c b/src/xen/hvm.c
index 8135e97..3e3e12c 100644
--- a/src/xen/hvm.c
+++ b/src/xen/hvm.c
@@ -166,3 +166,31 @@ HvmPagetableDying(
 fail1:
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+HvmSetEvtchnUpcallVector(
+    IN  unsigned int                        vcpu_id,
+    IN  UCHAR                               Vector
+    )
+{
+    struct xen_hvm_set_evtchn_upcall_vector op;
+    LONG_PTR                                rc;
+    NTSTATUS                                status;
+
+    op.vcpu = vcpu_id;
+    op.vector = Vector;
+
+    rc = HvmOp(HVMOP_set_evtchn_upcall_vector, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 44043d4..c6ac30d 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -73,6 +73,7 @@ typedef struct _XENBUS_EVTCHN_PARAMETERS {
 
 struct _XENBUS_EVTCHN_CHANNEL {
     ULONG                       Magic;
+    KSPIN_LOCK                  Lock;
     LIST_ENTRY                  ListEntry;
     PVOID                       Caller;
     PKSERVICE_ROUTINE           Callback;
@@ -82,13 +83,17 @@ struct _XENBUS_EVTCHN_CHANNEL {
     XENBUS_EVTCHN_PARAMETERS    Parameters;
     BOOLEAN                     Mask;
     ULONG                       LocalPort;
+    ULONG                       Cpu;
+    PXENBUS_INTERRUPT           Interrupt;
 };
 
 struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    PXENBUS_INTERRUPT               Interrupt;
+    PXENBUS_INTERRUPT               LevelSensitiveInterrupt;
+    PXENBUS_INTERRUPT               LatchedInterrupt[MAXIMUM_PROCESSORS];
+    KAFFINITY                       Affinity;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -102,6 +107,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     BOOLEAN                         UseEvtchnFifoAbi;
     PXENBUS_HASH_TABLE              Table;
     LIST_ENTRY                      List;
+    KDPC                            Dpc;
 };
 
 #define XENBUS_EVTCHN_TAG  'CTVE'
@@ -127,15 +133,39 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     ULONG                       Line;
     NTSTATUS                    status;
 
-    Trace("<===>\n");
+    Trace("====>\n");
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        unsigned int    vcpu_id;
+        UCHAR           Vector;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+        Vector = FdoGetInterruptVector(Context->Fdo,
+                                       Context->LatchedInterrupt[Cpu]);
+
+        status = HvmSetEvtchnUpcallVector(vcpu_id, Vector);
+        if (NT_SUCCESS(status)) {
+            Info("CPU %u\n", Cpu);
+            Context->Affinity |= (KAFFINITY)1 << Cpu;
+        }
+
+        Cpu++;
+    }
 
-    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+    Line = FdoGetInterruptLine(Context->Fdo,
+                               Context->LevelSensitiveInterrupt);
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
+
+    Trace("<====\n");
 }
 
 static VOID
@@ -143,14 +173,29 @@ EvtchnInterruptDisable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    LONG                        Cpu;
     NTSTATUS                    status;
 
     UNREFERENCED_PARAMETER(Context);
 
-    Trace("<===>\n");
+    Trace("====>\n");
 
     status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, 0);
     ASSERT(NT_SUCCESS(status));
+
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        unsigned int    vcpu_id;
+
+        vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+        (VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
+        Context->Affinity &= ~((KAFFINITY)1 << Cpu);
+    }
+
+    ASSERT3U(Context->Affinity, ==, 0);
+
+    Trace("<====\n");
 }
 
 static FORCEINLINE
@@ -159,10 +204,11 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 __EvtchnAcquireInterruptLock(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+    IN  PXENBUS_EVTCHN_CONTEXT  Context,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
+    return FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,10 +216,11 @@ __drv_requiresIRQL(HIGH_LEVEL)
 VOID
 __EvtchnReleaseInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT      Context,
+    IN  PXENBUS_EVTCHN_CHANNEL      Channel,
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -358,6 +405,11 @@ EvtchnOpen(
 
     LocalPort = Channel->LocalPort;
 
+    Channel->Cpu = 0;
+    Channel->Interrupt = (Context->Affinity != 0) ? // Latched available
+                         Context->LatchedInterrupt[0] :
+                         Context->LevelSensitiveInterrupt;
+
     status = XENBUS_EVTCHN_ABI(PortEnable,
                                &Context->EvtchnAbi,
                                LocalPort);
@@ -385,6 +437,8 @@ EvtchnOpen(
 
     KeLowerIrql(Irql);
 
+    KeInitializeSpinLock(&Channel->Lock);
+
     return Channel;
 
 fail4:
@@ -422,6 +476,150 @@ fail1:
     return NULL;
 }
 
+#define EVTCHN_SWAP_POINTER(_X, _Y)                             \
+        do {                                                    \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_Y) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+            (_X) = (PVOID)((ULONG_PTR)(_X) ^ (ULONG_PTR)(_Y));  \
+        } while (FALSE)
+
+static NTSTATUS
+EvtchnBind(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PXENBUS_INTERRUPT           Interrupt;
+    ULONG                       LocalPort;
+    unsigned int                vcpu_id;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Cpu >= (ULONG)KeNumberProcessors)
+        goto fail1;
+
+    ASSERT(Context->Enabled);
+
+    status = STATUS_NOT_SUPPORTED;
+    if (~Context->Affinity & ((KAFFINITY)1 << Cpu))
+        goto fail2;
+
+    KeAcquireSpinLock(&Channel->Lock, &Irql);
+
+    if (Channel->Cpu == Cpu)
+        goto done;
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    (VOID) KfRaiseIrql(HIGH_LEVEL);
+
+    // Make sure we always lock in a consistent order
+    if ((ULONG_PTR)Interrupt < (ULONG_PTR)Channel->Interrupt) {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+    } else {
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Channel->Interrupt);
+        (VOID) FdoAcquireInterruptLock(Context->Fdo, Interrupt);
+    }
+
+    LocalPort = Channel->LocalPort;
+    vcpu_id = SystemVirtualCpuIndex(Cpu);
+
+    status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    EVTCHN_SWAP_POINTER(Channel->Interrupt, Interrupt);
+    Channel->Cpu = Cpu;
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+#pragma prefast(suppress:28138) // Use constant rather than variable
+    KeLowerIrql(DISPATCH_LEVEL);
+
+    Info("[%u]: CPU %u\n", LocalPort, Cpu);
+
+done:
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    FdoReleaseInterruptLock(Context->Fdo, Channel->Interrupt, HIGH_LEVEL);
+    FdoReleaseInterruptLock(Context->Fdo, Interrupt, HIGH_LEVEL);
+
+#pragma prefast(suppress:28138) // Use constant rather than variable
+    KeLowerIrql(DISPATCH_LEVEL);
+
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
+VOID
+EvtchnCallback(
+    IN  PKDPC               Dpc,
+    IN  PVOID               _Context,
+    IN  PVOID               Argument1,
+    IN  PVOID               Argument2
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT  Context = _Context;
+    PXENBUS_EVTCHN_CHANNEL  Channel = Argument1;
+    KIRQL                   Irql;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    if (!Channel->Active)
+        return;
+
+    Irql = __EvtchnAcquireInterruptLock(Context, Channel);
+
+#pragma warning(suppress:6387)  // NULL argument
+    (VOID) Channel->Callback(NULL, Channel->Argument);
+
+    __EvtchnReleaseInterruptLock(Context, Channel, Irql);
+}
+
+static VOID
+EvtchnTrigger(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel
+    )
+{
+    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
+    PKDPC                       Dpc = &Context->Dpc;
+    KIRQL                       Irql;
+
+    ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
+
+    KeAcquireSpinLock(&Channel->Lock, &Irql);
+
+    KeSetTargetProcessorDpc(Dpc, (CCHAR)Channel->Cpu);
+    KeInsertQueueDpc(Dpc, Channel, NULL);
+
+    KeReleaseSpinLock(&Channel->Lock, Irql);
+}
+
 static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
@@ -432,27 +630,55 @@ EvtchnUnmask(
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     KIRQL                       Irql = PASSIVE_LEVEL;
     BOOLEAN                     Pending = FALSE;
+    ULONG                       Cpu;
+    PXENBUS_INTERRUPT           Interrupt;
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
     if (!InCallback)
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
+        KeAcquireSpinLock(&Channel->Lock, &Irql);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
-    if (Channel->Active) {
-        Pending = XENBUS_EVTCHN_ABI(PortUnmask,
-                                    &Context->EvtchnAbi,
-                                    Channel->LocalPort);
-
-        if (Pending && Channel->Mask)
-            XENBUS_EVTCHN_ABI(PortMask,
-                              &Context->EvtchnAbi,
-                              Channel->LocalPort);
-    }
+    if (!Channel->Active)
+        goto done;
+
+    Pending = XENBUS_EVTCHN_ABI(PortUnmask,
+                                &Context->EvtchnAbi,
+                                Channel->LocalPort);
+
+    if (!Pending)
+        goto done;
+
+    if (InCallback)
+        goto mask;
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
+
+    Interrupt = Context->LatchedInterrupt[Cpu];
+
+    if (Channel->Interrupt == Interrupt)
+        goto mask;
 
+    //
+    // We are not on the CPU to which the event is bound so
+    // we must trigger.
+    //
+    EvtchnTrigger(Interface, Channel);
+
+    Pending = FALSE;
+    goto done;
+
+mask:
+    if (Channel->Mask)
+        XENBUS_EVTCHN_ABI(PortMask,
+                          &Context->EvtchnAbi,
+                          Channel->LocalPort);
+
+done:
     if (!InCallback)
-        KeLowerIrql(Irql);
+        KeReleaseSpinLock(&Channel->Lock, Irql);
 
     return Pending;
 }
@@ -485,53 +711,6 @@ done:
     return status;
 }
 
-static BOOLEAN
-EvtchnCallback(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context,
-    IN  PXENBUS_EVTCHN_CHANNEL  Channel
-    )
-{
-    BOOLEAN                     DoneSomething;
-
-    UNREFERENCED_PARAMETER(Context);
-
-    ASSERT(Channel != NULL);
-    ASSERT(Channel->Active);
-
-#pragma warning(suppress:6387)  // NULL argument
-    DoneSomething = Channel->Callback(NULL, Channel->Argument);
-
-    return DoneSomething;
-}
-
-static BOOLEAN
-EvtchnTrigger(
-    IN  PINTERFACE              Interface,
-    IN  PXENBUS_EVTCHN_CHANNEL  Channel
-    )
-{
-    PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
-    KIRQL                       Irql;
-    BOOLEAN                     DoneSomething;
-
-    ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
-
-    Irql = __EvtchnAcquireInterruptLock(Context);
-
-    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
-
-    if (Channel->Active) {
-        DoneSomething = EvtchnCallback(Context, Channel);
-    } else {
-        Warning("[%d]: INVALID PORT\n", Channel->LocalPort);
-        DoneSomething = FALSE;
-    }
-
-    __EvtchnReleaseInterruptLock(Context, Irql);
-
-    return DoneSomething;
-}
-
 static VOID
 EvtchnClose(
     IN  PINTERFACE              Interface,
@@ -543,6 +722,8 @@ EvtchnClose(
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
+    RtlZeroMemory(&Channel->Lock, sizeof (KSPIN_LOCK));
+
     KeRaiseIrql(DISPATCH_LEVEL, &Irql); // Prevent suspend
 
     KeAcquireSpinLockAtDpcLevel(&Context->Lock);
@@ -575,6 +756,9 @@ EvtchnClose(
         ASSERT(NT_SUCCESS(status));
     }
 
+    Channel->Interrupt = NULL;
+    Channel->Cpu = 0;
+
     Channel->LocalPort = 0;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
@@ -617,6 +801,8 @@ EvtchnPollCallback(
     BOOLEAN                 DoneSomething;
     NTSTATUS                status;
 
+    DoneSomething = FALSE;
+
     status = HashTableLookup(Context->Table,
                              LocalPort,
                              (PULONG_PTR)&Channel);
@@ -628,10 +814,20 @@ EvtchnPollCallback(
                           &Context->EvtchnAbi,
                           LocalPort);
 
-        DoneSomething = FALSE;
         goto done;
     }
 
+    if (Context->Affinity != 0) {
+        ULONG   Cpu;
+
+        ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+        Cpu = KeGetCurrentProcessorNumber();
+
+        // Only handle events on the correct CPU
+        if (Channel->Interrupt != Context->LatchedInterrupt[Cpu])
+            goto done;
+    }
+
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
@@ -641,7 +837,8 @@ EvtchnPollCallback(
                       &Context->EvtchnAbi,
                       LocalPort);
 
-    DoneSomething = EvtchnCallback(Context, Channel);
+#pragma warning(suppress:6387)  // NULL argument
+    DoneSomething = Channel->Callback(NULL, Channel->Argument);
 
 done:
     return DoneSomething;
@@ -767,8 +964,10 @@ EvtchnSuspendCallbackLate(
     status = EvtchnAbiAcquire(Context);
     ASSERT(NT_SUCCESS(status));
 
-    if (Context->Enabled)
+    if (Context->Enabled) {
+        EvtchnInterruptDisable(Context);
         EvtchnInterruptEnable(Context);
+    }
 }
 
 static VOID
@@ -862,6 +1061,7 @@ EvtchnAcquire(
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
     PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
     NTSTATUS                status;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
@@ -919,10 +1119,24 @@ EvtchnAcquire(
                                   0,
                                   EvtchnInterruptCallback,
                                   Context,
-                                  &Context->Interrupt);
+                                  &Context->LevelSensitiveInterrupt);
     if (!NT_SUCCESS(status))
         goto fail8;
 
+    Cpu = 0;
+    while (Cpu < KeNumberProcessors) {
+        status = FdoAllocateInterrupt(Fdo,
+                                      Latched,
+                                      Cpu,
+                                      EvtchnInterruptCallback,
+                                      Context,
+                                      &Context->LatchedInterrupt[Cpu]);
+        if (!NT_SUCCESS(status))
+            goto fail9;
+
+        Cpu++;
+    }
+
     Trace("<====\n");
 
 done:
@@ -930,6 +1144,17 @@ done:
 
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
+
 fail8:
     Error("fail8\n");
 
@@ -990,7 +1215,9 @@ EvtchnRelease(
     )
 {
     PXENBUS_EVTCHN_CONTEXT  Context = Interface->Context;
+    PXENBUS_FDO             Fdo = Context->Fdo;
     KIRQL                   Irql;
+    LONG                    Cpu;
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -1002,8 +1229,14 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
-    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
-    Context->Interrupt = NULL;
+    Cpu = KeNumberProcessors;
+    while (--Cpu >= 0) {
+        FdoFreeInterrupt(Fdo, Context->LatchedInterrupt[Cpu]);
+        Context->LatchedInterrupt[Cpu] = NULL;
+    }
+
+    FdoFreeInterrupt(Fdo, Context->LevelSensitiveInterrupt);
+    Context->LevelSensitiveInterrupt = NULL;
 
     EvtchnAbiRelease(Context);
 
@@ -1046,6 +1279,19 @@ static struct _XENBUS_EVTCHN_INTERFACE_V1 EvtchnInterfaceVersion1 = {
     EvtchnClose
 };
                      
+static struct _XENBUS_EVTCHN_INTERFACE_V2 EvtchnInterfaceVersion2 = {
+    { sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2), 2, NULL, NULL, NULL },
+    EvtchnAcquire,
+    EvtchnRelease,
+    EvtchnOpen,
+    EvtchnBind,
+    EvtchnUnmask,
+    EvtchnSend,
+    EvtchnTrigger,
+    EvtchnGetPort,
+    EvtchnClose
+};
+
 NTSTATUS
 EvtchnInitialize(
     IN  PXENBUS_FDO             Fdo,
@@ -1110,6 +1356,7 @@ EvtchnInitialize(
 
     InitializeListHead(&(*Context)->List);
     KeInitializeSpinLock(&(*Context)->Lock);
+    KeInitializeDpc(&(*Context)->Dpc, EvtchnCallback, Context);
 
     (*Context)->Fdo = Fdo;
 
@@ -1171,6 +1418,23 @@ EvtchnGetInterface(
         status = STATUS_SUCCESS;
         break;
     }
+    case 2: {
+        struct _XENBUS_EVTCHN_INTERFACE_V2  *EvtchnInterface;
+
+        EvtchnInterface = (struct _XENBUS_EVTCHN_INTERFACE_V2 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_EVTCHN_INTERFACE_V2))
+            break;
+
+        *EvtchnInterface = EvtchnInterfaceVersion2;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
     default:
         status = STATUS_NOT_SUPPORTED;
         break;
@@ -1188,6 +1452,7 @@ EvtchnTeardown(
 
     Context->Fdo = NULL;
 
+    RtlZeroMemory(&Context->Dpc, sizeof (KDPC));
     RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
     RtlZeroMemory(&Context->List, sizeof (LIST_ENTRY));
 
diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 22c2a12..04fce3a 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -1848,6 +1848,15 @@ StoreEnable(
                                      FALSE);
     ASSERT(Context->Channel != NULL);
 
+    // 
+    // Attempt to use some CPU other than 0 for events from
+    // xenstored.
+    //
+    (VOID) XENBUS_EVTCHN(Bind,
+                         &Context->EvtchnInterface,
+                         Context->Channel,
+                         KeNumberProcessors - 1);
+
     Pending = XENBUS_EVTCHN(Unmask,
                             &Context->EvtchnInterface,
                             Context->Channel,
-- 
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 Nov 07 16:37:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37: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 1XmmXP-0000md-82; Fri, 07 Nov 2014 16:37:27 +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 1XmmXO-0000m7-9q
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:26 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	C8/FB-28296-545FC545; Fri, 07 Nov 2014 16:37:25 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20372 invoked from network); 7 Nov 2014 16:37:24 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196340"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-S9;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:45 +0000
Message-ID: <1415378147-17816-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |   8 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 896 insertions(+), 224 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..669e866 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -82,16 +82,22 @@ StartType=%SERVICE_BOOT_START%
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 16:37:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:37: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 1XmmXP-0000md-82; Fri, 07 Nov 2014 16:37:27 +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 1XmmXO-0000m7-9q
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:37:26 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	C8/FB-28296-545FC545; Fri, 07 Nov 2014 16:37:25 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1415378237!7435080!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20372 invoked from network); 7 Nov 2014 16:37:24 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:37:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189196340"
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.181.6;
	Fri, 7 Nov 2014 11:35:58 -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 1XmmVx-0007Tr-S9;
	Fri, 07 Nov 2014 16:35:57 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:35:45 +0000
Message-ID: <1415378147-17816-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415378147-17816-1-git-send-email-paul.durrant@citrix.com>
References: <1415378147-17816-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 v3 2/4] Re-work interrupt code in FDO
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

This patch adds code to the FDO handler to acquire extra message signaled
(i.e. edge triggered) interrupt vectors that can be used for per-CPU event
channel upcalls (with extra support in Xen).
The existing callback via is also limited to upcall on CPU 0 meaning the
interrupt callback in the EVTCHN code can pass the current CPU value through
to the ABI.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/common/names.h  | 122 ++++++-
 src/xenbus.inf      |   8 +-
 src/xenbus/evtchn.c |  55 +++-
 src/xenbus/fdo.c    | 894 +++++++++++++++++++++++++++++++++++++++++-----------
 src/xenbus/fdo.h    |  39 ++-
 src/xenbus/pdo.c    |   2 +-
 6 files changed, 896 insertions(+), 224 deletions(-)

diff --git a/src/common/names.h b/src/common/names.h
index 89894b9..f4a8bd0 100644
--- a/src/common/names.h
+++ b/src/common/names.h
@@ -196,32 +196,124 @@ PnpMinorFunctionName(
 }
 
 static FORCEINLINE const CHAR *
-PartialResourceDescriptorTypeName(
+ResourceDescriptorTypeName(
     IN  UCHAR   Type
     )
 {
-#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
-    case CmResourceType ## _Type:                       \
+#define _RESOURCE_DESCRIPTOR_TYPE_NAME(_Type)   \
+    case CmResourceType ## _Type:               \
         return #_Type;
 
     switch (Type) {
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
-    _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Null);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Port);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Memory);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(Dma);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData);
+    _RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate);
     default:
         break;
     }
 
     return "UNKNOWN";
 
-#undef  _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME
+#undef  _RESOURCE_DESCRIPTOR_TYPE_NAME
+}
+
+static FORCEINLINE const CHAR *
+ResourceDescriptorShareDispositionName(
+    IN  UCHAR   Disposition
+    )
+{
+#define _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(_Disposition)  \
+    case CmResourceShare ## _Disposition:                           \
+        return #_Disposition;
+
+    switch (Disposition) {
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Undetermined);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DeviceExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(DriverExclusive);
+    _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME(Shared);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _RESOURCE_DESCRIPTOR_SHARE_DISPOSITION_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqDevicePolicyName(
+    IN  IRQ_DEVICE_POLICY   Policy
+    )
+{
+#define _IRQ_DEVICE_POLICY_NAME(_Policy)    \
+    case IrqPolicy ## _Policy:              \
+        return #_Policy;
+
+    switch (Policy) {
+    _IRQ_DEVICE_POLICY_NAME(MachineDefault);
+    _IRQ_DEVICE_POLICY_NAME(AllCloseProcessors);
+    _IRQ_DEVICE_POLICY_NAME(OneCloseProcessor);
+    _IRQ_DEVICE_POLICY_NAME(AllProcessorsInMachine);
+    _IRQ_DEVICE_POLICY_NAME(SpecifiedProcessors);
+    _IRQ_DEVICE_POLICY_NAME(SpreadMessagesAcrossAllProcessors);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_DEVICE_POLICY_NAME
+}
+
+static FORCEINLINE const CHAR *
+IrqPriorityName(
+    IN  IRQ_PRIORITY    Priority
+    )
+{
+#define _IRQ_PRIORITY_NAME(_Priority)   \
+    case IrqPriority ## _Priority:      \
+        return #_Priority;
+
+    switch (Priority) {
+    _IRQ_PRIORITY_NAME(Undefined);
+    _IRQ_PRIORITY_NAME(Low);
+    _IRQ_PRIORITY_NAME(Normal);
+    _IRQ_PRIORITY_NAME(High);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _IRQ_PRIORITY_NAME
+}
+
+static FORCEINLINE const CHAR *
+InterruptModeName(
+    IN  KINTERRUPT_MODE Mode
+    )
+{
+#define _INTERRUPT_MODE_NAME(_Mode) \
+    case _Mode:                     \
+        return #_Mode;
+
+    switch (Mode) {
+    _INTERRUPT_MODE_NAME(LevelSensitive);
+    _INTERRUPT_MODE_NAME(Latched);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _INTERRUPT_MODE_NAME
 }
 
 static FORCEINLINE const CHAR *
@@ -358,4 +450,6 @@ BusQueryIdTypeName(
 #undef  _BUS_QUERY_ID_TYPE_NAME
 }
 
+
+
 #endif // _COMMON_NAMES_H_
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 544bb2c..669e866 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -82,16 +82,22 @@ StartType=%SERVICE_BOOT_START%
 ErrorControl=%SERVICE_ERROR_NORMAL% 
 ServiceBinary=%12%\xenbus.sys 
 LoadOrderGroup="Boot Bus Extender"
-AddReg = XenBus_Parameters, XenBus_Interfaces
+AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts
 
 [XenBus_Parameters]
 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
 
+[XenBus_Interrupts]
+HKR,"Interrupt Management",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010
+HKR,"Interrupt Management\MessageSignaledInterruptProperties","MSISupported",0x00010001,1
+
 [XenFilt_Service] 
 DisplayName=%XenFiltDesc%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index 1bd5e5f..44043d4 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -88,7 +88,7 @@ struct _XENBUS_EVTCHN_CONTEXT {
     PXENBUS_FDO                     Fdo;
     KSPIN_LOCK                      Lock;
     LONG                            References;
-    ULONG                           Vector;
+    PXENBUS_INTERRUPT               Interrupt;
     BOOLEAN                         Enabled;
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackEarly;
@@ -127,11 +127,14 @@ EvtchnInterruptEnable(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
+    ULONG                       Line;
     NTSTATUS                    status;
 
     Trace("<===>\n");
 
-    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Context->Vector);
+    Line = FdoGetInterruptLine(Context->Fdo, Context->Interrupt);
+
+    status = HvmSetParam(HVM_PARAM_CALLBACK_IRQ, Line);
     ASSERT(NT_SUCCESS(status));
 }
 
@@ -159,7 +162,7 @@ __EvtchnAcquireInterruptLock(
     IN  PXENBUS_EVTCHN_CONTEXT  Context
     )
 {
-    return FdoAcquireInterruptLock(Context->Fdo);
+    return FdoAcquireInterruptLock(Context->Fdo, Context->Interrupt);
 }
 
 static FORCEINLINE
@@ -170,7 +173,7 @@ __EvtchnReleaseInterruptLock(
     IN  __drv_restoresIRQL KIRQL    Irql
     )
 {
-    FdoReleaseInterruptLock(Context->Fdo, Irql);
+    FdoReleaseInterruptLock(Context->Fdo, Context->Interrupt, Irql);
 }
 
 static NTSTATUS
@@ -644,21 +647,32 @@ done:
     return DoneSomething;
 }
 
+static
+_Function_class_(KSERVICE_ROUTINE)
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-EvtchnInterrupt(
-    IN  PXENBUS_EVTCHN_CONTEXT  Context
+EvtchnInterruptCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
     )
 {
-    BOOLEAN                     DoneSomething;
+    PXENBUS_EVTCHN_CONTEXT  Context = Argument;
+    ULONG                   Cpu;
+    BOOLEAN                 DoneSomething;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
+    Cpu = KeGetCurrentProcessorNumber();
 
     DoneSomething = FALSE;
 
     while (XENBUS_SHARED_INFO(UpcallPending,
                               &Context->SharedInfoInterface,
-                              0))
+                              Cpu))
         DoneSomething |= XENBUS_EVTCHN_ABI(Poll,
                                            &Context->EvtchnAbi,
-                                           0,
+                                           Cpu,
                                            EvtchnPollCallback,
                                            Context);
 
@@ -857,8 +871,6 @@ EvtchnAcquire(
 
     Trace("====>\n");
 
-    Context->Vector = FdoGetInterruptVector(Fdo);
-
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
@@ -902,6 +914,15 @@ EvtchnAcquire(
     if (!NT_SUCCESS(status))
         goto fail7;
 
+    status = FdoAllocateInterrupt(Fdo,
+                                  LevelSensitive,
+                                  0,
+                                  EvtchnInterruptCallback,
+                                  Context,
+                                  &Context->Interrupt);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
     Trace("<====\n");
 
 done:
@@ -909,6 +930,11 @@ done:
 
     return STATUS_SUCCESS;
 
+fail8:
+    Error("fail8\n");
+
+    EvtchnAbiRelease(Context);
+
 fail7:
     Error("fail7\n");
 
@@ -948,8 +974,6 @@ fail2:
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -978,6 +1002,9 @@ EvtchnRelease(
     if (!IsListEmpty(&Context->List))
         BUG("OUTSTANDING EVENT CHANNELS");
 
+    FdoFreeInterrupt(Context->Fdo, Context->Interrupt);
+    Context->Interrupt = NULL;
+
     EvtchnAbiRelease(Context);
 
     XENBUS_SHARED_INFO(Release, &Context->SharedInfoInterface);
@@ -1001,8 +1028,6 @@ EvtchnRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Context->Vector = 0;
-
     Trace("<====\n");
 
 done:
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index 215c997..cc0c775 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -45,6 +45,7 @@
 #include "fdo.h"
 #include "pdo.h"
 #include "thread.h"
+#include "high.h"
 #include "mutex.h"
 #include "shared_info.h"
 #include "evtchn.h"
@@ -64,16 +65,17 @@
 
 #define MAXNAMELEN  128
 
-typedef enum _XENBUS_RESOURCE_TYPE {
-    MEMORY_RESOURCE = 0,
-    INTERRUPT_RESOURCE,
-    RESOURCE_COUNT
-} XENBUS_RESOURCE_TYPE, *PXENBUS_RESOURCE_TYPE;
-
-typedef struct _XENBUS_RESOURCE {
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Raw;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
-} XENBUS_RESOURCE, *PXENBUS_RESOURCE;
+struct _XENBUS_INTERRUPT {
+    PXENBUS_FDO         Fdo;
+    LIST_ENTRY          ListEntry;
+    KINTERRUPT_MODE     InterruptMode;
+    PKINTERRUPT         InterruptObject;
+    ULONG               Cpu;
+    UCHAR               Vector;
+    ULONG               Line;
+    PKSERVICE_ROUTINE   Callback;
+    PVOID               Argument;
+};
 
 struct _XENBUS_FDO {
     PXENBUS_DX                      Dx;
@@ -108,8 +110,8 @@ struct _XENBUS_FDO {
     PXENBUS_STORE_WATCH             BalloonWatch;
     MUTEX                           BalloonSuspendMutex;
 
-    XENBUS_RESOURCE                 Resource[RESOURCE_COUNT];
-    PKINTERRUPT                     InterruptObject;
+    PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
+    PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
@@ -129,9 +131,11 @@ struct _XENBUS_FDO {
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
     XENFILT_UNPLUG_INTERFACE        UnplugInterface;
 
+    PXENBUS_RANGE_SET               RangeSet;
+    LIST_ENTRY                      List;
+
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
-    PXENBUS_RANGE_SET               RangeSet;
 };
 
 static FORCEINLINE PVOID
@@ -187,6 +191,16 @@ __FdoGetDevicePnpState(
     return Dx->DevicePnpState;
 }
 
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    PXENBUS_DX      Dx = Fdo->Dx;
+
+    return Dx->PreviousDevicePnpState;
+}
+
 static FORCEINLINE VOID
 __FdoSetDevicePowerState(
     IN  PXENBUS_FDO         Fdo,
@@ -1383,219 +1397,595 @@ loop:
 }
 
 static VOID
-FdoParseResources(
+FdoDumpIoResourceDescriptor(
     IN  PXENBUS_FDO             Fdo,
-    IN  PCM_RESOURCE_LIST       RawResourceList,
-    IN  PCM_RESOURCE_LIST       TranslatedResourceList
+    IN  PIO_RESOURCE_DESCRIPTOR Descriptor
     )
 {
-    PCM_PARTIAL_RESOURCE_LIST   RawPartialList;
-    PCM_PARTIAL_RESOURCE_LIST   TranslatedPartialList;
-    ULONG                       Index;
+    Trace("%s: %s\n",
+          __FdoGetName(Fdo),
+          ResourceDescriptorTypeName(Descriptor->Type));
+
+    if (Descriptor->Option == 0)
+        Trace("Required\n");
+    else if (Descriptor->Option == IO_RESOURCE_ALTERNATIVE)
+        Trace("Alternative\n");
+    else if (Descriptor->Option == IO_RESOURCE_PREFERRED)
+        Trace("Preferred\n");
+    else if (Descriptor->Option == (IO_RESOURCE_ALTERNATIVE | IO_RESOURCE_PREFERRED))
+        Trace("Preferred Alternative\n");
+
+    Trace("ShareDisposition=%s Flags=%04x\n",
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("Length = %08x Alignment = %08x\n MinimumAddress = %08x.%08x MaximumAddress = %08x.%08x\n",
+              Descriptor->u.Memory.Length,
+              Descriptor->u.Memory.Alignment,
+              Descriptor->u.Memory.MinimumAddress.HighPart,
+              Descriptor->u.Memory.MinimumAddress.LowPart,
+              Descriptor->u.Memory.MaximumAddress.HighPart,
+              Descriptor->u.Memory.MaximumAddress.LowPart);
+        break;
 
-    ASSERT3U(RawResourceList->Count, ==, 1);
-    RawPartialList = &RawResourceList->List[0].PartialResourceList;
+    case CmResourceTypeInterrupt:
+        Trace("MinimumVector=%08x MaximumVector=%08x AffinityPolicy=%s PriorityPolicy=%s TargettedProcessors = %p\n",
+              Descriptor->u.Interrupt.MinimumVector,
+              Descriptor->u.Interrupt.MaximumVector,
+              IrqDevicePolicyName(Descriptor->u.Interrupt.AffinityPolicy),
+              IrqPriorityName(Descriptor->u.Interrupt.PriorityPolicy),
+              (PVOID)Descriptor->u.Interrupt.TargetedProcessors);
+        break;
 
-    ASSERT3U(RawPartialList->Version, ==, 1);
-    ASSERT3U(RawPartialList->Revision, ==, 1);
+    default:
+        break;
+    }
+}
 
-    ASSERT3U(TranslatedResourceList->Count, ==, 1);
-    TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList;
+static VOID
+FdoDumpIoResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PIO_RESOURCE_LIST   List
+    )
+{
+    ULONG                   Index;
 
-    ASSERT3U(TranslatedPartialList->Version, ==, 1);
-    ASSERT3U(TranslatedPartialList->Revision, ==, 1);
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
 
-    for (Index = 0; Index < TranslatedPartialList->Count; Index++) {
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor;
-        PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor;
+        Trace("%s: %d\n",
+              __FdoGetName(Fdo),
+              Index);
 
-        RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index];
-        TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index];
+        FdoDumpIoResourceDescriptor(Fdo, Descriptor);
+    }
+}
 
-        Trace("%s: [%d] %02x:%s\n",
-              __FdoGetName(Fdo),
-              Index,
-              TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
-
-        switch (TranslatedPartialDescriptor->Type) {
-        case CmResourceTypeMemory:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Memory.Start.HighPart,
-                  RawPartialDescriptor->u.Memory.Start.LowPart,
-                  RawPartialDescriptor->u.Memory.Length);
-
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Start = %08x.%08x Length = %08x\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Memory.Start.HighPart,
-                  TranslatedPartialDescriptor->u.Memory.Start.LowPart,
-                  TranslatedPartialDescriptor->u.Memory.Length);
-
-            Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor;
+static NTSTATUS
+FdoFilterResourceRequirements(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
+    )
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST  Old;
+    ULONG                           Size;
+    PIO_RESOURCE_REQUIREMENTS_LIST  New;
+    IO_RESOURCE_DESCRIPTOR          Interrupt;
+    PIO_RESOURCE_LIST               List;
+    ULONG                           Index;
+    NTSTATUS                        status;
 
-            break;
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        case CmResourceTypeInterrupt:
-            Trace("RAW: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  RawPartialDescriptor->ShareDisposition,
-                  RawPartialDescriptor->Flags,
-                  RawPartialDescriptor->u.Interrupt.Level,
-                  RawPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)RawPartialDescriptor->u.Interrupt.Affinity);
+    if (!__FdoIsActive(Fdo))
+        goto not_active;
 
-            Trace("TRANSLATED: SharedDisposition=%02x Flags=%04x Level = %08x Vector = %08x Affinity = %p\n",
-                  TranslatedPartialDescriptor->ShareDisposition,
-                  TranslatedPartialDescriptor->Flags,
-                  TranslatedPartialDescriptor->u.Interrupt.Level,
-                  TranslatedPartialDescriptor->u.Interrupt.Vector,
-                  (PVOID)TranslatedPartialDescriptor->u.Interrupt.Affinity);
+    Old = (PIO_RESOURCE_REQUIREMENTS_LIST)Irp->IoStatus.Information;
+    ASSERT3U(Old->AlternativeLists, ==, 1);
 
-            Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor;
-            Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor;
+    Size = Old->ListSize +
+        (sizeof (IO_RESOURCE_DESCRIPTOR) * KeNumberProcessors);
 
-            break;
+    New = __AllocatePoolWithTag(PagedPool, Size, 'SUB');
 
-        default:
-            break;
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail2;
+
+    RtlCopyMemory(New, Old, Old->ListSize);
+    New->ListSize = Size;
+
+    List = &New->List[0];
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PIO_RESOURCE_DESCRIPTOR Descriptor = &List->Descriptors[Index];
+
+        if (Descriptor->Type != CmResourceTypeInterrupt)
+            continue;
+
+        Descriptor->Flags |= CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+        Descriptor->u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+        Descriptor->u.Interrupt.TargetedProcessors = (KAFFINITY)1;
+    }
+
+    RtlZeroMemory(&Interrupt, sizeof (IO_RESOURCE_DESCRIPTOR));
+    Interrupt.Option = 0; // Required
+    Interrupt.Type = CmResourceTypeInterrupt;
+    Interrupt.ShareDisposition = CmResourceShareDeviceExclusive;
+    Interrupt.Flags = CM_RESOURCE_INTERRUPT_LATCHED |
+                      CM_RESOURCE_INTERRUPT_MESSAGE |
+                      CM_RESOURCE_INTERRUPT_POLICY_INCLUDED;
+
+    Interrupt.u.Interrupt.MinimumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.MaximumVector = CM_RESOURCE_INTERRUPT_MESSAGE_TOKEN;
+    Interrupt.u.Interrupt.AffinityPolicy = IrqPolicySpecifiedProcessors;
+    Interrupt.u.Interrupt.PriorityPolicy = IrqPriorityUndefined;
+
+    for (Index = 0; Index < (ULONG)KeNumberProcessors; Index++) {
+        Interrupt.u.Interrupt.TargetedProcessors = (KAFFINITY)1 << Index;
+        List->Descriptors[List->Count++] = Interrupt;
+    }
+
+    FdoDumpIoResourceList(Fdo, List);
+
+    Irp->IoStatus.Information = (ULONG_PTR)New;
+    status = STATUS_SUCCESS;
+
+    ExFreePool(Old);
+
+not_active:
+    status = Irp->IoStatus.Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+static VOID
+FdoDumpCmPartialResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+    )
+{
+    Trace("%s: %s: %s SharedDisposition=%s Flags=%04x\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          ResourceDescriptorTypeName(Descriptor->Type),
+          ResourceDescriptorShareDispositionName(Descriptor->ShareDisposition),
+          Descriptor->Flags);
+    
+    switch (Descriptor->Type) {
+    case CmResourceTypeMemory:
+        Trace("%s: %s: Start = %08x.%08x Length = %08x\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Descriptor->u.Memory.Start.HighPart,
+              Descriptor->u.Memory.Start.LowPart,
+              Descriptor->u.Memory.Length);
+        break;
+
+    case CmResourceTypeInterrupt:
+        if (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+            if (Translated)
+                Trace("%s: TRANSLATED: Level = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Translated.Level,
+                      Descriptor->u.MessageInterrupt.Translated.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Translated.Affinity);
+            else
+                Trace("%s: RAW: MessageCount = %08x Vector = %08x Affinity = %p\n",
+                      __FdoGetName(Fdo),
+                      Descriptor->u.MessageInterrupt.Raw.MessageCount,
+                      Descriptor->u.MessageInterrupt.Raw.Vector,
+                      (PVOID)Descriptor->u.MessageInterrupt.Raw.Affinity);
+        } else {
+            Trace("%s: %s: Level = %08x Vector = %08x Affinity = %p\n",
+                  __FdoGetName(Fdo),
+                  (Translated) ? "TRANSLATED" : "RAW",
+                  Descriptor->u.Interrupt.Level,
+                  Descriptor->u.Interrupt.Vector,
+                  (PVOID)Descriptor->u.Interrupt.Affinity);
         }
+        break;
+    default:
+        break;
     }
+}
 
-    Trace("<====\n");
+static VOID
+FdoDumpCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  BOOLEAN                     Translated,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    Trace("%s: %s: Version = %d Revision = %d Count = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          List->Version,
+          List->Revision,
+          List->Count);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        Trace("%s: %s: %d\n",
+              __FdoGetName(Fdo),
+              (Translated) ? "TRANSLATED" : "RAW",
+              Index);
+
+        FdoDumpCmPartialResourceDescriptor(Fdo, Translated, Descriptor);
+    }
 }
 
-static FORCEINLINE PXENBUS_RESOURCE
-__FdoGetResource(
-    IN  PXENBUS_FDO             Fdo,
-    IN  XENBUS_RESOURCE_TYPE    Type
+static VOID
+FdoDumpCmFullResourceDescriptor(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  BOOLEAN                         Translated,
+    IN  PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor
     )
 {
-    ASSERT3U(Type, <, RESOURCE_COUNT);
+    Trace("%s: %s: InterfaceType = %s BusNumber = %d\n",
+          __FdoGetName(Fdo),
+          (Translated) ? "TRANSLATED" : "RAW",
+          InterfaceTypeName(Descriptor->InterfaceType),
+          Descriptor->BusNumber);
 
-    return &Fdo->Resource[Type];
+    FdoDumpCmPartialResourceList(Fdo, Translated, &Descriptor->PartialResourceList);
+}
+
+static VOID
+FdoDumpCmResourceList(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BOOLEAN             Translated,
+    IN  PCM_RESOURCE_LIST   List
+    )
+{
+    FdoDumpCmFullResourceDescriptor(Fdo, Translated, &List->List[0]);
+}
+
+_IRQL_requires_max_(HIGH_LEVEL)
+_IRQL_saves_
+_IRQL_raises_(HIGH_LEVEL)
+KIRQL
+FdoAcquireInterruptLock(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return KeAcquireInterruptSpinLock(Interrupt->InterruptObject);
+}
+
+_IRQL_requires_(HIGH_LEVEL)
+VOID
+FdoReleaseInterruptLock(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
+    IN  __drv_restoresIRQL KIRQL    Irql
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    KeReleaseInterruptSpinLock(Interrupt->InterruptObject, Irql);
 }
 
 static
 _Function_class_(KSERVICE_ROUTINE)
-_IRQL_requires_(HIGH_LEVEL)
-_IRQL_requires_same_
+__drv_requiresIRQL(HIGH_LEVEL)
 BOOLEAN
-FdoInterrupt(
+FdoInterruptCallback(
     IN  PKINTERRUPT             InterruptObject,
     IN  PVOID                   Context
     )
 {
-    PXENBUS_FDO                 Fdo = Context;
+    PXENBUS_INTERRUPT           Interrupt = Context;
 
-    UNREFERENCED_PARAMETER(InterruptObject);
+    if (Interrupt->Callback == NULL)
+        return FALSE;
 
-    ASSERT(Fdo != NULL);
-
-    return EvtchnInterrupt(__FdoGetEvtchnContext(Fdo));
+    return Interrupt->Callback(InterruptObject,
+                               Interrupt->Argument);
 }
 
 static NTSTATUS
 FdoConnectInterrupt(
-    IN  PXENBUS_FDO                 Fdo
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw,
+    IN  PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated,
+    OUT PXENBUS_INTERRUPT               *Interrupt
     )
 {
-    PXENBUS_RESOURCE                Interrupt;
-    IO_CONNECT_INTERRUPT_PARAMETERS Connect;
-    NTSTATUS                        status;
+    IO_CONNECT_INTERRUPT_PARAMETERS     Connect;
+    ULONG                               Cpu;
+    NTSTATUS                            status;
 
     Trace("====>\n");
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+    *Interrupt = __FdoAllocate(sizeof (XENBUS_INTERRUPT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Interrupt == NULL)
+        goto fail1;
+
+    (*Interrupt)->Fdo = Fdo;
+    (*Interrupt)->InterruptMode = (Translated->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
+                                  Latched :
+                                  LevelSensitive;
+
+    if (~Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
+        (*Interrupt)->Line = Raw->u.Interrupt.Vector;
 
     RtlZeroMemory(&Connect, sizeof (IO_CONNECT_INTERRUPT_PARAMETERS));
     Connect.Version = CONNECT_FULLY_SPECIFIED;
     Connect.FullySpecified.PhysicalDeviceObject = __FdoGetPhysicalDeviceObject(Fdo);
-    Connect.FullySpecified.SynchronizeIrql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.ShareVector = (BOOLEAN)(Interrupt->Translated.ShareDisposition == CmResourceShareShared);
-    Connect.FullySpecified.Vector = Interrupt->Translated.u.Interrupt.Vector;
-    Connect.FullySpecified.Irql = (KIRQL)Interrupt->Translated.u.Interrupt.Level;
-    Connect.FullySpecified.InterruptMode = (Interrupt->Translated.Flags & CM_RESOURCE_INTERRUPT_LATCHED) ?
-                                           Latched :
-                                           LevelSensitive;
-    Connect.FullySpecified.ProcessorEnableMask = Interrupt->Translated.u.Interrupt.Affinity;
-    Connect.FullySpecified.InterruptObject = &Fdo->InterruptObject;
-    Connect.FullySpecified.ServiceRoutine = FdoInterrupt;
-    Connect.FullySpecified.ServiceContext = Fdo;
+    Connect.FullySpecified.ShareVector = (BOOLEAN)(Translated->ShareDisposition == CmResourceShareShared);
+    Connect.FullySpecified.InterruptMode = (*Interrupt)->InterruptMode;
+    Connect.FullySpecified.InterruptObject = &(*Interrupt)->InterruptObject;
+    Connect.FullySpecified.ServiceRoutine = FdoInterruptCallback;
+    Connect.FullySpecified.ServiceContext = *Interrupt;
+
+    if (Translated->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
+        Connect.FullySpecified.Vector = Translated->u.MessageInterrupt.Translated.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.MessageInterrupt.Translated.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.MessageInterrupt.Translated.Affinity;
+    } else {
+        Connect.FullySpecified.Vector = Translated->u.Interrupt.Vector;
+        Connect.FullySpecified.Irql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.SynchronizeIrql = (KIRQL)Translated->u.Interrupt.Level;
+        Connect.FullySpecified.ProcessorEnableMask = Translated->u.Interrupt.Affinity;
+    }
 
     status = IoConnectInterruptEx(&Connect);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
+
+    (*Interrupt)->Vector = (UCHAR)Connect.FullySpecified.Vector;
+
+#if defined(__i386__)
+    (VOID)_BitScanReverse(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#elif defined(__x86_64__)
+    (VOID)_BitScanReverse64(&Cpu, Connect.FullySpecified.ProcessorEnableMask);
+#else
+#error 'Unrecognised architecture'
+#endif
+
+    (*Interrupt)->Cpu = Cpu;
+
+    Info("%p: %s %s CPU %u VECTOR %02x\n",
+         (*Interrupt)->InterruptObject,
+         ResourceDescriptorShareDispositionName(Translated->ShareDisposition),
+         InterruptModeName((*Interrupt)->InterruptMode),
+         (*Interrupt)->Cpu,
+         (*Interrupt)->Vector);
 
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    __FdoFree(*Interrupt);
+    *Interrupt = NULL;
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-_IRQL_requires_max_(HIGH_LEVEL)
-_IRQL_saves_
-_IRQL_raises_(HIGH_LEVEL)
-KIRQL
-FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+static VOID
+FdoDisconnectInterrupt(
+    IN  PXENBUS_FDO                     Fdo,
+    IN  PXENBUS_INTERRUPT               Interrupt
     )
 {
-    PKINTERRUPT     InterruptObject = Fdo->InterruptObject;
+    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    Trace("====>\n");
+
+    Info("%p: CPU %u VECTOR %02x\n",
+         Interrupt->InterruptObject,
+         Interrupt->Cpu,
+         Interrupt->Vector);
+
+    Interrupt->Cpu = 0;
+    Interrupt->Vector = 0;
+
+    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
+    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
+    Disconnect.ConnectionContext.InterruptObject = Interrupt->InterruptObject;
 
-    return KeAcquireInterruptSpinLock(InterruptObject);
+    IoDisconnectInterruptEx(&Disconnect);
+
+    Interrupt->Line = 0;
+    Interrupt->InterruptObject = NULL;
+    Interrupt->InterruptMode = 0;
+    Interrupt->Fdo = NULL;
+
+    ASSERT(IsZeroMemory(Interrupt, sizeof (XENBUS_INTERRUPT)));
+    __FdoFree(Interrupt);
+
+    Trace("<====\n");
 }
-                      
-_IRQL_requires_(HIGH_LEVEL)
-VOID
-FdoReleaseInterruptLock(
-    IN  PXENBUS_FDO                 Fdo,
-    IN  __drv_restoresIRQL KIRQL    Irql
+
+static NTSTATUS
+FdoCreateInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                     InterruptObject = Fdo->InterruptObject;
+    ULONG               Index;
+    PXENBUS_INTERRUPT   Interrupt;
+    NTSTATUS            status;
+
+    InitializeListHead(&Fdo->List);
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Raw = &Fdo->RawResourceList->PartialDescriptors[Index];
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
+
+        if (Translated->Type != CmResourceTypeInterrupt)
+            continue;
+
+        status = FdoConnectInterrupt(Fdo, Raw, Translated, &Interrupt);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        InsertTailList(&Fdo->List, &Interrupt->ListEntry);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY ListEntry;
+
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 
-    KeReleaseInterruptSpinLock(InterruptObject, Irql);
+    return status;
 }
 
-ULONG
+NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    )
+{
+    PLIST_ENTRY             ListEntry;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    for (ListEntry = Fdo->List.Flink;
+         ListEntry != &Fdo->List;
+         ListEntry = ListEntry->Flink) {
+        *Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
+
+        if ((*Interrupt)->Callback == NULL &&
+            (*Interrupt)->InterruptMode == InterruptMode &&
+            (*Interrupt)->Cpu == Cpu)
+            goto found;
+    }
+
+    *Interrupt = NULL;
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
+
+found:
+    Irql = FdoAcquireInterruptLock(Fdo, *Interrupt);
+    (*Interrupt)->Callback = Callback;
+    (*Interrupt)->Argument = Argument;
+    FdoReleaseInterruptLock(Fdo, *Interrupt, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+UCHAR
 FdoGetInterruptVector(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Vector;
+}
+
+ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     )
 {
-    PXENBUS_RESOURCE    Interrupt;
+    UNREFERENCED_PARAMETER(Fdo);
+
+    return Interrupt->Line;
+}
 
-    Interrupt = __FdoGetResource(Fdo, INTERRUPT_RESOURCE);
+VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    )
+{
+    KIRQL                   Irql;
 
-    return Interrupt->Raw.u.Interrupt.Vector;
+    Irql = FdoAcquireInterruptLock(Fdo, Interrupt);
+    Interrupt->Callback = NULL;
+    Interrupt->Argument = NULL;
+    FdoReleaseInterruptLock(Fdo, Interrupt, Irql);
 }
 
 static VOID
-FdoDisconnectInterrupt(
-    IN  PXENBUS_FDO                     Fdo
+FdoDestroyInterrupt(
+    IN  PXENBUS_FDO     Fdo
     )
 {
-    PKINTERRUPT                         InterruptObject;
-    IO_DISCONNECT_INTERRUPT_PARAMETERS  Disconnect;
+    while (!IsListEmpty(&Fdo->List)) {
+        PLIST_ENTRY         ListEntry;
+        PXENBUS_INTERRUPT   Interrupt;
 
-    Trace("====>\n");
+        ListEntry = RemoveHeadList(&Fdo->List);
+        ASSERT(ListEntry != &Fdo->List);
 
-    InterruptObject = Fdo->InterruptObject;
-    Fdo->InterruptObject = NULL;
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
 
-    RtlZeroMemory(&Disconnect, sizeof (IO_DISCONNECT_INTERRUPT_PARAMETERS));
-    Disconnect.Version = CONNECT_FULLY_SPECIFIED;
-    Disconnect.ConnectionContext.InterruptObject = InterruptObject;
+        Interrupt = CONTAINING_RECORD(ListEntry, XENBUS_INTERRUPT, ListEntry);
 
-    IoDisconnectInterruptEx(&Disconnect);
+#pragma warning(push)
+#pragma warning(disable:4054)   // 'type cast' : from function pointer to data pointer
+        ASSERT3P(Interrupt->Callback, ==, NULL);
+#pragma warning(pop)
 
-    Trace("<====\n");
+        ASSERT3P(Interrupt->Argument, ==, NULL);
+
+        FdoDisconnectInterrupt(Fdo, Interrupt);
+    }
+
+    RtlZeroMemory(&Fdo->List, sizeof (LIST_ENTRY));
 }
 
 static
@@ -1800,39 +2190,61 @@ FdoSuspendCallbackLate(
 
 static NTSTATUS
 FdoCreateIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    PHYSICAL_ADDRESS                End;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    status = STATUS_OBJECT_NAME_NOT_FOUND;
+    goto fail1;
 
+found:
     status = XENBUS_RANGE_SET(Create,
                               &Fdo->RangeSetInterface,
                               "io_space",
                               &Fdo->RangeSet);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     status = XENBUS_RANGE_SET(Put,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
+
+    End.QuadPart = Translated->u.Memory.Start.QuadPart + Translated->u.Memory.Length - 1;
+
+    Info("%08x.%08x - %08x.%08x\n",
+         Translated->u.Memory.Start.HighPart,
+         Translated->u.Memory.Start.LowPart,
+         End.HighPart,
+         End.LowPart);
 
     return STATUS_SUCCESS;
 
-fail2:
-    Error("fail2\n");
+fail3:
+    Error("fail3\n");
 
     XENBUS_RANGE_SET(Destroy,
                      &Fdo->RangeSetInterface,
                      Fdo->RangeSet);
     Fdo->RangeSet = NULL;
 
+fail2:
+    Error("fail2\n");
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -1890,19 +2302,29 @@ FdoFreeIoSpace(
 
 static VOID
 FdoDestroyIoSpace(
-    IN  PXENBUS_FDO     Fdo
+    IN  PXENBUS_FDO                 Fdo
     )
 {
-    PXENBUS_RESOURCE    Memory;
-    NTSTATUS            status;
+    ULONG                           Index;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR Translated;
+    NTSTATUS                        status;
+
+    for (Index = 0; Index < Fdo->TranslatedResourceList->Count; Index++) {
+        Translated = &Fdo->TranslatedResourceList->PartialDescriptors[Index];
 
-    Memory = __FdoGetResource(Fdo, MEMORY_RESOURCE);
+        if (Translated->Type == CmResourceTypeMemory)
+            goto found;
+    }
+
+    ASSERT(FALSE);
+    return;
 
+found:
     status = XENBUS_RANGE_SET(Get,
                               &Fdo->RangeSetInterface,
                               Fdo->RangeSet,
-                              Memory->Translated.u.Memory.Start.QuadPart,
-                              Memory->Translated.u.Memory.Length);
+                              Translated->u.Memory.Start.QuadPart,
+                              Translated->u.Memory.Length);
     ASSERT(NT_SUCCESS(status));
 
     XENBUS_RANGE_SET(Destroy,
@@ -2214,39 +2636,111 @@ FdoS3ToS4(
     Trace("<====\n");
 }
 
+static VOID
+FdoFilterCmPartialResourceList(
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PCM_PARTIAL_RESOURCE_LIST   List
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Fdo);
+
+    for (Index = 0; Index < List->Count; Index++) {
+        PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &List->PartialDescriptors[Index];
+
+        //
+        // These are additional resources that XENBUS requested, so they must
+        // be filtered out before the underlying PCI bus driver sees them. Happily
+        // it appears that swapping the type to DevicePrivate causes PCI.SYS to ignore
+        // them.
+        //
+        if (Descriptor->Type == CmResourceTypeInterrupt &&
+            (Descriptor->Flags & CM_RESOURCE_INTERRUPT_MESSAGE))
+            Descriptor->Type = CmResourceTypeDevicePrivate;
+    }
+}
+
 static NTSTATUS
 FdoStartDevice(
-    IN  PXENBUS_FDO     Fdo,
-    IN  PIRP            Irp
+    IN  PXENBUS_FDO                 Fdo,
+    IN  PIRP                        Irp
     )
 {
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
+    PIO_STACK_LOCATION              StackLocation;
+    PCM_RESOURCE_LIST               ResourceList;
+    PCM_FULL_RESOURCE_DESCRIPTOR    Descriptor;
+    ULONG                           Size;
+    NTSTATUS                        status;
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
-    status = FdoForwardIrpSynchronously(Fdo, Irp);
-    if (!NT_SUCCESS(status))
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    // Raw
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResources;
+    FdoDumpCmResourceList(Fdo, FALSE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->RawResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->RawResourceList == NULL)
         goto fail1;
 
-    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    RtlCopyMemory(Fdo->RawResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
+
+    // Translated
+
+    ResourceList = StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
+    FdoDumpCmResourceList(Fdo, TRUE, ResourceList);
+
+    ASSERT3U(ResourceList->Count, ==, 1);
+    Descriptor = &ResourceList->List[0];
+
+    ASSERT3U(Descriptor->InterfaceType, ==, PCIBus);
+    ASSERT3U(Descriptor->BusNumber, ==, 0);
+
+    Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+           (Descriptor->PartialResourceList.Count) * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+    Fdo->TranslatedResourceList = __FdoAllocate(Size);
+
+    status = STATUS_NO_MEMORY;
+    if (Fdo->TranslatedResourceList == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Fdo->TranslatedResourceList, &Descriptor->PartialResourceList, Size);
+
+    FdoFilterCmPartialResourceList(Fdo, &Descriptor->PartialResourceList);
 
-    FdoParseResources(Fdo,
-                      StackLocation->Parameters.StartDevice.AllocatedResources,
-                      StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated);
+    status = FdoForwardIrpSynchronously(Fdo, Irp);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
     if (!__FdoIsActive(Fdo))
         goto not_active;
 
-    status = FdoConnectInterrupt(Fdo);
+    status = FdoCreateInterrupt(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
     KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE);
 
     status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail5;
 
     InitializeMutex(&Fdo->BalloonSuspendMutex);
 
@@ -2254,20 +2748,20 @@ FdoStartDevice(
 
     status = ThreadCreate(FdoSuspend, Fdo, &Fdo->SuspendThread);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail6;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         KeInitializeEvent(&Fdo->BalloonEvent, NotificationEvent, FALSE);
 
         status = ThreadCreate(FdoBalloon, Fdo, &Fdo->BalloonThread);
         if (!NT_SUCCESS(status))
-            goto fail5;
+            goto fail7;
     }
 
 not_active:
     status = FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail6;
+        goto fail8;
 
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         BOOLEAN Warned;
@@ -2306,11 +2800,11 @@ not_active:
 
     return status;
 
-fail6:
-    Error("fail6\n");
+fail8:
+    Error("fail8\n");
 
     if (!__FdoIsActive(Fdo))
-        goto fail2;
+        goto fail4;
     
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         ThreadAlert(Fdo->BalloonThread);
@@ -2318,8 +2812,8 @@ fail6:
         Fdo->BalloonThread = NULL;
     }
 
-fail5:
-    Error("fail5\n");
+fail7:
+    Error("fail7\n");
 
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         RtlZeroMemory(&Fdo->BalloonEvent, sizeof (KEVENT));
@@ -2328,8 +2822,8 @@ fail5:
     ThreadJoin(Fdo->SuspendThread);
     Fdo->SuspendThread = NULL;
 
-fail4:
-    Error("fail4\n");
+fail6:
+    Error("fail6\n");
 
     RtlZeroMemory(&Fdo->SuspendEvent, sizeof (KEVENT));
 
@@ -2339,17 +2833,27 @@ fail4:
     ThreadJoin(Fdo->ScanThread);
     Fdo->ScanThread = NULL;
 
-fail3:
-    Error("fail3\n");
+fail5:
+    Error("fail5\n");
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
+
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
 
 fail2:
     Error("fail2\n");
 
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -2445,10 +2949,14 @@ FdoStopDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
     __FdoSetDevicePnpState(Fdo, Stopped);
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2554,6 +3062,9 @@ FdoRemoveDevice(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+        goto done;
+
     if (__FdoIsActive(Fdo)) {
         Trace("waiting for scan thread...\n");
 
@@ -2621,11 +3132,16 @@ FdoRemoveDevice(
 
     RtlZeroMemory(&Fdo->ScanEvent, sizeof (KEVENT));
 
-    FdoDisconnectInterrupt(Fdo);
+    FdoDestroyInterrupt(Fdo);
 
 not_active:
-    RtlZeroMemory(&Fdo->Resource, sizeof (XENBUS_RESOURCE) * RESOURCE_COUNT);
+    __FdoFree(Fdo->TranslatedResourceList);
+    Fdo->TranslatedResourceList = NULL;
+
+    __FdoFree(Fdo->RawResourceList);
+    Fdo->RawResourceList = NULL;
 
+done:
     __FdoSetDevicePnpState(Fdo, Deleted);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -2937,6 +3453,10 @@ FdoDispatchPnp(
           PnpMinorFunctionName(MinorFunction)); 
 
     switch (StackLocation->MinorFunction) {
+    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+        status = FdoFilterResourceRequirements(Fdo, Irp);
+        break;
+
     case IRP_MN_START_DEVICE:
         status = FdoStartDevice(Fdo, Irp);
         break;
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index fdb6f79..4916be4 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -38,6 +38,8 @@
 #include "driver.h"
 #include "types.h"
 
+typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, *PXENBUS_INTERRUPT;
+
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject,
@@ -140,11 +142,6 @@ FdoFreeIoSpace(
     IN  ULONG               Size
     );
 
-extern ULONG
-FdoGetInterruptVector(
-    IN  PXENBUS_FDO Fdo
-    );
-
 // Disable erroneous SAL warnings around use of interrupt locks
 #pragma warning(disable:28230)
 #pragma warning(disable:28285)
@@ -155,7 +152,8 @@ _IRQL_saves_
 _IRQL_raises_(HIGH_LEVEL)
 KIRQL
 FdoAcquireInterruptLock(
-    IN  PXENBUS_FDO Fdo
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
     );
 
 extern
@@ -163,9 +161,38 @@ _IRQL_requires_(HIGH_LEVEL)
 VOID
 FdoReleaseInterruptLock(
     IN  PXENBUS_FDO                 Fdo,
+    IN  PXENBUS_INTERRUPT           Interrupt,
     IN  __drv_restoresIRQL KIRQL    Irql
     );
 
+extern NTSTATUS
+FdoAllocateInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  KINTERRUPT_MODE     InterruptMode,
+    IN  ULONG               Cpu,
+    IN  KSERVICE_ROUTINE    Callback,
+    IN  PVOID               Argument OPTIONAL,
+    OUT PXENBUS_INTERRUPT   *Interrupt
+    );
+
+extern UCHAR
+FdoGetInterruptVector(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern ULONG
+FdoGetInterruptLine(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
+extern VOID
+FdoFreeInterrupt(
+    IN  PXENBUS_FDO         Fdo,
+    IN  PXENBUS_INTERRUPT   Interrupt
+    );
+
 #include "suspend.h"
 
 extern PXENBUS_SUSPEND_CONTEXT
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 650e84d..ad0d4de 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -682,7 +682,7 @@ PdoParseResources(
               __PdoGetName(Pdo),
               Index,
               TranslatedPartialDescriptor->Type,
-              PartialResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
+              ResourceDescriptorTypeName(TranslatedPartialDescriptor->Type));
 
         switch (TranslatedPartialDescriptor->Type) {
         case CmResourceTypeMemory:
-- 
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 Nov 07 16:53:03 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:03 +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 1XmmmV-00013S-QJ; Fri, 07 Nov 2014 16:53:03 +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 1XmmmU-00013M-Uo
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:03 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	B5/F7-09842-EE8FC545; Fri, 07 Nov 2014 16:53:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13867 invoked from network); 7 Nov 2014 16:53:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209699"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-VN;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:45 +0000
Message-ID: <1415379165-27748-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
References: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Ben Chalmers <ben.chalmers@citrix.com>,
	Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 3/3] Avoid incorrecly extending checksum
	accumulator
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

It was noticed that checksums were occasionally being incorrectly verified.
The reason for this turned out to be that the value passed to
ChecksumVerify as a USHORT was being extended to ULONG prior to being
inverted, thus leaving bits 16-31 set and thus an overflow from the lower
bits was not being correctly folded.

Signed-off-by: Ben Chalmers <ben.chalmers@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/checksum.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/xenvif/checksum.c b/src/xenvif/checksum.c
index 5f9c800..19a9616 100644
--- a/src/xenvif/checksum.c
+++ b/src/xenvif/checksum.c
@@ -87,6 +87,12 @@ ChecksumVerify(
 {
     ULONG       Accumulator = ~Calculated;
 
+    // 
+    // MSVC extends Calculated to ULONG prior to inverting it
+    // so we must explicitly zero out the upper half
+    //
+    Accumulator &= 0xFFFF;
+
     // See RFC 1624, section 5
     __AccumulateChecksum(&Accumulator, (PUCHAR)&Embedded, sizeof (USHORT));
 
-- 
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 Nov 07 16:53:03 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:03 +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 1XmmmV-00013S-QJ; Fri, 07 Nov 2014 16:53:03 +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 1XmmmU-00013M-Uo
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:03 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	B5/F7-09842-EE8FC545; Fri, 07 Nov 2014 16:53:02 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13867 invoked from network); 7 Nov 2014 16:53:01 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:01 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209699"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-VN;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:45 +0000
Message-ID: <1415379165-27748-3-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
References: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Ben Chalmers <ben.chalmers@citrix.com>,
	Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 3/3] Avoid incorrecly extending checksum
	accumulator
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

It was noticed that checksums were occasionally being incorrectly verified.
The reason for this turned out to be that the value passed to
ChecksumVerify as a USHORT was being extended to ULONG prior to being
inverted, thus leaving bits 16-31 set and thus an overflow from the lower
bits was not being correctly folded.

Signed-off-by: Ben Chalmers <ben.chalmers@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/checksum.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/xenvif/checksum.c b/src/xenvif/checksum.c
index 5f9c800..19a9616 100644
--- a/src/xenvif/checksum.c
+++ b/src/xenvif/checksum.c
@@ -87,6 +87,12 @@ ChecksumVerify(
 {
     ULONG       Accumulator = ~Calculated;
 
+    // 
+    // MSVC extends Calculated to ULONG prior to inverting it
+    // so we must explicitly zero out the upper half
+    //
+    Accumulator &= 0xFFFF;
+
     // See RFC 1624, section 5
     __AccumulateChecksum(&Accumulator, (PUCHAR)&Embedded, sizeof (USHORT));
 
-- 
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 Nov 07 16:53:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:04 +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 1XmmmW-00013z-RF; Fri, 07 Nov 2014 16:53:04 +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 1XmmmV-00013R-PQ
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:03 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	0C/F7-09842-FE8FC545; Fri, 07 Nov 2014 16:53:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14019 invoked from network); 7 Nov 2014 16:53:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209695"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-Rp;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:43 +0000
Message-ID: <1415379165-27748-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/3] Fix a stupid if-then-else
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/xenvif/receiver.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 88ee07c..c7510ce 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -467,6 +467,7 @@ ReceiverRingProcessChecksum(
     }
 
     flags = (uint16_t)(ULONG_PTR)Packet->Cookie;
+    ASSERT3U(Packet->Flags.Value, ==, 0);
 
     if (Info->IpHeader.Length == 0)
         return;
@@ -537,17 +538,10 @@ ReceiverRingProcessChecksum(
                 Calculated = ChecksumPseudoHeader(StartVa, Info);
                 Calculated = ChecksumTcpPacket(StartVa, Info, Calculated, &Payload);
 
-                if (IpHeader->Version == 4) {
-                    if (ChecksumVerify(Calculated, Embedded))
-                        Packet->Flags.TcpChecksumSucceeded = 1;
-                    else
-                        Packet->Flags.TcpChecksumFailed = 1;
-                } else {
-                    if (ChecksumVerify(Calculated, Embedded))
-                        Packet->Flags.TcpChecksumSucceeded = 1;
-                    else
-                        Packet->Flags.TcpChecksumFailed = 1;
-                }
+                if (ChecksumVerify(Calculated, Embedded))
+                    Packet->Flags.TcpChecksumSucceeded = 1;
+                else
+                    Packet->Flags.TcpChecksumFailed = 1;
             }
         }
         
-- 
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 Nov 07 16:53:04 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:04 +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 1XmmmW-00013z-RF; Fri, 07 Nov 2014 16:53:04 +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 1XmmmV-00013R-PQ
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:03 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	0C/F7-09842-FE8FC545; Fri, 07 Nov 2014 16:53:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!2
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14019 invoked from network); 7 Nov 2014 16:53:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209695"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-Rp;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:43 +0000
Message-ID: <1415379165-27748-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/3] Fix a stupid if-then-else
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/xenvif/receiver.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 88ee07c..c7510ce 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -467,6 +467,7 @@ ReceiverRingProcessChecksum(
     }
 
     flags = (uint16_t)(ULONG_PTR)Packet->Cookie;
+    ASSERT3U(Packet->Flags.Value, ==, 0);
 
     if (Info->IpHeader.Length == 0)
         return;
@@ -537,17 +538,10 @@ ReceiverRingProcessChecksum(
                 Calculated = ChecksumPseudoHeader(StartVa, Info);
                 Calculated = ChecksumTcpPacket(StartVa, Info, Calculated, &Payload);
 
-                if (IpHeader->Version == 4) {
-                    if (ChecksumVerify(Calculated, Embedded))
-                        Packet->Flags.TcpChecksumSucceeded = 1;
-                    else
-                        Packet->Flags.TcpChecksumFailed = 1;
-                } else {
-                    if (ChecksumVerify(Calculated, Embedded))
-                        Packet->Flags.TcpChecksumSucceeded = 1;
-                    else
-                        Packet->Flags.TcpChecksumFailed = 1;
-                }
+                if (ChecksumVerify(Calculated, Embedded))
+                    Packet->Flags.TcpChecksumSucceeded = 1;
+                else
+                    Packet->Flags.TcpChecksumFailed = 1;
             }
         }
         
-- 
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 Nov 07 16:53:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:05 +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 1XmmmX-00014M-S9; Fri, 07 Nov 2014 16:53:05 +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 1XmmmW-00013q-Jy
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:04 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	48/19-09936-0F8FC545; Fri, 07 Nov 2014 16:53:04 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14164 invoked from network); 7 Nov 2014 16:53:03 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209704"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-T8;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:44 +0000
Message-ID: <1415379165-27748-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
References: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Ben Chalmers <ben.chalmers@citrix.com>,
	Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/3] Set correct payload offset when
	processing checksums
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 receiver code was not accounting for a non-zero packet offset when
processing checksums. This lead to inbound packets being corrupted.

Signed-off-by: Ben Chalmers <ben.chalmers@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/receiver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index c7510ce..c9e865e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -455,7 +455,7 @@ ReceiverRingProcessChecksum(
     Info = Packet->Info;
 
     Payload.Mdl = &Packet->Mdl;
-    Payload.Offset = Info->Length;
+    Payload.Offset = Packet->Offset + Info->Length;
     Payload.Length = Packet->Length - Info->Length;
 
     ASSERT3U(Payload.Offset, <=, Payload.Mdl->ByteCount);
-- 
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 Nov 07 16:53:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 16:53:05 +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 1XmmmX-00014M-S9; Fri, 07 Nov 2014 16:53:05 +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 1XmmmW-00013q-Jy
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 16:53:04 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	48/19-09936-0F8FC545; Fri, 07 Nov 2014 16:53:04 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415379179!12284787!3
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14164 invoked from network); 7 Nov 2014 16:53:03 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 16:53:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189209704"
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.181.6;
	Fri, 7 Nov 2014 11:52:55 -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 1XmmmM-0007sf-T8;
	Fri, 07 Nov 2014 16:52:54 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 16:52:44 +0000
Message-ID: <1415379165-27748-2-git-send-email-paul.durrant@citrix.com>
X-Mailer: git-send-email 2.1.1
In-Reply-To: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
References: <1415379165-27748-1-git-send-email-paul.durrant@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: Ben Chalmers <ben.chalmers@citrix.com>,
	Paul Durrant <paul.durrant@citrix.com>
Subject: [win-pv-devel] [PATCH 2/3] Set correct payload offset when
	processing checksums
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 receiver code was not accounting for a non-zero packet offset when
processing checksums. This lead to inbound packets being corrupted.

Signed-off-by: Ben Chalmers <ben.chalmers@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenvif/receiver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index c7510ce..c9e865e 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -455,7 +455,7 @@ ReceiverRingProcessChecksum(
     Info = Packet->Info;
 
     Payload.Mdl = &Packet->Mdl;
-    Payload.Offset = Info->Length;
+    Payload.Offset = Packet->Offset + Info->Length;
     Payload.Length = Packet->Length - Info->Length;
 
     ASSERT3U(Payload.Offset, <=, Payload.Mdl->ByteCount);
-- 
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 Nov 07 17:21:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 17:21: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 1XmnE8-0001EQ-Ve; Fri, 07 Nov 2014 17:21:36 +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 1XmnE7-0001EL-G8
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 17:21:35 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	49/4A-27785-E9FFC545; Fri, 07 Nov 2014 17:21:34 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1415380892!12124045!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7403 invoked from network); 7 Nov 2014 17:21:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 17:21:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189221363"
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.181.6;
	Fri, 7 Nov 2014 12:21:31 -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 1XmnE3-0008Rn-0E;
	Fri, 07 Nov 2014 17:21:31 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 17:21:21 +0000
Message-ID: <1415380881-22832-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] Update to latest XENBUS interfaces
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>
---
 include/cache_interface.h     |  1 +
 include/debug_interface.h     |  1 +
 include/emulated_interface.h  |  1 +
 include/evtchn_interface.h    | 42 +++++++++++++++++++++++++++++++++++++-----
 include/gnttab_interface.h    |  1 +
 include/range_set_interface.h |  1 +
 include/store_interface.h     |  1 +
 include/suspend_interface.h   |  1 +
 src/xenvif.inf                |  6 +++---
 9 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/include/cache_interface.h b/include/cache_interface.h
index 12599ef..dae3ac6 100644
--- a/include/cache_interface.h
+++ b/include/cache_interface.h
@@ -205,6 +205,7 @@ DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE,
 
 /*! \struct _XENBUS_CACHE_INTERFACE_V1
     \brief CACHE interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_CACHE_INTERFACE_V1 {
     INTERFACE               Interface;
diff --git a/include/debug_interface.h b/include/debug_interface.h
index 0b4f763..cc71db0 100644
--- a/include/debug_interface.h
+++ b/include/debug_interface.h
@@ -146,6 +146,7 @@ DEFINE_GUID(GUID_XENBUS_DEBUG_INTERFACE,
 
 /*! \struct _XENBUS_DEBUG_INTERFACE_V1
     \brief DEBUG interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_DEBUG_INTERFACE_V1 {
     INTERFACE               Interface;
diff --git a/include/emulated_interface.h b/include/emulated_interface.h
index 0019c1b..85ed2b8 100644
--- a/include/emulated_interface.h
+++ b/include/emulated_interface.h
@@ -101,6 +101,7 @@ DEFINE_GUID(GUID_XENFILT_EMULATED_INTERFACE,
 
 /*! \struct _XENFILT_EMULATED_INTERFACE_V1
     \brief EMULATED interface version 1
+    \ingroup interfaces
 */
 struct _XENFILT_EMULATED_INTERFACE_V1 {
     INTERFACE                           Interface;
diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 207f341..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,19 +112,33 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
     \param Interface The interface header
     \param Channel The channel handle
-    \param Locked Set to TRUE if this method is invoked in context of the channel callback
+    \param InCallback Set to TRUE if this method is invoked in context of the channel callback
     \return TRUE if there was an event pending at the point of unmask, FALSE otherwise
 */
 typedef BOOLEAN
 (*XENBUS_EVTCHN_UNMASK)(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     );
 
 /*! \typedef XENBUS_EVTCHN_SEND
@@ -182,6 +196,7 @@ DEFINE_GUID(GUID_XENBUS_EVTCHN_INTERFACE,
 
 /*! \struct _XENBUS_EVTCHN_INTERFACE_V1
     \brief EVTCHN interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_EVTCHN_INTERFACE_V1 {
     INTERFACE               Interface;
@@ -190,12 +205,29 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
     XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
     XENBUS_EVTCHN_SEND      EvtchnSend;
-    XENBUS_EVTCHN_SEND      EvtchnTrigger;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
     XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -206,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h
index c9d005f..d29440a 100644
--- a/include/gnttab_interface.h
+++ b/include/gnttab_interface.h
@@ -169,6 +169,7 @@ DEFINE_GUID(GUID_XENBUS_GNTTAB_INTERFACE,
 
 /*! \struct _XENBUS_GNTTAB_INTERFACE_V1
     \brief GNTTAB interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_GNTTAB_INTERFACE_V1 {
     INTERFACE                           Interface;
diff --git a/include/range_set_interface.h b/include/range_set_interface.h
index b05ab3c..5ab416d 100644
--- a/include/range_set_interface.h
+++ b/include/range_set_interface.h
@@ -149,6 +149,7 @@ DEFINE_GUID(GUID_XENBUS_RANGE_SET_INTERFACE,
 
 /*! \struct _XENBUS_RANGE_SET_INTERFACE_V1
     \brief RANGE_SET interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_RANGE_SET_INTERFACE_V1 {
     INTERFACE                   Interface;
diff --git a/include/store_interface.h b/include/store_interface.h
index f052b8f..5bcbba3 100644
--- a/include/store_interface.h
+++ b/include/store_interface.h
@@ -269,6 +269,7 @@ struct _XENBUS_STORE_INTERFACE_V1 {
 
 /*! \struct _XENBUS_STORE_INTERFACE_V1
     \brief STORE interface version 1
+    \ingroup interfaces
 */
 typedef struct _XENBUS_STORE_INTERFACE_V1 XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
 
diff --git a/include/suspend_interface.h b/include/suspend_interface.h
index 1a39141..df1b4b0 100644
--- a/include/suspend_interface.h
+++ b/include/suspend_interface.h
@@ -148,6 +148,7 @@ DEFINE_GUID(GUID_XENBUS_SUSPEND_INTERFACE,
 
 /*! \struct _XENBUS_SUSPEND_INTERFACE_V1
     \brief SUSPEND interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_SUSPEND_INTERFACE_V1 {
     INTERFACE                   Interface;
diff --git a/src/xenvif.inf b/src/xenvif.inf
index beaa8f4..74231ce 100644
--- a/src/xenvif.inf
+++ b/src/xenvif.inf
@@ -58,9 +58,9 @@ xenvif_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll
 ; DisplayName		Section		DeviceID
 ; -----------		-------		--------
 
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XSC000&DEV_VIF&REV_00000001
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0001&DEV_VIF&REV_00000001
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0002&DEV_VIF&REV_00000001
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XSC000&DEV_VIF&REV_00000004
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0001&DEV_VIF&REV_00000004
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0002&DEV_VIF&REV_00000004
 
 [XenVif_Inst] 
 CopyFiles=XenVif_Copyfiles
-- 
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 Nov 07 17:21:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 07 Nov 2014 17:21: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 1XmnE8-0001EQ-Ve; Fri, 07 Nov 2014 17:21:36 +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 1XmnE7-0001EL-G8
	for win-pv-devel@lists.xenproject.org; Fri, 07 Nov 2014 17:21:35 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	49/4A-27785-E9FFC545; Fri, 07 Nov 2014 17:21:34 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1415380892!12124045!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7403 invoked from network); 7 Nov 2014 17:21:34 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	7 Nov 2014 17:21:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,333,1413244800"; d="scan'208";a="189221363"
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.181.6;
	Fri, 7 Nov 2014 12:21:31 -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 1XmnE3-0008Rn-0E;
	Fri, 07 Nov 2014 17:21:31 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 7 Nov 2014 17:21:21 +0000
Message-ID: <1415380881-22832-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] Update to latest XENBUS interfaces
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>
---
 include/cache_interface.h     |  1 +
 include/debug_interface.h     |  1 +
 include/emulated_interface.h  |  1 +
 include/evtchn_interface.h    | 42 +++++++++++++++++++++++++++++++++++++-----
 include/gnttab_interface.h    |  1 +
 include/range_set_interface.h |  1 +
 include/store_interface.h     |  1 +
 include/suspend_interface.h   |  1 +
 src/xenvif.inf                |  6 +++---
 9 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/include/cache_interface.h b/include/cache_interface.h
index 12599ef..dae3ac6 100644
--- a/include/cache_interface.h
+++ b/include/cache_interface.h
@@ -205,6 +205,7 @@ DEFINE_GUID(GUID_XENBUS_CACHE_INTERFACE,
 
 /*! \struct _XENBUS_CACHE_INTERFACE_V1
     \brief CACHE interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_CACHE_INTERFACE_V1 {
     INTERFACE               Interface;
diff --git a/include/debug_interface.h b/include/debug_interface.h
index 0b4f763..cc71db0 100644
--- a/include/debug_interface.h
+++ b/include/debug_interface.h
@@ -146,6 +146,7 @@ DEFINE_GUID(GUID_XENBUS_DEBUG_INTERFACE,
 
 /*! \struct _XENBUS_DEBUG_INTERFACE_V1
     \brief DEBUG interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_DEBUG_INTERFACE_V1 {
     INTERFACE               Interface;
diff --git a/include/emulated_interface.h b/include/emulated_interface.h
index 0019c1b..85ed2b8 100644
--- a/include/emulated_interface.h
+++ b/include/emulated_interface.h
@@ -101,6 +101,7 @@ DEFINE_GUID(GUID_XENFILT_EMULATED_INTERFACE,
 
 /*! \struct _XENFILT_EMULATED_INTERFACE_V1
     \brief EMULATED interface version 1
+    \ingroup interfaces
 */
 struct _XENFILT_EMULATED_INTERFACE_V1 {
     INTERFACE                           Interface;
diff --git a/include/evtchn_interface.h b/include/evtchn_interface.h
index 207f341..4ab2b28 100644
--- a/include/evtchn_interface.h
+++ b/include/evtchn_interface.h
@@ -112,19 +112,33 @@ typedef PXENBUS_EVTCHN_CHANNEL
     ...
     );
 
+/*! \typedef XENBUS_EVTCHN_BIND
+    \brief Bind an event channel to a specific CPU
+
+    \param Interface The interface header
+    \param Channel The channel handle
+    \param Cpu The CPU that should handle events
+*/
+typedef NTSTATUS
+(*XENBUS_EVTCHN_BIND)(
+    IN  PINTERFACE              Interface,
+    IN  PXENBUS_EVTCHN_CHANNEL  Channel,
+    IN  ULONG                   Cpu
+    );
+
 /*! \typedef XENBUS_EVTCHN_UNMASK
     \brief Unmask an event channel
 
     \param Interface The interface header
     \param Channel The channel handle
-    \param Locked Set to TRUE if this method is invoked in context of the channel callback
+    \param InCallback Set to TRUE if this method is invoked in context of the channel callback
     \return TRUE if there was an event pending at the point of unmask, FALSE otherwise
 */
 typedef BOOLEAN
 (*XENBUS_EVTCHN_UNMASK)(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 Locked
+    IN  BOOLEAN                 InCallback
     );
 
 /*! \typedef XENBUS_EVTCHN_SEND
@@ -182,6 +196,7 @@ DEFINE_GUID(GUID_XENBUS_EVTCHN_INTERFACE,
 
 /*! \struct _XENBUS_EVTCHN_INTERFACE_V1
     \brief EVTCHN interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_EVTCHN_INTERFACE_V1 {
     INTERFACE               Interface;
@@ -190,12 +205,29 @@ struct _XENBUS_EVTCHN_INTERFACE_V1 {
     XENBUS_EVTCHN_OPEN      EvtchnOpen;
     XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
     XENBUS_EVTCHN_SEND      EvtchnSend;
-    XENBUS_EVTCHN_SEND      EvtchnTrigger;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
+    XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
+    XENBUS_EVTCHN_CLOSE     EvtchnClose;
+};
+
+/*! \struct _XENBUS_EVTCHN_INTERFACE_V2
+    \brief EVTCHN interface version 2
+    \ingroup interfaces
+*/
+struct _XENBUS_EVTCHN_INTERFACE_V2 {
+    INTERFACE               Interface;
+    XENBUS_EVTCHN_ACQUIRE   EvtchnAcquire;
+    XENBUS_EVTCHN_RELEASE   EvtchnRelease;
+    XENBUS_EVTCHN_OPEN      EvtchnOpen;
+    XENBUS_EVTCHN_BIND      EvtchnBind;
+    XENBUS_EVTCHN_UNMASK    EvtchnUnmask;
+    XENBUS_EVTCHN_SEND      EvtchnSend;
+    XENBUS_EVTCHN_TRIGGER   EvtchnTrigger;
     XENBUS_EVTCHN_GET_PORT  EvtchnGetPort;
     XENBUS_EVTCHN_CLOSE     EvtchnClose;
 };
 
-typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
+typedef struct _XENBUS_EVTCHN_INTERFACE_V2 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVTCHN_INTERFACE;
 
 /*! \def XENBUS_EVTCHN
     \brief Macro at assist in method invocation
@@ -206,7 +238,7 @@ typedef struct _XENBUS_EVTCHN_INTERFACE_V1 XENBUS_EVTCHN_INTERFACE, *PXENBUS_EVT
 #endif  // _WINDLL
 
 #define XENBUS_EVTCHN_INTERFACE_VERSION_MIN 1
-#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 1
+#define XENBUS_EVTCHN_INTERFACE_VERSION_MAX 2
 
 #endif  // _XENBUS_EVTCHN_INTERFACE_H
 
diff --git a/include/gnttab_interface.h b/include/gnttab_interface.h
index c9d005f..d29440a 100644
--- a/include/gnttab_interface.h
+++ b/include/gnttab_interface.h
@@ -169,6 +169,7 @@ DEFINE_GUID(GUID_XENBUS_GNTTAB_INTERFACE,
 
 /*! \struct _XENBUS_GNTTAB_INTERFACE_V1
     \brief GNTTAB interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_GNTTAB_INTERFACE_V1 {
     INTERFACE                           Interface;
diff --git a/include/range_set_interface.h b/include/range_set_interface.h
index b05ab3c..5ab416d 100644
--- a/include/range_set_interface.h
+++ b/include/range_set_interface.h
@@ -149,6 +149,7 @@ DEFINE_GUID(GUID_XENBUS_RANGE_SET_INTERFACE,
 
 /*! \struct _XENBUS_RANGE_SET_INTERFACE_V1
     \brief RANGE_SET interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_RANGE_SET_INTERFACE_V1 {
     INTERFACE                   Interface;
diff --git a/include/store_interface.h b/include/store_interface.h
index f052b8f..5bcbba3 100644
--- a/include/store_interface.h
+++ b/include/store_interface.h
@@ -269,6 +269,7 @@ struct _XENBUS_STORE_INTERFACE_V1 {
 
 /*! \struct _XENBUS_STORE_INTERFACE_V1
     \brief STORE interface version 1
+    \ingroup interfaces
 */
 typedef struct _XENBUS_STORE_INTERFACE_V1 XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
 
diff --git a/include/suspend_interface.h b/include/suspend_interface.h
index 1a39141..df1b4b0 100644
--- a/include/suspend_interface.h
+++ b/include/suspend_interface.h
@@ -148,6 +148,7 @@ DEFINE_GUID(GUID_XENBUS_SUSPEND_INTERFACE,
 
 /*! \struct _XENBUS_SUSPEND_INTERFACE_V1
     \brief SUSPEND interface version 1
+    \ingroup interfaces
 */
 struct _XENBUS_SUSPEND_INTERFACE_V1 {
     INTERFACE                   Interface;
diff --git a/src/xenvif.inf b/src/xenvif.inf
index beaa8f4..74231ce 100644
--- a/src/xenvif.inf
+++ b/src/xenvif.inf
@@ -58,9 +58,9 @@ xenvif_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll
 ; DisplayName		Section		DeviceID
 ; -----------		-------		--------
 
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XSC000&DEV_VIF&REV_00000001
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0001&DEV_VIF&REV_00000001
-%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0002&DEV_VIF&REV_00000001
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XSC000&DEV_VIF&REV_00000004
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0001&DEV_VIF&REV_00000004
+%XenVifDesc%		=XenVif_Inst,	XENBUS\VEN_XS0002&DEV_VIF&REV_00000004
 
 [XenVif_Inst] 
 CopyFiles=XenVif_Copyfiles
-- 
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 Nov 10 15:29:20 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 10 Nov 2014 15:29:20 +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 1Xnqu8-0000zl-Ek; Mon, 10 Nov 2014 15:29:20 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <david.vrabel@citrix.com>) id 1Xnqu6-0000zg-V1
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 15:29:19 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	67/6C-09842-EC9D0645; Mon, 10 Nov 2014 15:29:18 +0000
X-Env-Sender: david.vrabel@citrix.com
X-Msg-Ref: server-14.tower-21.messagelabs.com!1415633354!12791972!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13784 invoked from network); 10 Nov 2014 15:29:17 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 15:29:17 -0000
X-IronPort-AV: E=Sophos;i="5.07,353,1413244800"; d="scan'208";a="189779920"
Message-ID: <5460D9A8.4050705@citrix.com>
Date: Mon, 10 Nov 2014 15:28:40 +0000
From: David Vrabel <david.vrabel@citrix.com>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
	rv:24.0) Gecko/20100101 Icedove/24.5.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
X-DLP: MIA2
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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 07/11/14 14:47, Paul Durrant wrote:
>> -----Original Message-----
>> From: David Vrabel
>> Sent: 07 November 2014 14:37
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
>>
>> On 07/11/14 14:02, Paul Durrant wrote:
>>>> -----Original Message-----
>>>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
>>>> +static BOOLEAN
>>>> +EvtchnFifoPortUnmask(
>>>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
>>>> +    IN  ULONG                       Port
>>>> +    )
>>>> +{
>>>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
>>>> +    event_word_t                    *EventWord;
>>>> +    LONG                            Old;
>>>> +    LONG                            New;
>>>> +
>>>> +    EventWord = EvtchnFifoEventWord(Context, Port);
>>>> +
>>>> +    // Clear masked bit, spinning if busy
>>>> +    do {
>>>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
>>>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
>>>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
>> Old) !=
>>>> Old);
>>>> +
>>>> +    // Check whether the port was masked
>>>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
>>>> +        return FALSE;
>>>> +
>>>> +    // If we cleared the mask then check whether something is pending
>>>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
>> EVTCHN_FIFO_PENDING))
>>>> +        return FALSE;
>>
>> The doc says you should do an EVTCHNOP_unmask hypercall here, but
>> picking up any pending event here is fine.
>>
>> You may want to be more careful if you unmask an event while running on
>> a VCPU that is not the one the event is bound to.
>>
> 
> Yes - I do need to allow for that. It won't happen at the moment but nothing in the API prevents it.

Actually, picking up the PENDING bit on unmask like this will prioritise
this event over any other pending events.  This subvert the ABI's FIFO
properties and will also result in lower priority events being handled
before higher priority ones.

I would recommend: do not clear PENDING, do the unmask hypercall and
always return FALSE.

David

_______________________________________________
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 Nov 10 15:29:20 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 10 Nov 2014 15:29:20 +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 1Xnqu8-0000zl-Ek; Mon, 10 Nov 2014 15:29:20 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <david.vrabel@citrix.com>) id 1Xnqu6-0000zg-V1
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 15:29:19 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	67/6C-09842-EC9D0645; Mon, 10 Nov 2014 15:29:18 +0000
X-Env-Sender: david.vrabel@citrix.com
X-Msg-Ref: server-14.tower-21.messagelabs.com!1415633354!12791972!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13784 invoked from network); 10 Nov 2014 15:29:17 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-14.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 15:29:17 -0000
X-IronPort-AV: E=Sophos;i="5.07,353,1413244800"; d="scan'208";a="189779920"
Message-ID: <5460D9A8.4050705@citrix.com>
Date: Mon, 10 Nov 2014 15:28:40 +0000
From: David Vrabel <david.vrabel@citrix.com>
User-Agent: Mozilla/5.0 (X11; Linux x86_64;
	rv:24.0) Gecko/20100101 Icedove/24.5.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
X-DLP: MIA2
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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 07/11/14 14:47, Paul Durrant wrote:
>> -----Original Message-----
>> From: David Vrabel
>> Sent: 07 November 2014 14:37
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
>>
>> On 07/11/14 14:02, Paul Durrant wrote:
>>>> -----Original Message-----
>>>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
>>>> +static BOOLEAN
>>>> +EvtchnFifoPortUnmask(
>>>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
>>>> +    IN  ULONG                       Port
>>>> +    )
>>>> +{
>>>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
>>>> +    event_word_t                    *EventWord;
>>>> +    LONG                            Old;
>>>> +    LONG                            New;
>>>> +
>>>> +    EventWord = EvtchnFifoEventWord(Context, Port);
>>>> +
>>>> +    // Clear masked bit, spinning if busy
>>>> +    do {
>>>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
>>>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
>>>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
>> Old) !=
>>>> Old);
>>>> +
>>>> +    // Check whether the port was masked
>>>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
>>>> +        return FALSE;
>>>> +
>>>> +    // If we cleared the mask then check whether something is pending
>>>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
>> EVTCHN_FIFO_PENDING))
>>>> +        return FALSE;
>>
>> The doc says you should do an EVTCHNOP_unmask hypercall here, but
>> picking up any pending event here is fine.
>>
>> You may want to be more careful if you unmask an event while running on
>> a VCPU that is not the one the event is bound to.
>>
> 
> Yes - I do need to allow for that. It won't happen at the moment but nothing in the API prevents it.

Actually, picking up the PENDING bit on unmask like this will prioritise
this event over any other pending events.  This subvert the ABI's FIFO
properties and will also result in lower priority events being handled
before higher priority ones.

I would recommend: do not clear PENDING, do the unmask hypercall and
always return FALSE.

David

_______________________________________________
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 Nov 10 16:10:29 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 10 Nov 2014 16:10:29 +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 1XnrXx-000345-OO; Mon, 10 Nov 2014 16:10:29 +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 1XnrXw-000340-Lr
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 16:10:28 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	D6/13-27785-473E0645; Mon, 10 Nov 2014 16:10:28 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-27.messagelabs.com!1415635826!12444343!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16802 invoked from network); 10 Nov 2014 16:10:27 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 16:10:27 -0000
X-IronPort-AV: E=Sophos;i="5.07,353,1413244800"; d="scan'208";a="26683619"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: David Vrabel <david.vrabel@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ///4+ACAABDwgIAEtGgAgAAbQEA=
Date: Mon, 10 Nov 2014 16:10:25 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011149E6A@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
	<5460D9A8.4050705@citrix.com>
In-Reply-To: <5460D9A8.4050705@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
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: David Vrabel
> Sent: 10 November 2014 15:29
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> On 07/11/14 14:47, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: David Vrabel
> >> Sent: 07 November 2014 14:37
> >> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> >> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> >>
> >> On 07/11/14 14:02, Paul Durrant wrote:
> >>>> -----Original Message-----
> >>>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> >>>> +static BOOLEAN
> >>>> +EvtchnFifoPortUnmask(
> >>>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> >>>> +    IN  ULONG                       Port
> >>>> +    )
> >>>> +{
> >>>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> >>>> +    event_word_t                    *EventWord;
> >>>> +    LONG                            Old;
> >>>> +    LONG                            New;
> >>>> +
> >>>> +    EventWord = EvtchnFifoEventWord(Context, Port);
> >>>> +
> >>>> +    // Clear masked bit, spinning if busy
> >>>> +    do {
> >>>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> >>>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> >>>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
> >> Old) !=
> >>>> Old);
> >>>> +
> >>>> +    // Check whether the port was masked
> >>>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> >>>> +        return FALSE;
> >>>> +
> >>>> +    // If we cleared the mask then check whether something is pending
> >>>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
> >> EVTCHN_FIFO_PENDING))
> >>>> +        return FALSE;
> >>
> >> The doc says you should do an EVTCHNOP_unmask hypercall here, but
> >> picking up any pending event here is fine.
> >>
> >> You may want to be more careful if you unmask an event while running
> on
> >> a VCPU that is not the one the event is bound to.
> >>
> >
> > Yes - I do need to allow for that. It won't happen at the moment but
> nothing in the API prevents it.
> 
> Actually, picking up the PENDING bit on unmask like this will prioritise
> this event over any other pending events.  This subvert the ABI's FIFO
> properties and will also result in lower priority events being handled
> before higher priority ones.
> 

That is true if the unmask is done in the event handler. If the unmask is done from a DPC then a higher priority event can still come in at any time, since the evtchn upcall will be at > DISPATCH_LEVEL. So, I'll add the hypercall for the former case.

Cheers,

  Paul

> I would recommend: do not clear PENDING, do the unmask hypercall and
> always return FALSE.
> 
> David

_______________________________________________
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 Nov 10 16:10:29 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 10 Nov 2014 16:10:29 +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 1XnrXx-000345-OO; Mon, 10 Nov 2014 16:10:29 +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 1XnrXw-000340-Lr
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 16:10:28 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	D6/13-27785-473E0645; Mon, 10 Nov 2014 16:10:28 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-3.tower-27.messagelabs.com!1415635826!12444343!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 16802 invoked from network); 10 Nov 2014 16:10:27 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-3.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 16:10:27 -0000
X-IronPort-AV: E=Sophos;i="5.07,353,1413244800"; d="scan'208";a="26683619"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: David Vrabel <david.vrabel@citrix.com>,
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Thread-Topic: [PATCH 10/10] Add support for the FIFO event channel ABI
Thread-Index: AQHP+c5NP1cgEqUF1k2LOjEC6/g6VpxVM1FQ///4+ACAABDwgIAEtGgAgAAbQEA=
Date: Mon, 10 Nov 2014 16:10:25 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011149E6A@AMSPEX01CL01.citrite.net>
References: <1415284254-25504-1-git-send-email-paul.durrant@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD0111483BD@AMSPEX01CL01.citrite.net>
	<545CD91E.5090504@citrix.com>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011148657@AMSPEX01CL01.citrite.net>
	<5460D9A8.4050705@citrix.com>
In-Reply-To: <5460D9A8.4050705@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
Subject: Re: [win-pv-devel] [PATCH 10/10] Add support for the FIFO event
	channel ABI
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: David Vrabel
> Sent: 10 November 2014 15:29
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> 
> On 07/11/14 14:47, Paul Durrant wrote:
> >> -----Original Message-----
> >> From: David Vrabel
> >> Sent: 07 November 2014 14:37
> >> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> >> Subject: Re: [PATCH 10/10] Add support for the FIFO event channel ABI
> >>
> >> On 07/11/14 14:02, Paul Durrant wrote:
> >>>> -----Original Message-----
> >>>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> >>>> +static BOOLEAN
> >>>> +EvtchnFifoPortUnmask(
> >>>> +    IN  PXENBUS_EVTCHN_ABI_CONTEXT  _Context,
> >>>> +    IN  ULONG                       Port
> >>>> +    )
> >>>> +{
> >>>> +    PXENBUS_EVTCHN_FIFO_CONTEXT     Context = (PVOID)_Context;
> >>>> +    event_word_t                    *EventWord;
> >>>> +    LONG                            Old;
> >>>> +    LONG                            New;
> >>>> +
> >>>> +    EventWord = EvtchnFifoEventWord(Context, Port);
> >>>> +
> >>>> +    // Clear masked bit, spinning if busy
> >>>> +    do {
> >>>> +        Old = *EventWord & ~(1 << EVTCHN_FIFO_BUSY);
> >>>> +        New = Old & ~(1 << EVTCHN_FIFO_MASKED);
> >>>> +    } while (InterlockedCompareExchange((LONG *)EventWord, New,
> >> Old) !=
> >>>> Old);
> >>>> +
> >>>> +    // Check whether the port was masked
> >>>> +    if (~Old & (1 << EVTCHN_FIFO_MASKED))
> >>>> +        return FALSE;
> >>>> +
> >>>> +    // If we cleared the mask then check whether something is pending
> >>>> +    if (!__EvtchnFifoTestAndClearFlag(EventWord,
> >> EVTCHN_FIFO_PENDING))
> >>>> +        return FALSE;
> >>
> >> The doc says you should do an EVTCHNOP_unmask hypercall here, but
> >> picking up any pending event here is fine.
> >>
> >> You may want to be more careful if you unmask an event while running
> on
> >> a VCPU that is not the one the event is bound to.
> >>
> >
> > Yes - I do need to allow for that. It won't happen at the moment but
> nothing in the API prevents it.
> 
> Actually, picking up the PENDING bit on unmask like this will prioritise
> this event over any other pending events.  This subvert the ABI's FIFO
> properties and will also result in lower priority events being handled
> before higher priority ones.
> 

That is true if the unmask is done in the event handler. If the unmask is done from a DPC then a higher priority event can still come in at any time, since the evtchn upcall will be at > DISPATCH_LEVEL. So, I'll add the hypercall for the former case.

Cheers,

  Paul

> I would recommend: do not clear PENDING, do the unmask hypercall and
> always return FALSE.
> 
> David

_______________________________________________
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 Nov 11 09:45:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 09:45: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 1Xo80z-0008Ae-Dg; Tue, 11 Nov 2014 09:45:33 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <hanjiunit@gmail.com>) id 1Xnw4Q-00054A-W1
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 21:00:19 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	E8/DD-02576-26721645; Mon, 10 Nov 2014 21:00:18 +0000
X-Env-Sender: hanjiunit@gmail.com
X-Msg-Ref: server-3.tower-27.messagelabs.com!1415653217!12490361!1
X-Originating-IP: [74.125.82.51]
X-SpamReason: No, hits=0.4 required=7.0 tests=HTML_30_40,HTML_MESSAGE,
	RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23970 invoked from network); 10 Nov 2014 21:00:17 -0000
Received: from mail-wg0-f51.google.com (HELO mail-wg0-f51.google.com)
	(74.125.82.51)
	by server-3.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 21:00:17 -0000
Received: by mail-wg0-f51.google.com with SMTP id l18so9822724wgh.24
	for <win-pv-devel@lists.xenproject.org>;
	Mon, 10 Nov 2014 13:00:17 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=mime-version:date:message-id:subject:from:to:content-type;
	bh=GrW15oVfn+JM3GWviw94ob5sgg2SMagUwhegK8wg1js=;
	b=mLTaCOtvNaq6FJwppDJSqXUz/3GJYsZB4WmRAaiPc38rJOm1PDuFBtHvQQErH8+I1k
	CDMMypoKV5NFDX8Hd8auzaDbFzIbirjTNJaA1WAEXa1kBWlyTW5HbrEdbJ03Rrdf3QgT
	CMM8FgLuo2mo3SdGFFZJ97aKruMn8AFoMALrLfvike5YB8ut+eYHl7zM4NpNw8dG3Kns
	B4SrKyWSQMOWB/LqdwvsYD5FbHRXzHLQ0mWzdzXDe9342IJD2wAjHdQ9Eo2BD0idxuqE
	Wh1f5VNFjw6Ztq+dRV9RZ7oCeaU7rL+fSmNslZRRwykOP4z5lut6AsLp/hF0xCKY1lW7
	uaUg==
MIME-Version: 1.0
X-Received: by 10.180.188.41 with SMTP id fx9mr33438026wic.59.1415653216277;
	Mon, 10 Nov 2014 13:00:16 -0800 (PST)
Received: by 10.216.179.65 with HTTP; Mon, 10 Nov 2014 13:00:16 -0800 (PST)
Date: Mon, 10 Nov 2014 13:00:16 -0800
Message-ID: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
From: hanji unit <hanjiunit@gmail.com>
To: win-pv-devel@lists.xenproject.org
X-Mailman-Approved-At: Tue, 11 Nov 2014 09:45:31 +0000
Subject: [win-pv-devel] Windows Paravirtualization for Xen
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: multipart/mixed; boundary="===============2159701589022398138=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============2159701589022398138==
Content-Type: multipart/alternative; boundary=001a11c263141510a8050787739c

--001a11c263141510a8050787739c
Content-Type: text/plain; charset=UTF-8

Hello. I am looking at windows Paravirtualization support and I've seen a
few projects including:

1) win-pvdrivers by James Harper (http://wiki.xen.org/wiki/Xen_Windows_GplPv
)
2) Windows PV-Driver Subproject (
http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F
)
3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver)

Are these 3 projects all different or do any of them refer to the same
projects? If different, which is the one that is most widely supported and
used that has future support plans? I am trying to write to XenStore from
Windows and looking to modify some of these drivers if needed, but dont
want to work on a dead project.

Thanks.

--001a11c263141510a8050787739c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><div><div><div><div>Hello. I am looking at windows Pa=
ravirtualization support and I&#39;ve seen a few projects including:<br><br=
></div>1) win-pvdrivers by James Harper (<a href=3D"http://wiki.xen.org/wik=
i/Xen_Windows_GplPv">http://wiki.xen.org/wiki/Xen_Windows_GplPv</a>)<br></d=
iv>2)
 Windows PV-Driver Subproject=20
(<a href=3D"http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_W=
indows_PV_Driver_Subproject.2Fteam.3F">http://wiki.xen.org/wiki/Xen_FAQ_Dri=
vers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F</a>)<br></=
div>3) Open Sourced XenServer Windows PV Drivers (<a href=3D"https://github=
.com/xenserver">https://github.com/xenserver</a>)<br><br></div>Are
 these 3 projects all different or do any of them refer to the same=20
projects? If different, which is the one that is most widely supported=20
and used that has future support plans? I am trying to write to XenStore
 from Windows and looking to modify some of these drivers if needed, but
 dont want to work on a dead project.<br><br></div>Thanks.</div>

--001a11c263141510a8050787739c--


--===============2159701589022398138==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Tue Nov 11 09:45:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 09:45: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 1Xo80z-0008Ae-Dg; Tue, 11 Nov 2014 09:45:33 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <hanjiunit@gmail.com>) id 1Xnw4Q-00054A-W1
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 21:00:19 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	E8/DD-02576-26721645; Mon, 10 Nov 2014 21:00:18 +0000
X-Env-Sender: hanjiunit@gmail.com
X-Msg-Ref: server-3.tower-27.messagelabs.com!1415653217!12490361!1
X-Originating-IP: [74.125.82.51]
X-SpamReason: No, hits=0.4 required=7.0 tests=HTML_30_40,HTML_MESSAGE,
	RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23970 invoked from network); 10 Nov 2014 21:00:17 -0000
Received: from mail-wg0-f51.google.com (HELO mail-wg0-f51.google.com)
	(74.125.82.51)
	by server-3.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 21:00:17 -0000
Received: by mail-wg0-f51.google.com with SMTP id l18so9822724wgh.24
	for <win-pv-devel@lists.xenproject.org>;
	Mon, 10 Nov 2014 13:00:17 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=mime-version:date:message-id:subject:from:to:content-type;
	bh=GrW15oVfn+JM3GWviw94ob5sgg2SMagUwhegK8wg1js=;
	b=mLTaCOtvNaq6FJwppDJSqXUz/3GJYsZB4WmRAaiPc38rJOm1PDuFBtHvQQErH8+I1k
	CDMMypoKV5NFDX8Hd8auzaDbFzIbirjTNJaA1WAEXa1kBWlyTW5HbrEdbJ03Rrdf3QgT
	CMM8FgLuo2mo3SdGFFZJ97aKruMn8AFoMALrLfvike5YB8ut+eYHl7zM4NpNw8dG3Kns
	B4SrKyWSQMOWB/LqdwvsYD5FbHRXzHLQ0mWzdzXDe9342IJD2wAjHdQ9Eo2BD0idxuqE
	Wh1f5VNFjw6Ztq+dRV9RZ7oCeaU7rL+fSmNslZRRwykOP4z5lut6AsLp/hF0xCKY1lW7
	uaUg==
MIME-Version: 1.0
X-Received: by 10.180.188.41 with SMTP id fx9mr33438026wic.59.1415653216277;
	Mon, 10 Nov 2014 13:00:16 -0800 (PST)
Received: by 10.216.179.65 with HTTP; Mon, 10 Nov 2014 13:00:16 -0800 (PST)
Date: Mon, 10 Nov 2014 13:00:16 -0800
Message-ID: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
From: hanji unit <hanjiunit@gmail.com>
To: win-pv-devel@lists.xenproject.org
X-Mailman-Approved-At: Tue, 11 Nov 2014 09:45:31 +0000
Subject: [win-pv-devel] Windows Paravirtualization for Xen
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: multipart/mixed; boundary="===============2159701589022398138=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============2159701589022398138==
Content-Type: multipart/alternative; boundary=001a11c263141510a8050787739c

--001a11c263141510a8050787739c
Content-Type: text/plain; charset=UTF-8

Hello. I am looking at windows Paravirtualization support and I've seen a
few projects including:

1) win-pvdrivers by James Harper (http://wiki.xen.org/wiki/Xen_Windows_GplPv
)
2) Windows PV-Driver Subproject (
http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F
)
3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver)

Are these 3 projects all different or do any of them refer to the same
projects? If different, which is the one that is most widely supported and
used that has future support plans? I am trying to write to XenStore from
Windows and looking to modify some of these drivers if needed, but dont
want to work on a dead project.

Thanks.

--001a11c263141510a8050787739c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div><div><div><div><div>Hello. I am looking at windows Pa=
ravirtualization support and I&#39;ve seen a few projects including:<br><br=
></div>1) win-pvdrivers by James Harper (<a href=3D"http://wiki.xen.org/wik=
i/Xen_Windows_GplPv">http://wiki.xen.org/wiki/Xen_Windows_GplPv</a>)<br></d=
iv>2)
 Windows PV-Driver Subproject=20
(<a href=3D"http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_W=
indows_PV_Driver_Subproject.2Fteam.3F">http://wiki.xen.org/wiki/Xen_FAQ_Dri=
vers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F</a>)<br></=
div>3) Open Sourced XenServer Windows PV Drivers (<a href=3D"https://github=
.com/xenserver">https://github.com/xenserver</a>)<br><br></div>Are
 these 3 projects all different or do any of them refer to the same=20
projects? If different, which is the one that is most widely supported=20
and used that has future support plans? I am trying to write to XenStore
 from Windows and looking to modify some of these drivers if needed, but
 dont want to work on a dead project.<br><br></div>Thanks.</div>

--001a11c263141510a8050787739c--


--===============2159701589022398138==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Tue Nov 11 09:45:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 09:45:54 +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 1Xo81K-0008CJ-FX; Tue, 11 Nov 2014 09:45:54 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <hanjiunit@gmail.com>) id 1XnwDJ-0005LX-3P
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 21:09:29 +0000
Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id
	2C/2B-22737-88921645; Mon, 10 Nov 2014 21:09:28 +0000
X-Env-Sender: hanjiunit@gmail.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1415653767!7505071!1
X-Originating-IP: [209.85.212.175]
X-SpamReason: No, hits=0.9 required=7.0 tests=HTML_40_50,HTML_MESSAGE,
	RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31660 invoked from network); 10 Nov 2014 21:09:27 -0000
Received: from mail-wi0-f175.google.com (HELO mail-wi0-f175.google.com)
	(209.85.212.175)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 21:09:27 -0000
Received: by mail-wi0-f175.google.com with SMTP id ex7so11856522wid.2
	for <win-pv-devel@lists.xenproject.org>;
	Mon, 10 Nov 2014 13:09:27 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=mime-version:in-reply-to:references:date:message-id:subject:from:to
	:content-type; bh=xoPy3cP9c+H4h+0DfrDVT9fR5thExYASxNfyDNSA5Vo=;
	b=oQQ8g5EXTBMy3In/z/gZMBq8qAoI8hAsA+vy0xRfw7ym4GMZaQnCLDp3x+rEdtw/NZ
	2eY/gxjgwq/DkVOO+S+qwQL//dM9tIKYuQBfRayAtiCy/yoWWiweL2NncZJlLoVSgzjJ
	V5ZDVAenQBSWVBrvDaszrdbgP4pQ9H+et380E9Z0yJ6ibS8meVTpMeaEzPLL2nzQwHbk
	6eUFk2EIsVh3dg5/jBbyRDP1zshosGelqiAlvEQQW4PuTEFBkvebNrHHuwb0VHBoJrY7
	Kh8MBn+XCm4LnD14tH3WOFxm1OFWl9+UUYsbsu26I3sgaar0cBKN3ouD9CSQNqCZC4q9
	gZtw==
MIME-Version: 1.0
X-Received: by 10.181.8.72 with SMTP id di8mr43334667wid.1.1415653766911; Mon,
	10 Nov 2014 13:09:26 -0800 (PST)
Received: by 10.216.179.65 with HTTP; Mon, 10 Nov 2014 13:09:26 -0800 (PST)
In-Reply-To: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
References: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
Date: Mon, 10 Nov 2014 13:09:26 -0800
Message-ID: <CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.com>
From: hanji unit <hanjiunit@gmail.com>
To: win-pv-devel@lists.xenproject.org, xen-devel@lists.xen.org
X-Mailman-Approved-At: Tue, 11 Nov 2014 09:45:53 +0000
Subject: Re: [win-pv-devel] Windows Paravirtualization for Xen
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: multipart/mixed; boundary="===============3189172333153508823=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============3189172333153508823==
Content-Type: multipart/alternative; boundary=001a1134cdeee6db7c0507879366

--001a1134cdeee6db7c0507879366
Content-Type: text/plain; charset=UTF-8

Adding main Xen development list too.

On Mon, Nov 10, 2014 at 1:00 PM, hanji unit <hanjiunit@gmail.com> wrote:

> Hello. I am looking at windows Paravirtualization support and I've seen a
> few projects including:
>
> 1) win-pvdrivers by James Harper (
> http://wiki.xen.org/wiki/Xen_Windows_GplPv)
> 2) Windows PV-Driver Subproject (
> http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F
> )
> 3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver
> )
>
> Are these 3 projects all different or do any of them refer to the same
> projects? If different, which is the one that is most widely supported and
> used that has future support plans? I am trying to write to XenStore from
> Windows and looking to modify some of these drivers if needed, but dont
> want to work on a dead project.
>
> Thanks.
>

--001a1134cdeee6db7c0507879366
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Adding main Xen development list too.<br><div class=3D"gma=
il_extra"><br><div class=3D"gmail_quote">On Mon, Nov 10, 2014 at 1:00 PM, h=
anji unit <span dir=3D"ltr">&lt;<a href=3D"mailto:hanjiunit@gmail.com" targ=
et=3D"_blank">hanjiunit@gmail.com</a>&gt;</span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div><div><div><div><div>Hello. I am lookin=
g at windows Paravirtualization support and I&#39;ve seen a few projects in=
cluding:<br><br></div>1) win-pvdrivers by James Harper (<a href=3D"http://w=
iki.xen.org/wiki/Xen_Windows_GplPv" target=3D"_blank">http://wiki.xen.org/w=
iki/Xen_Windows_GplPv</a>)<br></div>2)
 Windows PV-Driver Subproject=20
(<a href=3D"http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_W=
indows_PV_Driver_Subproject.2Fteam.3F" target=3D"_blank">http://wiki.xen.or=
g/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2F=
team.3F</a>)<br></div>3) Open Sourced XenServer Windows PV Drivers (<a href=
=3D"https://github.com/xenserver" target=3D"_blank">https://github.com/xens=
erver</a>)<br><br></div>Are
 these 3 projects all different or do any of them refer to the same=20
projects? If different, which is the one that is most widely supported=20
and used that has future support plans? I am trying to write to XenStore
 from Windows and looking to modify some of these drivers if needed, but
 dont want to work on a dead project.<br><br></div>Thanks.</div>
</blockquote></div><br></div></div>

--001a1134cdeee6db7c0507879366--


--===============3189172333153508823==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Tue Nov 11 09:45:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 09:45:54 +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 1Xo81K-0008CJ-FX; Tue, 11 Nov 2014 09:45:54 +0000
Received: from mail6.bemta5.messagelabs.com ([195.245.231.135])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <hanjiunit@gmail.com>) id 1XnwDJ-0005LX-3P
	for win-pv-devel@lists.xenproject.org; Mon, 10 Nov 2014 21:09:29 +0000
Received: from [85.158.139.211] by server-4.bemta-5.messagelabs.com id
	2C/2B-22737-88921645; Mon, 10 Nov 2014 21:09:28 +0000
X-Env-Sender: hanjiunit@gmail.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1415653767!7505071!1
X-Originating-IP: [209.85.212.175]
X-SpamReason: No, hits=0.9 required=7.0 tests=HTML_40_50,HTML_MESSAGE,
	RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31660 invoked from network); 10 Nov 2014 21:09:27 -0000
Received: from mail-wi0-f175.google.com (HELO mail-wi0-f175.google.com)
	(209.85.212.175)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	10 Nov 2014 21:09:27 -0000
Received: by mail-wi0-f175.google.com with SMTP id ex7so11856522wid.2
	for <win-pv-devel@lists.xenproject.org>;
	Mon, 10 Nov 2014 13:09:27 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
	h=mime-version:in-reply-to:references:date:message-id:subject:from:to
	:content-type; bh=xoPy3cP9c+H4h+0DfrDVT9fR5thExYASxNfyDNSA5Vo=;
	b=oQQ8g5EXTBMy3In/z/gZMBq8qAoI8hAsA+vy0xRfw7ym4GMZaQnCLDp3x+rEdtw/NZ
	2eY/gxjgwq/DkVOO+S+qwQL//dM9tIKYuQBfRayAtiCy/yoWWiweL2NncZJlLoVSgzjJ
	V5ZDVAenQBSWVBrvDaszrdbgP4pQ9H+et380E9Z0yJ6ibS8meVTpMeaEzPLL2nzQwHbk
	6eUFk2EIsVh3dg5/jBbyRDP1zshosGelqiAlvEQQW4PuTEFBkvebNrHHuwb0VHBoJrY7
	Kh8MBn+XCm4LnD14tH3WOFxm1OFWl9+UUYsbsu26I3sgaar0cBKN3ouD9CSQNqCZC4q9
	gZtw==
MIME-Version: 1.0
X-Received: by 10.181.8.72 with SMTP id di8mr43334667wid.1.1415653766911; Mon,
	10 Nov 2014 13:09:26 -0800 (PST)
Received: by 10.216.179.65 with HTTP; Mon, 10 Nov 2014 13:09:26 -0800 (PST)
In-Reply-To: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
References: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
Date: Mon, 10 Nov 2014 13:09:26 -0800
Message-ID: <CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.com>
From: hanji unit <hanjiunit@gmail.com>
To: win-pv-devel@lists.xenproject.org, xen-devel@lists.xen.org
X-Mailman-Approved-At: Tue, 11 Nov 2014 09:45:53 +0000
Subject: Re: [win-pv-devel] Windows Paravirtualization for Xen
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: multipart/mixed; boundary="===============3189172333153508823=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============3189172333153508823==
Content-Type: multipart/alternative; boundary=001a1134cdeee6db7c0507879366

--001a1134cdeee6db7c0507879366
Content-Type: text/plain; charset=UTF-8

Adding main Xen development list too.

On Mon, Nov 10, 2014 at 1:00 PM, hanji unit <hanjiunit@gmail.com> wrote:

> Hello. I am looking at windows Paravirtualization support and I've seen a
> few projects including:
>
> 1) win-pvdrivers by James Harper (
> http://wiki.xen.org/wiki/Xen_Windows_GplPv)
> 2) Windows PV-Driver Subproject (
> http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F
> )
> 3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver
> )
>
> Are these 3 projects all different or do any of them refer to the same
> projects? If different, which is the one that is most widely supported and
> used that has future support plans? I am trying to write to XenStore from
> Windows and looking to modify some of these drivers if needed, but dont
> want to work on a dead project.
>
> Thanks.
>

--001a1134cdeee6db7c0507879366
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Adding main Xen development list too.<br><div class=3D"gma=
il_extra"><br><div class=3D"gmail_quote">On Mon, Nov 10, 2014 at 1:00 PM, h=
anji unit <span dir=3D"ltr">&lt;<a href=3D"mailto:hanjiunit@gmail.com" targ=
et=3D"_blank">hanjiunit@gmail.com</a>&gt;</span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div><div><div><div><div>Hello. I am lookin=
g at windows Paravirtualization support and I&#39;ve seen a few projects in=
cluding:<br><br></div>1) win-pvdrivers by James Harper (<a href=3D"http://w=
iki.xen.org/wiki/Xen_Windows_GplPv" target=3D"_blank">http://wiki.xen.org/w=
iki/Xen_Windows_GplPv</a>)<br></div>2)
 Windows PV-Driver Subproject=20
(<a href=3D"http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_W=
indows_PV_Driver_Subproject.2Fteam.3F" target=3D"_blank">http://wiki.xen.or=
g/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2F=
team.3F</a>)<br></div>3) Open Sourced XenServer Windows PV Drivers (<a href=
=3D"https://github.com/xenserver" target=3D"_blank">https://github.com/xens=
erver</a>)<br><br></div>Are
 these 3 projects all different or do any of them refer to the same=20
projects? If different, which is the one that is most widely supported=20
and used that has future support plans? I am trying to write to XenStore
 from Windows and looking to modify some of these drivers if needed, but
 dont want to work on a dead project.<br><br></div>Thanks.</div>
</blockquote></div><br></div></div>

--001a1134cdeee6db7c0507879366--


--===============3189172333153508823==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Tue Nov 11 10:00:43 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 10:00: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 1Xo8Fe-0000Fm-LI; Tue, 11 Nov 2014 10:00:42 +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 1Xo8Fc-0000Fc-P2
	for win-pv-devel@lists.xenproject.org; Tue, 11 Nov 2014 10:00:40 +0000
Received: from [85.158.137.68] by server-15.bemta-3.messagelabs.com id
	F8/4F-17735-74ED1645; Tue, 11 Nov 2014 10:00:39 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-31.messagelabs.com!1415700038!11714806!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17229 invoked from network); 11 Nov 2014 10:00:39 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	11 Nov 2014 10:00:39 -0000
X-IronPort-AV: E=Sophos;i="5.07,360,1413244800"; d="scan'208";a="26696407"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: hanji unit <hanjiunit@gmail.com>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>, "xen-devel@lists.xen.org"
	<xen-devel@lists.xen.org>
Thread-Topic: [Xen-devel] Windows Paravirtualization for Xen
Thread-Index: AQHP/YWa0ApY9KYiqkSs6r4iYKHxB5xbL/ug
Date: Tue, 11 Nov 2014 10:00:36 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114A95C@AMSPEX01CL01.citrite.net>
References: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
	<CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.com>
In-Reply-To: <CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.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
Subject: Re: [win-pv-devel] [Xen-devel] Windows Paravirtualization for Xen
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

Please don't use HTML...

From: xen-devel-bounces@lists.xen.org [mailto:xen-devel-bounces@lists.xen.org] On Behalf Of hanji unit
Sent: 10 November 2014 21:09
To: win-pv-devel@lists.xenproject.org; xen-devel@lists.xen.org
Subject: Re: [Xen-devel] Windows Paravirtualization for Xen

Adding main Xen development list too.

On Mon, Nov 10, 2014 at 1:00 PM, hanji unit <hanjiunit@gmail.com> wrote:
Hello. I am looking at windows Paravirtualization support and I've seen a few projects including:
1) win-pvdrivers by James Harper (http://wiki.xen.org/wiki/Xen_Windows_GplPv)
2) Windows PV-Driver Subproject (http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F)
3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver)
Are these 3 projects all different or do any of them refer to the same projects? If different, which is the one that is most widely supported and used that has future support plans? I am trying to write to XenStore from Windows and looking to modify some of these drivers if needed, but dont want to work on a dead project.
Thanks.

-----

3 supercedes 2, and 1 is a different set of open source drivers that preceded the open-sourcing of the XenServer drivers.

If you want to try to access xenstore from Windows user space then the XENIFACE driver in 2 will already allow you to do that via WMI. See http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xeniface.git;a=blob;f=WmiDocumentation.txt. If you don't want to use WMI then there are also basic read/write/directory IOCTLS too (see http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xeniface.git;a=blob;f=src/xeniface/ioctls.c).

  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 Tue Nov 11 10:00:43 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 10:00: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 1Xo8Fe-0000Fm-LI; Tue, 11 Nov 2014 10:00:42 +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 1Xo8Fc-0000Fc-P2
	for win-pv-devel@lists.xenproject.org; Tue, 11 Nov 2014 10:00:40 +0000
Received: from [85.158.137.68] by server-15.bemta-3.messagelabs.com id
	F8/4F-17735-74ED1645; Tue, 11 Nov 2014 10:00:39 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-31.messagelabs.com!1415700038!11714806!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17229 invoked from network); 11 Nov 2014 10:00:39 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	11 Nov 2014 10:00:39 -0000
X-IronPort-AV: E=Sophos;i="5.07,360,1413244800"; d="scan'208";a="26696407"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: hanji unit <hanjiunit@gmail.com>, "win-pv-devel@lists.xenproject.org"
	<win-pv-devel@lists.xenproject.org>, "xen-devel@lists.xen.org"
	<xen-devel@lists.xen.org>
Thread-Topic: [Xen-devel] Windows Paravirtualization for Xen
Thread-Index: AQHP/YWa0ApY9KYiqkSs6r4iYKHxB5xbL/ug
Date: Tue, 11 Nov 2014 10:00:36 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114A95C@AMSPEX01CL01.citrite.net>
References: <CA+J4q6eSw0RCaK3WSAbSVOXx3s6ErTq-CmgijjyiJqNjQgrVQg@mail.gmail.com>
	<CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.com>
In-Reply-To: <CA+J4q6fLSzA+Rw51r7FYy2o6x8+ZTpX6W7U7G526Q-OSgSHtGA@mail.gmail.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
Subject: Re: [win-pv-devel] [Xen-devel] Windows Paravirtualization for Xen
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

Please don't use HTML...

From: xen-devel-bounces@lists.xen.org [mailto:xen-devel-bounces@lists.xen.org] On Behalf Of hanji unit
Sent: 10 November 2014 21:09
To: win-pv-devel@lists.xenproject.org; xen-devel@lists.xen.org
Subject: Re: [Xen-devel] Windows Paravirtualization for Xen

Adding main Xen development list too.

On Mon, Nov 10, 2014 at 1:00 PM, hanji unit <hanjiunit@gmail.com> wrote:
Hello. I am looking at windows Paravirtualization support and I've seen a few projects including:
1) win-pvdrivers by James Harper (http://wiki.xen.org/wiki/Xen_Windows_GplPv)
2) Windows PV-Driver Subproject (http://wiki.xen.org/wiki/Xen_FAQ_Drivers,_Windows#What_is_the_Windows_PV_Driver_Subproject.2Fteam.3F)
3) Open Sourced XenServer Windows PV Drivers (https://github.com/xenserver)
Are these 3 projects all different or do any of them refer to the same projects? If different, which is the one that is most widely supported and used that has future support plans? I am trying to write to XenStore from Windows and looking to modify some of these drivers if needed, but dont want to work on a dead project.
Thanks.

-----

3 supercedes 2, and 1 is a different set of open source drivers that preceded the open-sourcing of the XenServer drivers.

If you want to try to access xenstore from Windows user space then the XENIFACE driver in 2 will already allow you to do that via WMI. See http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xeniface.git;a=blob;f=WmiDocumentation.txt. If you don't want to use WMI then there are also basic read/write/directory IOCTLS too (see http://xenbits.xen.org/gitweb/?p=pvdrivers/win/xeniface.git;a=blob;f=src/xeniface/ioctls.c).

  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 Tue Nov 11 13:40:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 13:40:31 +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 1XoBgM-0001RI-OZ; Tue, 11 Nov 2014 13:40:30 +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 1XoBgL-0001RD-NK
	for win-pv-devel@lists.xenproject.org; Tue, 11 Nov 2014 13:40:29 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	26/D2-29352-CC112645; Tue, 11 Nov 2014 13:40:28 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-6.tower-206.messagelabs.com!1415713225!11779560!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6378 invoked from network); 11 Nov 2014 13:40:28 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-6.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	11 Nov 2014 13:40:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,361,1413244800"; d="scan'208";a="191556680"
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.181.6;
	Tue, 11 Nov 2014 08:40:23 -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 1XoBgE-0004WG-My;
	Tue, 11 Nov 2014 13:40:22 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 11 Nov 2014 13:40:12 +0000
Message-ID: <1415713212-29488-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] Use EVTCHNOP_unmask to unmask in some cases
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

If the EVTCHN Unmask method is called in context of the event channel
upcall, or on a CPU to which the event is not bound then use the unmask
hypercall. In the former case not doing this may lead to priorty
inversion once setting event channel priorities is enabled. In the latter
case not doing it again stops a lower priority event handler trigger from
blocking a higher priority event injection.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/xen.h            |  7 ++++++
 src/xen/event_channel.c  | 28 ++++++++++++++++++++++++
 src/xenbus/evtchn.c      | 56 +++++++++++++++++++++++++++++-------------------
 src/xenbus/evtchn_fifo.c |  5 +----
 src/xenbus/shared_info.c |  5 +----
 5 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/include/xen.h b/include/xen.h
index 84197a5..fa95edd 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -212,6 +212,13 @@ EventChannelBindVirtualCpu(
     IN  unsigned int        vcpu_id
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelUnmask(
+    IN  ULONG   LocalPort
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index 94a6b82..aa9fb48 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -357,3 +357,31 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelUnmask(
+    IN  ULONG               LocalPort
+    )
+{
+    struct evtchn_unmask    op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+
+    rc = EventChannelOp(EVTCHNOP_unmask, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index c6ac30d..f88c208 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -624,60 +624,72 @@ static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 InCallback
+    IN  BOOLEAN                 InUpcall
     )
 {
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     KIRQL                       Irql = PASSIVE_LEVEL;
-    BOOLEAN                     Pending = FALSE;
+    BOOLEAN                     Pending;
+    ULONG                       LocalPort;
     ULONG                       Cpu;
-    PXENBUS_INTERRUPT           Interrupt;
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    if (!InCallback)
+    if (!InUpcall)
         KeAcquireSpinLock(&Channel->Lock, &Irql);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
+    Pending = FALSE;
+
     if (!Channel->Active)
         goto done;
 
+    LocalPort = Channel->LocalPort;
+
     Pending = XENBUS_EVTCHN_ABI(PortUnmask,
                                 &Context->EvtchnAbi,
-                                Channel->LocalPort);
+                                LocalPort);
 
     if (!Pending)
         goto done;
 
-    if (InCallback)
-        goto mask;
-
-    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
-    Cpu = KeGetCurrentProcessorNumber();
-
-    Interrupt = Context->LatchedInterrupt[Cpu];
+    //
+    // If we are in context of the upcall then use a hypercall
+    // to schedule the pending event.
+    //
+    if (InUpcall) {
+        (VOID) EventChannelUnmask(LocalPort);
 
-    if (Channel->Interrupt == Interrupt)
-        goto mask;
+        Pending = FALSE;
+        goto done;
+    }
 
     //
-    // We are not on the CPU to which the event is bound so
-    // we must trigger.
+    // If we are not unmasking on the same CPU to which the
+    // event channel is bound, then we need to use a hypercall
+    // to schedule the upcall on the correct CPU.
     //
-    EvtchnTrigger(Interface, Channel);
+    Cpu = KeGetCurrentProcessorNumber();
 
-    Pending = FALSE;
-    goto done;
+    if (Channel->Cpu != Cpu) {
+        (VOID) EventChannelUnmask(LocalPort);
+
+        Pending = FALSE;
+        goto done;
+    }
 
-mask:
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
-                          Channel->LocalPort);
+                          LocalPort);
+
+    XENBUS_EVTCHN_ABI(PortAck,
+                      &Context->EvtchnAbi,
+                      LocalPort);
 
 done:
-    if (!InCallback)
+    if (!InUpcall)
         KeReleaseSpinLock(&Channel->Lock, Irql);
 
     return Pending;
diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index f65cc1b..e045cd0 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -437,10 +437,7 @@ EvtchnFifoPortUnmask(
         return FALSE;
 
     // If we cleared the mask then check whether something is pending
-    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
-        return FALSE;
-
-    return TRUE;
+    return __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING);
 }
 
 static VOID
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 67be20c..240d87b 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -316,10 +316,7 @@ SharedInfoEvtchnUnmask(
     KeMemoryBarrier();
 
     // If we cleared the mask then check whether something was pending
-    if (!SharedInfoClearBit(&Shared->evtchn_pending[SelectorBit], PortBit))
-        return FALSE;
-
-    return TRUE;
+    return SharedInfoTestBit(&Shared->evtchn_pending[SelectorBit], PortBit);
 }
 
 static LARGE_INTEGER
-- 
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 Nov 11 13:40:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 11 Nov 2014 13:40:31 +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 1XoBgM-0001RI-OZ; Tue, 11 Nov 2014 13:40:30 +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 1XoBgL-0001RD-NK
	for win-pv-devel@lists.xenproject.org; Tue, 11 Nov 2014 13:40:29 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	26/D2-29352-CC112645; Tue, 11 Nov 2014 13:40:28 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-6.tower-206.messagelabs.com!1415713225!11779560!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6378 invoked from network); 11 Nov 2014 13:40:28 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-6.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	11 Nov 2014 13:40:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,361,1413244800"; d="scan'208";a="191556680"
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.181.6;
	Tue, 11 Nov 2014 08:40:23 -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 1XoBgE-0004WG-My;
	Tue, 11 Nov 2014 13:40:22 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Tue, 11 Nov 2014 13:40:12 +0000
Message-ID: <1415713212-29488-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] Use EVTCHNOP_unmask to unmask in some cases
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

If the EVTCHN Unmask method is called in context of the event channel
upcall, or on a CPU to which the event is not bound then use the unmask
hypercall. In the former case not doing this may lead to priorty
inversion once setting event channel priorities is enabled. In the latter
case not doing it again stops a lower priority event handler trigger from
blocking a higher priority event injection.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 include/xen.h            |  7 ++++++
 src/xen/event_channel.c  | 28 ++++++++++++++++++++++++
 src/xenbus/evtchn.c      | 56 +++++++++++++++++++++++++++++-------------------
 src/xenbus/evtchn_fifo.c |  5 +----
 src/xenbus/shared_info.c |  5 +----
 5 files changed, 71 insertions(+), 30 deletions(-)

diff --git a/include/xen.h b/include/xen.h
index 84197a5..fa95edd 100644
--- a/include/xen.h
+++ b/include/xen.h
@@ -212,6 +212,13 @@ EventChannelBindVirtualCpu(
     IN  unsigned int        vcpu_id
     );
 
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelUnmask(
+    IN  ULONG   LocalPort
+    );
+
 // GRANT TABLE
 
 __checkReturn
diff --git a/src/xen/event_channel.c b/src/xen/event_channel.c
index 94a6b82..aa9fb48 100644
--- a/src/xen/event_channel.c
+++ b/src/xen/event_channel.c
@@ -357,3 +357,31 @@ fail1:
 
     return status;
 }
+
+__checkReturn
+XEN_API
+NTSTATUS
+EventChannelUnmask(
+    IN  ULONG               LocalPort
+    )
+{
+    struct evtchn_unmask    op;
+    LONG_PTR                rc;
+    NTSTATUS                status;
+
+    op.port = LocalPort;
+
+    rc = EventChannelOp(EVTCHNOP_unmask, &op);
+
+    if (rc < 0) {
+        ERRNO_TO_STATUS(-rc, status);
+        goto fail1;
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index c6ac30d..f88c208 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -624,60 +624,72 @@ static BOOLEAN
 EvtchnUnmask(
     IN  PINTERFACE              Interface,
     IN  PXENBUS_EVTCHN_CHANNEL  Channel,
-    IN  BOOLEAN                 InCallback
+    IN  BOOLEAN                 InUpcall
     )
 {
     PXENBUS_EVTCHN_CONTEXT      Context = Interface->Context;
     KIRQL                       Irql = PASSIVE_LEVEL;
-    BOOLEAN                     Pending = FALSE;
+    BOOLEAN                     Pending;
+    ULONG                       LocalPort;
     ULONG                       Cpu;
-    PXENBUS_INTERRUPT           Interrupt;
 
     ASSERT3U(Channel->Magic, ==, XENBUS_EVTCHN_CHANNEL_MAGIC);
 
-    if (!InCallback)
+    if (!InUpcall)
         KeAcquireSpinLock(&Channel->Lock, &Irql);
 
     ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
 
+    Pending = FALSE;
+
     if (!Channel->Active)
         goto done;
 
+    LocalPort = Channel->LocalPort;
+
     Pending = XENBUS_EVTCHN_ABI(PortUnmask,
                                 &Context->EvtchnAbi,
-                                Channel->LocalPort);
+                                LocalPort);
 
     if (!Pending)
         goto done;
 
-    if (InCallback)
-        goto mask;
-
-    ASSERT3U(KeGetCurrentIrql(), >=, DISPATCH_LEVEL);
-    Cpu = KeGetCurrentProcessorNumber();
-
-    Interrupt = Context->LatchedInterrupt[Cpu];
+    //
+    // If we are in context of the upcall then use a hypercall
+    // to schedule the pending event.
+    //
+    if (InUpcall) {
+        (VOID) EventChannelUnmask(LocalPort);
 
-    if (Channel->Interrupt == Interrupt)
-        goto mask;
+        Pending = FALSE;
+        goto done;
+    }
 
     //
-    // We are not on the CPU to which the event is bound so
-    // we must trigger.
+    // If we are not unmasking on the same CPU to which the
+    // event channel is bound, then we need to use a hypercall
+    // to schedule the upcall on the correct CPU.
     //
-    EvtchnTrigger(Interface, Channel);
+    Cpu = KeGetCurrentProcessorNumber();
 
-    Pending = FALSE;
-    goto done;
+    if (Channel->Cpu != Cpu) {
+        (VOID) EventChannelUnmask(LocalPort);
+
+        Pending = FALSE;
+        goto done;
+    }
 
-mask:
     if (Channel->Mask)
         XENBUS_EVTCHN_ABI(PortMask,
                           &Context->EvtchnAbi,
-                          Channel->LocalPort);
+                          LocalPort);
+
+    XENBUS_EVTCHN_ABI(PortAck,
+                      &Context->EvtchnAbi,
+                      LocalPort);
 
 done:
-    if (!InCallback)
+    if (!InUpcall)
         KeReleaseSpinLock(&Channel->Lock, Irql);
 
     return Pending;
diff --git a/src/xenbus/evtchn_fifo.c b/src/xenbus/evtchn_fifo.c
index f65cc1b..e045cd0 100644
--- a/src/xenbus/evtchn_fifo.c
+++ b/src/xenbus/evtchn_fifo.c
@@ -437,10 +437,7 @@ EvtchnFifoPortUnmask(
         return FALSE;
 
     // If we cleared the mask then check whether something is pending
-    if (!__EvtchnFifoTestAndClearFlag(EventWord, EVTCHN_FIFO_PENDING))
-        return FALSE;
-
-    return TRUE;
+    return __EvtchnFifoTestFlag(EventWord, EVTCHN_FIFO_PENDING);
 }
 
 static VOID
diff --git a/src/xenbus/shared_info.c b/src/xenbus/shared_info.c
index 67be20c..240d87b 100644
--- a/src/xenbus/shared_info.c
+++ b/src/xenbus/shared_info.c
@@ -316,10 +316,7 @@ SharedInfoEvtchnUnmask(
     KeMemoryBarrier();
 
     // If we cleared the mask then check whether something was pending
-    if (!SharedInfoClearBit(&Shared->evtchn_pending[SelectorBit], PortBit))
-        return FALSE;
-
-    return TRUE;
+    return SharedInfoTestBit(&Shared->evtchn_pending[SelectorBit], PortBit);
 }
 
 static LARGE_INTEGER
-- 
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 Nov 12 15:09:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 15:09:05 +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 1XoZXd-0006fo-4h; Wed, 12 Nov 2014 15:09:05 +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 1XoZXc-0006fi-Ai
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 15:09:04 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	17/43-09842-F0873645; Wed, 12 Nov 2014 15:09:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1415804940!12198410!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13396 invoked from network); 12 Nov 2014 15:09:03 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 15:09:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="191989546"
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.181.6;
	Wed, 12 Nov 2014 10:07:43 -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 1XoZWJ-00077H-7y;
	Wed, 12 Nov 2014 15:07:43 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 15:07:34 +0000
Message-ID: <1415804854-4136-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 ASSERTion failure in EVTCHN Close
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 EVTCHN Channel structure contains a BOOLEAN Mask field that specifies
whether the Channel is aut0-masked on event upcall. The Close method was
failing to zero then and then falling over a later assertion that the
Channel structure had been zeroed out.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index f88c208..b1528d5 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -772,6 +772,7 @@ EvtchnClose(
     Channel->Cpu = 0;
 
     Channel->LocalPort = 0;
+    Channel->Mask = FALSE;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
     Channel->Argument = 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 Nov 12 15:09:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 15:09:05 +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 1XoZXd-0006fo-4h; Wed, 12 Nov 2014 15:09:05 +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 1XoZXc-0006fi-Ai
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 15:09:04 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	17/43-09842-F0873645; Wed, 12 Nov 2014 15:09:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-21.messagelabs.com!1415804940!12198410!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 13396 invoked from network); 12 Nov 2014 15:09:03 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-11.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 15:09:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="191989546"
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.181.6;
	Wed, 12 Nov 2014 10:07:43 -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 1XoZWJ-00077H-7y;
	Wed, 12 Nov 2014 15:07:43 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 15:07:34 +0000
Message-ID: <1415804854-4136-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 ASSERTion failure in EVTCHN Close
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 EVTCHN Channel structure contains a BOOLEAN Mask field that specifies
whether the Channel is aut0-masked on event upcall. The Close method was
failing to zero then and then falling over a later assertion that the
Channel structure had been zeroed out.

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

diff --git a/src/xenbus/evtchn.c b/src/xenbus/evtchn.c
index f88c208..b1528d5 100644
--- a/src/xenbus/evtchn.c
+++ b/src/xenbus/evtchn.c
@@ -772,6 +772,7 @@ EvtchnClose(
     Channel->Cpu = 0;
 
     Channel->LocalPort = 0;
+    Channel->Mask = FALSE;
     RtlZeroMemory(&Channel->Parameters, sizeof (XENBUS_EVTCHN_PARAMETERS));
 
     Channel->Argument = 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 Nov 12 16:39:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawk-0003SB-8V; Wed, 12 Nov 2014 16:39:06 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawi-0003S0-A9
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:04 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	0C/04-17958-72D83645; Wed, 12 Nov 2014 16:39:03 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17324 invoked from network); 12 Nov 2014 16:39:02 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032056"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:49 +0000
Message-ID: <1415810330-1152-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/4] Pullup headers and calculate hash over
	IP addresses and 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

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h   |  2 ++
 src/xennet/toeplitzhash.h | 71 ++++++++++++++++++++++++++++++++++++++++++
 src/xennet/transmitter.c  | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 src/xennet/toeplitzhash.h

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 4ce61c4..83e3846 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
     ULONG                                       Length;
     /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Hash value calculated from packet's headers */
+    ULONGLONG                                   HashValue;
     /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
     /*! Information passed up from subscriber for packet completion */
diff --git a/src/xennet/toeplitzhash.h b/src/xennet/toeplitzhash.h
new file mode 100644
index 0000000..df9e924
--- /dev/null
+++ b/src/xennet/toeplitzhash.h
@@ -0,0 +1,71 @@
+/* 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_TOEPLITZ_HASH_H
+#define _XENVIF_TOEPLITZ_HASH_H
+
+static const UCHAR ToeplitzKey[] = {
+    0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+    0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+    0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+    0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+    0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
+};
+
+static FORCEINLINE ULONG
+ToeplitzHash(
+    IN  PUCHAR              Input,
+    IN  ULONG               Length
+    )
+{
+    ULONG                   Bit, Byte;
+    ULONG                   Keyword;
+    ULONG                   HashValue;
+    const UCHAR*            Next;
+
+    Next = ToeplitzKey + sizeof(ULONG);
+    Keyword = RtlUlongByteSwap(*(PULONG)ToeplitzKey);
+    HashValue = 0;
+
+    for (Byte = 0; Byte < Length; ++Byte) {
+        for (Bit = 0; Bit < 8; ++Bit) {
+            if (Input[Byte] & (1 << (8 - Bit)))
+                HashValue ^= Keyword;
+            Keyword = (Keyword << 1) | ((*Next) >> (8 - Bit) & 1);
+        }
+        ++Next;
+    }
+
+    return HashValue;
+}
+
+#endif // _XENVIF_TOEPLITZ_HASH_H
+
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 9bf730c..e408364 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -32,6 +32,8 @@
 #include <ndis.h>
 #include "transmitter.h"
 #include "adapter.h"
+#include "toeplitzhash.h"
+#include <tcpip.h>
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -281,6 +283,82 @@ __OffloadOptions(
     }
 }
 
+static FORCEINLINE ULONGLONG
+__TransmitterCalculateHash(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    UCHAR               Buffer[1024];
+    UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 + sizeof(USHORT)*2
+    PUCHAR              Ptr;
+    XENVIF_PACKET_INFO  Info;
+    NTSTATUS            status;
+
+    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
+
+    status = XENVIF_VIF(TransmitterGetPacketHeaders,
+                        Transmitter->VifInterface,
+                        Packet->Mdl,
+                        Packet->Offset,
+                        Packet->Length,
+                        Buffer,
+                        sizeof(Buffer),
+                        &Info);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Ptr = HashOver;
+    if (Info.IpHeader.Length) {
+        PIP_HEADER  IpHeader;
+
+        IpHeader = (PIP_HEADER)(Buffer + Info.IpHeader.Offset);
+
+        if (IpHeader->Version == 4) {
+            RtlCopyMemory(Ptr, &IpHeader->Version4.SourceAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            RtlCopyMemory(Ptr, &IpHeader->Version4.DestinationAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+        } else if (IpHeader->Version == 6) {
+            RtlCopyMemory(Ptr, &IpHeader->Version6.SourceAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            RtlCopyMemory(Ptr, &IpHeader->Version6.DestinationAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+        }
+    }
+    if (Info.TcpHeader.Length) {
+        PTCP_HEADER TcpHeader;
+
+        TcpHeader = (PTCP_HEADER)(Buffer + Info.TcpHeader.Offset);
+
+        *(PUSHORT)Ptr = TcpHeader->SourcePort;
+        Ptr += sizeof(USHORT);
+        *(PUSHORT)Ptr = TcpHeader->DestinationPort;
+        Ptr += sizeof(USHORT);
+    } else if (Info.UdpHeader.Length) {
+        PUDP_HEADER UdpHeader;
+
+        UdpHeader = (PUDP_HEADER)(Buffer + Info.UdpHeader.Offset);
+
+        *(PUSHORT)Ptr = UdpHeader->SourcePort;
+        Ptr += sizeof(USHORT);
+        *(PUSHORT)Ptr = UdpHeader->DestinationPort;
+        Ptr += sizeof(USHORT);
+    }
+    if (Ptr - HashOver == 0)
+        goto done;
+
+    return ToeplitzHash(HashOver, (ULONG)(Ptr - HashOver));
+
+done:
+    return 0;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return 0;
+}
+
 static FORCEINLINE VOID
 __TransmitterSendNetBufferListsV1(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -400,6 +478,7 @@ __TransmitterSendNetBufferListsV2(
             Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
             Packet->Offset                      = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
             Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            Packet->HashValue                   = __TransmitterCalculateHash(Transmitter, Packet);
             RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
 
             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 Wed Nov 12 16:39:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawk-0003SB-8V; Wed, 12 Nov 2014 16:39:06 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawi-0003S0-A9
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:04 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	0C/04-17958-72D83645; Wed, 12 Nov 2014 16:39:03 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17324 invoked from network); 12 Nov 2014 16:39:02 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032056"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:49 +0000
Message-ID: <1415810330-1152-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 3/4] Pullup headers and calculate hash over
	IP addresses and 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

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h   |  2 ++
 src/xennet/toeplitzhash.h | 71 ++++++++++++++++++++++++++++++++++++++++++
 src/xennet/transmitter.c  | 79 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 src/xennet/toeplitzhash.h

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 4ce61c4..83e3846 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
     ULONG                                       Length;
     /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Hash value calculated from packet's headers */
+    ULONGLONG                                   HashValue;
     /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
     /*! Information passed up from subscriber for packet completion */
diff --git a/src/xennet/toeplitzhash.h b/src/xennet/toeplitzhash.h
new file mode 100644
index 0000000..df9e924
--- /dev/null
+++ b/src/xennet/toeplitzhash.h
@@ -0,0 +1,71 @@
+/* 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_TOEPLITZ_HASH_H
+#define _XENVIF_TOEPLITZ_HASH_H
+
+static const UCHAR ToeplitzKey[] = {
+    0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
+    0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
+    0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
+    0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
+    0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
+};
+
+static FORCEINLINE ULONG
+ToeplitzHash(
+    IN  PUCHAR              Input,
+    IN  ULONG               Length
+    )
+{
+    ULONG                   Bit, Byte;
+    ULONG                   Keyword;
+    ULONG                   HashValue;
+    const UCHAR*            Next;
+
+    Next = ToeplitzKey + sizeof(ULONG);
+    Keyword = RtlUlongByteSwap(*(PULONG)ToeplitzKey);
+    HashValue = 0;
+
+    for (Byte = 0; Byte < Length; ++Byte) {
+        for (Bit = 0; Bit < 8; ++Bit) {
+            if (Input[Byte] & (1 << (8 - Bit)))
+                HashValue ^= Keyword;
+            Keyword = (Keyword << 1) | ((*Next) >> (8 - Bit) & 1);
+        }
+        ++Next;
+    }
+
+    return HashValue;
+}
+
+#endif // _XENVIF_TOEPLITZ_HASH_H
+
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index 9bf730c..e408364 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -32,6 +32,8 @@
 #include <ndis.h>
 #include "transmitter.h"
 #include "adapter.h"
+#include "toeplitzhash.h"
+#include <tcpip.h>
 #include "dbg_print.h"
 #include "assert.h"
 
@@ -281,6 +283,82 @@ __OffloadOptions(
     }
 }
 
+static FORCEINLINE ULONGLONG
+__TransmitterCalculateHash(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    UCHAR               Buffer[1024];
+    UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 + sizeof(USHORT)*2
+    PUCHAR              Ptr;
+    XENVIF_PACKET_INFO  Info;
+    NTSTATUS            status;
+
+    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
+
+    status = XENVIF_VIF(TransmitterGetPacketHeaders,
+                        Transmitter->VifInterface,
+                        Packet->Mdl,
+                        Packet->Offset,
+                        Packet->Length,
+                        Buffer,
+                        sizeof(Buffer),
+                        &Info);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Ptr = HashOver;
+    if (Info.IpHeader.Length) {
+        PIP_HEADER  IpHeader;
+
+        IpHeader = (PIP_HEADER)(Buffer + Info.IpHeader.Offset);
+
+        if (IpHeader->Version == 4) {
+            RtlCopyMemory(Ptr, &IpHeader->Version4.SourceAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+            RtlCopyMemory(Ptr, &IpHeader->Version4.DestinationAddress, sizeof(IPV4_ADDRESS));
+            Ptr += sizeof(IPV4_ADDRESS);
+        } else if (IpHeader->Version == 6) {
+            RtlCopyMemory(Ptr, &IpHeader->Version6.SourceAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+            RtlCopyMemory(Ptr, &IpHeader->Version6.DestinationAddress, sizeof(IPV6_ADDRESS));
+            Ptr += sizeof(IPV6_ADDRESS);
+        }
+    }
+    if (Info.TcpHeader.Length) {
+        PTCP_HEADER TcpHeader;
+
+        TcpHeader = (PTCP_HEADER)(Buffer + Info.TcpHeader.Offset);
+
+        *(PUSHORT)Ptr = TcpHeader->SourcePort;
+        Ptr += sizeof(USHORT);
+        *(PUSHORT)Ptr = TcpHeader->DestinationPort;
+        Ptr += sizeof(USHORT);
+    } else if (Info.UdpHeader.Length) {
+        PUDP_HEADER UdpHeader;
+
+        UdpHeader = (PUDP_HEADER)(Buffer + Info.UdpHeader.Offset);
+
+        *(PUSHORT)Ptr = UdpHeader->SourcePort;
+        Ptr += sizeof(USHORT);
+        *(PUSHORT)Ptr = UdpHeader->DestinationPort;
+        Ptr += sizeof(USHORT);
+    }
+    if (Ptr - HashOver == 0)
+        goto done;
+
+    return ToeplitzHash(HashOver, (ULONG)(Ptr - HashOver));
+
+done:
+    return 0;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return 0;
+}
+
 static FORCEINLINE VOID
 __TransmitterSendNetBufferListsV1(
     IN  PXENNET_TRANSMITTER     Transmitter,
@@ -400,6 +478,7 @@ __TransmitterSendNetBufferListsV2(
             Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
             Packet->Offset                      = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
             Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            Packet->HashValue                   = __TransmitterCalculateHash(Transmitter, Packet);
             RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
 
             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 Wed Nov 12 16:39:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawl-0003SW-9Z; Wed, 12 Nov 2014 16:39:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawj-0003S5-3J
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:05 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	9C/68-25727-82D83645; Wed, 12 Nov 2014 16:39:04 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17463 invoked from network); 12 Nov 2014 16:39:03 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032057"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:50 +0000
Message-ID: <1415810330-1152-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/4] Use a cache for header buffers,
	to fix a 'function uses too much stack' warning
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

Tweak GetPacketHeaders interface call to pass less parameters.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  16 +++---
 src/xennet/transmitter.c | 142 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 136 insertions(+), 22 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 83e3846..5662293 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -528,16 +528,18 @@ typedef NTSTATUS
     \brief Get a copy of the packet headers and each the offset of each
 
     \param Interface The interface header
+    \param Packet The packet
+    \param HeaderBuffer Buffer to receive a copy of the headers
+    \param HeaderLength Length in bytes of Buffer
+    \param Info Location to receive offsets of headers into Buffer
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
-    IN  PINTERFACE          Interface,
-    IN  PMDL                Mdl,
-    IN  ULONG               Offset,
-    IN  ULONG               Length,
-    OUT PVOID               HeaderBuffer,
-    IN  ULONG               HeaderLength,
-    OUT PXENVIF_PACKET_INFO Info
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet,
+    OUT PVOID                           HeaderBuffer,
+    IN  ULONG                           HeaderLength,
+    OUT PXENVIF_PACKET_INFO             Info
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index e408364..4738eed 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -43,10 +43,13 @@ struct _XENNET_TRANSMITTER {
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
 
     PXENBUS_CACHE_INTERFACE     CacheInterface;
-    PXENBUS_CACHE               Cache;
+    PXENBUS_CACHE               PacketCache;
+    PXENBUS_CACHE               BufferCache;
+    KSPIN_LOCK                  Lock;
 };
 
 #define TRANSMITTER_POOL_TAG    'teNX'
+#define BUFFER_SIZE             PAGE_SIZE
 
 static NTSTATUS
 __PacketCtor(
@@ -74,7 +77,8 @@ __PacketAcquire(
     IN  PVOID           Argument
     )
 {
-    UNREFERENCED_PARAMETER(Argument);
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
 }
 
 static VOID
@@ -82,7 +86,47 @@ __PacketRelease(
     IN  PVOID           Argument
     )
 {
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
+}
+
+static NTSTATUS
+__BufferCtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, BUFFER_SIZE);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__BufferDtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
     UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__BufferAcquire(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
+}
+
+static VOID
+__BufferRelease(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
 }
 
 static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
@@ -92,11 +136,11 @@ __TransmitterGetPacket(
 {
     ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
     ASSERT(Transmitter->CacheInterface != NULL);
-    ASSERT(Transmitter->Cache != NULL);
+    ASSERT(Transmitter->PacketCache != NULL);
 
     return XENBUS_CACHE(Get,
                         Transmitter->CacheInterface,
-                        Transmitter->Cache,
+                        Transmitter->PacketCache,
                         FALSE);
 }
 
@@ -108,15 +152,47 @@ __TransmitterPutPacket(
 {
     ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
     ASSERT(Transmitter->CacheInterface != NULL);
-    ASSERT(Transmitter->Cache != NULL);
+    ASSERT(Transmitter->PacketCache != NULL);
 
     XENBUS_CACHE(Put,
                  Transmitter->CacheInterface,
-                 Transmitter->Cache,
+                 Transmitter->PacketCache,
                  Packet,
                  FALSE);
 }
 
+static FORCEINLINE PVOID
+__TransmitterGetBuffer(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->BufferCache != NULL);
+
+    return XENBUS_CACHE(Get,
+                        Transmitter->CacheInterface,
+                        Transmitter->BufferCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutBuffer(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PVOID                   Buffer
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->BufferCache != NULL);
+
+    XENBUS_CACHE(Put,
+                 Transmitter->CacheInterface,
+                 Transmitter->BufferCache,
+                 Buffer,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -289,24 +365,27 @@ __TransmitterCalculateHash(
     IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
     )
 {
-    UCHAR               Buffer[1024];
+    PUCHAR              Buffer;
     UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 + sizeof(USHORT)*2
     PUCHAR              Ptr;
     XENVIF_PACKET_INFO  Info;
     NTSTATUS            status;
 
+    status = STATUS_NO_MEMORY;
+    Buffer = __TransmitterGetBuffer(Transmitter);
+    if (Buffer == NULL)
+        goto fail1;
+
     RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
 
     status = XENVIF_VIF(TransmitterGetPacketHeaders,
                         Transmitter->VifInterface,
-                        Packet->Mdl,
-                        Packet->Offset,
-                        Packet->Length,
+                        Packet,
                         Buffer,
-                        sizeof(Buffer),
+                        BUFFER_SIZE,
                         &Info);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     Ptr = HashOver;
     if (Info.IpHeader.Length) {
@@ -345,6 +424,9 @@ __TransmitterCalculateHash(
         *(PUSHORT)Ptr = UdpHeader->DestinationPort;
         Ptr += sizeof(USHORT);
     }
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+
     if (Ptr - HashOver == 0)
         goto done;
 
@@ -353,6 +435,11 @@ __TransmitterCalculateHash(
 done:
     return 0;
 
+fail2:
+    Error("fail2\n");
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -619,6 +706,7 @@ TransmitterInitialize(
     if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
         goto done;
 
+    KeInitializeSpinLock(&(*Transmitter)->Lock);
     (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
     status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
     if (!NT_SUCCESS(status))
@@ -634,19 +722,38 @@ TransmitterInitialize(
                           __PacketAcquire,
                           __PacketRelease,
                           *Transmitter,
-                          &(*Transmitter)->Cache);
+                          &(*Transmitter)->PacketCache);
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = XENBUS_CACHE(Create,
+                          (*Transmitter)->CacheInterface,
+                          "buffers",
+                          BUFFER_SIZE,
+                          4,
+                          __BufferCtor,
+                          __BufferDtor,
+                          __BufferAcquire,
+                          __BufferRelease,
+                          *Transmitter,
+                          &(*Transmitter)->BufferCache);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
 done:
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+    XENBUS_CACHE(Destroy, (*Transmitter)->CacheInterface, (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
 fail4:
     Error("fail4\n");
     XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
     (*Transmitter)->CacheInterface = NULL;
 fail3:
     Error("fail3\n");
+    RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK));
     XENVIF_VIF(Release, (*Transmitter)->VifInterface);
     (*Transmitter)->VifInterface = NULL;
 fail2:
@@ -666,12 +773,17 @@ TransmitterTeardown(
     if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
         goto done;
 
-    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->Cache);
-    Transmitter->Cache = NULL;
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->BufferCache);
+    Transmitter->BufferCache = NULL;
+
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
 
     XENBUS_CACHE(Release, Transmitter->CacheInterface);
     Transmitter->CacheInterface = NULL;
 
+    RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK));
+
 done:
     XENVIF_VIF(Release, Transmitter->VifInterface);
     Transmitter->VifInterface = NULL;
-- 
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 Wed Nov 12 16:39:07 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawl-0003SW-9Z; Wed, 12 Nov 2014 16:39:07 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawj-0003S5-3J
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:05 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	9C/68-25727-82D83645; Wed, 12 Nov 2014 16:39:04 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17463 invoked from network); 12 Nov 2014 16:39:03 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032057"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:50 +0000
Message-ID: <1415810330-1152-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 4/4] Use a cache for header buffers,
	to fix a 'function uses too much stack' warning
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

Tweak GetPacketHeaders interface call to pass less parameters.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  16 +++---
 src/xennet/transmitter.c | 142 ++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 136 insertions(+), 22 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 83e3846..5662293 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -528,16 +528,18 @@ typedef NTSTATUS
     \brief Get a copy of the packet headers and each the offset of each
 
     \param Interface The interface header
+    \param Packet The packet
+    \param HeaderBuffer Buffer to receive a copy of the headers
+    \param HeaderLength Length in bytes of Buffer
+    \param Info Location to receive offsets of headers into Buffer
 */
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
-    IN  PINTERFACE          Interface,
-    IN  PMDL                Mdl,
-    IN  ULONG               Offset,
-    IN  ULONG               Length,
-    OUT PVOID               HeaderBuffer,
-    IN  ULONG               HeaderLength,
-    OUT PXENVIF_PACKET_INFO Info
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet,
+    OUT PVOID                           HeaderBuffer,
+    IN  ULONG                           HeaderLength,
+    OUT PXENVIF_PACKET_INFO             Info
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index e408364..4738eed 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -43,10 +43,13 @@ struct _XENNET_TRANSMITTER {
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
 
     PXENBUS_CACHE_INTERFACE     CacheInterface;
-    PXENBUS_CACHE               Cache;
+    PXENBUS_CACHE               PacketCache;
+    PXENBUS_CACHE               BufferCache;
+    KSPIN_LOCK                  Lock;
 };
 
 #define TRANSMITTER_POOL_TAG    'teNX'
+#define BUFFER_SIZE             PAGE_SIZE
 
 static NTSTATUS
 __PacketCtor(
@@ -74,7 +77,8 @@ __PacketAcquire(
     IN  PVOID           Argument
     )
 {
-    UNREFERENCED_PARAMETER(Argument);
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
 }
 
 static VOID
@@ -82,7 +86,47 @@ __PacketRelease(
     IN  PVOID           Argument
     )
 {
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
+}
+
+static NTSTATUS
+__BufferCtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, BUFFER_SIZE);
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__BufferDtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
     UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__BufferAcquire(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
+}
+
+static VOID
+__BufferRelease(
+    IN  PVOID           Argument
+    )
+{
+    PXENNET_TRANSMITTER Transmitter = Argument;
+    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
 }
 
 static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
@@ -92,11 +136,11 @@ __TransmitterGetPacket(
 {
     ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
     ASSERT(Transmitter->CacheInterface != NULL);
-    ASSERT(Transmitter->Cache != NULL);
+    ASSERT(Transmitter->PacketCache != NULL);
 
     return XENBUS_CACHE(Get,
                         Transmitter->CacheInterface,
-                        Transmitter->Cache,
+                        Transmitter->PacketCache,
                         FALSE);
 }
 
@@ -108,15 +152,47 @@ __TransmitterPutPacket(
 {
     ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
     ASSERT(Transmitter->CacheInterface != NULL);
-    ASSERT(Transmitter->Cache != NULL);
+    ASSERT(Transmitter->PacketCache != NULL);
 
     XENBUS_CACHE(Put,
                  Transmitter->CacheInterface,
-                 Transmitter->Cache,
+                 Transmitter->PacketCache,
                  Packet,
                  FALSE);
 }
 
+static FORCEINLINE PVOID
+__TransmitterGetBuffer(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->BufferCache != NULL);
+
+    return XENBUS_CACHE(Get,
+                        Transmitter->CacheInterface,
+                        Transmitter->BufferCache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutBuffer(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PVOID                   Buffer
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->BufferCache != NULL);
+
+    XENBUS_CACHE(Put,
+                 Transmitter->CacheInterface,
+                 Transmitter->BufferCache,
+                 Buffer,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -289,24 +365,27 @@ __TransmitterCalculateHash(
     IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
     )
 {
-    UCHAR               Buffer[1024];
+    PUCHAR              Buffer;
     UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 + sizeof(USHORT)*2
     PUCHAR              Ptr;
     XENVIF_PACKET_INFO  Info;
     NTSTATUS            status;
 
+    status = STATUS_NO_MEMORY;
+    Buffer = __TransmitterGetBuffer(Transmitter);
+    if (Buffer == NULL)
+        goto fail1;
+
     RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
 
     status = XENVIF_VIF(TransmitterGetPacketHeaders,
                         Transmitter->VifInterface,
-                        Packet->Mdl,
-                        Packet->Offset,
-                        Packet->Length,
+                        Packet,
                         Buffer,
-                        sizeof(Buffer),
+                        BUFFER_SIZE,
                         &Info);
     if (!NT_SUCCESS(status))
-        goto fail1;
+        goto fail2;
 
     Ptr = HashOver;
     if (Info.IpHeader.Length) {
@@ -345,6 +424,9 @@ __TransmitterCalculateHash(
         *(PUSHORT)Ptr = UdpHeader->DestinationPort;
         Ptr += sizeof(USHORT);
     }
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+
     if (Ptr - HashOver == 0)
         goto done;
 
@@ -353,6 +435,11 @@ __TransmitterCalculateHash(
 done:
     return 0;
 
+fail2:
+    Error("fail2\n");
+
+    __TransmitterPutBuffer(Transmitter, Buffer);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -619,6 +706,7 @@ TransmitterInitialize(
     if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
         goto done;
 
+    KeInitializeSpinLock(&(*Transmitter)->Lock);
     (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
     status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
     if (!NT_SUCCESS(status))
@@ -634,19 +722,38 @@ TransmitterInitialize(
                           __PacketAcquire,
                           __PacketRelease,
                           *Transmitter,
-                          &(*Transmitter)->Cache);
+                          &(*Transmitter)->PacketCache);
     if (!NT_SUCCESS(status))
         goto fail4;
 
+    status = XENBUS_CACHE(Create,
+                          (*Transmitter)->CacheInterface,
+                          "buffers",
+                          BUFFER_SIZE,
+                          4,
+                          __BufferCtor,
+                          __BufferDtor,
+                          __BufferAcquire,
+                          __BufferRelease,
+                          *Transmitter,
+                          &(*Transmitter)->BufferCache);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
 done:
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+    XENBUS_CACHE(Destroy, (*Transmitter)->CacheInterface, (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
 fail4:
     Error("fail4\n");
     XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
     (*Transmitter)->CacheInterface = NULL;
 fail3:
     Error("fail3\n");
+    RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK));
     XENVIF_VIF(Release, (*Transmitter)->VifInterface);
     (*Transmitter)->VifInterface = NULL;
 fail2:
@@ -666,12 +773,17 @@ TransmitterTeardown(
     if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
         goto done;
 
-    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->Cache);
-    Transmitter->Cache = NULL;
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->BufferCache);
+    Transmitter->BufferCache = NULL;
+
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
 
     XENBUS_CACHE(Release, Transmitter->CacheInterface);
     Transmitter->CacheInterface = NULL;
 
+    RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK));
+
 done:
     XENVIF_VIF(Release, Transmitter->VifInterface);
     Transmitter->VifInterface = NULL;
-- 
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 Wed Nov 12 16:39:08 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:08 +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 1Xoawm-0003T1-Ag; Wed, 12 Nov 2014 16:39:08 +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 1Xoawk-0003SA-Av
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:06 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	49/D7-19763-92D83645; Wed, 12 Nov 2014 16:39:05 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415810341!10957645!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8326 invoked from network); 12 Nov 2014 16:39:03 -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;
	12 Nov 2014 16:39:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032058"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:48 +0000
Message-ID: <1415810330-1152-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/4] Add VIF interface version 2
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 | 232 +++++++++++++++++++++++
 include/vif_interface.h   | 454 ++++++++++++++++++++++++++++++++++++++++++++--
 src/xennet/adapter.c      |  73 +++++++-
 src/xennet/adapter.h      |   6 +
 src/xennet/receiver.c     |  22 ++-
 src/xennet/transmitter.c  | 354 +++++++++++++++++++++++++++++++-----
 src/xennet/transmitter.h  |  12 +-
 7 files changed, 1072 insertions(+), 81 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..12599ef
--- /dev/null
+++ b/include/cache_interface.h
@@ -0,0 +1,232 @@
+/* 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
+*/
+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/include/vif_interface.h b/include/vif_interface.h
index 60a3e9c..4ce61c4 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -29,6 +29,12 @@
  * SUCH DAMAGE.
  */
 
+/*! \file vif_interface.h
+    \brief XENVIF VIF Interface
+
+    This interface provides access to the PV network frontend
+*/
+
 #ifndef _XENVIF_VIF_INTERFACE_H
 #define _XENVIF_VIF_INTERFACE_H
 
@@ -37,21 +43,39 @@
 #include <ifdef.h>
 #include <ethernet.h>
 
+/*! \struct _XENVIF_PACKET_HEADER_V1
+    \brief Packet header information
+*/
 struct  _XENVIF_PACKET_HEADER_V1 {
+    /*! Offset from beginning of packet */
     ULONG   Offset;
+    /*! Length of header (0 indicates a header is not present) */
     ULONG   Length;
 };
 
+/*! \struct _XENVIF_PACKET_INFO_V1
+    \brief Packet information
+*/
 struct _XENVIF_PACKET_INFO_V1 {
+    /*! Total length of all headers */
     ULONG                           Length;
+    /*! VLAN TCI if present (0 indicates not present) */
     USHORT                          TagControlInformation;
+    /*! TRUE if the packet is an IP fragment */
     BOOLEAN                         IsAFragment;
+    /*! Ethernet header (stripped of any VLAN tag) */
     struct _XENVIF_PACKET_HEADER_V1 EthernetHeader;
+    /*! LLC header (used for IPX or 802.3 IP) */
     struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader;
+    /*! IP header (v4 or v6) */
     struct _XENVIF_PACKET_HEADER_V1 IpHeader;
+    /*! IP options (v4 or v6) */
     struct _XENVIF_PACKET_HEADER_V1 IpOptions;
+    /*! TCP header */
     struct _XENVIF_PACKET_HEADER_V1 TcpHeader;
+    /*! TCP options */
     struct _XENVIF_PACKET_HEADER_V1 TcpOptions;
+    /*! UDP header */
     struct _XENVIF_PACKET_HEADER_V1 UdpHeader;
 };
 
@@ -61,38 +85,63 @@ typedef struct _XENVIF_PACKET_INFO_V1   XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO
 #pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
+    \brief Packet checksum flags
+*/
 struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
     union {
         struct {
+            /*! IPv4 header checksum validation succeeded */
             ULONG   IpChecksumSucceeded:1;
+            /*! IPv4 header checksum validation failed */
             ULONG   IpChecksumFailed:1;
+            /*! IPv4 header checksum is present */
             ULONG   IpChecksumPresent:1;
+            /*! TCP checksum validation succeeded */
             ULONG   TcpChecksumSucceeded:1;
+            /*! TCP checksum validation failed */
             ULONG   TcpChecksumFailed:1;
+            /*! TCP checksum is present */
             ULONG   TcpChecksumPresent:1;
+            /*! UDP checksum validation succeeded */
             ULONG   UdpChecksumSucceeded:1;
+            /*! UDP checksum validation failed */
             ULONG   UdpChecksumFailed:1;
+            /*! UDP checksum is present */
             ULONG   UdpChecksumPresent:1;
             ULONG   Reserved:23;
         };
-
+        /*! Raw representation */
         ULONG   Value;
     };
 };
 
+
 typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS, *PXENVIF_PACKET_CHECKSUM_FLAGS;
 
 #pragma warning(pop)
 
+/*! \struct _XENVIF_RECEIVER_PACKET_V1
+    \brief Receive-side packet structure
+*/
 struct _XENVIF_RECEIVER_PACKET_V1 {
+    /*! List entry used for chaining packets together */
     LIST_ENTRY                              ListEntry;
+    /*! Pointer to packet information */
     struct _XENVIF_PACKET_INFO_V1           *Info;
+    /*! Offset of start of packet in MDL */
     ULONG                                   Offset;
+    /*! Total length of packet */
     ULONG                                   Length;
+    /*! Checksum flags */
     struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags;
+    /*! TCP MSS if the packet contains a TCP large segment */
     USHORT                                  MaximumSegmentSize;
+    /*! Opaque cookie used to store context information for packet return */
     PVOID                                   Cookie;
+    /*! MDL referencing the initial buffer of the packet */
     MDL                                     Mdl;
+    /*! PFN information, which must always follow an MDL */
     PFN_NUMBER                              __Pfn;
 };
 
@@ -102,22 +151,36 @@ typedef struct _XENVIF_RECEIVER_PACKET_V1 XENVIF_RECEIVER_PACKET, *PXENVIF_RECEI
 #pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
+    \brief Offload options
+*/
 struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 {
     union {
         struct {
+            /*! Insert/strip VLAN tags */
             USHORT  OffloadTagManipulation:1;
+            /*! Segment/coalesce IPv4 packets containing TCP large segments */ 
             USHORT  OffloadIpVersion4LargePacket:1;
+            /*! Calculate/validate IPv4 header checksum */
             USHORT  OffloadIpVersion4HeaderChecksum:1;
+            /*! Calculate/validate IPv4 TCP checksum */
             USHORT  OffloadIpVersion4TcpChecksum:1;
+            /*! Calculate/validate IPv4 UDP checksum */
             USHORT  OffloadIpVersion4UdpChecksum:1;
+            /*! Segment/coalesce IPv6 packets containing TCP large segments */ 
             USHORT  OffloadIpVersion6LargePacket:1;
+            /*! Calculate/validate IPv6 TCP checksum */
             USHORT  OffloadIpVersion6TcpChecksum:1;
+            /*! Calculate/validate IPv6 UDP checksum */
             USHORT  OffloadIpVersion6UdpChecksum:1;
+            /*! Force calculation of any missing checksums on receive side */
             USHORT  NeedChecksumValue:1;
+            /*! Force segmentation of packets containing TCP large segments on receive side */
             USHORT  NeedLargePacketSplit:1;
             USHORT  Reserved:6;
         };
 
+        /*! Raw representation */
         USHORT  Value;
     };
 };
@@ -126,28 +189,55 @@ typedef struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 XENVIF_VIF_OFFLOAD_OPTIONS, *PXENV
 
 #pragma warning(pop)
 
-// To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures the XENVIF_TRANSMITTER_PACKET
-// structure must be at most the size of 3 pointer types.
-
 #pragma pack(push, 1) 
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
+    \brief Packet information passed from subscriber to provider on
+    transmit side packet send
+
+    To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+    this structure must be at most the size of 3 pointer types.
+*/
 struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 {
+    /*! Offload options for this packet */
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-    USHORT                      MaximumSegmentSize;     // Only used if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set
-    USHORT                      TagControlInformation;  // Only used if OffloadOptions.OffloadTagManipulation is set
+    /*! TCP MSS (used only if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set) */
+    USHORT                      MaximumSegmentSize;
+    /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set) */
+    USHORT                      TagControlInformation;
 };
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 XENVIF_TRANSMITTER_PACKET_SEND_INFO, *PXENVIF_TRANSMITTER_PACKET_SEND_INFO;
 
+/*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS
+    \brief Transmit-side packet status
+*/
+typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS {
+    /*! Packet was queued for the backend */
+    XENVIF_TRANSMITTER_PACKET_PENDING = 1,
+    /*! Packet has been successfully processed by the backend */
+    XENVIF_TRANSMITTER_PACKET_OK,
+    /*! Packet was dropped */
+    XENVIF_TRANSMITTER_PACKET_DROPPED,
+    /*! There was a problem handling the packet */
+    XENVIF_TRANSMITTER_PACKET_ERROR
+} XENVIF_TRANSMITTER_PACKET_STATUS, *PXENVIF_TRANSMITTER_PACKET_STATUS;
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
+    \brief Packet information passed from provider to subsriber on
+    transmit side packet return
+
+    To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+    this structure must be at most the size of 3 pointer types.
+*/
 struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 {
+    /*! Ethernet address type (see \ref _ETHERNET_ADDRESS_TYPE) */
     UCHAR   Type;
+    /*! Send status (see \ref _XENVIF_TRANSMITTER_PACKET_STATUS) */
     UCHAR   Status;
-
-#define XENVIF_TRANSMITTER_PACKET_PENDING   1
-#define XENVIF_TRANSMITTER_PACKET_OK        2
-#define XENVIF_TRANSMITTER_PACKET_DROPPED   3
-#define XENVIF_TRANSMITTER_PACKET_ERROR     4
-
+    /*! Total length of the sent packet */
     USHORT  PacketLength;
+    /*! Length of packet payload after recognized headers are removed */
     USHORT  PayloadLength;
 };
 
@@ -156,7 +246,11 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 XENVIF_TRANSMITTER_
 #pragma warning(push)
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V1
+    \brief Transmit-side packet structure
+*/
 struct _XENVIF_TRANSMITTER_PACKET_V1 {
+    /*! Pointer used for chaining packets together */
     struct _XENVIF_TRANSMITTER_PACKET_V1                        *Next;
     union {
         struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1          Send;
@@ -164,7 +258,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)
 
@@ -172,64 +266,169 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
+    \brief Transmit-side packet structure
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! MDL referencing the packet's buffer */
+    PMDL                                        Mdl;
+    /*! Offset of start of packet in MDL */
+    ULONG                                       Offset;
+    /*! Total length of packet */
+    ULONG                                       Length;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Packet information passed down to subscriber */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Information passed up from subscriber for packet completion */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
+
+
+/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
+    \brief Offsets of packet metadata relative to
+    XENVIF_TRANSMITTER_PACKET_V1 pointer
+
+    Because the transmit side packet structure is limited to 3 pointer
+    types in size, not all information about the packet can be passed in
+    the structure. Other information can, however, be found by applying
+    these byte offsets to the structure pointer and then dereferencing the
+    specified type.
+*/
 typedef enum _XENVIF_TRANSMITTER_PACKET_OFFSET {
+    /*! The offset of the start of the packet within the MDL (type ULONG) */
     XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET = 0,
+    /*! The total length of the packet (type ULONG) */
     XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
+    /*! MDL referencing the initial buffer of the packet (type PMDL) */
     XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
     XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT
 } XENVIF_TRANSMITTER_PACKET_OFFSET, *PXENVIF_TRANSMITTER_PACKET_OFFSET;
 
+/*! \enum _XENVIF_VIF_STATISTIC
+    \brief Interface statistics
+*/
 typedef enum _XENVIF_VIF_STATISTIC {
+    /*! RFC 2863 ifOutDiscards */
     XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
+    /*! Backend component of RFC 2863 ifOutErrors */
     XENVIF_TRANSMITTER_BACKEND_ERRORS,
+    /*! Frontend component of RFC 2863 ifOutErrors */
     XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+    /*! RFC 2863 ifOutUcastPkts */
     XENVIF_TRANSMITTER_UNICAST_PACKETS,
+    /*! Total number of octets in ifOutUcastPkts */
     XENVIF_TRANSMITTER_UNICAST_OCTETS,
+    /*! RFC 2863 ifOutMulticastPkts */
     XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+    /*! Total number of octets in ifOutMulticastPkts */
     XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+    /*! RFC 2863 ifOutBroadcastPkts */
     XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+    /*! Total number of octets in ifOutBroadcastPkts */
     XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+    /*! RFC 2863 ifInDiscards */
     XENVIF_RECEIVER_PACKETS_DROPPED,
+    /*! Backend component of RFC 2863 ifInErrors */
     XENVIF_RECEIVER_BACKEND_ERRORS,
+    /*! Frontend component of RFC 2863 ifInErrors */
     XENVIF_RECEIVER_FRONTEND_ERRORS,
+    /*! RFC 2863 ifInUcastPkts */
     XENVIF_RECEIVER_UNICAST_PACKETS,
+    /*! Total number of octets in ifInUcastPkts */
     XENVIF_RECEIVER_UNICAST_OCTETS,
+    /*! RFC 2863 ifInMulticastPkts */
     XENVIF_RECEIVER_MULTICAST_PACKETS,
+    /*! Total number of octets in ifInMulticastPkts */
     XENVIF_RECEIVER_MULTICAST_OCTETS,
+    /*! RFC 2863 ifInBroadcastPkts */
     XENVIF_RECEIVER_BROADCAST_PACKETS,
+    /*! Total number of octets in ifInBroadcastPkts */
     XENVIF_RECEIVER_BROADCAST_OCTETS,
     XENVIF_VIF_STATISTIC_COUNT
 } XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
 
+/*! \enum _XENVIF_MAC_FILTER_LEVEL
+    \brief Filter level applied to packets
+*/
 typedef enum _XENVIF_MAC_FILTER_LEVEL {
+    /*! Don't filter out any packets */
     XENVIF_MAC_FILTER_NONE = 0,
+    /*! Filter out all packets except those with a matching destination address */
     XENVIF_MAC_FILTER_MATCHING = 1,
+    /*! Filter out all packets */
     XENVIF_MAC_FILTER_ALL = 2
 } XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
 
+/*! \enum _XENVIF_VIF_CALLBACK_TYPE
+    \brief Type of callback (see \ref XENVIF_VIF_CALLBACK)
+*/
 typedef enum _XENVIF_VIF_CALLBACK_TYPE {
+    /*! Return transmit side packets to the subscriber */
     XENVIF_TRANSMITTER_RETURN_PACKETS = 0,
+    /*! Queue receive side packets at the subscriber */
     XENVIF_RECEIVER_QUEUE_PACKETS,
+    /*! Notify the subscriber of a MAC (link) state has change */
     XENVIF_MAC_STATE_CHANGE
 } XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE;
 
+/*! \typedef XENVIF_VIF_ACQUIRE
+    \brief Acquire a reference to the VIF interface
+
+    \param Interface The interface header
+*/  
 typedef NTSTATUS
 (*XENVIF_VIF_ACQUIRE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_RELEASE
+    \brief Release a reference to the VIF interface
+
+    \param Interface The interface header
+*/  
 typedef VOID
 (*XENVIF_VIF_RELEASE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_CALLBACK
+    \brief Provider to subscriber callback function
+
+    \param Argument An optional context argument passed to the callback
+    \param Type The callback type
+    \param ... Additional paramaters required by \a Type
+
+    \b XENVIF_TRANSMITTER_RETURN_PACKETS:
+    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
+
+    \b XENVIF_RECEIVER_QUEUE_PACKETS:
+    \param List List of XENVIF_RECEIVER_PACKET
+
+    \b XENVIF_MAC_STATE_CHANGE:
+    No additional arguments
+*/
 typedef VOID
 (*XENVIF_VIF_CALLBACK)(
-    IN  PVOID                       Argument,
+    IN  PVOID                       Argument OPTIONAL,
     IN  XENVIF_VIF_CALLBACK_TYPE    Type,
     ...
     );
 
+/*! \typedef XENVIF_VIF_ENABLE
+    \brief Enable the VIF interface
+
+    All packets queued for transmit will be rejected and no packets will
+    be queued for receive until this method completes. 
+
+    \param Interface The interface header
+    \param Callback The subscriber's callback function
+    \param Argument An optional context argument passed to the callback
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_ENABLE)(
     IN  PINTERFACE          Interface,
@@ -237,11 +436,31 @@ typedef NTSTATUS
     IN  PVOID               Argument OPTIONAL
     );
 
+/*! \typedef XENVIF_VIF_DISABLE
+    \brief Disable the VIF interface
+
+    This method will not complete until any packets queued for receive
+    have been returned. Any packets queued for transmit may be aborted.
+
+    \param Interface The interface header
+*/
 typedef VOID
 (*XENVIF_VIF_DISABLE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_QUERY_STATISTIC
+    \brief Query the value of an interface statistic
+
+    Interface statistics are 64-bits wide and zero based. They are
+    zeroed when the vif device object is created. They are not
+    zeroed by this call or by any vif state change (e.g. reconnection
+    across migration).
+
+    \param Interface The interface header
+    \param Index The index of the statistic in \ref _XENVIF_VIF_STATISTIC
+    \param Value Buffer to receive the value of the statistic
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_QUERY_STATISTIC)(
     IN  PINTERFACE              Interface,
@@ -249,12 +468,29 @@ typedef NTSTATUS
     OUT PULONGLONG              Value
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS
+    \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK
+    (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS)
+
+    \param Interface The interface header
+    \param List List of \ref _XENVIF_RECEIVER_PACKET_V1
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_RETURN_PACKETS)(
     IN  PINTERFACE  Interface,
     IN  PLIST_ENTRY List
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
+    \brief Set byte offset of packet information relative to
+    XENVIF_TRANSMITTER_PACKET_V1 pointer.
+
+    See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
+
+    \param Interface The interface header
+    \param Type The offset type
+    \param Value The offset value
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET)(
     IN  PINTERFACE                          Interface,
@@ -262,24 +498,80 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \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
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
+    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_GET_PACKET_HEADERS
+    \brief Get a copy of the packet headers and each the offset of each
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
+    \brief Query the available set of transmit side offload options
+
+    \param Interface The interface header
+    \param Options Buffer to receive the avilable options
+    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS)(
     IN  PINTERFACE                  Interface,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
+    \brief Set the required set of receive side offload options
+
+    \param Interface The interface header
+    \param Options The required options
+    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS)(
     IN  PINTERFACE                  Interface,
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
+    \brief Query the maximum size of packet containing a TCP large segment
+    that can be handled by the transmit side
+
+    \param Interface The interface header
+    \param Version The IP version (4 or 6)
+    \param Size Buffer to receive the maximum packet size
+*/ 
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE)(
     IN  PINTERFACE  Interface,
@@ -287,18 +579,40 @@ typedef VOID
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
+    \brief Query the maximum number of transmit side packets that can
+    be queued in the shared ring between frontend and backend
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum number of packets
+*/
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE
+    \brief Query the maximum number of receive side packets that can
+    be queued in the shared ring between backend and frontend
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum number of packets
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_QUERY_RING_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
+    \brief Query the current MAC (link) state
+
+    \param Interface The interface header
+    \param MediaConnectState Buffer to receive the current connection state
+    \param LinkSpeed Buffer to receive the current link speed in Gbps
+    \param MediaDuplexState Buffer to receive the current duplex state
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_STATE)(
     IN  PINTERFACE                  Interface,
@@ -307,24 +621,58 @@ typedef VOID
     OUT PNET_IF_MEDIA_DUPLEX_STATE  MediaDuplexState OPTIONAL
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE
+    \brief Query the maximum MAC (i.e. on the wire) frame size (not
+    including CRC)
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum frame size
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS
+    \brief Query the permanent MAC address (set by the toolstack)
+
+    \param Interface The interface header
+    \param Address Buffer to receive the permanent address
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS)(
     IN  PINTERFACE          Interface,
     OUT PETHERNET_ADDRESS   Address
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS
+    \brief Query the current MAC address (may be set by the guest)
+
+    The guest OS may override the MAC address using the registry. If this
+    is not done then the current address will be identical to the
+    permanent address.
+
+    \param Interface The interface header
+    \param Address Buffer to receive the current address
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS)(
     IN  PINTERFACE          Interface,
     OUT PETHERNET_ADDRESS   Address
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES
+    \brief Query the current set of active multicast addresses
+
+    \param Interface The interface header
+    \param Address An optional buffer to receive the set of addresses
+    \param Count A buffer to receive the number of active addresses
+
+    Call this method with \a Address set to NULL to get the \a Count,
+    which can then be used to allocate a buffer of suitable size to receive
+    the array of addresses.
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES)(
     IN      PINTERFACE          Interface,
@@ -332,6 +680,16 @@ typedef NTSTATUS
     IN OUT  PULONG              Count
     );
 
+/*! \typedef XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
+    \brief Update the set of active multicast addresses
+
+    \param Interface The interface header
+    \param Address An optional buffer containing the set of addresses
+    \param Count The number of addresses in the buffer
+
+    The \a Address buffer may only by NULL if \a Count is zero, in which
+    case the set of active multicast addresses will be cleared.
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES)(
     IN  PINTERFACE          Interface,
@@ -339,6 +697,14 @@ typedef NTSTATUS
     IN  ULONG               Count
     );
 
+/*! \typedef XENVIF_VIF_MAC_SET_FILTER_LEVEL
+    \brief Set a filter level for a given type of packet
+
+    \param Interface The interface header
+    \param Type The destination address type of the packet
+    (see \ref _ETHERNET_ADDRESS_TYPE)
+    \param Level The new filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_SET_FILTER_LEVEL)(
     IN  PINTERFACE              Interface,
@@ -346,6 +712,14 @@ typedef NTSTATUS
     IN  XENVIF_MAC_FILTER_LEVEL Level
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_FILTER_LEVEL
+    \brief Query the current filter level for a given type of packet
+
+    \param Interface The interface header
+    \param Type The destination address type of the packet
+    (see \ref _ETHERNET_ADDRESS_TYPE)
+    \param Level Buffer to receive the filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_QUERY_FILTER_LEVEL)(
     IN  PINTERFACE                  Interface,
@@ -368,7 +742,34 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
     XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
     XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET        TransmitterSetPacketOffset;
-    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS            TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         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_V1 XENVIF_VIF_INTERFACE_V1, *PXENVIF_VIF_INTERFACE_V1;
+
+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_SET_PACKET_OFFSET        TransmitterSetPacketOffset; // obsolete
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;    // obsolete
     XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
     XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
     XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
@@ -380,16 +781,29 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
     XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePacketsV2;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2, *PXENVIF_VIF_INTERFACE_V2;
 
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \def XENVIF_VIF
+    \brief Macro to assist in method invocation
+*/
 #define XENVIF_VIF(_Method, _Interface, ...)    \
     (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
 
+/*! \def XENVIF_VIF_VERSION
+    \brief Macro to assist in getting interface version in use
+*/
+#define XENVIF_VIF_VERSION(_Interface)          \
+    ((_Interface)->Interface.Version)
+
 #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/xennet/adapter.c b/src/xennet/adapter.c
index 6b32d1a..e3d6e05 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -41,6 +41,7 @@
 
 struct _XENNET_ADAPTER {
     XENVIF_VIF_INTERFACE        VifInterface;
+    XENBUS_CACHE_INTERFACE      CacheInterface;
 
     BOOLEAN                     Enabled;
     ULONG                       MaximumFrameSize;
@@ -171,14 +172,30 @@ AdapterVifCallback(
     va_start(Arguments, Type);
 
     switch (Type) {
-    case XENVIF_TRANSMITTER_RETURN_PACKETS: {
-        PXENVIF_TRANSMITTER_PACKET HeadPacket;
+    case XENVIF_TRANSMITTER_RETURN_PACKETS:
+        switch (XENVIF_VIF_VERSION(&Adapter->VifInterface)) {
+        case 1: {
+            PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
+            
+            HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET_V1);
+
+            TransmitterCompletePacketsV1(Adapter->Transmitter, HeadPacket);
+            break;
+        }
+        case 2: {
+            PLIST_ENTRY List;
 
-        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+            List = va_arg(Arguments, PLIST_ENTRY);
 
-        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+            TransmitterCompletePacketsV2(Adapter->Transmitter, List);
+            break;
+        }
+        default:
+            ASSERT(FALSE);
+            break;
+        }
         break;
-    }
+
     case XENVIF_RECEIVER_QUEUE_PACKETS: {
         PLIST_ENTRY List;
 
@@ -1986,6 +2003,14 @@ AdapterGetVifInterface(
     return &Adapter->VifInterface;
 }
 
+PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return &Adapter->CacheInterface;
+}
+
 NDIS_HANDLE
 AdapterGetHandle(
     IN  PXENNET_ADAPTER             Adapter
@@ -2026,14 +2051,39 @@ AdapterInitialize(
                              VIF,
                              XENVIF_VIF_INTERFACE_VERSION_MAX,
                              (PINTERFACE)&(*Adapter)->VifInterface,
-                             sizeof ((*Adapter)->VifInterface),
+                             sizeof (XENVIF_VIF_INTERFACE_V2),
+                             FALSE);
+    if (!NT_SUCCESS(status)) {
+        Trace("QUERY_INTERFACE (VIF v2) failed (%08x)\n", status);
+        status = QUERY_INTERFACE(DeviceObject,
+                                 XENVIF,
+                                 VIF,
+                                 XENVIF_VIF_INTERFACE_VERSION_MIN,
+                                 (PINTERFACE)&(*Adapter)->VifInterface,
+                                 sizeof (XENVIF_VIF_INTERFACE_V1),
+                                 FALSE);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
+    Trace("VIF interface version %u\n", (*Adapter)->VifInterface.Interface.Version);
+
+    status = QUERY_INTERFACE(DeviceObject,
+                             XENBUS,
+                             CACHE,
+                             XENBUS_CACHE_INTERFACE_VERSION_MAX,
+                             (PINTERFACE)&(*Adapter)->CacheInterface,
+                             sizeof (XENBUS_CACHE_INTERFACE),
                              FALSE);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail2a;
 
     status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
     if (!NT_SUCCESS(status))
         goto fail3;
+    
+    status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3a;
 
     status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
     if (!NT_SUCCESS(status))
@@ -2103,9 +2153,15 @@ fail5:
     (*Adapter)->Transmitter = NULL;
 fail4:
     Error("fail4\n");
+    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
+fail3a:
+    Error("fail3a\n");
     XENVIF_VIF(Release, &(*Adapter)->VifInterface);
 fail3:
     Error("fail3\n");
+    RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+fail2a:
+    Error("fail2a\n");
     RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 fail2:
     Error("fail2\n");
@@ -2130,6 +2186,9 @@ AdapterTeardown(
     TransmitterTeardown(Adapter->Transmitter);
     Adapter->Transmitter = 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 a1f4b85..02eb6fd 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -96,6 +96,12 @@ AdapterGetVifInterface(
     IN  PXENNET_ADAPTER             Adapter
     );
 
+#include <cache_interface.h>
+extern PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    );
+
 extern NDIS_HANDLE
 AdapterGetHandle(
     IN  PXENNET_ADAPTER             Adapter
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index ee01a18..e09db55 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -38,6 +38,7 @@
 
 struct _XENNET_RECEIVER {
     PXENNET_ADAPTER             Adapter;
+    PXENVIF_VIF_INTERFACE       VifInterface;
     NDIS_HANDLE                 NetBufferListPool;
     PNET_BUFFER_LIST            PutList;
     PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
@@ -185,12 +186,9 @@ __ReceiverReturnNetBufferLists(
     IN  BOOLEAN                 Cache
     )
 {
-    PXENNET_ADAPTER             Adapter;
     LIST_ENTRY                  List;
     ULONG                       Count;
 
-    Adapter = Receiver->Adapter;
-
     InitializeListHead(&List);
 
     Count = 0;
@@ -220,7 +218,7 @@ __ReceiverReturnNetBufferLists(
 
     if (Count != 0) {
         XENVIF_VIF(ReceiverReturnPackets,
-                   AdapterGetVifInterface(Adapter),
+                   Receiver->VifInterface,
                    &List);
     }
     return Count;
@@ -292,13 +290,11 @@ ReceiverReceivePackets(
     IN  PLIST_ENTRY             List
     )
 {
-    PXENNET_ADAPTER     Adapter;
     PNET_BUFFER_LIST    HeadNetBufferList;
     PNET_BUFFER_LIST    *TailNetBufferList;
     ULONG               Count;
     BOOLEAN             LowResources;
 
-    Adapter = Receiver->Adapter;
     LowResources = FALSE;
 
 again:
@@ -354,7 +350,7 @@ again:
             InsertTailList(&PacketList, &Packet->ListEntry);
 
             XENVIF_VIF(ReceiverReturnPackets,
-                       AdapterGetVifInterface(Adapter),
+                       Receiver->VifInterface,
                        &PacketList);
         }
     }
@@ -411,8 +407,17 @@ ReceiverInitialize(
     if ((*Receiver)->NetBufferListPool == NULL)
         goto fail2;
 
+    (*Receiver)->VifInterface = AdapterGetVifInterface(Adapter);
+    status = XENVIF_VIF(Acquire, (*Receiver)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+    NdisFreeNetBufferListPool((*Receiver)->NetBufferListPool);
+    (*Receiver)->NetBufferListPool = NULL;
 fail2:
     Error("fail2\n");
     ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
@@ -460,6 +465,9 @@ ReceiverTeardown(
     NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
     Receiver->NetBufferListPool = NULL;
 
+    XENVIF_VIF(Release, Receiver->VifInterface);
+    Receiver->VifInterface = NULL;
+
     ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
 }
 
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index be07458..9bf730c 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -37,11 +37,84 @@
 
 struct _XENNET_TRANSMITTER {
     PXENNET_ADAPTER             Adapter;
+    PXENVIF_VIF_INTERFACE       VifInterface;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+
+    PXENBUS_CACHE_INTERFACE     CacheInterface;
+    PXENBUS_CACHE               Cache;
 };
 
 #define TRANSMITTER_POOL_TAG    'teNX'
 
+static NTSTATUS
+__PacketCtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__PacketDtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__PacketAcquire(
+    IN  PVOID           Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static VOID
+__PacketRelease(
+    IN  PVOID           Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
+__TransmitterGetPacket(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->Cache != NULL);
+
+    return XENBUS_CACHE(Get,
+                        Transmitter->CacheInterface,
+                        Transmitter->Cache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->Cache != NULL);
+
+    XENBUS_CACHE(Put,
+                 Transmitter->CacheInterface,
+                 Transmitter->Cache,
+                 Packet,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -49,8 +122,8 @@ 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;
+    XENVIF_TRANSMITTER_PACKET_V1    Packet;
+    PNET_BUFFER_LIST                NetBufferList;
 } NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
 
 C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
@@ -83,17 +156,17 @@ TransmitterCompleteNetBufferList(
 }
 
 static VOID
-__TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
-    IN  NDIS_STATUS                 NdisStatus
+__TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet,
+    IN  NDIS_STATUS                     NdisStatus
     )
 {
     while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
+        PNET_BUFFER_RESERVED            Reserved;
+        PNET_BUFFER_LIST                NetBufferList;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
 
         Next = Packet->Next;
         Packet->Next = NULL;
@@ -112,7 +185,38 @@ __TransmitterCompletePackets(
         Packet = Next;
     }
 }
-    
+
+static VOID
+__TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PLIST_ENTRY                 List,
+    IN  NDIS_STATUS                 NdisStatus
+    )
+{
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+        PNET_BUFFER_LIST                NetBufferList;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
+
+        ListEntry = RemoveHeadList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
+        NetBufferList = Packet->Cookie;
+        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, NdisStatus);
+
+        __TransmitterPutPacket(Transmitter, Packet);
+    }
+}
+
 static FORCEINLINE VOID
 __OffloadOptions(
     IN  PNET_BUFFER_LIST            NetBufferList,
@@ -177,31 +281,18 @@ __OffloadOptions(
     }
 }
 
-VOID
-TransmitterSendNetBufferLists(
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV1(
     IN  PXENNET_TRANSMITTER     Transmitter,
-    IN  PNET_BUFFER_LIST        NetBufferList,
-    IN  NDIS_PORT_NUMBER        PortNumber,
-    IN  ULONG                   SendFlags
+    IN  PNET_BUFFER_LIST        NetBufferList
     )
 {
-    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
-    KIRQL                       Irql;
-
-    UNREFERENCED_PARAMETER(PortNumber);
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
 
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
- 
-    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
-        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
-        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
-    } else {
-        Irql = DISPATCH_LEVEL;
-    }
- 
+
     while (NetBufferList != NULL) {
         PNET_BUFFER_LIST                ListNext;
         PNET_BUFFER_LIST_RESERVED       ListReserved;
@@ -220,8 +311,8 @@ TransmitterSendNetBufferLists(
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
-            PNET_BUFFER_RESERVED        Reserved;
-            PXENVIF_TRANSMITTER_PACKET  Packet;
+            PNET_BUFFER_RESERVED            Reserved;
+            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
             Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
             RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
@@ -248,24 +339,146 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            AdapterGetVifInterface(Adapter),
+                            Transmitter->VifInterface,
                             HeadPacket);
         if (!NT_SUCCESS(status))
-            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
+            __TransmitterCompletePacketsV1(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
     }
+}    
 
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList
+    )
+{
+    LIST_ENTRY          List;
+
+    InitializeListHead(&List);
+
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST                ListNext;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
+        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+        USHORT                          TagControlInformation;
+        USHORT                          MaximumSegmentSize;
+        PNET_BUFFER                     NetBuffer;
+
+        ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+        RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+
+        __OffloadOptions(NetBufferList, &Options, &TagControlInformation, &MaximumSegmentSize);
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        while (NetBuffer != NULL) {
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+            Packet = __TransmitterGetPacket(Transmitter);
+            if (Packet == NULL) {
+                while (ListReserved->Reference--) {
+                    PLIST_ENTRY     ListEntry;
+
+                    ListEntry = RemoveTailList(&List);
+                    ASSERT3U(ListEntry, !=, &List);
+
+                    Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+                    __TransmitterPutPacket(Transmitter, Packet);
+                }
+                TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NDIS_STATUS_NOT_ACCEPTED);
+                break;
+            }
+
+            Packet->Cookie = NetBufferList;
+            ListReserved->Reference++;
+
+            Packet->Send.OffloadOptions.Value   = Options.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.TagControlInformation  = TagControlInformation;
+            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
+            Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
+            Packet->Offset                      = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+            Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
+
+            InsertTailList(&List, &Packet->ListEntry);
+
+            NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
+        }
+
+        NetBufferList = ListNext;
+    }
+
+    if (!IsListEmpty(&List)) {
+        NTSTATUS    status; 
+
+        status = XENVIF_VIF(TransmitterQueuePacketsV2,
+                            Transmitter->VifInterface,
+                            &List);
+        if (!NT_SUCCESS(status))
+            __TransmitterCompletePacketsV2(Transmitter, &List, NDIS_STATUS_NOT_ACCEPTED);
+    }
+}
+
+VOID
+TransmitterSendNetBufferLists(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    KIRQL                       Irql;
+
+    UNREFERENCED_PARAMETER(PortNumber);
+
+    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
+        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
+        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
+    } else {
+        Irql = DISPATCH_LEVEL;
+    }
+
+    switch (XENVIF_VIF_VERSION(Transmitter->VifInterface)) {
+    case 1:
+        __TransmitterSendNetBufferListsV1(Transmitter, NetBufferList);
+        break;
+
+    case 2:
+        __TransmitterSendNetBufferListsV2(Transmitter, NetBufferList);
+        break;
+
+    default:
+        ASSERT(FALSE);
+        break;
+    }
+ 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
 }
 
 VOID
-TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
-    __TransmitterCompletePackets(Transmitter,
-                                 Packet,
-                                 NDIS_STATUS_SUCCESS);
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 1);
+    __TransmitterCompletePacketsV1(Transmitter,
+                                   Packet,
+                                   NDIS_STATUS_SUCCESS);
+}
+
+VOID
+TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    __TransmitterCompletePacketsV2(Transmitter,
+                                   List,
+                                   NDIS_STATUS_SUCCESS);
 }
 
 VOID
@@ -273,22 +486,23 @@ TransmitterEnable(
     IN  PXENNET_TRANSMITTER     Transmitter
     )
 {
-    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter->Adapter);
+    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) != 1)
+        return;
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      Vif,
+                      Transmitter->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,
-                      Vif,
+                      Transmitter->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,
-                      Vif,
+                      Transmitter->VifInterface,
                       XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
@@ -318,8 +532,47 @@ TransmitterInitialize(
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
 
+    (*Transmitter)->VifInterface = AdapterGetVifInterface(Adapter);
+    status = XENVIF_VIF(Acquire, (*Transmitter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
+        goto done;
+
+    (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
+    status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_CACHE(Create,
+                          (*Transmitter)->CacheInterface,
+                          "packets",
+                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
+                          32,
+                          __PacketCtor,
+                          __PacketDtor,
+                          __PacketAcquire,
+                          __PacketRelease,
+                          *Transmitter,
+                          &(*Transmitter)->Cache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+done:
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+    XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
+    (*Transmitter)->CacheInterface = NULL;
+fail3:
+    Error("fail3\n");
+    XENVIF_VIF(Release, (*Transmitter)->VifInterface);
+    (*Transmitter)->VifInterface = NULL;
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
 fail1:
     Error("fail1 (%08x)\n", status);
     return status;
@@ -331,6 +584,19 @@ TransmitterTeardown(
     IN  PXENNET_TRANSMITTER     Transmitter
     )
 {
+    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
+        goto done;
+
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->Cache);
+    Transmitter->Cache = NULL;
+
+    XENBUS_CACHE(Release, Transmitter->CacheInterface);
+    Transmitter->CacheInterface = NULL;
+
+done:
+    XENVIF_VIF(Release, Transmitter->VifInterface);
+    Transmitter->VifInterface = NULL;
+
     ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index f99ffd3..adf3b4c 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -45,9 +45,15 @@ TransmitterSendNetBufferLists(
     );
 
 extern VOID
-TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    );
+
+extern VOID
+TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
     );
 
 extern VOID
-- 
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 Wed Nov 12 16:39:08 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:08 +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 1Xoawm-0003T1-Ag; Wed, 12 Nov 2014 16:39:08 +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 1Xoawk-0003SA-Av
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:06 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	49/D7-19763-92D83645; Wed, 12 Nov 2014 16:39:05 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415810341!10957645!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8326 invoked from network); 12 Nov 2014 16:39:03 -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;
	12 Nov 2014 16:39:03 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032058"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:48 +0000
Message-ID: <1415810330-1152-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/4] Add VIF interface version 2
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 | 232 +++++++++++++++++++++++
 include/vif_interface.h   | 454 ++++++++++++++++++++++++++++++++++++++++++++--
 src/xennet/adapter.c      |  73 +++++++-
 src/xennet/adapter.h      |   6 +
 src/xennet/receiver.c     |  22 ++-
 src/xennet/transmitter.c  | 354 +++++++++++++++++++++++++++++++-----
 src/xennet/transmitter.h  |  12 +-
 7 files changed, 1072 insertions(+), 81 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..12599ef
--- /dev/null
+++ b/include/cache_interface.h
@@ -0,0 +1,232 @@
+/* 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
+*/
+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/include/vif_interface.h b/include/vif_interface.h
index 60a3e9c..4ce61c4 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -29,6 +29,12 @@
  * SUCH DAMAGE.
  */
 
+/*! \file vif_interface.h
+    \brief XENVIF VIF Interface
+
+    This interface provides access to the PV network frontend
+*/
+
 #ifndef _XENVIF_VIF_INTERFACE_H
 #define _XENVIF_VIF_INTERFACE_H
 
@@ -37,21 +43,39 @@
 #include <ifdef.h>
 #include <ethernet.h>
 
+/*! \struct _XENVIF_PACKET_HEADER_V1
+    \brief Packet header information
+*/
 struct  _XENVIF_PACKET_HEADER_V1 {
+    /*! Offset from beginning of packet */
     ULONG   Offset;
+    /*! Length of header (0 indicates a header is not present) */
     ULONG   Length;
 };
 
+/*! \struct _XENVIF_PACKET_INFO_V1
+    \brief Packet information
+*/
 struct _XENVIF_PACKET_INFO_V1 {
+    /*! Total length of all headers */
     ULONG                           Length;
+    /*! VLAN TCI if present (0 indicates not present) */
     USHORT                          TagControlInformation;
+    /*! TRUE if the packet is an IP fragment */
     BOOLEAN                         IsAFragment;
+    /*! Ethernet header (stripped of any VLAN tag) */
     struct _XENVIF_PACKET_HEADER_V1 EthernetHeader;
+    /*! LLC header (used for IPX or 802.3 IP) */
     struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader;
+    /*! IP header (v4 or v6) */
     struct _XENVIF_PACKET_HEADER_V1 IpHeader;
+    /*! IP options (v4 or v6) */
     struct _XENVIF_PACKET_HEADER_V1 IpOptions;
+    /*! TCP header */
     struct _XENVIF_PACKET_HEADER_V1 TcpHeader;
+    /*! TCP options */
     struct _XENVIF_PACKET_HEADER_V1 TcpOptions;
+    /*! UDP header */
     struct _XENVIF_PACKET_HEADER_V1 UdpHeader;
 };
 
@@ -61,38 +85,63 @@ typedef struct _XENVIF_PACKET_INFO_V1   XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO
 #pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
+    \brief Packet checksum flags
+*/
 struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
     union {
         struct {
+            /*! IPv4 header checksum validation succeeded */
             ULONG   IpChecksumSucceeded:1;
+            /*! IPv4 header checksum validation failed */
             ULONG   IpChecksumFailed:1;
+            /*! IPv4 header checksum is present */
             ULONG   IpChecksumPresent:1;
+            /*! TCP checksum validation succeeded */
             ULONG   TcpChecksumSucceeded:1;
+            /*! TCP checksum validation failed */
             ULONG   TcpChecksumFailed:1;
+            /*! TCP checksum is present */
             ULONG   TcpChecksumPresent:1;
+            /*! UDP checksum validation succeeded */
             ULONG   UdpChecksumSucceeded:1;
+            /*! UDP checksum validation failed */
             ULONG   UdpChecksumFailed:1;
+            /*! UDP checksum is present */
             ULONG   UdpChecksumPresent:1;
             ULONG   Reserved:23;
         };
-
+        /*! Raw representation */
         ULONG   Value;
     };
 };
 
+
 typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS, *PXENVIF_PACKET_CHECKSUM_FLAGS;
 
 #pragma warning(pop)
 
+/*! \struct _XENVIF_RECEIVER_PACKET_V1
+    \brief Receive-side packet structure
+*/
 struct _XENVIF_RECEIVER_PACKET_V1 {
+    /*! List entry used for chaining packets together */
     LIST_ENTRY                              ListEntry;
+    /*! Pointer to packet information */
     struct _XENVIF_PACKET_INFO_V1           *Info;
+    /*! Offset of start of packet in MDL */
     ULONG                                   Offset;
+    /*! Total length of packet */
     ULONG                                   Length;
+    /*! Checksum flags */
     struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags;
+    /*! TCP MSS if the packet contains a TCP large segment */
     USHORT                                  MaximumSegmentSize;
+    /*! Opaque cookie used to store context information for packet return */
     PVOID                                   Cookie;
+    /*! MDL referencing the initial buffer of the packet */
     MDL                                     Mdl;
+    /*! PFN information, which must always follow an MDL */
     PFN_NUMBER                              __Pfn;
 };
 
@@ -102,22 +151,36 @@ typedef struct _XENVIF_RECEIVER_PACKET_V1 XENVIF_RECEIVER_PACKET, *PXENVIF_RECEI
 #pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
+    \brief Offload options
+*/
 struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 {
     union {
         struct {
+            /*! Insert/strip VLAN tags */
             USHORT  OffloadTagManipulation:1;
+            /*! Segment/coalesce IPv4 packets containing TCP large segments */ 
             USHORT  OffloadIpVersion4LargePacket:1;
+            /*! Calculate/validate IPv4 header checksum */
             USHORT  OffloadIpVersion4HeaderChecksum:1;
+            /*! Calculate/validate IPv4 TCP checksum */
             USHORT  OffloadIpVersion4TcpChecksum:1;
+            /*! Calculate/validate IPv4 UDP checksum */
             USHORT  OffloadIpVersion4UdpChecksum:1;
+            /*! Segment/coalesce IPv6 packets containing TCP large segments */ 
             USHORT  OffloadIpVersion6LargePacket:1;
+            /*! Calculate/validate IPv6 TCP checksum */
             USHORT  OffloadIpVersion6TcpChecksum:1;
+            /*! Calculate/validate IPv6 UDP checksum */
             USHORT  OffloadIpVersion6UdpChecksum:1;
+            /*! Force calculation of any missing checksums on receive side */
             USHORT  NeedChecksumValue:1;
+            /*! Force segmentation of packets containing TCP large segments on receive side */
             USHORT  NeedLargePacketSplit:1;
             USHORT  Reserved:6;
         };
 
+        /*! Raw representation */
         USHORT  Value;
     };
 };
@@ -126,28 +189,55 @@ typedef struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 XENVIF_VIF_OFFLOAD_OPTIONS, *PXENV
 
 #pragma warning(pop)
 
-// To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures the XENVIF_TRANSMITTER_PACKET
-// structure must be at most the size of 3 pointer types.
-
 #pragma pack(push, 1) 
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
+    \brief Packet information passed from subscriber to provider on
+    transmit side packet send
+
+    To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+    this structure must be at most the size of 3 pointer types.
+*/
 struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 {
+    /*! Offload options for this packet */
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-    USHORT                      MaximumSegmentSize;     // Only used if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set
-    USHORT                      TagControlInformation;  // Only used if OffloadOptions.OffloadTagManipulation is set
+    /*! TCP MSS (used only if OffloadOptions.OffloadIpVersion[4|6]LargePacket is set) */
+    USHORT                      MaximumSegmentSize;
+    /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set) */
+    USHORT                      TagControlInformation;
 };
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 XENVIF_TRANSMITTER_PACKET_SEND_INFO, *PXENVIF_TRANSMITTER_PACKET_SEND_INFO;
 
+/*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS
+    \brief Transmit-side packet status
+*/
+typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS {
+    /*! Packet was queued for the backend */
+    XENVIF_TRANSMITTER_PACKET_PENDING = 1,
+    /*! Packet has been successfully processed by the backend */
+    XENVIF_TRANSMITTER_PACKET_OK,
+    /*! Packet was dropped */
+    XENVIF_TRANSMITTER_PACKET_DROPPED,
+    /*! There was a problem handling the packet */
+    XENVIF_TRANSMITTER_PACKET_ERROR
+} XENVIF_TRANSMITTER_PACKET_STATUS, *PXENVIF_TRANSMITTER_PACKET_STATUS;
+
+/*! \struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
+    \brief Packet information passed from provider to subsriber on
+    transmit side packet return
+
+    To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures
+    this structure must be at most the size of 3 pointer types.
+*/
 struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 {
+    /*! Ethernet address type (see \ref _ETHERNET_ADDRESS_TYPE) */
     UCHAR   Type;
+    /*! Send status (see \ref _XENVIF_TRANSMITTER_PACKET_STATUS) */
     UCHAR   Status;
-
-#define XENVIF_TRANSMITTER_PACKET_PENDING   1
-#define XENVIF_TRANSMITTER_PACKET_OK        2
-#define XENVIF_TRANSMITTER_PACKET_DROPPED   3
-#define XENVIF_TRANSMITTER_PACKET_ERROR     4
-
+    /*! Total length of the sent packet */
     USHORT  PacketLength;
+    /*! Length of packet payload after recognized headers are removed */
     USHORT  PayloadLength;
 };
 
@@ -156,7 +246,11 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 XENVIF_TRANSMITTER_
 #pragma warning(push)
 #pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
 
+/*! \struct _XENVIF_TRANSMITTER_PACKET_V1
+    \brief Transmit-side packet structure
+*/
 struct _XENVIF_TRANSMITTER_PACKET_V1 {
+    /*! Pointer used for chaining packets together */
     struct _XENVIF_TRANSMITTER_PACKET_V1                        *Next;
     union {
         struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1          Send;
@@ -164,7 +258,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)
 
@@ -172,64 +266,169 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
+    \brief Transmit-side packet structure
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
+    LIST_ENTRY                                  ListEntry;
+    /*! MDL referencing the packet's buffer */
+    PMDL                                        Mdl;
+    /*! Offset of start of packet in MDL */
+    ULONG                                       Offset;
+    /*! Total length of packet */
+    ULONG                                       Length;
+    /*! Opaque cookie used to store context information for packet return */
+    PVOID                                       Cookie;
+    /*! Packet information passed down to subscriber */
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Information passed up from subscriber for packet completion */
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
+
+
+/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
+    \brief Offsets of packet metadata relative to
+    XENVIF_TRANSMITTER_PACKET_V1 pointer
+
+    Because the transmit side packet structure is limited to 3 pointer
+    types in size, not all information about the packet can be passed in
+    the structure. Other information can, however, be found by applying
+    these byte offsets to the structure pointer and then dereferencing the
+    specified type.
+*/
 typedef enum _XENVIF_TRANSMITTER_PACKET_OFFSET {
+    /*! The offset of the start of the packet within the MDL (type ULONG) */
     XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET = 0,
+    /*! The total length of the packet (type ULONG) */
     XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
+    /*! MDL referencing the initial buffer of the packet (type PMDL) */
     XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
     XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT
 } XENVIF_TRANSMITTER_PACKET_OFFSET, *PXENVIF_TRANSMITTER_PACKET_OFFSET;
 
+/*! \enum _XENVIF_VIF_STATISTIC
+    \brief Interface statistics
+*/
 typedef enum _XENVIF_VIF_STATISTIC {
+    /*! RFC 2863 ifOutDiscards */
     XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
+    /*! Backend component of RFC 2863 ifOutErrors */
     XENVIF_TRANSMITTER_BACKEND_ERRORS,
+    /*! Frontend component of RFC 2863 ifOutErrors */
     XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+    /*! RFC 2863 ifOutUcastPkts */
     XENVIF_TRANSMITTER_UNICAST_PACKETS,
+    /*! Total number of octets in ifOutUcastPkts */
     XENVIF_TRANSMITTER_UNICAST_OCTETS,
+    /*! RFC 2863 ifOutMulticastPkts */
     XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+    /*! Total number of octets in ifOutMulticastPkts */
     XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+    /*! RFC 2863 ifOutBroadcastPkts */
     XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+    /*! Total number of octets in ifOutBroadcastPkts */
     XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+    /*! RFC 2863 ifInDiscards */
     XENVIF_RECEIVER_PACKETS_DROPPED,
+    /*! Backend component of RFC 2863 ifInErrors */
     XENVIF_RECEIVER_BACKEND_ERRORS,
+    /*! Frontend component of RFC 2863 ifInErrors */
     XENVIF_RECEIVER_FRONTEND_ERRORS,
+    /*! RFC 2863 ifInUcastPkts */
     XENVIF_RECEIVER_UNICAST_PACKETS,
+    /*! Total number of octets in ifInUcastPkts */
     XENVIF_RECEIVER_UNICAST_OCTETS,
+    /*! RFC 2863 ifInMulticastPkts */
     XENVIF_RECEIVER_MULTICAST_PACKETS,
+    /*! Total number of octets in ifInMulticastPkts */
     XENVIF_RECEIVER_MULTICAST_OCTETS,
+    /*! RFC 2863 ifInBroadcastPkts */
     XENVIF_RECEIVER_BROADCAST_PACKETS,
+    /*! Total number of octets in ifInBroadcastPkts */
     XENVIF_RECEIVER_BROADCAST_OCTETS,
     XENVIF_VIF_STATISTIC_COUNT
 } XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
 
+/*! \enum _XENVIF_MAC_FILTER_LEVEL
+    \brief Filter level applied to packets
+*/
 typedef enum _XENVIF_MAC_FILTER_LEVEL {
+    /*! Don't filter out any packets */
     XENVIF_MAC_FILTER_NONE = 0,
+    /*! Filter out all packets except those with a matching destination address */
     XENVIF_MAC_FILTER_MATCHING = 1,
+    /*! Filter out all packets */
     XENVIF_MAC_FILTER_ALL = 2
 } XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
 
+/*! \enum _XENVIF_VIF_CALLBACK_TYPE
+    \brief Type of callback (see \ref XENVIF_VIF_CALLBACK)
+*/
 typedef enum _XENVIF_VIF_CALLBACK_TYPE {
+    /*! Return transmit side packets to the subscriber */
     XENVIF_TRANSMITTER_RETURN_PACKETS = 0,
+    /*! Queue receive side packets at the subscriber */
     XENVIF_RECEIVER_QUEUE_PACKETS,
+    /*! Notify the subscriber of a MAC (link) state has change */
     XENVIF_MAC_STATE_CHANGE
 } XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE;
 
+/*! \typedef XENVIF_VIF_ACQUIRE
+    \brief Acquire a reference to the VIF interface
+
+    \param Interface The interface header
+*/  
 typedef NTSTATUS
 (*XENVIF_VIF_ACQUIRE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_RELEASE
+    \brief Release a reference to the VIF interface
+
+    \param Interface The interface header
+*/  
 typedef VOID
 (*XENVIF_VIF_RELEASE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_CALLBACK
+    \brief Provider to subscriber callback function
+
+    \param Argument An optional context argument passed to the callback
+    \param Type The callback type
+    \param ... Additional paramaters required by \a Type
+
+    \b XENVIF_TRANSMITTER_RETURN_PACKETS:
+    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
+
+    \b XENVIF_RECEIVER_QUEUE_PACKETS:
+    \param List List of XENVIF_RECEIVER_PACKET
+
+    \b XENVIF_MAC_STATE_CHANGE:
+    No additional arguments
+*/
 typedef VOID
 (*XENVIF_VIF_CALLBACK)(
-    IN  PVOID                       Argument,
+    IN  PVOID                       Argument OPTIONAL,
     IN  XENVIF_VIF_CALLBACK_TYPE    Type,
     ...
     );
 
+/*! \typedef XENVIF_VIF_ENABLE
+    \brief Enable the VIF interface
+
+    All packets queued for transmit will be rejected and no packets will
+    be queued for receive until this method completes. 
+
+    \param Interface The interface header
+    \param Callback The subscriber's callback function
+    \param Argument An optional context argument passed to the callback
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_ENABLE)(
     IN  PINTERFACE          Interface,
@@ -237,11 +436,31 @@ typedef NTSTATUS
     IN  PVOID               Argument OPTIONAL
     );
 
+/*! \typedef XENVIF_VIF_DISABLE
+    \brief Disable the VIF interface
+
+    This method will not complete until any packets queued for receive
+    have been returned. Any packets queued for transmit may be aborted.
+
+    \param Interface The interface header
+*/
 typedef VOID
 (*XENVIF_VIF_DISABLE)(
     IN  PINTERFACE  Interface
     );
 
+/*! \typedef XENVIF_VIF_QUERY_STATISTIC
+    \brief Query the value of an interface statistic
+
+    Interface statistics are 64-bits wide and zero based. They are
+    zeroed when the vif device object is created. They are not
+    zeroed by this call or by any vif state change (e.g. reconnection
+    across migration).
+
+    \param Interface The interface header
+    \param Index The index of the statistic in \ref _XENVIF_VIF_STATISTIC
+    \param Value Buffer to receive the value of the statistic
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_QUERY_STATISTIC)(
     IN  PINTERFACE              Interface,
@@ -249,12 +468,29 @@ typedef NTSTATUS
     OUT PULONGLONG              Value
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS
+    \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK
+    (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS)
+
+    \param Interface The interface header
+    \param List List of \ref _XENVIF_RECEIVER_PACKET_V1
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_RETURN_PACKETS)(
     IN  PINTERFACE  Interface,
     IN  PLIST_ENTRY List
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
+    \brief Set byte offset of packet information relative to
+    XENVIF_TRANSMITTER_PACKET_V1 pointer.
+
+    See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
+
+    \param Interface The interface header
+    \param Type The offset type
+    \param Value The offset value
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET)(
     IN  PINTERFACE                          Interface,
@@ -262,24 +498,80 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
+    \brief Queue transmit side packets at the provider
+
+    \param Interface The interface header
+    \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
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
+    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_GET_PACKET_HEADERS
+    \brief Get a copy of the packet headers and each the offset of each
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
+    \brief Query the available set of transmit side offload options
+
+    \param Interface The interface header
+    \param Options Buffer to receive the avilable options
+    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS)(
     IN  PINTERFACE                  Interface,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
+    \brief Set the required set of receive side offload options
+
+    \param Interface The interface header
+    \param Options The required options
+    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS)(
     IN  PINTERFACE                  Interface,
     IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
+    \brief Query the maximum size of packet containing a TCP large segment
+    that can be handled by the transmit side
+
+    \param Interface The interface header
+    \param Version The IP version (4 or 6)
+    \param Size Buffer to receive the maximum packet size
+*/ 
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE)(
     IN  PINTERFACE  Interface,
@@ -287,18 +579,40 @@ typedef VOID
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
+    \brief Query the maximum number of transmit side packets that can
+    be queued in the shared ring between frontend and backend
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum number of packets
+*/
 typedef VOID
 (*XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE
+    \brief Query the maximum number of receive side packets that can
+    be queued in the shared ring between backend and frontend
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum number of packets
+*/
 typedef VOID
 (*XENVIF_VIF_RECEIVER_QUERY_RING_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
+    \brief Query the current MAC (link) state
+
+    \param Interface The interface header
+    \param MediaConnectState Buffer to receive the current connection state
+    \param LinkSpeed Buffer to receive the current link speed in Gbps
+    \param MediaDuplexState Buffer to receive the current duplex state
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_STATE)(
     IN  PINTERFACE                  Interface,
@@ -307,24 +621,58 @@ typedef VOID
     OUT PNET_IF_MEDIA_DUPLEX_STATE  MediaDuplexState OPTIONAL
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE
+    \brief Query the maximum MAC (i.e. on the wire) frame size (not
+    including CRC)
+
+    \param Interface The interface header
+    \param Size Buffer to receive the maximum frame size
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE)(
     IN  PINTERFACE  Interface,
     OUT PULONG      Size
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS
+    \brief Query the permanent MAC address (set by the toolstack)
+
+    \param Interface The interface header
+    \param Address Buffer to receive the permanent address
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS)(
     IN  PINTERFACE          Interface,
     OUT PETHERNET_ADDRESS   Address
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS
+    \brief Query the current MAC address (may be set by the guest)
+
+    The guest OS may override the MAC address using the registry. If this
+    is not done then the current address will be identical to the
+    permanent address.
+
+    \param Interface The interface header
+    \param Address Buffer to receive the current address
+*/
 typedef VOID
 (*XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS)(
     IN  PINTERFACE          Interface,
     OUT PETHERNET_ADDRESS   Address
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES
+    \brief Query the current set of active multicast addresses
+
+    \param Interface The interface header
+    \param Address An optional buffer to receive the set of addresses
+    \param Count A buffer to receive the number of active addresses
+
+    Call this method with \a Address set to NULL to get the \a Count,
+    which can then be used to allocate a buffer of suitable size to receive
+    the array of addresses.
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES)(
     IN      PINTERFACE          Interface,
@@ -332,6 +680,16 @@ typedef NTSTATUS
     IN OUT  PULONG              Count
     );
 
+/*! \typedef XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
+    \brief Update the set of active multicast addresses
+
+    \param Interface The interface header
+    \param Address An optional buffer containing the set of addresses
+    \param Count The number of addresses in the buffer
+
+    The \a Address buffer may only by NULL if \a Count is zero, in which
+    case the set of active multicast addresses will be cleared.
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES)(
     IN  PINTERFACE          Interface,
@@ -339,6 +697,14 @@ typedef NTSTATUS
     IN  ULONG               Count
     );
 
+/*! \typedef XENVIF_VIF_MAC_SET_FILTER_LEVEL
+    \brief Set a filter level for a given type of packet
+
+    \param Interface The interface header
+    \param Type The destination address type of the packet
+    (see \ref _ETHERNET_ADDRESS_TYPE)
+    \param Level The new filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_SET_FILTER_LEVEL)(
     IN  PINTERFACE              Interface,
@@ -346,6 +712,14 @@ typedef NTSTATUS
     IN  XENVIF_MAC_FILTER_LEVEL Level
     );
 
+/*! \typedef XENVIF_VIF_MAC_QUERY_FILTER_LEVEL
+    \brief Query the current filter level for a given type of packet
+
+    \param Interface The interface header
+    \param Type The destination address type of the packet
+    (see \ref _ETHERNET_ADDRESS_TYPE)
+    \param Level Buffer to receive the filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
+*/
 typedef NTSTATUS
 (*XENVIF_VIF_MAC_QUERY_FILTER_LEVEL)(
     IN  PINTERFACE                  Interface,
@@ -368,7 +742,34 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
     XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
     XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET        TransmitterSetPacketOffset;
-    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS            TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         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_V1 XENVIF_VIF_INTERFACE_V1, *PXENVIF_VIF_INTERFACE_V1;
+
+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_SET_PACKET_OFFSET        TransmitterSetPacketOffset; // obsolete
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;    // obsolete
     XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
     XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
     XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
@@ -380,16 +781,29 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES          MacSetMulticastAddresses;
     XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePacketsV2;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2, *PXENVIF_VIF_INTERFACE_V2;
 
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+/*! \def XENVIF_VIF
+    \brief Macro to assist in method invocation
+*/
 #define XENVIF_VIF(_Method, _Interface, ...)    \
     (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
 
+/*! \def XENVIF_VIF_VERSION
+    \brief Macro to assist in getting interface version in use
+*/
+#define XENVIF_VIF_VERSION(_Interface)          \
+    ((_Interface)->Interface.Version)
+
 #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/xennet/adapter.c b/src/xennet/adapter.c
index 6b32d1a..e3d6e05 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -41,6 +41,7 @@
 
 struct _XENNET_ADAPTER {
     XENVIF_VIF_INTERFACE        VifInterface;
+    XENBUS_CACHE_INTERFACE      CacheInterface;
 
     BOOLEAN                     Enabled;
     ULONG                       MaximumFrameSize;
@@ -171,14 +172,30 @@ AdapterVifCallback(
     va_start(Arguments, Type);
 
     switch (Type) {
-    case XENVIF_TRANSMITTER_RETURN_PACKETS: {
-        PXENVIF_TRANSMITTER_PACKET HeadPacket;
+    case XENVIF_TRANSMITTER_RETURN_PACKETS:
+        switch (XENVIF_VIF_VERSION(&Adapter->VifInterface)) {
+        case 1: {
+            PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
+            
+            HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET_V1);
+
+            TransmitterCompletePacketsV1(Adapter->Transmitter, HeadPacket);
+            break;
+        }
+        case 2: {
+            PLIST_ENTRY List;
 
-        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+            List = va_arg(Arguments, PLIST_ENTRY);
 
-        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+            TransmitterCompletePacketsV2(Adapter->Transmitter, List);
+            break;
+        }
+        default:
+            ASSERT(FALSE);
+            break;
+        }
         break;
-    }
+
     case XENVIF_RECEIVER_QUEUE_PACKETS: {
         PLIST_ENTRY List;
 
@@ -1986,6 +2003,14 @@ AdapterGetVifInterface(
     return &Adapter->VifInterface;
 }
 
+PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return &Adapter->CacheInterface;
+}
+
 NDIS_HANDLE
 AdapterGetHandle(
     IN  PXENNET_ADAPTER             Adapter
@@ -2026,14 +2051,39 @@ AdapterInitialize(
                              VIF,
                              XENVIF_VIF_INTERFACE_VERSION_MAX,
                              (PINTERFACE)&(*Adapter)->VifInterface,
-                             sizeof ((*Adapter)->VifInterface),
+                             sizeof (XENVIF_VIF_INTERFACE_V2),
+                             FALSE);
+    if (!NT_SUCCESS(status)) {
+        Trace("QUERY_INTERFACE (VIF v2) failed (%08x)\n", status);
+        status = QUERY_INTERFACE(DeviceObject,
+                                 XENVIF,
+                                 VIF,
+                                 XENVIF_VIF_INTERFACE_VERSION_MIN,
+                                 (PINTERFACE)&(*Adapter)->VifInterface,
+                                 sizeof (XENVIF_VIF_INTERFACE_V1),
+                                 FALSE);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
+    Trace("VIF interface version %u\n", (*Adapter)->VifInterface.Interface.Version);
+
+    status = QUERY_INTERFACE(DeviceObject,
+                             XENBUS,
+                             CACHE,
+                             XENBUS_CACHE_INTERFACE_VERSION_MAX,
+                             (PINTERFACE)&(*Adapter)->CacheInterface,
+                             sizeof (XENBUS_CACHE_INTERFACE),
                              FALSE);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail2a;
 
     status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
     if (!NT_SUCCESS(status))
         goto fail3;
+    
+    status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3a;
 
     status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
     if (!NT_SUCCESS(status))
@@ -2103,9 +2153,15 @@ fail5:
     (*Adapter)->Transmitter = NULL;
 fail4:
     Error("fail4\n");
+    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
+fail3a:
+    Error("fail3a\n");
     XENVIF_VIF(Release, &(*Adapter)->VifInterface);
 fail3:
     Error("fail3\n");
+    RtlZeroMemory(&(*Adapter)->CacheInterface, sizeof(XENBUS_CACHE_INTERFACE));
+fail2a:
+    Error("fail2a\n");
     RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
 fail2:
     Error("fail2\n");
@@ -2130,6 +2186,9 @@ AdapterTeardown(
     TransmitterTeardown(Adapter->Transmitter);
     Adapter->Transmitter = 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 a1f4b85..02eb6fd 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -96,6 +96,12 @@ AdapterGetVifInterface(
     IN  PXENNET_ADAPTER             Adapter
     );
 
+#include <cache_interface.h>
+extern PXENBUS_CACHE_INTERFACE
+AdapterGetCacheInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    );
+
 extern NDIS_HANDLE
 AdapterGetHandle(
     IN  PXENNET_ADAPTER             Adapter
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
index ee01a18..e09db55 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -38,6 +38,7 @@
 
 struct _XENNET_RECEIVER {
     PXENNET_ADAPTER             Adapter;
+    PXENVIF_VIF_INTERFACE       VifInterface;
     NDIS_HANDLE                 NetBufferListPool;
     PNET_BUFFER_LIST            PutList;
     PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
@@ -185,12 +186,9 @@ __ReceiverReturnNetBufferLists(
     IN  BOOLEAN                 Cache
     )
 {
-    PXENNET_ADAPTER             Adapter;
     LIST_ENTRY                  List;
     ULONG                       Count;
 
-    Adapter = Receiver->Adapter;
-
     InitializeListHead(&List);
 
     Count = 0;
@@ -220,7 +218,7 @@ __ReceiverReturnNetBufferLists(
 
     if (Count != 0) {
         XENVIF_VIF(ReceiverReturnPackets,
-                   AdapterGetVifInterface(Adapter),
+                   Receiver->VifInterface,
                    &List);
     }
     return Count;
@@ -292,13 +290,11 @@ ReceiverReceivePackets(
     IN  PLIST_ENTRY             List
     )
 {
-    PXENNET_ADAPTER     Adapter;
     PNET_BUFFER_LIST    HeadNetBufferList;
     PNET_BUFFER_LIST    *TailNetBufferList;
     ULONG               Count;
     BOOLEAN             LowResources;
 
-    Adapter = Receiver->Adapter;
     LowResources = FALSE;
 
 again:
@@ -354,7 +350,7 @@ again:
             InsertTailList(&PacketList, &Packet->ListEntry);
 
             XENVIF_VIF(ReceiverReturnPackets,
-                       AdapterGetVifInterface(Adapter),
+                       Receiver->VifInterface,
                        &PacketList);
         }
     }
@@ -411,8 +407,17 @@ ReceiverInitialize(
     if ((*Receiver)->NetBufferListPool == NULL)
         goto fail2;
 
+    (*Receiver)->VifInterface = AdapterGetVifInterface(Adapter);
+    status = XENVIF_VIF(Acquire, (*Receiver)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+    NdisFreeNetBufferListPool((*Receiver)->NetBufferListPool);
+    (*Receiver)->NetBufferListPool = NULL;
 fail2:
     Error("fail2\n");
     ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
@@ -460,6 +465,9 @@ ReceiverTeardown(
     NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
     Receiver->NetBufferListPool = NULL;
 
+    XENVIF_VIF(Release, Receiver->VifInterface);
+    Receiver->VifInterface = NULL;
+
     ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
 }
 
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
index be07458..9bf730c 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -37,11 +37,84 @@
 
 struct _XENNET_TRANSMITTER {
     PXENNET_ADAPTER             Adapter;
+    PXENVIF_VIF_INTERFACE       VifInterface;
     XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+
+    PXENBUS_CACHE_INTERFACE     CacheInterface;
+    PXENBUS_CACHE               Cache;
 };
 
 #define TRANSMITTER_POOL_TAG    'teNX'
 
+static NTSTATUS
+__PacketCtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
+    return STATUS_SUCCESS;
+}
+
+static VOID
+__PacketDtor(
+    IN  PVOID           Argument,
+    IN  PVOID           Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+__PacketAcquire(
+    IN  PVOID           Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static VOID
+__PacketRelease(
+    IN  PVOID           Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
+__TransmitterGetPacket(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->Cache != NULL);
+
+    return XENBUS_CACHE(Get,
+                        Transmitter->CacheInterface,
+                        Transmitter->Cache,
+                        FALSE);
+}
+
+static FORCEINLINE VOID
+__TransmitterPutPacket(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    ASSERT(Transmitter->CacheInterface != NULL);
+    ASSERT(Transmitter->Cache != NULL);
+
+    XENBUS_CACHE(Put,
+                 Transmitter->CacheInterface,
+                 Transmitter->Cache,
+                 Packet,
+                 FALSE);
+}
+
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
 } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
@@ -49,8 +122,8 @@ 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;
+    XENVIF_TRANSMITTER_PACKET_V1    Packet;
+    PNET_BUFFER_LIST                NetBufferList;
 } NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
 
 C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
@@ -83,17 +156,17 @@ TransmitterCompleteNetBufferList(
 }
 
 static VOID
-__TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
-    IN  NDIS_STATUS                 NdisStatus
+__TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet,
+    IN  NDIS_STATUS                     NdisStatus
     )
 {
     while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
+        PXENVIF_TRANSMITTER_PACKET_V1   Next;
+        PNET_BUFFER_RESERVED            Reserved;
+        PNET_BUFFER_LIST                NetBufferList;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
 
         Next = Packet->Next;
         Packet->Next = NULL;
@@ -112,7 +185,38 @@ __TransmitterCompletePackets(
         Packet = Next;
     }
 }
-    
+
+static VOID
+__TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PLIST_ENTRY                 List,
+    IN  NDIS_STATUS                 NdisStatus
+    )
+{
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+        PNET_BUFFER_LIST                NetBufferList;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
+
+        ListEntry = RemoveHeadList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
+        NetBufferList = Packet->Cookie;
+        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, NdisStatus);
+
+        __TransmitterPutPacket(Transmitter, Packet);
+    }
+}
+
 static FORCEINLINE VOID
 __OffloadOptions(
     IN  PNET_BUFFER_LIST            NetBufferList,
@@ -177,31 +281,18 @@ __OffloadOptions(
     }
 }
 
-VOID
-TransmitterSendNetBufferLists(
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV1(
     IN  PXENNET_TRANSMITTER     Transmitter,
-    IN  PNET_BUFFER_LIST        NetBufferList,
-    IN  NDIS_PORT_NUMBER        PortNumber,
-    IN  ULONG                   SendFlags
+    IN  PNET_BUFFER_LIST        NetBufferList
     )
 {
-    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
-    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
-    KIRQL                       Irql;
-
-    UNREFERENCED_PARAMETER(PortNumber);
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
 
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
- 
-    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
-        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
-        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
-    } else {
-        Irql = DISPATCH_LEVEL;
-    }
- 
+
     while (NetBufferList != NULL) {
         PNET_BUFFER_LIST                ListNext;
         PNET_BUFFER_LIST_RESERVED       ListReserved;
@@ -220,8 +311,8 @@ TransmitterSendNetBufferLists(
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
-            PNET_BUFFER_RESERVED        Reserved;
-            PXENVIF_TRANSMITTER_PACKET  Packet;
+            PNET_BUFFER_RESERVED            Reserved;
+            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
 
             Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
             RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
@@ -248,24 +339,146 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            AdapterGetVifInterface(Adapter),
+                            Transmitter->VifInterface,
                             HeadPacket);
         if (!NT_SUCCESS(status))
-            __TransmitterCompletePackets(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
+            __TransmitterCompletePacketsV1(Transmitter, HeadPacket, NDIS_STATUS_NOT_ACCEPTED);
     }
+}    
 
+static FORCEINLINE VOID
+__TransmitterSendNetBufferListsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList
+    )
+{
+    LIST_ENTRY          List;
+
+    InitializeListHead(&List);
+
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST                ListNext;
+        PNET_BUFFER_LIST_RESERVED       ListReserved;
+        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+        USHORT                          TagControlInformation;
+        USHORT                          MaximumSegmentSize;
+        PNET_BUFFER                     NetBuffer;
+
+        ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+        RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+
+        __OffloadOptions(NetBufferList, &Options, &TagControlInformation, &MaximumSegmentSize);
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        while (NetBuffer != NULL) {
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+            Packet = __TransmitterGetPacket(Transmitter);
+            if (Packet == NULL) {
+                while (ListReserved->Reference--) {
+                    PLIST_ENTRY     ListEntry;
+
+                    ListEntry = RemoveTailList(&List);
+                    ASSERT3U(ListEntry, !=, &List);
+
+                    Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+                    __TransmitterPutPacket(Transmitter, Packet);
+                }
+                TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NDIS_STATUS_NOT_ACCEPTED);
+                break;
+            }
+
+            Packet->Cookie = NetBufferList;
+            ListReserved->Reference++;
+
+            Packet->Send.OffloadOptions.Value   = Options.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.TagControlInformation  = TagControlInformation;
+            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
+            Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
+            Packet->Offset                      = NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
+            Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
+            RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
+
+            InsertTailList(&List, &Packet->ListEntry);
+
+            NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
+        }
+
+        NetBufferList = ListNext;
+    }
+
+    if (!IsListEmpty(&List)) {
+        NTSTATUS    status; 
+
+        status = XENVIF_VIF(TransmitterQueuePacketsV2,
+                            Transmitter->VifInterface,
+                            &List);
+        if (!NT_SUCCESS(status))
+            __TransmitterCompletePacketsV2(Transmitter, &List, NDIS_STATUS_NOT_ACCEPTED);
+    }
+}
+
+VOID
+TransmitterSendNetBufferLists(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    KIRQL                       Irql;
+
+    UNREFERENCED_PARAMETER(PortNumber);
+
+    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
+        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
+        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
+    } else {
+        Irql = DISPATCH_LEVEL;
+    }
+
+    switch (XENVIF_VIF_VERSION(Transmitter->VifInterface)) {
+    case 1:
+        __TransmitterSendNetBufferListsV1(Transmitter, NetBufferList);
+        break;
+
+    case 2:
+        __TransmitterSendNetBufferListsV2(Transmitter, NetBufferList);
+        break;
+
+    default:
+        ASSERT(FALSE);
+        break;
+    }
+ 
     NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
 }
 
 VOID
-TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
     )
 {
-    __TransmitterCompletePackets(Transmitter,
-                                 Packet,
-                                 NDIS_STATUS_SUCCESS);
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 1);
+    __TransmitterCompletePacketsV1(Transmitter,
+                                   Packet,
+                                   NDIS_STATUS_SUCCESS);
+}
+
+VOID
+TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
+    )
+{
+    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
+    __TransmitterCompletePacketsV2(Transmitter,
+                                   List,
+                                   NDIS_STATUS_SUCCESS);
 }
 
 VOID
@@ -273,22 +486,23 @@ TransmitterEnable(
     IN  PXENNET_TRANSMITTER     Transmitter
     )
 {
-    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter->Adapter);
+    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) != 1)
+        return;
 
     (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      Vif,
+                      Transmitter->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,
-                      Vif,
+                      Transmitter->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,
-                      Vif,
+                      Transmitter->VifInterface,
                       XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
                       (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
                       (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
@@ -318,8 +532,47 @@ TransmitterInitialize(
     RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
     (*Transmitter)->Adapter = Adapter;
 
+    (*Transmitter)->VifInterface = AdapterGetVifInterface(Adapter);
+    status = XENVIF_VIF(Acquire, (*Transmitter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
+        goto done;
+
+    (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
+    status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_CACHE(Create,
+                          (*Transmitter)->CacheInterface,
+                          "packets",
+                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
+                          32,
+                          __PacketCtor,
+                          __PacketDtor,
+                          __PacketAcquire,
+                          __PacketRelease,
+                          *Transmitter,
+                          &(*Transmitter)->Cache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+done:
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+    XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
+    (*Transmitter)->CacheInterface = NULL;
+fail3:
+    Error("fail3\n");
+    XENVIF_VIF(Release, (*Transmitter)->VifInterface);
+    (*Transmitter)->VifInterface = NULL;
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
 fail1:
     Error("fail1 (%08x)\n", status);
     return status;
@@ -331,6 +584,19 @@ TransmitterTeardown(
     IN  PXENNET_TRANSMITTER     Transmitter
     )
 {
+    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
+        goto done;
+
+    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter->Cache);
+    Transmitter->Cache = NULL;
+
+    XENBUS_CACHE(Release, Transmitter->CacheInterface);
+    Transmitter->CacheInterface = NULL;
+
+done:
+    XENVIF_VIF(Release, Transmitter->VifInterface);
+    Transmitter->VifInterface = NULL;
+
     ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
 
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index f99ffd3..adf3b4c 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -45,9 +45,15 @@ TransmitterSendNetBufferLists(
     );
 
 extern VOID
-TransmitterCompletePackets(
-    IN  PXENNET_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+TransmitterCompletePacketsV1(
+    IN  PXENNET_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
+    );
+
+extern VOID
+TransmitterCompletePacketsV2(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
     );
 
 extern VOID
-- 
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 Wed Nov 12 16:39:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawp-0003TU-DS; Wed, 12 Nov 2014 16:39:11 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawm-0003T0-QY
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:09 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	A1/E3-25547-C2D83645; Wed, 12 Nov 2014 16:39:08 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17598 invoked from network); 12 Nov 2014 16:39:05 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032059"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:47 +0000
Message-ID: <1415810330-1152-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/4] Refactor for maintainability/coding style
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

Removes common headers and the disabling of warnings via #pragmas
Fits code into driver.c (DriverEntry/Dispatch overrides), adapter.c
(NDIS miniport). Resolves differences in receiver/transmitter
implementations.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/adapter.c         | 3833 +++++++++++++++++++-----------------------
 src/xennet/adapter.h         |  154 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  550 ++++++
 src/xennet/main.c            |  361 ----
 src/xennet/miniport.c        |  297 ----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  393 +++--
 src/xennet/receiver.h        |   59 +-
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  330 ++--
 src/xennet/transmitter.h     |   61 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 14 files changed, 2770 insertions(+), 3421 deletions(-)
 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/miniport.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..6b32d1a 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -28,51 +28,44 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  * SUCH DAMAGE.
  */
+#define INITGUID
 
+#include <ndis.h>
+#include <ntstrsafe.h>
 #include <version.h>
-#include "common.h"
 
-#pragma warning(disable:4711)
+#include "adapter.h"
+#include "registry.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-//
-// List of supported OIDs.
-//
+struct _XENNET_ADAPTER {
+    XENVIF_VIF_INTERFACE        VifInterface;
 
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    );
+    BOOLEAN                     Enabled;
+    ULONG                       MaximumFrameSize;
+    ULONG                       CurrentLookahead;
 
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    );
+    NDIS_HANDLE                 NdisHandle;
+    NDIS_HANDLE                 NdisDmaHandle;
+    NDIS_PNP_CAPABILITIES       Capabilities;
+    NDIS_OFFLOAD                Offload;
+    XENNET_PROPERTIES           Properties;
 
-static NDIS_STATUS
-AdapterSetOffloadAttributes (
-    IN  PADAPTER Adapter
-    );
+    PXENNET_RECEIVER            Receiver;
+    PXENNET_TRANSMITTER         Transmitter;
+};
 
-static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
-static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
-    );
+#define XENNET_POOL_TAG         'tenX'
 
-static NDIS_STATUS
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+#define XENNET_MEDIA_MAX_SPEED  1000000000ull
 
-static NDIS_STATUS
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+#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)
 
 static NDIS_OID XennetSupportedOids[] =
 {
@@ -129,31 +122,9 @@ 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)
-
-NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
-{
-    if (Adapter == NULL)
-        return STATUS_INVALID_PARAMETER;
-
-    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof (ADAPTER), ' TEN');
-    if (*Adapter == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    return STATUS_SUCCESS;
-}
-
-//
-// Scatter gather allocate handler callback.
-// Should never get called.
-//
 __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
 static VOID
-AdapterAllocateComplete (
+AdapterAllocateComplete(
     IN NDIS_HANDLE              MiniportAdapterContext,
     IN PVOID                    VirtualAddress,
     IN PNDIS_PHYSICAL_ADDRESS   PhysicalAddress,
@@ -168,139 +139,33 @@ 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;
 }
 
+__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
 static VOID
-AdapterMediaStateChange(
-    IN  PADAPTER                Adapter
+AdapterProcessSGList(
+    IN PDEVICE_OBJECT           DeviceObject,
+    IN PVOID                    Reserved,
+    IN PSCATTER_GATHER_LIST     SGL,
+    IN PVOID                    Context
     )
 {
-    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);
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Reserved);
+    UNREFERENCED_PARAMETER(SGL);
+    UNREFERENCED_PARAMETER(Context);
 
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
+    ASSERT(FALSE);
 }
 
-
-//
-// 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;
+    PXENNET_ADAPTER                 Adapter = Context;
     va_list                         Arguments;
 
     va_start(Arguments, Type);
@@ -319,7 +184,7 @@ AdapterVifCallback(
 
         List = va_arg(Arguments, PLIST_ENTRY);
 
-        ReceiverReceivePackets(&Adapter->Receiver, List);
+        ReceiverReceivePackets(Adapter->Receiver, List);
         break;
     }
     case XENVIF_MAC_STATE_CHANGE: {
@@ -331,39 +196,220 @@ AdapterVifCallback(
     va_end(Arguments);
 }
 
-NDIS_STATUS
-AdapterGetAdvancedSettings(
-    IN PADAPTER pAdapter
+#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,
+    IN  ULONG           Size,
+    IN  BOOLEAN         Optional
     )
 {
-    NDIS_CONFIGURATION_OBJECT configObject;
-    NDIS_HANDLE hConfigurationHandle;
-    NDIS_STRING ndisValue;
-    PNDIS_CONFIGURATION_PARAMETER pNdisData;
-    NDIS_STATUS ndisStatus;
-    NTSTATUS status;
+    UNICODE_STRING      Unicode;
+    HANDLE              InterfacesKey;
+    HANDLE              SubscriberKey;
+    KEVENT              Event;
+    IO_STATUS_BLOCK     StatusBlock;
+    PIRP                Irp;
+    PIO_STACK_LOCATION  StackLocation;
+    NTSTATUS            status;
+
+    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));
 
-    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;
+    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
 
-    ndisStatus = NdisOpenConfigurationEx(&configObject, &hConfigurationHandle);
+    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));
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
 
     status = STATUS_UNSUCCESSFUL;
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
+    if (Irp == NULL)
+        goto fail4;
+
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
+
+    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;
+    }
+
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_NOT_SUPPORTED && Optional)
+            goto done;
+
+        goto fail5;
+    }
+
+    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);
+
+    return status;
+}
+
+#define QUERY_INTERFACE(                                                                \
+    _DeviceObject,                                                                      \
+    _ProviderName,                                                                      \
+    _InterfaceName,                                                                     \
+    _Version,                                                                           \
+    _Interface,                                                                         \
+    _Size,                                                                              \
+    _Optional)                                                                          \
+    __QueryInterface((_DeviceObject),                                                   \
+                     L ## #_ProviderName,                                               \
+                     #_InterfaceName,                                                   \
+                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
+                     (_Version),                                                        \
+                     (_Interface),                                                      \
+                     (_Size),                                                           \
+                     (_Optional))
+
+static FORCEINLINE NDIS_STATUS
+AdapterSetRegistrationAttributes(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs;
+    NDIS_STATUS                                   status;
+
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    Attribs.Header.Type                 = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    Attribs.Header.Size                 = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    Attribs.Header.Revision             = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    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;
+
+    status = NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
+    return status;
+}
+
+static FORCEINLINE NDIS_STATUS
+AdapterGetAdvancedSettings(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_CONFIGURATION_OBJECT   Config;
+    NDIS_HANDLE                 Handle;
+    NDIS_STRING                 Value;
+    PNDIS_CONFIGURATION_PARAMETER Data;
+    NDIS_STATUS                 NdisStatus;
+
+    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
+    Config.Header.Type      = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    Config.Header.Size      = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    Config.Header.Revision  = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    Config.NdisHandle       = Adapter->NdisHandle;
+    Config.Flags            = 0;
+
+    NdisStatus = NdisOpenConfigurationEx(&Config, &Handle);
+    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; \
-        } \
+#define read_property(_field, _name, _default_val)                                          \
+    do {                                                                                    \
+        RtlInitUnicodeString(&Value, _name);                                                \
+        NdisReadConfiguration(&NdisStatus, &Data, Handle, &Value, NdisParameterInteger);    \
+        if (NdisStatus == NDIS_STATUS_SUCCESS) {                                            \
+            Adapter->Properties._field = Data->ParameterData.IntegerData;                   \
+        } else {                                                                            \
+            Adapter->Properties._field = _default_val;                                      \
+        }                                                                                   \
     } while (FALSE);
 
     read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
@@ -377,465 +423,827 @@ AdapterGetAdvancedSettings(
     read_property(lrov6, L"LROIPv6", 1);
     read_property(need_csum_value, L"NeedChecksumValue", 1);
 
-    NdisCloseConfiguration(hConfigurationHandle);
-
+    NdisCloseConfiguration(Handle);
     return NDIS_STATUS_SUCCESS;
 
 fail1:
-    Error("fail1\n");
-    return NDIS_STATUS_FAILURE;
+    Error("fail1 (%08x)\n", NdisStatus);
+    return NdisStatus;
 }
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+static FORCEINLINE NDIS_STATUS
+AdapterSetGeneralAttributes(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    NDIS_STATUS ndisStatus;
-    NDIS_SG_DMA_DESCRIPTION DmaDescription;
-    NTSTATUS status;
-
-    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
-    if (!NT_SUCCESS(status))
-        return NDIS_STATUS_FAILURE;
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
 
-    Adapter->AcquiredInterfaces = TRUE;
+    XENVIF_VIF(MacQueryMaximumFrameSize,
+               &Adapter->VifInterface,
+               (PULONG)&Adapter->MaximumFrameSize);
 
-    Trace("====>\n");
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
+
+    Attribs.Header.Type         = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    Attribs.Header.Size         = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+    Attribs.Header.Revision     = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    Attribs.MediaType               = XENNET_MEDIA_TYPE;
+    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;
+    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;
+    Attribs.SupportedOidList        = XennetSupportedOids;
+    Attribs.SupportedOidListLength  = sizeof(XennetSupportedOids);
 
-    Adapter->NdisAdapterHandle = AdapterHandle;
+    XENVIF_VIF(MacQueryPermanentAddress,
+               &Adapter->VifInterface,
+               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
+    XENVIF_VIF(MacQueryCurrentAddress,
+               &Adapter->VifInterface,
+               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
 
-    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
+    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
+}
 
-    Adapter->Transmitter = (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSMITTER), ' TEN');
-    if (!Adapter->Transmitter) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto exit;
+static FORCEINLINE NDIS_STATUS
+AdapterSetOffloadAttributes(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
+    NDIS_OFFLOAD                                Default;
+    NDIS_OFFLOAD                                Supported;
+
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
+
+    if (Adapter->Properties.need_csum_value) {
+        RxOptions->NeedChecksumValue = 1;
     }
-
-    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
-
-    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (Adapter->Properties.lrov4) {
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
-
-    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (Adapter->Properties.lrov6) {
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-    ndisStatus = AdapterGetAdvancedSettings(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               TxOptions);
+
+    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
+    Supported.Header.Type       = NDIS_OBJECT_TYPE_OFFLOAD;
+    Supported.Header.Size       = sizeof(NDIS_OFFLOAD);
+    Supported.Header.Revision   = NDIS_OFFLOAD_REVISION_1;
+
+    Supported.Checksum.IPv4Receive.Encapsulation        = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Receive.IpChecksum           = 1;
+    Supported.Checksum.IPv4Receive.IpOptionsSupported   = 1;
+    Supported.Checksum.IPv4Receive.TcpChecksum          = 1;
+    Supported.Checksum.IPv4Receive.TcpOptionsSupported  = 1;
+    Supported.Checksum.IPv4Receive.UdpChecksum          = 1;
+
+    Supported.Checksum.IPv6Receive.Encapsulation        = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Receive.TcpChecksum          = 1;
+    Supported.Checksum.IPv6Receive.TcpOptionsSupported  = 1;
+    Supported.Checksum.IPv6Receive.UdpChecksum          = 1;
+
+    Supported.Checksum.IPv4Transmit.Encapsulation       = NDIS_ENCAPSULATION_IEEE_802_3;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Supported.Checksum.IPv4Transmit.IpChecksum          = 1;
+        Supported.Checksum.IPv4Transmit.IpOptionsSupported  = 1;
     }
-
-    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Supported.Checksum.IPv4Transmit.TcpChecksum         = 1;
+        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Supported.Checksum.IPv4Transmit.UdpChecksum         = 1;
     }
 
-    ndisStatus = AdapterSetGeneralAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    Supported.Checksum.IPv6Transmit.Encapsulation       = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Supported.Checksum.IPv6Transmit.TcpChecksum         = 1;
+        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Supported.Checksum.IPv6Transmit.UdpChecksum         = 1;
     }
 
-    ndisStatus = AdapterSetOffloadAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   4,
+                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
+        Supported.LsoV2.IPv4.Encapsulation              = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv4.MinSegmentCount            = 2;
     }
 
-    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
+    if (TxOptions->OffloadIpVersion6LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   6,
+                   &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;
+    }
 
-    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;
+    Default = Supported;
 
-    ndisStatus = NdisMRegisterScatterGatherDma(Adapter->NdisAdapterHandle,
-                                               &DmaDescription,
-                                               &Adapter->NdisDmaHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        Adapter->NdisDmaHandle = NULL;
+    if (!(Adapter->Properties.ipv4_csum & 2))
+        Default.Checksum.IPv4Receive.IpChecksum = 0;
+    if (!(Adapter->Properties.tcpv4_csum & 2))
+        Default.Checksum.IPv4Receive.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv4_csum & 2))
+        Default.Checksum.IPv4Receive.UdpChecksum = 0;
+    if (!(Adapter->Properties.tcpv6_csum & 2))
+        Default.Checksum.IPv6Receive.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv6_csum & 2))
+        Default.Checksum.IPv6Receive.UdpChecksum = 0;
+    if (!(Adapter->Properties.ipv4_csum & 1))
+        Default.Checksum.IPv4Transmit.IpChecksum = 0;
+    if (!(Adapter->Properties.tcpv4_csum & 1))
+        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv4_csum & 1))
+        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
+    if (!(Adapter->Properties.tcpv6_csum & 1))
+        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv6_csum & 1))
+        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
+    if (!(Adapter->Properties.lsov4)) {
+        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv4.MinSegmentCount = 0;
+    }
+    if (!(Adapter->Properties.lsov6)) {
+        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv6.MinSegmentCount = 0;
+    }
 
-    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, &Default, sizeof(NDIS_OFFLOAD))) {
+        Adapter->Offload = Default;
+        //DISPLAY_OFFLOAD(Default);
     }
 
-exit:
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Attribs, sizeof(Attribs));
+    Attribs.Header.Type         = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
+    Attribs.Header.Size         = sizeof(Attribs);
+    Attribs.Header.Revision     = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
+    Attribs.DefaultOffloadConfiguration = &Default;
+    Attribs.HardwareOffloadCapabilities = &Supported;
 
-    Trace("<==== (%08x)\n", ndisStatus);
-    return ndisStatus;
+    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 }
 
-//
-// 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
+AdapterIndicateOffloadChanged(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Reserved);
-    UNREFERENCED_PARAMETER(SGL);
-    UNREFERENCED_PARAMETER(Context);
-
-    ASSERT(FALSE);
-
-    return;
-}
+    NDIS_STATUS_INDICATION      Indication;
+    NDIS_OFFLOAD                Offload;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
 
-//
-// Get\Set OID handler.
-//
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    NDIS_STATUS ndisStatus;
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    switch (NdisRequest->RequestType) {
-        case NdisRequestSetInformation:            
-            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
-            break;
-                
-        case NdisRequestQueryInformation:
-        case NdisRequestQueryStatistics:
-            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
-            break;
+    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
+    Offload.Header.Type         = NDIS_OBJECT_TYPE_OFFLOAD;
+    Offload.Header.Size         = sizeof(NDIS_OFFLOAD);
+    Offload.Header.Revision     = NDIS_OFFLOAD_REVISION_1;
+    
+    Offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    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;
+    }
 
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+    Offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    if (RxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
+    }
 
-    return ndisStatus;
-}
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-//
-// Temporarily pauses adapter.
-//
-NDIS_STATUS
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
-    )
-{
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
-    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
 
-    Trace("====>\n");
+    Offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
+    }
 
-    if (!Adapter->Enabled)
-        goto done;
+    Offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
+    }
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    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;
+    }
+    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;
+    }
 
-    AdapterMediaStateChange(Adapter);
+    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = Offload;
+        //DISPLAY_OFFLOAD(Offload);
+    }
 
-    Adapter->Enabled = FALSE;
+    RtlZeroMemory(&Indication, sizeof(Indication));
+    Indication.Header.Type      = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    Indication.Header.Size      = sizeof(Indication);
+    Indication.Header.Revision  = NDIS_STATUS_INDICATION_REVISION_1;
+    Indication.SourceHandle     = Adapter->NdisHandle;
+    Indication.StatusCode       = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    Indication.StatusBuffer     = &Offload;
+    Indication.StatusBufferSize = sizeof(Offload);
 
-done:
-    Trace("<====\n");
-    return NDIS_STATUS_SUCCESS;
+    NdisMIndicateStatusEx(Adapter->NdisHandle, &Indication);
 }
 
-//
-// Handles PNP and Power events. NOP.
-//
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+static NDIS_STATUS
+AdapterSetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PULONG                  PacketFilter
     )
 {
-    UNREFERENCED_PARAMETER(NdisHandle);
+    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;
 
-    switch (NetDevicePnPEvent->DevicePnPEvent) {
-        case NdisDevicePnPEventQueryRemoved:
-            break;
+    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        goto done;
+    }
 
-        case NdisDevicePnPEventRemoved:
-            break;       
+    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
+        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-        case NdisDevicePnPEventSurpriseRemoved:
-            break;
+    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;
 
-        case NdisDevicePnPEventQueryStopped:
-            break;
+    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-        case NdisDevicePnPEventStopped:
-            break;      
-            
-        case NdisDevicePnPEventPowerProfileChanged:
-            break;      
-            
-        default:
-            break;         
-    };
+done:
+    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;
+    return NDIS_STATUS_SUCCESS;
 }
 
-//
-// Reports general statistics to NDIS.
-//
-static NDIS_STATUS 
-AdapterQueryGeneralStatistics (
-    IN  PADAPTER                Adapter,
-    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
+static NDIS_STATUS
+AdapterSetMulticastAddresses(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PETHERNET_ADDRESS       Address,
+    IN  ULONG                   Count
     )
 {
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    ULONGLONG   Value;
-
-    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);
+    NTSTATUS status;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    status = XENVIF_VIF(MacSetMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Address,
+                        Count);
+    if (!NT_SUCCESS(status))
+        return NDIS_STATUS_INVALID_DATA;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BACKEND_ERRORS,
-                      &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-    NdisStatisticsInfo->ifInErrors = Value;
+static NDIS_STATUS
+AdapterSetOffloadEncapsulation(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OFFLOAD_ENCAPSULATION Encapsulation
+    )
+{
+    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_FRONTEND_ERRORS,
-                      &Value);
+    if (Encapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Encapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto fail1;
+    if (Encapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Encapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto fail2;
 
-    NdisStatisticsInfo->ifInErrors += Value;
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+                &Adapter->VifInterface,
+                &Options);
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
+    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;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_PACKETS_DROPPED,
-                      &Value);
+    if (Adapter->Properties.need_csum_value)
+        RxOptions->NeedChecksumValue = 1;
+    if (Adapter->Properties.lrov4) {
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
+    }
+    if (Adapter->Properties.lrov6) {
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        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;
 
-    NdisStatisticsInfo->ifInDiscards = Value;
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
+static NDIS_STATUS
+AdapterSetTcpOffloadParameters(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OFFLOAD_PARAMETERS    Parameters
+    )
+{
+    BOOLEAN     Changed = FALSE;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+
+    if (Parameters->IPsecV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->LsoV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->TcpConnectionIPv4 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->TcpConnectionIPv6 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        goto fail1;
+    }
+    if (Parameters->LsoV2IPv4 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_OCTETS,
-                      &Value);
+        XENVIF_VIF(TransmitterQueryOffloadOptions,
+                    &Adapter->VifInterface,
+                    &Options);
 
-    NdisStatisticsInfo->ifHCInOctets = Value;
+        if (!(Options.OffloadIpVersion4LargePacket))
+            goto fail2;
+    }
+    if (Parameters->LsoV2IPv6 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_OCTETS,
-                      &Value);
+        XENVIF_VIF(TransmitterQueryOffloadOptions,
+                    &Adapter->VifInterface,
+                    &Options);
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
+        if (!(Options.OffloadIpVersion6LargePacket))
+            goto fail3;
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_OCTETS,
-                      &Value);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
+#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 set_value(x, y)     ((x) == (y)) ? FALSE : ( ((x) = (y)) == (y) )
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
+    if (Parameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 1);
+    } else if (Parameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_OCTETS,
-                      &Value);
+    if (Parameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 1);
+    } else if (Parameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInUcastOctets = Value;
+    if (tx_enabled(Parameters->IPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4HeaderChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4HeaderChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
+    if (tx_enabled(Parameters->TCPIPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_PACKETS,
-                      &Value);
+    if (tx_enabled(Parameters->UDPIPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInUcastPkts = Value;
+    if (tx_enabled(Parameters->TCPIPv6Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
+    if (tx_enabled(Parameters->UDPIPv6Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_OCTETS,
-                      &Value);
+    if (rx_enabled(Parameters->IPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4HeaderChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4HeaderChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
+    if (rx_enabled(Parameters->TCPIPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
+    if (rx_enabled(Parameters->UDPIPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_PACKETS,
-                      &Value);
+    if (rx_enabled(Parameters->TCPIPv6Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
+    if (rx_enabled(Parameters->UDPIPv6Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
+#undef tx_enabled
+#undef rx_enabled
+#undef set_value
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_OCTETS,
-                      &Value);
+    if (Changed)
+        AdapterIndicateOffloadChanged(Adapter);
 
-    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
+    return NDIS_STATUS_SUCCESS;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_PACKETS,
-                      &Value);
+static NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PNDIS_OID_REQUEST       Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded = 0;
+    ULONG           BytesRead   = 0;
+    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
 
-    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
+    Buffer          = Request->DATA.SET_INFORMATION.InformationBuffer;
+    BufferLength    = Request->DATA.SET_INFORMATION.InformationBufferLength;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+        case OID_PNP_SET_POWER:
+            BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                      &Value);
+        case OID_GEN_CURRENT_LOOKAHEAD:
+            BytesNeeded = sizeof(ULONG);
+            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
+            if (BufferLength == sizeof(ULONG)) {
+                Adapter->CurrentLookahead = *(PULONG)Buffer;
+                BytesRead = sizeof(ULONG);
+            }
+            break;
 
-    NdisStatisticsInfo->ifOutErrors = Value;
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            BytesNeeded = sizeof(ULONG);
+            if (BufferLength == sizeof(ULONG)) {
+                NdisStatus = AdapterSetPacketFilter(Adapter, (PULONG)Buffer);
+                BytesRead = sizeof(ULONG);
+            }
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                      &Value);
+        case OID_802_3_MULTICAST_LIST:
+            BytesNeeded = ETHERNET_ADDRESS_LENGTH;
+            if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
+                ULONG   Count = BufferLength / ETHERNET_ADDRESS_LENGTH;
+                NdisStatus = AdapterSetMulticastAddresses(Adapter, Buffer, Count);
+                BytesRead = BufferLength;
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    NdisStatisticsInfo->ifOutErrors += Value;
+        case OID_OFFLOAD_ENCAPSULATION:
+            BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+            if (BufferLength == sizeof(NDIS_OFFLOAD_ENCAPSULATION)) {
+                NdisStatus = AdapterSetOffloadEncapsulation(Adapter, Buffer);
+                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
+        case OID_TCP_OFFLOAD_PARAMETERS:
+            BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
+            if (BufferLength == sizeof(NDIS_OFFLOAD_PARAMETERS)) {
+                NdisStatus = AdapterSetTcpOffloadParameters(Adapter, Buffer);
+                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                      &Value);
+        case OID_GEN_INTERRUPT_MODERATION:
+            NdisStatus = NDIS_STATUS_INVALID_DATA;
+            break;
 
-    NdisStatisticsInfo->ifHCOutOctets = Value;
+        case OID_GEN_MACHINE_NAME:
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                      &Value);
+    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
+    if (NdisStatus == NDIS_STATUS_SUCCESS) {
+        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
+    }
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
+    return NdisStatus;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                      &Value);
+static FORCEINLINE ULONG64
+AdapterGetXmitOk(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                &Value);
+    Result = Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    return Result;
+}
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
+static FORCEINLINE ULONG64
+AdapterGetRcvOk(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_UNICAST_PACKETS,
+                &Value);
+    Result = Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_MULTICAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BROADCAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    return Result;
+}
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
+static FORCEINLINE ULONG64
+AdapterGetXmitError(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                      &Value);
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                &Value);
+    Result = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                &Value);
+    Result += Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
+    return Result;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                      &Value);
+static FORCEINLINE ULONG64
+AdapterGetRcvError(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
 
-    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BACKEND_ERRORS,
+                &Value);
+    Result = Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_FRONTEND_ERRORS,
+                &Value);
+    Result += Value;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                      &Value);
+    return Result;
+}
 
-    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
+static VOID
+AdapterGetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PULONG                  PacketFilter
+    )
+{
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               &UnicastFilterLevel);
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
-
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
-
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
-    NdisStatisticsInfo->ifOutDiscards = 0;
-
-    return ndisStatus;
-}
-
-static VOID
-GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
-{
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
-
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               &UnicastFilterLevel);
-
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               &MulticastFilterLevel);
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               &MulticastFilterLevel);
 
     XENVIF_VIF(MacQueryFilterLevel,
                &Adapter->VifInterface,
@@ -863,1715 +1271,934 @@ GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
         *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
 }
 
-#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
+AdapterQueryGeneralStatistics (
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PNDIS_STATISTICS_INFO   Stats
     )
 {
-    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");
+    ULONGLONG                   Value;
 
-            info = &Adapter->Capabilities;
-            bytesAvailable = sizeof(Adapter->Capabilities);
-            break;
+    RtlZeroMemory(Stats, sizeof(NDIS_STATISTICS_INFO));
+    Stats->Header.Type         = NDIS_OBJECT_TYPE_DEFAULT;
+    Stats->Header.Size         = sizeof(NDIS_STATISTICS_INFO);
+    Stats->Header.Revision     = NDIS_OBJECT_REVISION_1;
 
-        case OID_PNP_QUERY_POWER:
-            Trace("QUERY_POWER\n");
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BACKEND_ERRORS,
+                      &Value);
+    Stats->ifInErrors = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_FRONTEND_ERRORS,
+                      &Value);
+    Stats->ifInErrors += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_PACKETS_DROPPED,
+                      &Value);
+    Stats->ifInDiscards = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets += Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInUcastOctets = Value;
 
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_PACKETS,
+                      &Value);
+    Stats->ifHCInUcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInMulticastOctets = Value;
 
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Trace("D0\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_PACKETS,
+                      &Value);
+    Stats->ifHCInMulticastPkts = Value;
 
-                case NdisDeviceStateD1:
-                    Trace("D1\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCInBroadcastOctets = Value;
 
-                case NdisDeviceStateD2:
-                    Trace("D2\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_PACKETS,
+                      &Value);
+    Stats->ifHCInBroadcastPkts = Value;
 
-                case NdisDeviceStateD3:
-                    Trace("D3\n");
-                    break;
-                }
-            }
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                      &Value);
+    Stats->ifOutErrors = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                      &Value);
+    Stats->ifOutErrors += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets += Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutUcastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutUcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutMulticastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutMulticastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutBroadcastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutBroadcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
+    Stats->ifOutDiscards = 0;
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+AdapterGetInterruptModeration(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PNDIS_INTERRUPT_MODERATION_PARAMETERS   Parameters
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+
+    RtlZeroMemory(Parameters, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS));
+    Parameters->Header.Type      = NDIS_OBJECT_TYPE_DEFAULT;
+    Parameters->Header.Size      = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+    Parameters->Header.Revision  = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+    Parameters->Flags            = 0;
+    Parameters->InterruptModeration = NdisInterruptModerationNotSupported;
+}
+
+static NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
+    )
+{
+    ULONG           Value32;
+    ULONG64         Value64;
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    BOOLEAN         DoCopy = TRUE;
+    ULONG           BytesAvailable = 0;
+    PVOID           BytesToCopy = NULL;
+    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
+
+    Buffer          = Request->DATA.QUERY_INFORMATION.InformationBuffer;
+    BufferLength    = Request->DATA.QUERY_INFORMATION.InformationBufferLength;
+
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+        case OID_PNP_CAPABILITIES:
+            BytesToCopy = &Adapter->Capabilities;
+            BytesAvailable = sizeof(Adapter->Capabilities);
             break;
 
         case OID_GEN_SUPPORTED_LIST:
-            info = &XennetSupportedOids[0];
-            bytesAvailable = sizeof(XennetSupportedOids);
+            BytesToCopy = &XennetSupportedOids[0];
+            BytesAvailable = sizeof(XennetSupportedOids);
             break;
 
         case OID_GEN_HARDWARE_STATUS:
-            infoData = NdisHardwareStatusReady;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = NdisHardwareStatusReady;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MEDIA_SUPPORTED:
         case OID_GEN_MEDIA_IN_USE:
-            infoData = XENNET_MEDIA_TYPE;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = XENNET_MEDIA_TYPE;
+            BytesToCopy = &Value32;
+            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);
+            Value32 = Adapter->MaximumFrameSize;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_VENDOR_DESCRIPTION:
-            info = COMPANY_NAME_STR;
-            bytesAvailable = (ULONG)strlen(info) + 1;
+            BytesToCopy = COMPANY_NAME_STR;
+            BytesAvailable = (ULONG)strlen(BytesToCopy) + 1;
             break;
 
         case OID_GEN_VENDOR_DRIVER_VERSION:
-            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_DRIVER_VERSION:
-            infoData = (6 << 8) | 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = (6 << 8) | 0;
+            BytesToCopy = &Value32;
+            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);
-
-            }
-
+            Value32 = XENNET_MAC_OPTIONS;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_802_3_MULTICAST_LIST: {
-            ULONG Count;
-
-            doCopy = FALSE;
-
-            XENVIF_VIF(MacQueryMulticastAddresses,
+        case OID_GEN_TRANSMIT_BUFFER_SPACE:
+        case OID_GEN_RECEIVE_BUFFER_SPACE:
+            XENVIF_VIF(TransmitterQueryRingSize,
                        &Adapter->VifInterface,
-                       NULL,
-                       &Count);
-            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
-
-            if (informationBufferLength >= bytesAvailable) {
-                NTSTATUS status;
-
-                status = XENVIF_VIF(MacQueryMulticastAddresses,
-                                    &Adapter->VifInterface,
-                                    informationBuffer,
-                                    &Count);
-                if (!NT_SUCCESS(status))
-                    ndisStatus = NDIS_STATUS_FAILURE;
-            }
-
+                       (PULONG)&Value32);
+            Value32 *= Adapter->MaximumFrameSize;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
-        }
+
         case OID_802_3_PERMANENT_ADDRESS:
             XENVIF_VIF(MacQueryPermanentAddress,
                        &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
+                       (PETHERNET_ADDRESS)&Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_802_3_CURRENT_ADDRESS:
             XENVIF_VIF(MacQueryCurrentAddress,
                        &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
+                       (PETHERNET_ADDRESS)&Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MAXIMUM_FRAME_SIZE:
-            infoData = Adapter->MaximumFrameSize -
+            Value32 = Adapter->MaximumFrameSize -
                        sizeof (ETHERNET_TAGGED_HEADER);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MAXIMUM_TOTAL_SIZE:
-            infoData = Adapter->MaximumFrameSize -
+            Value32 = Adapter->MaximumFrameSize -
                        sizeof (ETHERNET_TAGGED_HEADER) +
                        sizeof (ETHERNET_UNTAGGED_HEADER);
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_CURRENT_LOOKAHEAD:
-            infoData = Adapter->CurrentLookahead;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = Adapter->CurrentLookahead;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_VENDOR_ID:
-            infoData = 0x5853;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = 0x5853;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_LINK_SPEED: {
-            ULONG64 LinkSpeed;
-
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &LinkSpeed,
-                       NULL);
-
-            infoData = (ULONG)(LinkSpeed / 100);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MEDIA_CONNECT_STATUS:
+        case OID_GEN_LINK_SPEED:
             XENVIF_VIF(MacQueryState,
                        &Adapter->VifInterface,
-                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
                        NULL,
+                       &Value64,
                        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);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_RCV_OK: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
+            Value32 = (ULONG)(Value64 / 100);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
-        }
-        case OID_GEN_XMIT_ERROR: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_ERROR: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BACKEND_ERRORS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_FRONTEND_ERRORS,
-                       &Value);
-
-            infoData += Value;
-
-            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);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        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;
-
-        // 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;
-        }
-
-        if (bytesWritten && doCopy) {
-            NdisMoveMemory(informationBuffer, info, bytesWritten);
-
-            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
-                ndisStatus = NDIS_STATUS_SUCCESS;
-        }
-    }
-    
-    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = bytesWritten;
-    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = bytesNeeded;
-    return ndisStatus;
-}
-#pragma warning(pop)
-
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
-    )
-{
-    UNREFERENCED_PARAMETER(MiniportAdapterContext);
-
-
-    *AddressingReset = FALSE;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-//
-// 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;
-
-    UNREFERENCED_PARAMETER(MiniportRestartParameters);
-
-    Trace("====>\n");
-
-    if (Adapter->Enabled) {
-        ndisStatus = NDIS_STATUS_SUCCESS;
-        goto done;
-    }
-
-    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;
-    }
-
-done:
-    Trace("<====\n");
-    return ndisStatus;
-}
-
-//
-// Recycle of received net buffer lists.
-//
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    ReceiverReturnNetBufferLists(&Adapter->Receiver,
-                                 NetBufferLists,
-                                 ReturnFlags);
-
-    return;
-}
-
-//
-// 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
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    TransmitterSendNetBufferLists(Adapter->Transmitter,
-                                  NetBufferList,
-                                  PortNumber,
-                                  SendFlags);
-}
-
-#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)
-
-//
-// Sets general adapter attributes. 
-//
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    )
-{
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
-    NDIS_STATUS ndisStatus;
-
-    NdisZeroMemory(&generalAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
-
-    generalAttributes.Header.Type = 
-                    NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
-
-    generalAttributes.Header.Revision = 
-                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
-
-    generalAttributes.Header.Size = 
-                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
-
-    generalAttributes.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;
-
-    XENVIF_VIF(MacQueryPermanentAddress,
-               &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.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;
-                      
-    generalAttributes.SupportedOidList = XennetSupportedOids;
-    generalAttributes.SupportedOidListLength = sizeof(XennetSupportedOids);
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
-
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
-    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
-    )
-{
-    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;
-
-    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;
-    }
-
-    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);
-
-    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
-    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
-    supported.Header.Size = sizeof(supported);
-
-    supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv4Receive.IpChecksum = 1;
-    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
-
-    supported.Checksum.IPv4Receive.TcpChecksum = 1;
-    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
-
-    supported.Checksum.IPv4Receive.UdpChecksum = 1;
-
-    supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
-
-    supported.Checksum.IPv6Receive.TcpChecksum = 1;
-    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
-
-    supported.Checksum.IPv6Receive.UdpChecksum = 1;
-
-    XENVIF_VIF(TransmitterQueryOffloadOptions,
-               &Adapter->VifInterface,
-               &Options);
-
-    supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Options.OffloadIpVersion4HeaderChecksum) {
-        supported.Checksum.IPv4Transmit.IpChecksum = 1;
-        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion4TcpChecksum) {
-        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion4UdpChecksum)
-        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
-
-    supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
-
-    if (Options.OffloadIpVersion6TcpChecksum) {
-        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion6UdpChecksum)
-        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;
-    }
-
-    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;
-    }
-
-    current = supported;
-
-    if (!(Adapter->Properties.ipv4_csum & 2))
-        current.Checksum.IPv4Receive.IpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv4_csum & 2))
-        current.Checksum.IPv4Receive.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv4_csum & 2))
-        current.Checksum.IPv4Receive.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv6_csum & 2))
-        current.Checksum.IPv6Receive.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv6_csum & 2))
-        current.Checksum.IPv6Receive.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.ipv4_csum & 1))
-        current.Checksum.IPv4Transmit.IpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv4_csum & 1))
-        current.Checksum.IPv4Transmit.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv4_csum & 1))
-        current.Checksum.IPv4Transmit.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv6_csum & 1))
-        current.Checksum.IPv6Transmit.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv6_csum & 1))
-        current.Checksum.IPv6Transmit.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.lsov4)) {
-        current.LsoV2.IPv4.MaxOffLoadSize = 0;
-        current.LsoV2.IPv4.MinSegmentCount = 0;
-    }
-
-    if (!(Adapter->Properties.lsov6)) {
-        current.LsoV2.IPv6.MaxOffLoadSize = 0;
-        current.LsoV2.IPv6.MinSegmentCount = 0;
-    }
-
-    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = current;
-
-        DISPLAY_OFFLOAD(current);
-    }
-
-    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;
-
-    adapterAttributes =
-        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
-    return ndisStatus;
-}
-
-static void
-AdapterIndicateOffloadChanged (
-    IN  PADAPTER 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;
-    }
-
-    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);
-    }
-
-    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);
-
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
-
-}
-
-static NDIS_STATUS
-SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address, ULONG Count)
-{
-    NTSTATUS status;
-
-    status = XENVIF_VIF(MacSetMulticastAddresses,
-                        &Adapter->VifInterface,
-                        Address,
-                        Count);
-    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;
-
-    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
-        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        goto done;
-    }
-
-    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
-        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
-
-    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;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
+        case OID_GEN_MEDIA_CONNECT_STATUS:
+            XENVIF_VIF(MacQueryState,
+                       &Adapter->VifInterface,
+                       (PNET_IF_MEDIA_CONNECT_STATE)&Value32,
+                       NULL,
+                       NULL);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-done:
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               UnicastFilterLevel);
+        case OID_GEN_MAXIMUM_SEND_PACKETS:
+            Value32 = 16;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               MulticastFilterLevel);
+        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:
+            Value32 = 0;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               BroadcastFilterLevel);
+        case OID_802_3_MAXIMUM_LIST_SIZE:
+            Value32 = 32;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    return NDIS_STATUS_SUCCESS;
-}
+        case OID_GEN_STATISTICS:
+            DoCopy = FALSE;
+            BytesAvailable = sizeof(NDIS_STATISTICS_INFO);
+            if (BufferLength >= sizeof(NDIS_STATISTICS_INFO))
+                NdisStatus = AdapterQueryGeneralStatistics(Adapter, Buffer);
+            break;
 
-//
-// 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;
+        case OID_802_3_MULTICAST_LIST:
+            DoCopy = FALSE;
+            XENVIF_VIF(MacQueryMulticastAddresses,
+                       &Adapter->VifInterface,
+                       NULL,
+                       &Value32);
+            BytesAvailable = Value32 * ETHERNET_ADDRESS_LENGTH;
+            if (BufferLength >= BytesAvailable) {
+                if (!NT_SUCCESS(XENVIF_VIF(MacQueryMulticastAddresses,
+                                           &Adapter->VifInterface,
+                                           Buffer,
+                                           &Value32))) {
+                    NdisStatus = NDIS_STATUS_FAILURE;
                 }
             }
             break;
 
-        case OID_GEN_MACHINE_NAME:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            AdapterGetPacketFilter(Adapter, &Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            bytesNeeded = sizeof(ULONG);
-            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
-            if (informationBufferLength == sizeof(ULONG)) {
-                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
-                bytesRead = sizeof(ULONG);
-            }
-
+        case OID_GEN_XMIT_OK:
+            Value64 = AdapterGetXmitOk(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
             break;
 
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            bytesNeeded = sizeof(ULONG);
-            if (informationBufferLength == sizeof(ULONG)) {
-                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
-                bytesRead = sizeof(ULONG);
-            }
-
+        case OID_GEN_RCV_OK:
+            Value64 = AdapterGetRcvOk(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
             break;
 
-        case OID_802_3_MULTICAST_LIST:
-            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
-            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
-                addressCount = informationBufferLength / ETHERNET_ADDRESS_LENGTH;
+        case OID_GEN_XMIT_ERROR:
+            Value64 = AdapterGetXmitError(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
+            break;
 
-                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer, addressCount);
-                if (ndisStatus == NDIS_STATUS_SUCCESS)
-                    bytesRead = informationBufferLength;
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
+        case OID_GEN_RCV_ERROR:
+            Value64 = AdapterGetRcvError(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
+            break;
 
+        case OID_GEN_DIRECTED_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_INTERRUPT_MODERATION:
-            ndisStatus = NDIS_STATUS_INVALID_DATA;
+        case OID_GEN_DIRECTED_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_OFFLOAD_ENCAPSULATION: {
-            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
+        case OID_GEN_MULTICAST_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-            bytesNeeded = sizeof(*offloadEncapsulation);
-            if (informationBufferLength >= bytesNeeded) {
-                XENVIF_VIF_OFFLOAD_OPTIONS Options;
+        case OID_GEN_MULTICAST_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                bytesRead = bytesNeeded;
-                offloadEncapsulation = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
+        case OID_GEN_BROADCAST_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+        case OID_GEN_BROADCAST_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+        case OID_GEN_DIRECTED_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_UNICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                XENVIF_VIF(TransmitterQueryOffloadOptions,
-                           &Adapter->VifInterface,
-                           &Options);
-                
-                Adapter->Transmitter->OffloadOptions.Value = 0;
-                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
+        case OID_GEN_DIRECTED_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_UNICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.lsov4) && (Options.OffloadIpVersion4LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
+        case OID_GEN_MULTICAST_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_MULTICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.lsov6) && (Options.OffloadIpVersion6LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
+        case OID_GEN_MULTICAST_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_MULTICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+        case OID_GEN_BROADCAST_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_BROADCAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+        case OID_GEN_BROADCAST_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_BROADCAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+        case OID_GEN_INTERRUPT_MODERATION:
+            DoCopy = FALSE;
+            BytesAvailable = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+            if (BufferLength >= BytesAvailable)
+                AdapterGetInterruptModeration(Adapter, Buffer);
+            else
+                NdisStatus = NDIS_STATUS_FAILURE;
+            break;
 
-                if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+        case OID_PNP_QUERY_POWER:
+            // do nothing!
+            break;
 
-                if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+        case OID_GEN_MAC_ADDRESS:
+        case OID_GEN_MAX_LINK_SPEED:
+        case OID_IP4_OFFLOAD_STATS:
+        case OID_IP6_OFFLOAD_STATS:
+        case OID_GEN_SUPPORTED_GUIDS:
+		case OID_GEN_INIT_TIME_MS:
+		case OID_GEN_RESET_COUNTS:
+		case OID_GEN_MEDIA_SENSE_COUNTS:
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
 
-                Adapter->Receiver.OffloadOptions.Value = 0;
-                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+    }
 
-                if (Adapter->Properties.need_csum_value)
-                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+    if (NdisStatus == NDIS_STATUS_SUCCESS) {
+        Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesAvailable;
+        if (BytesAvailable <= BufferLength) {
+            Request->DATA.QUERY_INFORMATION.BytesWritten = BytesAvailable;
+        } else {
+            Request->DATA.QUERY_INFORMATION.BytesWritten = BufferLength;
+            NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
+        }
+        if (Request->DATA.QUERY_INFORMATION.BytesWritten && DoCopy) {
+            RtlMoveMemory(Buffer, BytesToCopy, Request->DATA.QUERY_INFORMATION.BytesWritten);
 
-                if (Adapter->Properties.lrov4) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
+            // Its Ok to short transfers on these Oids
+            if (Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_XMIT_OK ||
+                Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_RCV_OK)
+                NdisStatus = NDIS_STATUS_SUCCESS;
+        }
+    }
 
-                if (Adapter->Properties.lrov6) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
+    return NdisStatus;
+}
 
-                if (Adapter->Properties.ipv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+NDIS_STATUS
+AdapterOidRequest(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
+    )
+{
+    NDIS_STATUS     NdisStatus;
+    
+    switch (Request->RequestType) {
+        case NdisRequestSetInformation:            
+            NdisStatus = AdapterSetInformation(Adapter, Request);
+            break;
+                
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            NdisStatus = AdapterQueryInformation(Adapter, Request);
+            break;
 
-                if (Adapter->Properties.tcpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
 
-                if (Adapter->Properties.udpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+    return NdisStatus;
+}
 
-                if (Adapter->Properties.tcpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+NTSTATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    NTSTATUS        status;
 
-                if (Adapter->Properties.udpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+    if (Adapter->Enabled)
+        goto done;
 
-                AdapterIndicateOffloadChanged(Adapter);
-            }
-            break;
-        }
-        case OID_TCP_OFFLOAD_PARAMETERS: {
-            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
+    status = XENVIF_VIF(Enable,
+                        &Adapter->VifInterface,
+                        AdapterVifCallback,
+                        Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+    
+    TransmitterEnable(Adapter->Transmitter);
+    Adapter->Enabled = TRUE;
 
-            bytesNeeded = sizeof(*offloadParameters);
-            if (informationBufferLength >= bytesNeeded) {
-                bytesRead = bytesNeeded;
-                offloadParameters = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
+done:
+    return STATUS_SUCCESS;
 
-#define no_change(x)  ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
 
-                if (!no_change(offloadParameters->IPsecV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                    
-                if (!no_change(offloadParameters->LsoV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    if (!Adapter->Enabled)
+        return FALSE;
 
-                if (!no_change(offloadParameters->TcpConnectionIPv4))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+    XENVIF_VIF(Disable, &Adapter->VifInterface);
+    Adapter->Enabled = FALSE;
+    return TRUE;
+}
 
-                if (!no_change(offloadParameters->TcpConnectionIPv6))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    NDIS_LINK_STATE                 LinkState;
+    NDIS_STATUS_INDICATION          StatusIndication;
 
-                if (!no_change(offloadParameters->LsoV2IPv4)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
+    LinkState.Header.Type       = NDIS_OBJECT_TYPE_DEFAULT;
+    LinkState.Header.Size       = sizeof(NDIS_LINK_STATE);
+    LinkState.Header.Revision   = NDIS_LINK_STATE_REVISION_1;
 
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
+    XENVIF_VIF(MacQueryState,
+               &Adapter->VifInterface,
+               &LinkState.MediaConnectState,
+               &LinkState.RcvLinkSpeed,
+               &LinkState.MediaDuplexState);
 
-                    if (!(Options.OffloadIpVersion4LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
+        Info("LINK: STATE UNKNOWN\n");
+    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
+        Info("LINK: DOWN\n");
+    } else {
+        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
 
-                if (!no_change(offloadParameters->LsoV2IPv6)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+        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);
+    }
 
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
+    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
 
-                    if (!(Options.OffloadIpVersion6LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
+    StatusIndication.Header.Type        = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    StatusIndication.Header.Size        = sizeof (NDIS_STATUS_INDICATION);
+    StatusIndication.Header.Revision    = NDIS_STATUS_INDICATION_REVISION_1;
+    StatusIndication.SourceHandle       = Adapter->NdisHandle;
+    StatusIndication.StatusCode         = NDIS_STATUS_LINK_STATE;
+    StatusIndication.StatusBuffer       = &LinkState;
+    StatusIndication.StatusBufferSize   = sizeof (NDIS_LINK_STATE);
 
-#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;
-                        }
-                    }
+    NdisMIndicateStatusEx(Adapter->NdisHandle, &StatusIndication);
+}
 
-#undef tx_enabled
-#undef rx_enabled
-#undef no_change
+PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->Receiver;
+}
 
-                    if (offloadChanged)
-                        AdapterIndicateOffloadChanged(Adapter);
-                }
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-            break;
-        }
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->Transmitter;
+}
 
-    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
-    }
+PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return &Adapter->VifInterface;
+}
 
-    return ndisStatus;
+NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->NdisHandle;
 }
 
-//
-// Sets miniport registration attributes.
-//
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
+NTSTATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE                 NdisHandle,
+    OUT PXENNET_ADAPTER             *Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registrationAttributes;
-    NDIS_STATUS ndisStatus;
+    PDEVICE_OBJECT          DeviceObject;
+    NTSTATUS                status;
+    NDIS_SG_DMA_DESCRIPTION DmaDescription;
+    NDIS_STATUS             NdisStatus;
+
+    status = STATUS_NO_MEMORY;
+    *Adapter = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_ADAPTER), XENNET_POOL_TAG);
+    if (*Adapter == NULL)
+        goto fail1;
 
+    RtlZeroMemory(*Adapter, sizeof(XENNET_ADAPTER));
+    (*Adapter)->NdisHandle = NdisHandle;
+
+    DeviceObject = NULL;
+    NdisMGetDeviceProperty(NdisHandle,
+                           &DeviceObject,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
+
+    status = QUERY_INTERFACE(DeviceObject,
+                             XENVIF,
+                             VIF,
+                             XENVIF_VIF_INTERFACE_VERSION_MAX,
+                             (PINTERFACE)&(*Adapter)->VifInterface,
+                             sizeof ((*Adapter)->VifInterface),
+                             FALSE);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    NdisZeroMemory(&registrationAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    registrationAttributes.Header.Type = 
-                NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
+    if (!NT_SUCCESS(status))
+        goto fail4;
 
-    registrationAttributes.Header.Revision = 
-                NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    status = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
-    registrationAttributes.Header.Size = 
-                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    NdisStatus = AdapterGetAdvancedSettings(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail6;
 
-    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;
+    NdisStatus = AdapterSetRegistrationAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail7;
 
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
+    NdisStatus = AdapterSetGeneralAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail8;
 
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
+    NdisStatus = AdapterSetOffloadAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail9;
 
-    return ndisStatus;
-}
+    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
+    DmaDescription.Header.Type      = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
+    DmaDescription.Header.Size      = sizeof(NDIS_SG_DMA_DESCRIPTION);
+    DmaDescription.Header.Revision  = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
+    DmaDescription.Flags            = NDIS_SG_DMA_64_BIT_ADDRESS;
+    DmaDescription.MaximumPhysicalMapping           = 65536;    
+    DmaDescription.ProcessSGListHandler             = AdapterProcessSGList;
+    DmaDescription.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
 
-//
-// Shuts down adapter.
-//
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+    NdisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisHandle,
+                                               &DmaDescription,
+                                               &(*Adapter)->NdisDmaHandle);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        (*Adapter)->NdisDmaHandle = NULL;
 
-    UNREFERENCED_PARAMETER(ShutdownAction);
+    status = AdapterEnable(*Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail10;
 
-    if (ShutdownAction != NdisShutdownBugCheck)
-        AdapterStop(Adapter);
+    return STATUS_SUCCESS;
 
-    return;
+fail10:
+    Error("fail10 (%08x)\n", status);
+    if ((*Adapter)->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
+    (*Adapter)->NdisDmaHandle = NULL;
+fail9:
+    Error("fail9\n");
+fail8:
+    Error("fail8\n");
+fail7:
+    Error("fail7\n");
+fail6:
+    Error("fail6 (%08x)\n", NdisStatus);
+    if (NT_SUCCESS(status))
+        status = STATUS_UNSUCCESSFUL;
+    ReceiverTeardown((*Adapter)->Receiver);
+    (*Adapter)->Receiver = NULL;
+fail5:
+    Error("fail5\n");
+    TransmitterTeardown((*Adapter)->Transmitter);
+    (*Adapter)->Transmitter = NULL;
+fail4:
+    Error("fail4\n");
+    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail3:
+    Error("fail3\n");
+    RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Adapter, XENNET_POOL_TAG);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
-//
-// 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
-)
+VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER             Adapter
+    )
 {
-    Trace("====>\n");
+    if (Adapter->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
+    Adapter->NdisDmaHandle = NULL;
 
-    if (!Adapter->Enabled)
-        goto done;
+    ReceiverTeardown(Adapter->Receiver);
+    Adapter->Receiver = NULL;
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    TransmitterTeardown(Adapter->Transmitter);
+    Adapter->Transmitter = 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, XENNET_POOL_TAG);
 }
+
+//
+//#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)
+//
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index e64e40d..a1f4b85 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -29,19 +29,20 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_ADAPTER_H_
+#define _XENNET_ADAPTER_H_
 
-#define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
+#define XENNET_INTERFACE_TYPE   NdisInterfaceInternal
 
-#define XENNET_MEDIA_TYPE               NdisMedium802_3
+#define XENNET_MEDIA_TYPE       NdisMedium802_3
 
-#define XENNET_MAC_OPTIONS              (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
-                                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
-                                         NDIS_MAC_OPTION_NO_LOOPBACK |          \
-                                         NDIS_MAC_OPTION_8021P_PRIORITY |       \
-                                         NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
+#define XENNET_MAC_OPTIONS      (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
+                                 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
+                                 NDIS_MAC_OPTION_NO_LOOPBACK |          \
+                                 NDIS_MAC_OPTION_8021P_PRIORITY |       \
+                                 NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
 
-typedef struct _PROPERTIES {
+typedef struct _XENNET_PROPERTIES {
     int ipv4_csum;
     int tcpv4_csum;
     int udpv4_csum;
@@ -52,122 +53,63 @@ typedef struct _PROPERTIES {
     int lsov6;
     int lrov4;
     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
-    );
-
-MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
-    );
+} XENNET_PROPERTIES, *PXENNET_PROPERTIES;
 
-MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    );
-
-VOID
-AdapterCleanup (
-    IN PADAPTER Adapter
-    );
+typedef struct _XENNET_ADAPTER  XENNET_ADAPTER, *PXENNET_ADAPTER;
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+extern NDIS_STATUS
+AdapterOidRequest(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
     );
 
-MINIPORT_OID_REQUEST AdapterOidRequest;
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+extern NTSTATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_PAUSE AdapterPause;
-NDIS_STATUS 
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+extern BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+extern VOID
+AdapterMediaStateChange(
+    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
+#include "transmitter.h"
+extern PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
+#include <vif_interface.h>
+extern PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    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 NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-NDIS_STATUS
-AdapterStop (
-    IN  PADAPTER    Adapter
-    );
-
-MINIPORT_SHUTDOWN AdapterShutdown;
-
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+extern NTSTATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE                 NdisHandle,
+    OUT PXENNET_ADAPTER             *Adapter
     );
 
 extern VOID
-ReceiverReceivePackets(
-    IN  PRECEIVER   Receiver,
-    IN  PLIST_ENTRY List
+AdapterTeardown(
+    IN  PXENNET_ADAPTER             Adapter
     );
+
+#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/driver.c b/src/xennet/driver.c
new file mode 100644
index 0000000..66aff1d
--- /dev/null
+++ b/src/xennet/driver.c
@@ -0,0 +1,550 @@
+/* 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 <ndis.h>
+#include <ntstrsafe.h>
+#include <version.h>
+
+#include "adapter.h"
+#include "transmitter.h"
+#include "receiver.h"
+#include "registry.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+extern PULONG InitSafeBootMode;
+
+typedef struct _XENNET_DRIVER {
+    PDRIVER_OBJECT              DriverObject;
+    NDIS_HANDLE                 MiniportHandle;
+    NTSTATUS                    (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
+} XENNET_DRIVER;
+
+static XENNET_DRIVER            Driver;
+
+MINIPORT_CANCEL_OID_REQUEST     DriverCancelOidRequest;
+VOID
+DriverCancelOidRequest(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PVOID                   RequestId
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(RequestId);
+}
+
+MINIPORT_CANCEL_SEND            DriverCancelSendNetBufferLists;
+VOID
+DriverCancelSendNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PVOID                   CancelId
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(CancelId);
+}
+
+MINIPORT_CHECK_FOR_HANG DriverCheckForHang;
+BOOLEAN
+DriverCheckForHang(
+    IN  NDIS_HANDLE             NdisHandle
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    return FALSE;
+}
+
+MINIPORT_DEVICE_PNP_EVENT_NOTIFY DriverPnPEventHandler;
+VOID
+DriverPnPEventHandler(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(NetDevicePnPEvent);
+}
+
+MINIPORT_RESET                  DriverReset;
+NDIS_STATUS
+DriverReset(
+    IN  NDIS_HANDLE             NdisHandle,
+    OUT PBOOLEAN                AddressingReset
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    *AddressingReset = FALSE;
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_OID_REQUEST            DriverOidRequest;
+NDIS_STATUS
+DriverOidRequest(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNDIS_OID_REQUEST       NdisRequest
+    )
+{
+    return AdapterOidRequest((PXENNET_ADAPTER)NdisHandle, NdisRequest);
+}
+
+MINIPORT_PAUSE DriverPause;
+NDIS_STATUS
+DriverPause(
+    IN  NDIS_HANDLE                     NdisHandle,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+    )
+{
+    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+
+    if (AdapterDisable((PXENNET_ADAPTER)NdisHandle))
+        AdapterMediaStateChange((PXENNET_ADAPTER)NdisHandle);
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_RESTART DriverRestart;
+NDIS_STATUS
+DriverRestart(
+    IN  NDIS_HANDLE                         NdisHandle,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+    )
+{
+    NTSTATUS    status;
+
+    UNREFERENCED_PARAMETER(MiniportRestartParameters);
+
+    status = AdapterEnable((PXENNET_ADAPTER)NdisHandle);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return NDIS_STATUS_FAILURE;
+}
+
+MINIPORT_RETURN_NET_BUFFER_LISTS DriverReturnNetBufferLists;
+VOID
+DriverReturnNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    PXENNET_RECEIVER            Receiver;
+    Receiver = AdapterGetReceiver((PXENNET_ADAPTER)NdisHandle);
+    ReceiverReturnNetBufferLists(Receiver,
+                                 NetBufferLists,
+                                 ReturnFlags);
+}
+
+MINIPORT_SEND_NET_BUFFER_LISTS  DriverSendNetBufferLists;
+VOID
+DriverSendNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    PXENNET_TRANSMITTER         Transmitter;
+    Transmitter = AdapterGetTransmitter((PXENNET_ADAPTER)NdisHandle);
+    TransmitterSendNetBufferLists(Transmitter,
+                                  NetBufferList,
+                                  PortNumber,
+                                  SendFlags);
+}
+
+MINIPORT_SHUTDOWN DriverShutdown;
+VOID
+DriverShutdown(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+    )
+{
+    UNREFERENCED_PARAMETER(ShutdownAction);
+
+    if (ShutdownAction != NdisShutdownBugCheck)
+        (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
+}
+
+MINIPORT_INITIALIZE             DriverInitialize;
+NDIS_STATUS 
+DriverInitialize(
+    IN  NDIS_HANDLE                        NdisHandle,
+    IN  NDIS_HANDLE                        DriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     Parameters
+    )
+{
+    NTSTATUS            status;
+    PXENNET_ADAPTER     Adapter;
+
+    UNREFERENCED_PARAMETER(DriverContext);
+    UNREFERENCED_PARAMETER(Parameters);
+
+    status = AdapterInitialize(NdisHandle, &Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return NDIS_STATUS_ADAPTER_NOT_FOUND;
+}
+
+MINIPORT_HALT                   DriverHalt;
+VOID 
+DriverHalt(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  NDIS_HALT_ACTION        HaltAction
+    )
+{
+    if (NdisHandle == NULL)
+        return;
+
+    UNREFERENCED_PARAMETER(HaltAction);
+
+    (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
+    AdapterTeardown((PXENNET_ADAPTER)NdisHandle);
+}
+
+typedef struct _XENNET_CONTEXT {
+    PDEVICE_CAPABILITIES    Capabilities;
+    PIO_COMPLETION_ROUTINE  CompletionRoutine;
+    PVOID                   CompletionContext;
+    UCHAR                   CompletionControl;
+} XENNET_CONTEXT, *PXENNET_CONTEXT;
+
+__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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
+
+    Trace("<====\n");
+
+    return status;    
+}
+
+_Dispatch_type_(IRP_MJ_PNP)
+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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
+        break;
+    }
+
+    return status;
+}
+
+_Dispatch_type_(IRP_MJ_CREATE)
+_Dispatch_type_(IRP_MJ_CLOSE)
+_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
+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
+    )
+{
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        goto done;
+
+    ASSERT3P(Driver.DriverObject, ==, DriverObject);
+    Driver.DriverObject = NULL;
+
+    if (Driver.MiniportHandle)
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+    Driver.NdisDispatchPnp = NULL;
+
+    RegistryTeardown();
+
+    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;
+    NTSTATUS                                status;
+
+    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        return NDIS_STATUS_SUCCESS;
+
+    ASSERT3P(Driver.DriverObject, ==, NULL);
+    Driver.DriverObject = DriverObject;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    status = RegistryInitialize(RegistryPath);
+
+    ndisStatus = (NT_SUCCESS(status)) ?
+                 NDIS_STATUS_SUCCESS :
+                 NDIS_STATUS_FAILURE;
+
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
+
+    //
+    // Register miniport with NDIS.
+    //
+
+    RtlZeroMemory(&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     = DriverCancelOidRequest;
+    mpChars.CancelSendHandler           = DriverCancelSendNetBufferLists;
+    mpChars.CheckForHangHandlerEx       = DriverCheckForHang;
+    mpChars.InitializeHandlerEx         = DriverInitialize;
+    mpChars.HaltHandlerEx               = DriverHalt;
+    mpChars.OidRequestHandler           = DriverOidRequest;    
+    mpChars.PauseHandler                = DriverPause;      
+    mpChars.DevicePnPEventNotifyHandler = DriverPnPEventHandler;
+    mpChars.ResetHandlerEx              = DriverReset;
+    mpChars.RestartHandler              = DriverRestart;    
+    mpChars.ReturnNetBufferListsHandler = DriverReturnNetBufferLists;
+    mpChars.SendNetBufferListsHandler   = DriverSendNetBufferLists;
+    mpChars.ShutdownHandlerEx           = DriverShutdown;
+    mpChars.UnloadHandler               = DriverUnload;
+
+    Driver.MiniportHandle = NULL;
+    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
+                                             RegistryPath,
+                                             NULL,
+                                             &mpChars,
+                                             &Driver.MiniportHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail2;
+
+    RtlZeroMemory(&ConfigurationObject, sizeof(ConfigurationObject));
+    ConfigurationObject.Header.Type     = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    ConfigurationObject.Header.Size     = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.NdisHandle      = Driver.MiniportHandle;
+    ConfigurationObject.Flags           = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail3;
+
+    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);
+
+    Driver.NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
+    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+    if (FailCreateClose != 0) {
+        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
+    }
+
+    if (FailDeviceControl != 0) {
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
+    }
+
+    Trace("<====\n");
+    return NDIS_STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+fail2:
+    Error("fail2\n");
+
+    RegistryTeardown();
+
+fail1:
+    Error("fail1\n");
+
+    Driver.DriverObject = NULL;
+    return ndisStatus;
+}
+
diff --git a/src/xennet/main.c b/src/xennet/main.c
deleted file mode 100644
index 6622e82..0000000
--- a/src/xennet/main.c
+++ /dev/null
@@ -1,361 +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"
-#include "registry.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;
-    NTSTATUS status;
-
-    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);
-
-    status = RegistryInitialize(RegistryPath);
-
-    ndisStatus = (NT_SUCCESS(status)) ?
-                 NDIS_STATUS_SUCCESS :
-                 NDIS_STATUS_FAILURE;
-
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail;
-
-    //
-    // 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);
-
-    RegistryTeardown();
-
-    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/miniport.c b/src/xennet/miniport.c
deleted file mode 100644
index a1d605f..0000000
--- a/src/xennet/miniport.c
+++ /dev/null
@@ -1,297 +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.
- */
-
-#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,
-    IN  ULONG           Size,
-    IN  BOOLEAN         Optional
-    )
-{
-    UNICODE_STRING      Unicode;
-    HANDLE              InterfacesKey;
-    HANDLE              SubscriberKey;
-    KEVENT              Event;
-    IO_STATUS_BLOCK     StatusBlock;
-    PIRP                Irp;
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
-
-    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));
-
-    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
-                                       DeviceObject,
-                                       NULL,
-                                       0,
-                                       NULL,
-                                       &Event,
-                                       &StatusBlock);
-
-    status = STATUS_UNSUCCESSFUL;
-    if (Irp == NULL)
-        goto fail4;
-
-    StackLocation = IoGetNextIrpStackLocation(Irp);
-    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
-
-    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;
-    }
-
-    if (!NT_SUCCESS(status)) {
-        if (status == STATUS_NOT_SUPPORTED && Optional)
-            goto done;
-
-        goto fail5;
-    }
-
-    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);
-
-    return status;
-}
-
-#define QUERY_INTERFACE(                                                                \
-    _DeviceObject,                                                                      \
-    _ProviderName,                                                                      \
-    _InterfaceName,                                                                     \
-    _Version,                                                                           \
-    _Interface,                                                                         \
-    _Size,                                                                              \
-    _Optional)                                                                          \
-    __QueryInterface((_DeviceObject),                                                   \
-                     L ## #_ProviderName,                                               \
-                     #_InterfaceName,                                                   \
-                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
-                     (_Version),                                                        \
-                     (_Interface),                                                      \
-                     (_Size),                                                           \
-                     (_Optional))
-
-NDIS_STATUS 
-MiniportInitialize (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HANDLE                        MiniportDriverContext,
-    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
-    )
-{
-    PADAPTER Adapter = NULL;
-    NDIS_STATUS ndisStatus;
-    PDEVICE_OBJECT DeviceObject;
-    NTSTATUS status;
-
-    UNREFERENCED_PARAMETER(MiniportDriverContext);
-    UNREFERENCED_PARAMETER(MiniportInitParameters);
-
-    Trace("====>\n");
-
-    status = AllocAdapter(&Adapter);
-
-    if (!NT_SUCCESS(status) || Adapter == NULL) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto fail1;
-    }
-
-    RtlZeroMemory(Adapter, sizeof (ADAPTER));
-
-    DeviceObject = NULL;
-    NdisMGetDeviceProperty(MiniportAdapterHandle,
-                           &DeviceObject,
-                           NULL,
-                           NULL,
-                           NULL,
-                           NULL);
-
-    status = QUERY_INTERFACE(DeviceObject,
-                             XENVIF,
-                             VIF,
-                             XENVIF_VIF_INTERFACE_VERSION_MAX,
-                             (PINTERFACE)&Adapter->VifInterface,
-                             sizeof (Adapter->VifInterface),
-                             FALSE);
-
-    if (!NT_SUCCESS(status)) {
-        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
-        goto fail2;
-    }
-
-    ndisStatus = AdapterInitialize(Adapter, MiniportAdapterHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto fail3;
-    }
-
-    Trace("<====\n");
-    return ndisStatus;
-
-fail3:
-    Error("fail3\n");
-
-    RtlZeroMemory(&Adapter->VifInterface,
-                  sizeof (XENVIF_VIF_INTERFACE));
-
-fail2:
-    Error("fail2\n");
-
-    ExFreePool(Adapter);
-
-fail1:
-    Error("fail1\n");
-
-    return ndisStatus;
-}
-
-//
-// Stops adapter and frees all resources.
-//
-VOID 
-MiniportHalt (
-    IN  NDIS_HANDLE             MiniportAdapterHandle,
-    IN  NDIS_HALT_ACTION        HaltAction
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterHandle;
-
-    UNREFERENCED_PARAMETER(HaltAction);
-
-    if (Adapter == NULL)
-        return;
-
-    (VOID) AdapterStop(Adapter);
-
-    AdapterCleanup(Adapter);
-
-    RtlZeroMemory(&Adapter->VifInterface,
-                  sizeof (XENVIF_VIF_INTERFACE));
-
-    ExFreePool(Adapter);
-}
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..ee01a18 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -29,103 +29,38 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
-
-#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;
-}
+#include <ndis.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       'teNX'
+#define IN_NDIS_MAX 1024
 
-PNET_BUFFER_LIST
+static PNET_BUFFER_LIST
 ReceiverAllocateNetBufferList(
-    IN  PRECEIVER       Receiver,
-    IN  PMDL            Mdl,
-    IN  ULONG           Offset,
-    IN  ULONG           Length
+    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();
-
     NetBufferList = Receiver->GetList[Cpu];
 
     if (NetBufferList == NULL)
@@ -158,16 +93,16 @@ ReceiverAllocateNetBufferList(
     return NetBufferList;
 }        
 
-VOID
+static VOID
 ReceiverReleaseNetBufferList(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  BOOLEAN             Cache
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  BOOLEAN                 Cache
     )
 {
     if (Cache) {
-        PNET_BUFFER_LIST    Old;
-        PNET_BUFFER_LIST    New;
+        PNET_BUFFER_LIST        Old;
+        PNET_BUFFER_LIST        New;
 
         ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
@@ -182,72 +117,9 @@ ReceiverReleaseNetBufferList(
     }
 }
 
-static FORCEINLINE ULONG
-__ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  BOOLEAN             Cache
-    )
-{
-    PADAPTER                Adapter;
-    LIST_ENTRY              List;
-    ULONG                   Count;
-
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    InitializeListHead(&List);
-
-    Count = 0;
-    while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST        Next;
-        PNET_BUFFER             NetBuffer;
-        PMDL                    Mdl;
-        PXENVIF_RECEIVER_PACKET Packet;
-
-        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
-        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
-
-        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
-
-        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
-
-        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
-
-        InsertTailList(&List, &Packet->ListEntry);
-
-        Count++;
-        NetBufferList = Next;
-    }
-
-    if (Count != 0)
-        XENVIF_VIF(ReceiverReturnPackets,
-                   &Adapter->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  PXENNET_RECEIVER                        Receiver,
     IN  PMDL                                    Mdl,
     IN  ULONG                                   Offset,
     IN  ULONG                                   Length,
@@ -255,11 +127,11 @@ ReceiverReceivePacket(
     IN  USHORT                                  TagControlInformation
     )
 {
-    PADAPTER                                    Adapter;
+    PXENNET_ADAPTER                             Adapter;
     PNET_BUFFER_LIST                            NetBufferList;
     NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    Adapter = Receiver->Adapter;
 
     NetBufferList = ReceiverAllocateNetBufferList(Receiver,
                                                   Mdl,
@@ -268,7 +140,7 @@ ReceiverReceivePacket(
     if (NetBufferList == NULL)
         goto fail1;
 
-    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
+    NetBufferList->SourceHandle = AdapterGetHandle(Adapter);
 
     csumInfo.Value = 0;
 
@@ -281,8 +153,8 @@ ReceiverReceivePacket(
     csumInfo.Receive.UdpChecksumSucceeded = Flags.UdpChecksumSucceeded;
     csumInfo.Receive.UdpChecksumFailed = Flags.UdpChecksumFailed;
 
-    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = (PVOID)(ULONG_PTR)csumInfo.Value;
-
+    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = 
+                                            (PVOID)(ULONG_PTR)csumInfo.Value;
     if (TagControlInformation != 0) {
         NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
 
@@ -306,20 +178,67 @@ fail1:
     return NULL;
 }
 
+static FORCEINLINE ULONG
+__ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  BOOLEAN                 Cache
+    )
+{
+    PXENNET_ADAPTER             Adapter;
+    LIST_ENTRY                  List;
+    ULONG                       Count;
+
+    Adapter = Receiver->Adapter;
+
+    InitializeListHead(&List);
+
+    Count = 0;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST        Next;
+        PNET_BUFFER             NetBuffer;
+        PMDL                    Mdl;
+        PXENVIF_RECEIVER_PACKET Packet;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
+
+        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
+
+        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
+
+        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
+
+        InsertTailList(&List, &Packet->ListEntry);
+
+        Count++;
+        NetBufferList = Next;
+    }
+
+    if (Count != 0) {
+        XENVIF_VIF(ReceiverReturnPackets,
+                   AdapterGetVifInterface(Adapter),
+                   &List);
+    }
+    return Count;
+}
+
 static VOID
 ReceiverPushPackets(
-    IN  PRECEIVER           Receiver,
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               Count,
     IN  BOOLEAN             LowResources
     )
 {
-    PADAPTER                Adapter;
+    PXENNET_ADAPTER         Adapter;
     ULONG                   Flags;
     LONG                    InNDIS;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
+    Adapter = Receiver->Adapter;
     InNDIS = Receiver->InNDIS;
 
     Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
@@ -342,7 +261,7 @@ ReceiverPushPackets(
             break;
     }
 
-    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
+    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Adapter),
                                        NetBufferList,
                                        NDIS_DEFAULT_PORT_NUMBER,
                                        Count,
@@ -352,21 +271,34 @@ ReceiverPushPackets(
         (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
 }
 
-#define IN_NDIS_MAX 1024
+VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    ULONG                   Count;
+
+    UNREFERENCED_PARAMETER(ReturnFlags);
+
+    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferLists, 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;
+    PXENNET_ADAPTER     Adapter;
     PNET_BUFFER_LIST    HeadNetBufferList;
     PNET_BUFFER_LIST    *TailNetBufferList;
     ULONG               Count;
     BOOLEAN             LowResources;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    Adapter = Receiver->Adapter;
     LowResources = FALSE;
 
 again:
@@ -404,21 +336,26 @@ 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);
+                       AdapterGetVifInterface(Adapter),
+                       &PacketList);
         }
     }
 
@@ -434,3 +371,95 @@ again:
         goto again;
     }
 }
+
+PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER        Receiver
+    )
+{
+    return &Receiver->OffloadOptions;
+}
+
+NTSTATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_RECEIVER        *Receiver
+    )
+{
+    NTSTATUS                        status;
+    NET_BUFFER_LIST_POOL_PARAMETERS Pool;
+
+    status = STATUS_NO_MEMORY;
+    *Receiver = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_RECEIVER), RECEIVER_POOL_TAG);
+    if (*Receiver == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
+    (*Receiver)->Adapter = Adapter;
+
+    RtlZeroMemory(&Pool, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
+    Pool.Header.Type        = NDIS_OBJECT_TYPE_DEFAULT;
+    Pool.Header.Size        = sizeof(NET_BUFFER_LIST_POOL_PARAMETERS);
+    Pool.Header.Revision    = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    Pool.ProtocolId         = 0;
+    Pool.ContextSize        = 0;
+    Pool.fAllocateNetBuffer = TRUE;
+    Pool.PoolTag            = RECEIVER_POOL_TAG;
+
+    (*Receiver)->NetBufferListPool = NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
+                                                                   &Pool);
+    if ((*Receiver)->NetBufferListPool == NULL)
+        goto fail2;
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    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;
+
+    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
+}
+
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
index 1a58053..715f02e 100644
--- a/src/xennet/receiver.h
+++ b/src/xennet/receiver.h
@@ -29,49 +29,42 @@
  * 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;
+typedef struct _XENNET_RECEIVER     XENNET_RECEIVER, *PXENNET_RECEIVER;
 
-VOID
-ReceiverDebugDump (
-    IN PRECEIVER Receiver
-    );
+#include <vif_interface.h>
 
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER Receiver
+extern VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
     );
 
-VOID
-ReceiverHandleNotification (
-    IN  PRECEIVER Receiver
+extern VOID
+ReceiverReceivePackets(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PLIST_ENTRY             List
     );
 
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER   Receiver
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER        Receiver
     );
 
-VOID 
-ReceiverReturnNetBufferLists (
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  ULONG               ReturnFlags
+#include "adapter.h"
+extern NTSTATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_RECEIVER        *Receiver
     );
 
-VOID
-ReceiverWaitForPacketReturn(
-    IN  PRECEIVER   Receiver,
-    IN  BOOLEAN     Locked
+extern VOID
+ReceiverTeardown(
+    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..be07458 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -29,59 +29,18 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include <ndis.h>
+#include "transmitter.h"
+#include "adapter.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_TRANSMITTER {
+    PXENNET_ADAPTER             Adapter;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
 
-NDIS_STATUS
-TransmitterInitialize(
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
-    )
-{
-    Transmitter->Adapter = Adapter;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-VOID
-TransmitterEnable(
-    IN  PTRANSMITTER    Transmitter
-    )
-{
-    PADAPTER            Adapter = Transmitter->Adapter;
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->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,
-                      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,
-                      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;
-    }
-}
+#define TRANSMITTER_POOL_TAG    'teNX'
 
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
@@ -97,24 +56,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             NdisStatus
     )
 {
+    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
+
     ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_NOT_ACCEPTED;
+    if (NdisStatus == 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;
+    }
+    NET_BUFFER_LIST_STATUS(NetBufferList) = NdisStatus;
 
-    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+    NdisMSendNetBufferListsComplete(AdapterGetHandle(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                 NdisStatus
     )
 {
     while (Packet != NULL) {
@@ -135,21 +107,85 @@ TransmitterAbortPackets(
 
         ASSERT(ListReserved->Reference != 0);
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
+            TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NdisStatus);
 
         Packet = Next;
     }
 }
+    
+static FORCEINLINE VOID
+__OffloadOptions(
+    IN  PNET_BUFFER_LIST            NetBufferList,
+    OUT PXENVIF_VIF_OFFLOAD_OPTIONS Offload,
+    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);
+
+    Offload->Value = 0;
+    *TagControlInformation = 0;
+    *MaximumSegmentSize = 0;
+
+    if (ChecksumInfo->Transmit.IsIPv4) {
+        if (ChecksumInfo->Transmit.IpHeaderChecksum)
+            Offload->OffloadIpVersion4HeaderChecksum = 1;
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            Offload->OffloadIpVersion4TcpChecksum = 1;
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            Offload->OffloadIpVersion4UdpChecksum = 1;
+    }
+
+    if (ChecksumInfo->Transmit.IsIPv6) {
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            Offload->OffloadIpVersion6TcpChecksum = 1;
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            Offload->OffloadIpVersion6UdpChecksum = 1;
+    }
+
+    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
+        Offload->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)
+            Offload->OffloadIpVersion4LargePacket = 1;
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
+            Offload->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;
+    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
     PXENVIF_TRANSMITTER_PACKET  HeadPacket;
     PXENVIF_TRANSMITTER_PACKET  *TailPacket;
     KIRQL                       Irql;
@@ -158,21 +194,21 @@ TransmitterSendNetBufferLists(
 
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
-
+ 
     if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
         ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
         NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
     } else {
         Irql = DISPATCH_LEVEL;
     }
-
+ 
     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;
+        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+        USHORT                          TagControlInformation;
+        USHORT                          MaximumSegmentSize;
+        PNET_BUFFER                     NetBuffer;
 
         ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
         NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
@@ -180,12 +216,7 @@ TransmitterSendNetBufferLists(
         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);
+        __OffloadOptions(NetBufferList, &Options, &TagControlInformation, &MaximumSegmentSize);
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
@@ -199,50 +230,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   = Options.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.TagControlInformation  = TagControlInformation;
+            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
 
             ASSERT3P(Packet->Next, ==, NULL);
             *TailPacket = Packet;
@@ -258,65 +248,89 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            &Adapter->VifInterface,
+                            AdapterGetVifInterface(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
+VOID
+TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
-    PADAPTER                                            Adapter = Transmitter->Adapter;
-    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+    __TransmitterCompletePackets(Transmitter,
+                                 Packet,
+                                 NDIS_STATUS_SUCCESS);
+}
 
-    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter->Adapter);
 
-    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                             TcpLargeSendNetBufferListInfo);
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
-    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
-        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
+}
 
-    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
-                                    NetBufferList,
-                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
+PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    return &Transmitter->OffloadOptions;
 }
 
-VOID
-TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+NTSTATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_TRANSMITTER     *Transmitter
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
+    NTSTATUS            status;
 
-        Next = Packet->Next;
-        Packet->Next = NULL;
+    status = STATUS_NO_MEMORY;
+    *Transmitter = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_TRANSMITTER), TRANSMITTER_POOL_TAG);
+    if (*Transmitter == NULL)
+        goto fail1;
 
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
+    (*Transmitter)->Adapter = Adapter;
 
-        NetBufferList = Reserved->NetBufferList;
-        ASSERT(NetBufferList != NULL);
+    return STATUS_SUCCESS;
 
-        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 
-        ASSERT(ListReserved->Reference != 0);
-        if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
+}
 
-        Packet = Next;
-    }
+VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
+
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index 8dc7e8d..f99ffd3 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -29,47 +29,48 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_TRANSMITTER_H_
+#define _XENNET_TRANSMITTER_H_
 
-typedef struct _TRANSMITTER {
-    PADAPTER                    Adapter;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} TRANSMITTER, *PTRANSMITTER;
+typedef struct _XENNET_TRANSMITTER  XENNET_TRANSMITTER, *PXENNET_TRANSMITTER;
 
-VOID 
-TransmitterCleanup (
-    IN OUT PTRANSMITTER* Transmitter
+#include <vif_interface.h>
+
+extern VOID
+TransmitterSendNetBufferLists(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
     );
 
-NDIS_STATUS
-TransmitterInitialize (
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+extern VOID
+TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     );
 
-VOID
-TransmitterEnable (
-    IN  PTRANSMITTER    Transmitter
+extern VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER* Transmitter
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-VOID
-TransmitterSendNetBufferLists (
-    IN  PTRANSMITTER        Transmitter,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+#include "adapter.h"
+extern NTSTATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_TRANSMITTER     *Transmitter
     );
 
-VOID
-TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+extern VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-void TransmitterPause(PTRANSMITTER Transmitter);
-void TransmitterUnpause(PTRANSMITTER Transmitter);
+#endif // _XENNET_TRANSMITTER_H_
+
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index db07e9b..4b6e780 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -84,9 +84,8 @@
 	</ItemGroup>
 	<ItemGroup>
 		<ClCompile Include="../../src/xennet/registry.c" />
+		<ClCompile Include="../../src/xennet/driver.c" />
 		<ClCompile Include="../../src/xennet/adapter.c" />
-		<ClCompile Include="../../src/xennet/main.c" />
-		<ClCompile Include="../../src/xennet/miniport.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 908bc2d..d890878 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -115,9 +115,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="../../src/xennet/registry.c" />
+    <ClCompile Include="../../src/xennet/driver.c" />
     <ClCompile Include="../../src/xennet/adapter.c" />
-    <ClCompile Include="../../src/xennet/main.c" />
-    <ClCompile Include="../../src/xennet/miniport.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 Wed Nov 12 16:39:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawp-0003TU-DS; Wed, 12 Nov 2014 16:39:11 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1Xoawm-0003T0-QY
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:09 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	A1/E3-25547-C2D83645; Wed, 12 Nov 2014 16:39:08 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1415810339!10918639!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17598 invoked from network); 12 Nov 2014 16:39:05 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:05 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032059"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:47 +0000
Message-ID: <1415810330-1152-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 1/4] Refactor for maintainability/coding style
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

Removes common headers and the disabling of warnings via #pragmas
Fits code into driver.c (DriverEntry/Dispatch overrides), adapter.c
(NDIS miniport). Resolves differences in receiver/transmitter
implementations.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xennet/adapter.c         | 3833 +++++++++++++++++++-----------------------
 src/xennet/adapter.h         |  154 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  550 ++++++
 src/xennet/main.c            |  361 ----
 src/xennet/miniport.c        |  297 ----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  393 +++--
 src/xennet/receiver.h        |   59 +-
 src/xennet/std.h             |   45 -
 src/xennet/transmitter.c     |  330 ++--
 src/xennet/transmitter.h     |   61 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 14 files changed, 2770 insertions(+), 3421 deletions(-)
 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/miniport.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..6b32d1a 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -28,51 +28,44 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  * SUCH DAMAGE.
  */
+#define INITGUID
 
+#include <ndis.h>
+#include <ntstrsafe.h>
 #include <version.h>
-#include "common.h"
 
-#pragma warning(disable:4711)
+#include "adapter.h"
+#include "registry.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-//
-// List of supported OIDs.
-//
+struct _XENNET_ADAPTER {
+    XENVIF_VIF_INTERFACE        VifInterface;
 
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
-    );
+    BOOLEAN                     Enabled;
+    ULONG                       MaximumFrameSize;
+    ULONG                       CurrentLookahead;
 
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    );
+    NDIS_HANDLE                 NdisHandle;
+    NDIS_HANDLE                 NdisDmaHandle;
+    NDIS_PNP_CAPABILITIES       Capabilities;
+    NDIS_OFFLOAD                Offload;
+    XENNET_PROPERTIES           Properties;
 
-static NDIS_STATUS
-AdapterSetOffloadAttributes (
-    IN  PADAPTER Adapter
-    );
+    PXENNET_RECEIVER            Receiver;
+    PXENNET_TRANSMITTER         Transmitter;
+};
 
-static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
-static VOID
-AdapterProcessSGList (
-    IN PDEVICE_OBJECT       DeviceObject,
-    IN PVOID                Reserved,
-    IN PSCATTER_GATHER_LIST SGL,
-    IN PVOID                Context
-    );
+#define XENNET_POOL_TAG         'tenX'
 
-static NDIS_STATUS
-AdapterSetInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+#define XENNET_MEDIA_MAX_SPEED  1000000000ull
 
-static NDIS_STATUS
-AdapterQueryInformation (
-    IN  PADAPTER            Adapter,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    );
+#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)
 
 static NDIS_OID XennetSupportedOids[] =
 {
@@ -129,31 +122,9 @@ 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)
-
-NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
-{
-    if (Adapter == NULL)
-        return STATUS_INVALID_PARAMETER;
-
-    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof (ADAPTER), ' TEN');
-    if (*Adapter == NULL)
-        return STATUS_INSUFFICIENT_RESOURCES;
-
-    return STATUS_SUCCESS;
-}
-
-//
-// Scatter gather allocate handler callback.
-// Should never get called.
-//
 __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
 static VOID
-AdapterAllocateComplete (
+AdapterAllocateComplete(
     IN NDIS_HANDLE              MiniportAdapterContext,
     IN PVOID                    VirtualAddress,
     IN PNDIS_PHYSICAL_ADDRESS   PhysicalAddress,
@@ -168,139 +139,33 @@ 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;
 }
 
+__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
 static VOID
-AdapterMediaStateChange(
-    IN  PADAPTER                Adapter
+AdapterProcessSGList(
+    IN PDEVICE_OBJECT           DeviceObject,
+    IN PVOID                    Reserved,
+    IN PSCATTER_GATHER_LIST     SGL,
+    IN PVOID                    Context
     )
 {
-    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);
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Reserved);
+    UNREFERENCED_PARAMETER(SGL);
+    UNREFERENCED_PARAMETER(Context);
 
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
+    ASSERT(FALSE);
 }
 
-
-//
-// 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;
+    PXENNET_ADAPTER                 Adapter = Context;
     va_list                         Arguments;
 
     va_start(Arguments, Type);
@@ -319,7 +184,7 @@ AdapterVifCallback(
 
         List = va_arg(Arguments, PLIST_ENTRY);
 
-        ReceiverReceivePackets(&Adapter->Receiver, List);
+        ReceiverReceivePackets(Adapter->Receiver, List);
         break;
     }
     case XENVIF_MAC_STATE_CHANGE: {
@@ -331,39 +196,220 @@ AdapterVifCallback(
     va_end(Arguments);
 }
 
-NDIS_STATUS
-AdapterGetAdvancedSettings(
-    IN PADAPTER pAdapter
+#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,
+    IN  ULONG           Size,
+    IN  BOOLEAN         Optional
     )
 {
-    NDIS_CONFIGURATION_OBJECT configObject;
-    NDIS_HANDLE hConfigurationHandle;
-    NDIS_STRING ndisValue;
-    PNDIS_CONFIGURATION_PARAMETER pNdisData;
-    NDIS_STATUS ndisStatus;
-    NTSTATUS status;
+    UNICODE_STRING      Unicode;
+    HANDLE              InterfacesKey;
+    HANDLE              SubscriberKey;
+    KEVENT              Event;
+    IO_STATUS_BLOCK     StatusBlock;
+    PIRP                Irp;
+    PIO_STACK_LOCATION  StackLocation;
+    NTSTATUS            status;
+
+    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));
 
-    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;
+    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
 
-    ndisStatus = NdisOpenConfigurationEx(&configObject, &hConfigurationHandle);
+    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));
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
 
     status = STATUS_UNSUCCESSFUL;
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
+    if (Irp == NULL)
+        goto fail4;
+
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
+
+    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;
+    }
+
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_NOT_SUPPORTED && Optional)
+            goto done;
+
+        goto fail5;
+    }
+
+    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);
+
+    return status;
+}
+
+#define QUERY_INTERFACE(                                                                \
+    _DeviceObject,                                                                      \
+    _ProviderName,                                                                      \
+    _InterfaceName,                                                                     \
+    _Version,                                                                           \
+    _Interface,                                                                         \
+    _Size,                                                                              \
+    _Optional)                                                                          \
+    __QueryInterface((_DeviceObject),                                                   \
+                     L ## #_ProviderName,                                               \
+                     #_InterfaceName,                                                   \
+                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
+                     (_Version),                                                        \
+                     (_Interface),                                                      \
+                     (_Size),                                                           \
+                     (_Optional))
+
+static FORCEINLINE NDIS_STATUS
+AdapterSetRegistrationAttributes(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs;
+    NDIS_STATUS                                   status;
+
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    Attribs.Header.Type                 = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    Attribs.Header.Size                 = sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    Attribs.Header.Revision             = NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    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;
+
+    status = NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
+    return status;
+}
+
+static FORCEINLINE NDIS_STATUS
+AdapterGetAdvancedSettings(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_CONFIGURATION_OBJECT   Config;
+    NDIS_HANDLE                 Handle;
+    NDIS_STRING                 Value;
+    PNDIS_CONFIGURATION_PARAMETER Data;
+    NDIS_STATUS                 NdisStatus;
+
+    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
+    Config.Header.Type      = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    Config.Header.Size      = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    Config.Header.Revision  = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    Config.NdisHandle       = Adapter->NdisHandle;
+    Config.Flags            = 0;
+
+    NdisStatus = NdisOpenConfigurationEx(&Config, &Handle);
+    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; \
-        } \
+#define read_property(_field, _name, _default_val)                                          \
+    do {                                                                                    \
+        RtlInitUnicodeString(&Value, _name);                                                \
+        NdisReadConfiguration(&NdisStatus, &Data, Handle, &Value, NdisParameterInteger);    \
+        if (NdisStatus == NDIS_STATUS_SUCCESS) {                                            \
+            Adapter->Properties._field = Data->ParameterData.IntegerData;                   \
+        } else {                                                                            \
+            Adapter->Properties._field = _default_val;                                      \
+        }                                                                                   \
     } while (FALSE);
 
     read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
@@ -377,465 +423,827 @@ AdapterGetAdvancedSettings(
     read_property(lrov6, L"LROIPv6", 1);
     read_property(need_csum_value, L"NeedChecksumValue", 1);
 
-    NdisCloseConfiguration(hConfigurationHandle);
-
+    NdisCloseConfiguration(Handle);
     return NDIS_STATUS_SUCCESS;
 
 fail1:
-    Error("fail1\n");
-    return NDIS_STATUS_FAILURE;
+    Error("fail1 (%08x)\n", NdisStatus);
+    return NdisStatus;
 }
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+static FORCEINLINE NDIS_STATUS
+AdapterSetGeneralAttributes(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    NDIS_STATUS ndisStatus;
-    NDIS_SG_DMA_DESCRIPTION DmaDescription;
-    NTSTATUS status;
-
-    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
-    if (!NT_SUCCESS(status))
-        return NDIS_STATUS_FAILURE;
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
 
-    Adapter->AcquiredInterfaces = TRUE;
+    XENVIF_VIF(MacQueryMaximumFrameSize,
+               &Adapter->VifInterface,
+               (PULONG)&Adapter->MaximumFrameSize);
 
-    Trace("====>\n");
+    RtlZeroMemory(&Attribs, sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
+
+    Attribs.Header.Type         = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+    Attribs.Header.Size         = sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+    Attribs.Header.Revision     = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+    Attribs.MediaType               = XENNET_MEDIA_TYPE;
+    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;
+    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;
+    Attribs.SupportedOidList        = XennetSupportedOids;
+    Attribs.SupportedOidListLength  = sizeof(XennetSupportedOids);
 
-    Adapter->NdisAdapterHandle = AdapterHandle;
+    XENVIF_VIF(MacQueryPermanentAddress,
+               &Adapter->VifInterface,
+               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
+    XENVIF_VIF(MacQueryCurrentAddress,
+               &Adapter->VifInterface,
+               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
 
-    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
+    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
+}
 
-    Adapter->Transmitter = (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSMITTER), ' TEN');
-    if (!Adapter->Transmitter) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto exit;
+static FORCEINLINE NDIS_STATUS
+AdapterSetOffloadAttributes(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
+    NDIS_OFFLOAD                                Default;
+    NDIS_OFFLOAD                                Supported;
+
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
+    RxOptions->Value = 0;
+    RxOptions->OffloadTagManipulation = 1;
+
+    if (Adapter->Properties.need_csum_value) {
+        RxOptions->NeedChecksumValue = 1;
     }
-
-    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
-
-    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (Adapter->Properties.lrov4) {
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
-
-    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (Adapter->Properties.lrov6) {
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
     }
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-    ndisStatus = AdapterGetAdvancedSettings(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+               &Adapter->VifInterface,
+               TxOptions);
+
+    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
+    Supported.Header.Type       = NDIS_OBJECT_TYPE_OFFLOAD;
+    Supported.Header.Size       = sizeof(NDIS_OFFLOAD);
+    Supported.Header.Revision   = NDIS_OFFLOAD_REVISION_1;
+
+    Supported.Checksum.IPv4Receive.Encapsulation        = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv4Receive.IpChecksum           = 1;
+    Supported.Checksum.IPv4Receive.IpOptionsSupported   = 1;
+    Supported.Checksum.IPv4Receive.TcpChecksum          = 1;
+    Supported.Checksum.IPv4Receive.TcpOptionsSupported  = 1;
+    Supported.Checksum.IPv4Receive.UdpChecksum          = 1;
+
+    Supported.Checksum.IPv6Receive.Encapsulation        = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    Supported.Checksum.IPv6Receive.TcpChecksum          = 1;
+    Supported.Checksum.IPv6Receive.TcpOptionsSupported  = 1;
+    Supported.Checksum.IPv6Receive.UdpChecksum          = 1;
+
+    Supported.Checksum.IPv4Transmit.Encapsulation       = NDIS_ENCAPSULATION_IEEE_802_3;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Supported.Checksum.IPv4Transmit.IpChecksum          = 1;
+        Supported.Checksum.IPv4Transmit.IpOptionsSupported  = 1;
     }
-
-    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Supported.Checksum.IPv4Transmit.TcpChecksum         = 1;
+        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Supported.Checksum.IPv4Transmit.UdpChecksum         = 1;
     }
 
-    ndisStatus = AdapterSetGeneralAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    Supported.Checksum.IPv6Transmit.Encapsulation       = NDIS_ENCAPSULATION_IEEE_802_3;
+    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Supported.Checksum.IPv6Transmit.TcpChecksum         = 1;
+        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Supported.Checksum.IPv6Transmit.UdpChecksum         = 1;
     }
 
-    ndisStatus = AdapterSetOffloadAttributes(Adapter);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto exit;
+    if (TxOptions->OffloadIpVersion4LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   4,
+                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
+        Supported.LsoV2.IPv4.Encapsulation              = NDIS_ENCAPSULATION_IEEE_802_3;
+        Supported.LsoV2.IPv4.MinSegmentCount            = 2;
     }
 
-    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
+    if (TxOptions->OffloadIpVersion6LargePacket) {
+        XENVIF_VIF(TransmitterQueryLargePacketSize,
+                   &Adapter->VifInterface,
+                   6,
+                   &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;
+    }
 
-    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;
+    Default = Supported;
 
-    ndisStatus = NdisMRegisterScatterGatherDma(Adapter->NdisAdapterHandle,
-                                               &DmaDescription,
-                                               &Adapter->NdisDmaHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        Adapter->NdisDmaHandle = NULL;
+    if (!(Adapter->Properties.ipv4_csum & 2))
+        Default.Checksum.IPv4Receive.IpChecksum = 0;
+    if (!(Adapter->Properties.tcpv4_csum & 2))
+        Default.Checksum.IPv4Receive.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv4_csum & 2))
+        Default.Checksum.IPv4Receive.UdpChecksum = 0;
+    if (!(Adapter->Properties.tcpv6_csum & 2))
+        Default.Checksum.IPv6Receive.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv6_csum & 2))
+        Default.Checksum.IPv6Receive.UdpChecksum = 0;
+    if (!(Adapter->Properties.ipv4_csum & 1))
+        Default.Checksum.IPv4Transmit.IpChecksum = 0;
+    if (!(Adapter->Properties.tcpv4_csum & 1))
+        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv4_csum & 1))
+        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
+    if (!(Adapter->Properties.tcpv6_csum & 1))
+        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
+    if (!(Adapter->Properties.udpv6_csum & 1))
+        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
+    if (!(Adapter->Properties.lsov4)) {
+        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv4.MinSegmentCount = 0;
+    }
+    if (!(Adapter->Properties.lsov6)) {
+        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
+        Default.LsoV2.IPv6.MinSegmentCount = 0;
+    }
 
-    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, &Default, sizeof(NDIS_OFFLOAD))) {
+        Adapter->Offload = Default;
+        //DISPLAY_OFFLOAD(Default);
     }
 
-exit:
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        XENVIF_VIF(Release, &Adapter->VifInterface);
+    RtlZeroMemory(&Attribs, sizeof(Attribs));
+    Attribs.Header.Type         = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
+    Attribs.Header.Size         = sizeof(Attribs);
+    Attribs.Header.Revision     = NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
+    Attribs.DefaultOffloadConfiguration = &Default;
+    Attribs.HardwareOffloadCapabilities = &Supported;
 
-    Trace("<==== (%08x)\n", ndisStatus);
-    return ndisStatus;
+    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
+                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
 }
 
-//
-// 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
+AdapterIndicateOffloadChanged(
+    IN  PXENNET_ADAPTER         Adapter
     )
 {
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Reserved);
-    UNREFERENCED_PARAMETER(SGL);
-    UNREFERENCED_PARAMETER(Context);
-
-    ASSERT(FALSE);
-
-    return;
-}
+    NDIS_STATUS_INDICATION      Indication;
+    NDIS_OFFLOAD                Offload;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
 
-//
-// Get\Set OID handler.
-//
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
-    )
-{
-    NDIS_STATUS ndisStatus;
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    switch (NdisRequest->RequestType) {
-        case NdisRequestSetInformation:            
-            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
-            break;
-                
-        case NdisRequestQueryInformation:
-        case NdisRequestQueryStatistics:
-            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
-            break;
+    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
+    Offload.Header.Type         = NDIS_OBJECT_TYPE_OFFLOAD;
+    Offload.Header.Size         = sizeof(NDIS_OFFLOAD);
+    Offload.Header.Revision     = NDIS_OFFLOAD_REVISION_1;
+    
+    Offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    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;
+    }
 
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+    Offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+    if (RxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
+        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    }
+    if (RxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
+    }
 
-    return ndisStatus;
-}
+    XENVIF_VIF(ReceiverSetOffloadOptions,
+               &Adapter->VifInterface,
+               *RxOptions);
 
-//
-// Temporarily pauses adapter.
-//
-NDIS_STATUS
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
-    )
-{
-    PADAPTER Adapter = (PADAPTER)NdisHandle;
-    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
 
-    Trace("====>\n");
+    Offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
+        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4TcpChecksum) {
+        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion4UdpChecksum) {
+        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
+    }
 
-    if (!Adapter->Enabled)
-        goto done;
+    Offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+    if (TxOptions->OffloadIpVersion6TcpChecksum) {
+        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
+        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+    if (TxOptions->OffloadIpVersion6UdpChecksum) {
+        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
+    }
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    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;
+    }
+    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;
+    }
 
-    AdapterMediaStateChange(Adapter);
+    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = Offload;
+        //DISPLAY_OFFLOAD(Offload);
+    }
 
-    Adapter->Enabled = FALSE;
+    RtlZeroMemory(&Indication, sizeof(Indication));
+    Indication.Header.Type      = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    Indication.Header.Size      = sizeof(Indication);
+    Indication.Header.Revision  = NDIS_STATUS_INDICATION_REVISION_1;
+    Indication.SourceHandle     = Adapter->NdisHandle;
+    Indication.StatusCode       = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    Indication.StatusBuffer     = &Offload;
+    Indication.StatusBufferSize = sizeof(Offload);
 
-done:
-    Trace("<====\n");
-    return NDIS_STATUS_SUCCESS;
+    NdisMIndicateStatusEx(Adapter->NdisHandle, &Indication);
 }
 
-//
-// Handles PNP and Power events. NOP.
-//
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+static NDIS_STATUS
+AdapterSetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PULONG                  PacketFilter
     )
 {
-    UNREFERENCED_PARAMETER(NdisHandle);
+    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;
 
-    switch (NetDevicePnPEvent->DevicePnPEvent) {
-        case NdisDevicePnPEventQueryRemoved:
-            break;
+    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+        goto done;
+    }
 
-        case NdisDevicePnPEventRemoved:
-            break;       
+    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
+        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
+    else
+        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-        case NdisDevicePnPEventSurpriseRemoved:
-            break;
+    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;
 
-        case NdisDevicePnPEventQueryStopped:
-            break;
+    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
+    else
+        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
 
-        case NdisDevicePnPEventStopped:
-            break;      
-            
-        case NdisDevicePnPEventPowerProfileChanged:
-            break;      
-            
-        default:
-            break;         
-    };
+done:
+    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;
+    return NDIS_STATUS_SUCCESS;
 }
 
-//
-// Reports general statistics to NDIS.
-//
-static NDIS_STATUS 
-AdapterQueryGeneralStatistics (
-    IN  PADAPTER                Adapter,
-    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
+static NDIS_STATUS
+AdapterSetMulticastAddresses(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PETHERNET_ADDRESS       Address,
+    IN  ULONG                   Count
     )
 {
-    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
-    ULONGLONG   Value;
-
-    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);
+    NTSTATUS status;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    status = XENVIF_VIF(MacSetMulticastAddresses,
+                        &Adapter->VifInterface,
+                        Address,
+                        Count);
+    if (!NT_SUCCESS(status))
+        return NDIS_STATUS_INVALID_DATA;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BACKEND_ERRORS,
-                      &Value);
+    return NDIS_STATUS_SUCCESS;
+}
 
-    NdisStatisticsInfo->ifInErrors = Value;
+static NDIS_STATUS
+AdapterSetOffloadEncapsulation(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OFFLOAD_ENCAPSULATION Encapsulation
+    )
+{
+    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_FRONTEND_ERRORS,
-                      &Value);
+    if (Encapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Encapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto fail1;
+    if (Encapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
+        Encapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+        goto fail2;
 
-    NdisStatisticsInfo->ifInErrors += Value;
+    XENVIF_VIF(TransmitterQueryOffloadOptions,
+                &Adapter->VifInterface,
+                &Options);
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
+    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;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_PACKETS_DROPPED,
-                      &Value);
+    if (Adapter->Properties.need_csum_value)
+        RxOptions->NeedChecksumValue = 1;
+    if (Adapter->Properties.lrov4) {
+        RxOptions->OffloadIpVersion4LargePacket = 1;
+        RxOptions->NeedLargePacketSplit = 1;
+    }
+    if (Adapter->Properties.lrov6) {
+        RxOptions->OffloadIpVersion6LargePacket = 1;
+        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;
 
-    NdisStatisticsInfo->ifInDiscards = Value;
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
+static NDIS_STATUS
+AdapterSetTcpOffloadParameters(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OFFLOAD_PARAMETERS    Parameters
+    )
+{
+    BOOLEAN     Changed = FALSE;
+    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
+    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
+
+    if (Parameters->IPsecV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->LsoV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->TcpConnectionIPv4 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
+        Parameters->TcpConnectionIPv6 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        goto fail1;
+    }
+    if (Parameters->LsoV2IPv4 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_OCTETS,
-                      &Value);
+        XENVIF_VIF(TransmitterQueryOffloadOptions,
+                    &Adapter->VifInterface,
+                    &Options);
 
-    NdisStatisticsInfo->ifHCInOctets = Value;
+        if (!(Options.OffloadIpVersion4LargePacket))
+            goto fail2;
+    }
+    if (Parameters->LsoV2IPv6 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
+        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_OCTETS,
-                      &Value);
+        XENVIF_VIF(TransmitterQueryOffloadOptions,
+                    &Adapter->VifInterface,
+                    &Options);
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
+        if (!(Options.OffloadIpVersion6LargePacket))
+            goto fail3;
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_OCTETS,
-                      &Value);
+    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
+    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
 
-    NdisStatisticsInfo->ifHCInOctets += Value;
+#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 set_value(x, y)     ((x) == (y)) ? FALSE : ( ((x) = (y)) == (y) )
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
+    if (Parameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 1);
+    } else if (Parameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_OCTETS,
-                      &Value);
+    if (Parameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 1);
+    } else if (Parameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInUcastOctets = Value;
+    if (tx_enabled(Parameters->IPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4HeaderChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4HeaderChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
+    if (tx_enabled(Parameters->TCPIPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_UNICAST_PACKETS,
-                      &Value);
+    if (tx_enabled(Parameters->UDPIPv4Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInUcastPkts = Value;
+    if (tx_enabled(Parameters->TCPIPv6Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
+    if (tx_enabled(Parameters->UDPIPv6Checksum)) {
+        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum, 1);
+    } else {
+        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_OCTETS,
-                      &Value);
+    if (rx_enabled(Parameters->IPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4HeaderChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4HeaderChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
+    if (rx_enabled(Parameters->TCPIPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
+    if (rx_enabled(Parameters->UDPIPv4Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum, 0);
+    }
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_MULTICAST_PACKETS,
-                      &Value);
+    if (rx_enabled(Parameters->TCPIPv6Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
+    if (rx_enabled(Parameters->UDPIPv6Checksum)) {
+        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum, 1);
+    } else {
+        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum, 0);
+    }
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
+#undef tx_enabled
+#undef rx_enabled
+#undef set_value
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_OCTETS,
-                      &Value);
+    if (Changed)
+        AdapterIndicateOffloadChanged(Adapter);
 
-    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
+    return NDIS_STATUS_SUCCESS;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
+    return NDIS_STATUS_INVALID_PARAMETER;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_RECEIVER_BROADCAST_PACKETS,
-                      &Value);
+static NDIS_STATUS
+AdapterSetInformation(
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PNDIS_OID_REQUEST       Request
+    )
+{
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    ULONG           BytesNeeded = 0;
+    ULONG           BytesRead   = 0;
+    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
 
-    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
+    Buffer          = Request->DATA.SET_INFORMATION.InformationBuffer;
+    BufferLength    = Request->DATA.SET_INFORMATION.InformationBufferLength;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+        case OID_PNP_SET_POWER:
+            BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                      &Value);
+        case OID_GEN_CURRENT_LOOKAHEAD:
+            BytesNeeded = sizeof(ULONG);
+            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
+            if (BufferLength == sizeof(ULONG)) {
+                Adapter->CurrentLookahead = *(PULONG)Buffer;
+                BytesRead = sizeof(ULONG);
+            }
+            break;
 
-    NdisStatisticsInfo->ifOutErrors = Value;
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            BytesNeeded = sizeof(ULONG);
+            if (BufferLength == sizeof(ULONG)) {
+                NdisStatus = AdapterSetPacketFilter(Adapter, (PULONG)Buffer);
+                BytesRead = sizeof(ULONG);
+            }
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                      &Value);
+        case OID_802_3_MULTICAST_LIST:
+            BytesNeeded = ETHERNET_ADDRESS_LENGTH;
+            if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
+                ULONG   Count = BufferLength / ETHERNET_ADDRESS_LENGTH;
+                NdisStatus = AdapterSetMulticastAddresses(Adapter, Buffer, Count);
+                BytesRead = BufferLength;
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    NdisStatisticsInfo->ifOutErrors += Value;
+        case OID_OFFLOAD_ENCAPSULATION:
+            BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+            if (BufferLength == sizeof(NDIS_OFFLOAD_ENCAPSULATION)) {
+                NdisStatus = AdapterSetOffloadEncapsulation(Adapter, Buffer);
+                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
+        case OID_TCP_OFFLOAD_PARAMETERS:
+            BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
+            if (BufferLength == sizeof(NDIS_OFFLOAD_PARAMETERS)) {
+                NdisStatus = AdapterSetTcpOffloadParameters(Adapter, Buffer);
+                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
+            } else {
+                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                      &Value);
+        case OID_GEN_INTERRUPT_MODERATION:
+            NdisStatus = NDIS_STATUS_INVALID_DATA;
+            break;
 
-    NdisStatisticsInfo->ifHCOutOctets = Value;
+        case OID_GEN_MACHINE_NAME:
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                      &Value);
+    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
+    if (NdisStatus == NDIS_STATUS_SUCCESS) {
+        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
+    }
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
+    return NdisStatus;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                      &Value);
+static FORCEINLINE ULONG64
+AdapterGetXmitOk(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                &Value);
+    Result = Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    return Result;
+}
 
-    NdisStatisticsInfo->ifHCOutOctets += Value;
+static FORCEINLINE ULONG64
+AdapterGetRcvOk(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_UNICAST_PACKETS,
+                &Value);
+    Result = Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_MULTICAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BROADCAST_PACKETS,
+                &Value);
+    Result += Value;
+
+    return Result;
+}
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
+static FORCEINLINE ULONG64
+AdapterGetXmitError(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
-                      &Value);
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                &Value);
+    Result = Value;
 
-    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                &Value);
+    Result += Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
+    return Result;
+}
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                      &Value);
+static FORCEINLINE ULONG64
+AdapterGetRcvError(
+    IN  PXENNET_ADAPTER         Adapter
+    )
+{
+    ULONGLONG   Value;
+    ULONG64     Result = 0;
 
-    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_BACKEND_ERRORS,
+                &Value);
+    Result = Value;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
+    XENVIF_VIF(QueryStatistic,
+                &Adapter->VifInterface,
+                XENVIF_RECEIVER_FRONTEND_ERRORS,
+                &Value);
+    Result += Value;
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                      &Value);
+    return Result;
+}
 
-    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
+static VOID
+AdapterGetPacketFilter(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PULONG                  PacketFilter
+    )
+{
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
 
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_UNICAST,
+               &UnicastFilterLevel);
 
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
-
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
-
-    (VOID) XENVIF_VIF(QueryStatistic,
-                      &Adapter->VifInterface,
-                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                      &Value);
-
-    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
-
-    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
-    NdisStatisticsInfo->ifOutDiscards = 0;
-
-    return ndisStatus;
-}
-
-static VOID
-GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
-{
-    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
-    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
-
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               &UnicastFilterLevel);
-
-    XENVIF_VIF(MacQueryFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               &MulticastFilterLevel);
+    XENVIF_VIF(MacQueryFilterLevel,
+               &Adapter->VifInterface,
+               ETHERNET_ADDRESS_MULTICAST,
+               &MulticastFilterLevel);
 
     XENVIF_VIF(MacQueryFilterLevel,
                &Adapter->VifInterface,
@@ -863,1715 +1271,934 @@ GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
         *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
 }
 
-#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
+AdapterQueryGeneralStatistics (
+    IN  PXENNET_ADAPTER         Adapter,
+    IN  PNDIS_STATISTICS_INFO   Stats
     )
 {
-    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");
+    ULONGLONG                   Value;
 
-            info = &Adapter->Capabilities;
-            bytesAvailable = sizeof(Adapter->Capabilities);
-            break;
+    RtlZeroMemory(Stats, sizeof(NDIS_STATISTICS_INFO));
+    Stats->Header.Type         = NDIS_OBJECT_TYPE_DEFAULT;
+    Stats->Header.Size         = sizeof(NDIS_STATISTICS_INFO);
+    Stats->Header.Revision     = NDIS_OBJECT_REVISION_1;
 
-        case OID_PNP_QUERY_POWER:
-            Trace("QUERY_POWER\n");
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BACKEND_ERRORS,
+                      &Value);
+    Stats->ifInErrors = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_FRONTEND_ERRORS,
+                      &Value);
+    Stats->ifInErrors += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_PACKETS_DROPPED,
+                      &Value);
+    Stats->ifInDiscards = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets += Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCInOctets += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInUcastOctets = Value;
 
-            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
-            if (informationBufferLength >= bytesNeeded) {
-                PNDIS_DEVICE_POWER_STATE state;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_UNICAST_PACKETS,
+                      &Value);
+    Stats->ifHCInUcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCInMulticastOctets = Value;
 
-                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
-                switch (*state) {
-                case NdisDeviceStateD0:
-                    Trace("D0\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_MULTICAST_PACKETS,
+                      &Value);
+    Stats->ifHCInMulticastPkts = Value;
 
-                case NdisDeviceStateD1:
-                    Trace("D1\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCInBroadcastOctets = Value;
 
-                case NdisDeviceStateD2:
-                    Trace("D2\n");
-                    break;
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_RECEIVER_BROADCAST_PACKETS,
+                      &Value);
+    Stats->ifHCInBroadcastPkts = Value;
 
-                case NdisDeviceStateD3:
-                    Trace("D3\n");
-                    break;
-                }
-            }
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
+                      &Value);
+    Stats->ifOutErrors = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
+                      &Value);
+    Stats->ifOutErrors += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets = Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets += Value;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutOctets += Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutUcastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutUcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutMulticastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutMulticastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                      &Value);
+    Stats->ifHCOutBroadcastOctets = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
+    (VOID) XENVIF_VIF(QueryStatistic,
+                      &Adapter->VifInterface,
+                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                      &Value);
+    Stats->ifHCOutBroadcastPkts = Value;
+
+    Stats->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
+    Stats->ifOutDiscards = 0;
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+AdapterGetInterruptModeration(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PNDIS_INTERRUPT_MODERATION_PARAMETERS   Parameters
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+
+    RtlZeroMemory(Parameters, sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS));
+    Parameters->Header.Type      = NDIS_OBJECT_TYPE_DEFAULT;
+    Parameters->Header.Size      = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+    Parameters->Header.Revision  = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+    Parameters->Flags            = 0;
+    Parameters->InterruptModeration = NdisInterruptModerationNotSupported;
+}
+
+static NDIS_STATUS
+AdapterQueryInformation(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
+    )
+{
+    ULONG           Value32;
+    ULONG64         Value64;
+    PVOID           Buffer;
+    ULONG           BufferLength;
+    BOOLEAN         DoCopy = TRUE;
+    ULONG           BytesAvailable = 0;
+    PVOID           BytesToCopy = NULL;
+    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
+
+    Buffer          = Request->DATA.QUERY_INFORMATION.InformationBuffer;
+    BufferLength    = Request->DATA.QUERY_INFORMATION.InformationBufferLength;
+
+    switch (Request->DATA.QUERY_INFORMATION.Oid) {
+        case OID_PNP_CAPABILITIES:
+            BytesToCopy = &Adapter->Capabilities;
+            BytesAvailable = sizeof(Adapter->Capabilities);
             break;
 
         case OID_GEN_SUPPORTED_LIST:
-            info = &XennetSupportedOids[0];
-            bytesAvailable = sizeof(XennetSupportedOids);
+            BytesToCopy = &XennetSupportedOids[0];
+            BytesAvailable = sizeof(XennetSupportedOids);
             break;
 
         case OID_GEN_HARDWARE_STATUS:
-            infoData = NdisHardwareStatusReady;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = NdisHardwareStatusReady;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MEDIA_SUPPORTED:
         case OID_GEN_MEDIA_IN_USE:
-            infoData = XENNET_MEDIA_TYPE;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = XENNET_MEDIA_TYPE;
+            BytesToCopy = &Value32;
+            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);
+            Value32 = Adapter->MaximumFrameSize;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_VENDOR_DESCRIPTION:
-            info = COMPANY_NAME_STR;
-            bytesAvailable = (ULONG)strlen(info) + 1;
+            BytesToCopy = COMPANY_NAME_STR;
+            BytesAvailable = (ULONG)strlen(BytesToCopy) + 1;
             break;
 
         case OID_GEN_VENDOR_DRIVER_VERSION:
-            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_DRIVER_VERSION:
-            infoData = (6 << 8) | 0;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = (6 << 8) | 0;
+            BytesToCopy = &Value32;
+            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);
-
-            }
-
+            Value32 = XENNET_MAC_OPTIONS;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_802_3_MULTICAST_LIST: {
-            ULONG Count;
-
-            doCopy = FALSE;
-
-            XENVIF_VIF(MacQueryMulticastAddresses,
+        case OID_GEN_TRANSMIT_BUFFER_SPACE:
+        case OID_GEN_RECEIVE_BUFFER_SPACE:
+            XENVIF_VIF(TransmitterQueryRingSize,
                        &Adapter->VifInterface,
-                       NULL,
-                       &Count);
-            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
-
-            if (informationBufferLength >= bytesAvailable) {
-                NTSTATUS status;
-
-                status = XENVIF_VIF(MacQueryMulticastAddresses,
-                                    &Adapter->VifInterface,
-                                    informationBuffer,
-                                    &Count);
-                if (!NT_SUCCESS(status))
-                    ndisStatus = NDIS_STATUS_FAILURE;
-            }
-
+                       (PULONG)&Value32);
+            Value32 *= Adapter->MaximumFrameSize;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
-        }
+
         case OID_802_3_PERMANENT_ADDRESS:
             XENVIF_VIF(MacQueryPermanentAddress,
                        &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
+                       (PETHERNET_ADDRESS)&Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_802_3_CURRENT_ADDRESS:
             XENVIF_VIF(MacQueryCurrentAddress,
                        &Adapter->VifInterface,
-                       (PETHERNET_ADDRESS)&infoData);
-            info = &infoData;
-            bytesAvailable = sizeof (ETHERNET_ADDRESS);
+                       (PETHERNET_ADDRESS)&Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MAXIMUM_FRAME_SIZE:
-            infoData = Adapter->MaximumFrameSize -
+            Value32 = Adapter->MaximumFrameSize -
                        sizeof (ETHERNET_TAGGED_HEADER);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_MAXIMUM_TOTAL_SIZE:
-            infoData = Adapter->MaximumFrameSize -
+            Value32 = Adapter->MaximumFrameSize -
                        sizeof (ETHERNET_TAGGED_HEADER) +
                        sizeof (ETHERNET_UNTAGGED_HEADER);
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_CURRENT_LOOKAHEAD:
-            infoData = Adapter->CurrentLookahead;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = Adapter->CurrentLookahead;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
         case OID_GEN_VENDOR_ID:
-            infoData = 0x5853;
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
+            Value32 = 0x5853;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_LINK_SPEED: {
-            ULONG64 LinkSpeed;
-
-            XENVIF_VIF(MacQueryState,
-                       &Adapter->VifInterface,
-                       NULL,
-                       &LinkSpeed,
-                       NULL);
-
-            infoData = (ULONG)(LinkSpeed / 100);
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MEDIA_CONNECT_STATUS:
+        case OID_GEN_LINK_SPEED:
             XENVIF_VIF(MacQueryState,
                        &Adapter->VifInterface,
-                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
                        NULL,
+                       &Value64,
                        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);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
-            break;
-        }
-        case OID_GEN_RCV_OK: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONGLONG);
+            Value32 = (ULONG)(Value64 / 100);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
-        }
-        case OID_GEN_XMIT_ERROR: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
-                       &Value);
-
-            infoData += Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_RCV_ERROR: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BACKEND_ERRORS,
-                       &Value);
-
-            infoData = Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_FRONTEND_ERRORS,
-                       &Value);
-
-            infoData += Value;
-
-            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);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_XMIT: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_DIRECTED_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_UNICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_MULTICAST_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_MULTICAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_BYTES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_OCTETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        case OID_GEN_BROADCAST_FRAMES_RCV: {
-            ULONGLONG   Value;
-
-            XENVIF_VIF(QueryStatistic,
-                       &Adapter->VifInterface,
-                       XENVIF_RECEIVER_BROADCAST_PACKETS,
-                       &Value);
-
-            infoData = Value;
-
-            info = &infoData;
-            bytesAvailable = sizeof(ULONG);
-            break;
-        }
-        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;
-
-        // 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;
-        }
-
-        if (bytesWritten && doCopy) {
-            NdisMoveMemory(informationBuffer, info, bytesWritten);
-
-            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
-                ndisStatus = NDIS_STATUS_SUCCESS;
-        }
-    }
-    
-    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = bytesWritten;
-    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = bytesNeeded;
-    return ndisStatus;
-}
-#pragma warning(pop)
-
-NDIS_STATUS 
-AdapterReset (
-    IN  NDIS_HANDLE     MiniportAdapterContext,
-    OUT PBOOLEAN        AddressingReset
-    )
-{
-    UNREFERENCED_PARAMETER(MiniportAdapterContext);
-
-
-    *AddressingReset = FALSE;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-//
-// 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;
-
-    UNREFERENCED_PARAMETER(MiniportRestartParameters);
-
-    Trace("====>\n");
-
-    if (Adapter->Enabled) {
-        ndisStatus = NDIS_STATUS_SUCCESS;
-        goto done;
-    }
-
-    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;
-    }
-
-done:
-    Trace("<====\n");
-    return ndisStatus;
-}
-
-//
-// Recycle of received net buffer lists.
-//
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    ReceiverReturnNetBufferLists(&Adapter->Receiver,
-                                 NetBufferLists,
-                                 ReturnFlags);
-
-    return;
-}
-
-//
-// 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
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
-
-    TransmitterSendNetBufferLists(Adapter->Transmitter,
-                                  NetBufferList,
-                                  PortNumber,
-                                  SendFlags);
-}
-
-#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)
-
-//
-// Sets general adapter attributes. 
-//
-static NDIS_STATUS
-AdapterSetGeneralAttributes (
-    IN  PADAPTER Adapter
-    )
-{
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
-    NDIS_STATUS ndisStatus;
-
-    NdisZeroMemory(&generalAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
-
-    generalAttributes.Header.Type = 
-                    NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
-
-    generalAttributes.Header.Revision = 
-                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
-
-    generalAttributes.Header.Size = 
-                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
-
-    generalAttributes.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;
-
-    XENVIF_VIF(MacQueryPermanentAddress,
-               &Adapter->VifInterface,
-               (PETHERNET_ADDRESS)&generalAttributes.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;
-                      
-    generalAttributes.SupportedOidList = XennetSupportedOids;
-    generalAttributes.SupportedOidListLength = sizeof(XennetSupportedOids);
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
-
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
-    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
-    )
-{
-    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;
-
-    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;
-    }
-
-    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);
-
-    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
-    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
-    supported.Header.Size = sizeof(supported);
-
-    supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv4Receive.IpChecksum = 1;
-    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
-
-    supported.Checksum.IPv4Receive.TcpChecksum = 1;
-    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
-
-    supported.Checksum.IPv4Receive.UdpChecksum = 1;
-
-    supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
-
-    supported.Checksum.IPv6Receive.TcpChecksum = 1;
-    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
-
-    supported.Checksum.IPv6Receive.UdpChecksum = 1;
-
-    XENVIF_VIF(TransmitterQueryOffloadOptions,
-               &Adapter->VifInterface,
-               &Options);
-
-    supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    if (Options.OffloadIpVersion4HeaderChecksum) {
-        supported.Checksum.IPv4Transmit.IpChecksum = 1;
-        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion4TcpChecksum) {
-        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion4UdpChecksum)
-        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
-
-    supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
-
-    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
-
-    if (Options.OffloadIpVersion6TcpChecksum) {
-        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
-        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
-    }
-
-    if (Options.OffloadIpVersion6UdpChecksum)
-        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;
-    }
-
-    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;
-    }
-
-    current = supported;
-
-    if (!(Adapter->Properties.ipv4_csum & 2))
-        current.Checksum.IPv4Receive.IpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv4_csum & 2))
-        current.Checksum.IPv4Receive.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv4_csum & 2))
-        current.Checksum.IPv4Receive.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv6_csum & 2))
-        current.Checksum.IPv6Receive.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv6_csum & 2))
-        current.Checksum.IPv6Receive.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.ipv4_csum & 1))
-        current.Checksum.IPv4Transmit.IpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv4_csum & 1))
-        current.Checksum.IPv4Transmit.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv4_csum & 1))
-        current.Checksum.IPv4Transmit.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.tcpv6_csum & 1))
-        current.Checksum.IPv6Transmit.TcpChecksum = 0;
-
-    if (!(Adapter->Properties.udpv6_csum & 1))
-        current.Checksum.IPv6Transmit.UdpChecksum = 0;
-
-    if (!(Adapter->Properties.lsov4)) {
-        current.LsoV2.IPv4.MaxOffLoadSize = 0;
-        current.LsoV2.IPv4.MinSegmentCount = 0;
-    }
-
-    if (!(Adapter->Properties.lsov6)) {
-        current.LsoV2.IPv6.MaxOffLoadSize = 0;
-        current.LsoV2.IPv6.MinSegmentCount = 0;
-    }
-
-    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof (NDIS_OFFLOAD))) {
-        Adapter->Offload = current;
-
-        DISPLAY_OFFLOAD(current);
-    }
-
-    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;
-
-    adapterAttributes =
-        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
-
-    return ndisStatus;
-}
-
-static void
-AdapterIndicateOffloadChanged (
-    IN  PADAPTER 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;
-    }
-
-    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);
-    }
-
-    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);
-
-    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
-
-}
-
-static NDIS_STATUS
-SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address, ULONG Count)
-{
-    NTSTATUS status;
-
-    status = XENVIF_VIF(MacSetMulticastAddresses,
-                        &Adapter->VifInterface,
-                        Address,
-                        Count);
-    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;
-
-    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
-        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-        goto done;
-    }
-
-    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
-        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
-    else
-        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
-
-    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;
 
-    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
-    else
-        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
+        case OID_GEN_MEDIA_CONNECT_STATUS:
+            XENVIF_VIF(MacQueryState,
+                       &Adapter->VifInterface,
+                       (PNET_IF_MEDIA_CONNECT_STATE)&Value32,
+                       NULL,
+                       NULL);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-done:
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_UNICAST,
-               UnicastFilterLevel);
+        case OID_GEN_MAXIMUM_SEND_PACKETS:
+            Value32 = 16;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_MULTICAST,
-               MulticastFilterLevel);
+        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:
+            Value32 = 0;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    XENVIF_VIF(MacSetFilterLevel,
-               &Adapter->VifInterface,
-               ETHERNET_ADDRESS_BROADCAST,
-               BroadcastFilterLevel);
+        case OID_802_3_MAXIMUM_LIST_SIZE:
+            Value32 = 32;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-    return NDIS_STATUS_SUCCESS;
-}
+        case OID_GEN_STATISTICS:
+            DoCopy = FALSE;
+            BytesAvailable = sizeof(NDIS_STATISTICS_INFO);
+            if (BufferLength >= sizeof(NDIS_STATISTICS_INFO))
+                NdisStatus = AdapterQueryGeneralStatistics(Adapter, Buffer);
+            break;
 
-//
-// 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;
+        case OID_802_3_MULTICAST_LIST:
+            DoCopy = FALSE;
+            XENVIF_VIF(MacQueryMulticastAddresses,
+                       &Adapter->VifInterface,
+                       NULL,
+                       &Value32);
+            BytesAvailable = Value32 * ETHERNET_ADDRESS_LENGTH;
+            if (BufferLength >= BytesAvailable) {
+                if (!NT_SUCCESS(XENVIF_VIF(MacQueryMulticastAddresses,
+                                           &Adapter->VifInterface,
+                                           Buffer,
+                                           &Value32))) {
+                    NdisStatus = NDIS_STATUS_FAILURE;
                 }
             }
             break;
 
-        case OID_GEN_MACHINE_NAME:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            AdapterGetPacketFilter(Adapter, &Value32);
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_CURRENT_LOOKAHEAD:
-            bytesNeeded = sizeof(ULONG);
-            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
-            if (informationBufferLength == sizeof(ULONG)) {
-                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
-                bytesRead = sizeof(ULONG);
-            }
-
+        case OID_GEN_XMIT_OK:
+            Value64 = AdapterGetXmitOk(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
             break;
 
-        case OID_GEN_CURRENT_PACKET_FILTER:
-            bytesNeeded = sizeof(ULONG);
-            if (informationBufferLength == sizeof(ULONG)) {
-                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
-                bytesRead = sizeof(ULONG);
-            }
-
+        case OID_GEN_RCV_OK:
+            Value64 = AdapterGetRcvOk(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
             break;
 
-        case OID_802_3_MULTICAST_LIST:
-            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
-            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
-                addressCount = informationBufferLength / ETHERNET_ADDRESS_LENGTH;
+        case OID_GEN_XMIT_ERROR:
+            Value64 = AdapterGetXmitError(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
+            break;
 
-                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer, addressCount);
-                if (ndisStatus == NDIS_STATUS_SUCCESS)
-                    bytesRead = informationBufferLength;
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
+        case OID_GEN_RCV_ERROR:
+            Value64 = AdapterGetRcvError(Adapter);
+            BytesToCopy = &Value64;
+            BytesAvailable = sizeof(ULONG64);
+            break;
 
+        case OID_GEN_DIRECTED_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_GEN_INTERRUPT_MODERATION:
-            ndisStatus = NDIS_STATUS_INVALID_DATA;
+        case OID_GEN_DIRECTED_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
             break;
 
-        case OID_OFFLOAD_ENCAPSULATION: {
-            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
+        case OID_GEN_MULTICAST_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-            bytesNeeded = sizeof(*offloadEncapsulation);
-            if (informationBufferLength >= bytesNeeded) {
-                XENVIF_VIF_OFFLOAD_OPTIONS Options;
+        case OID_GEN_MULTICAST_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                bytesRead = bytesNeeded;
-                offloadEncapsulation = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
+        case OID_GEN_BROADCAST_BYTES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+        case OID_GEN_BROADCAST_FRAMES_XMIT:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON) {
-                    if (offloadEncapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+        case OID_GEN_DIRECTED_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_UNICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                XENVIF_VIF(TransmitterQueryOffloadOptions,
-                           &Adapter->VifInterface,
-                           &Options);
-                
-                Adapter->Transmitter->OffloadOptions.Value = 0;
-                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
+        case OID_GEN_DIRECTED_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_UNICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.lsov4) && (Options.OffloadIpVersion4LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
+        case OID_GEN_MULTICAST_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_MULTICAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.lsov6) && (Options.OffloadIpVersion6LargePacket))
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
+        case OID_GEN_MULTICAST_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_MULTICAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+        case OID_GEN_BROADCAST_BYTES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_BROADCAST_OCTETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+        case OID_GEN_BROADCAST_FRAMES_RCV:
+            XENVIF_VIF(QueryStatistic,
+                       &Adapter->VifInterface,
+                       XENVIF_RECEIVER_BROADCAST_PACKETS,
+                       &Value64);
+            Value32 = (ULONG)Value64;
+            BytesToCopy = &Value32;
+            BytesAvailable = sizeof(ULONG);
+            break;
 
-                if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+        case OID_GEN_INTERRUPT_MODERATION:
+            DoCopy = FALSE;
+            BytesAvailable = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+            if (BufferLength >= BytesAvailable)
+                AdapterGetInterruptModeration(Adapter, Buffer);
+            else
+                NdisStatus = NDIS_STATUS_FAILURE;
+            break;
 
-                if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+        case OID_PNP_QUERY_POWER:
+            // do nothing!
+            break;
 
-                if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
-                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+        case OID_GEN_MAC_ADDRESS:
+        case OID_GEN_MAX_LINK_SPEED:
+        case OID_IP4_OFFLOAD_STATS:
+        case OID_IP6_OFFLOAD_STATS:
+        case OID_GEN_SUPPORTED_GUIDS:
+		case OID_GEN_INIT_TIME_MS:
+		case OID_GEN_RESET_COUNTS:
+		case OID_GEN_MEDIA_SENSE_COUNTS:
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
 
-                Adapter->Receiver.OffloadOptions.Value = 0;
-                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+    }
 
-                if (Adapter->Properties.need_csum_value)
-                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+    if (NdisStatus == NDIS_STATUS_SUCCESS) {
+        Request->DATA.QUERY_INFORMATION.BytesNeeded = BytesAvailable;
+        if (BytesAvailable <= BufferLength) {
+            Request->DATA.QUERY_INFORMATION.BytesWritten = BytesAvailable;
+        } else {
+            Request->DATA.QUERY_INFORMATION.BytesWritten = BufferLength;
+            NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
+        }
+        if (Request->DATA.QUERY_INFORMATION.BytesWritten && DoCopy) {
+            RtlMoveMemory(Buffer, BytesToCopy, Request->DATA.QUERY_INFORMATION.BytesWritten);
 
-                if (Adapter->Properties.lrov4) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
+            // Its Ok to short transfers on these Oids
+            if (Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_XMIT_OK ||
+                Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_RCV_OK)
+                NdisStatus = NDIS_STATUS_SUCCESS;
+        }
+    }
 
-                if (Adapter->Properties.lrov6) {
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
-                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
-                }
+    return NdisStatus;
+}
 
-                if (Adapter->Properties.ipv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+NDIS_STATUS
+AdapterOidRequest(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
+    )
+{
+    NDIS_STATUS     NdisStatus;
+    
+    switch (Request->RequestType) {
+        case NdisRequestSetInformation:            
+            NdisStatus = AdapterSetInformation(Adapter, Request);
+            break;
+                
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            NdisStatus = AdapterQueryInformation(Adapter, Request);
+            break;
 
-                if (Adapter->Properties.tcpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+        default:
+            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
 
-                if (Adapter->Properties.udpv4_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+    return NdisStatus;
+}
 
-                if (Adapter->Properties.tcpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+NTSTATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    NTSTATUS        status;
 
-                if (Adapter->Properties.udpv6_csum & 2)
-                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+    if (Adapter->Enabled)
+        goto done;
 
-                AdapterIndicateOffloadChanged(Adapter);
-            }
-            break;
-        }
-        case OID_TCP_OFFLOAD_PARAMETERS: {
-            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
+    status = XENVIF_VIF(Enable,
+                        &Adapter->VifInterface,
+                        AdapterVifCallback,
+                        Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+    
+    TransmitterEnable(Adapter->Transmitter);
+    Adapter->Enabled = TRUE;
 
-            bytesNeeded = sizeof(*offloadParameters);
-            if (informationBufferLength >= bytesNeeded) {
-                bytesRead = bytesNeeded;
-                offloadParameters = informationBuffer;
-                ndisStatus = NDIS_STATUS_SUCCESS;
+done:
+    return STATUS_SUCCESS;
 
-#define no_change(x)  ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
 
-                if (!no_change(offloadParameters->IPsecV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                    
-                if (!no_change(offloadParameters->LsoV1))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    if (!Adapter->Enabled)
+        return FALSE;
 
-                if (!no_change(offloadParameters->TcpConnectionIPv4))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+    XENVIF_VIF(Disable, &Adapter->VifInterface);
+    Adapter->Enabled = FALSE;
+    return TRUE;
+}
 
-                if (!no_change(offloadParameters->TcpConnectionIPv6))
-                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+VOID
+AdapterMediaStateChange(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    NDIS_LINK_STATE                 LinkState;
+    NDIS_STATUS_INDICATION          StatusIndication;
 
-                if (!no_change(offloadParameters->LsoV2IPv4)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
+    LinkState.Header.Type       = NDIS_OBJECT_TYPE_DEFAULT;
+    LinkState.Header.Size       = sizeof(NDIS_LINK_STATE);
+    LinkState.Header.Revision   = NDIS_LINK_STATE_REVISION_1;
 
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
+    XENVIF_VIF(MacQueryState,
+               &Adapter->VifInterface,
+               &LinkState.MediaConnectState,
+               &LinkState.RcvLinkSpeed,
+               &LinkState.MediaDuplexState);
 
-                    if (!(Options.OffloadIpVersion4LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
+        Info("LINK: STATE UNKNOWN\n");
+    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
+        Info("LINK: DOWN\n");
+    } else {
+        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
 
-                if (!no_change(offloadParameters->LsoV2IPv6)) {
-                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
+        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);
+    }
 
-                    XENVIF_VIF(TransmitterQueryOffloadOptions,
-                               &Adapter->VifInterface,
-                               &Options);
+    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
 
-                    if (!(Options.OffloadIpVersion6LargePacket))
-                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
-                }
+    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
+    StatusIndication.Header.Type        = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    StatusIndication.Header.Size        = sizeof (NDIS_STATUS_INDICATION);
+    StatusIndication.Header.Revision    = NDIS_STATUS_INDICATION_REVISION_1;
+    StatusIndication.SourceHandle       = Adapter->NdisHandle;
+    StatusIndication.StatusCode         = NDIS_STATUS_LINK_STATE;
+    StatusIndication.StatusBuffer       = &LinkState;
+    StatusIndication.StatusBufferSize   = sizeof (NDIS_LINK_STATE);
 
-#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;
-                        }
-                    }
+    NdisMIndicateStatusEx(Adapter->NdisHandle, &StatusIndication);
+}
 
-#undef tx_enabled
-#undef rx_enabled
-#undef no_change
+PXENNET_RECEIVER
+AdapterGetReceiver(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->Receiver;
+}
 
-                    if (offloadChanged)
-                        AdapterIndicateOffloadChanged(Adapter);
-                }
-            } else {
-                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
-            }
-            break;
-        }
-        default:
-            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
-            break;
-    };
+PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->Transmitter;
+}
 
-    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
-    if (ndisStatus == NDIS_STATUS_SUCCESS) {
-        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
-    }
+PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return &Adapter->VifInterface;
+}
 
-    return ndisStatus;
+NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER             Adapter
+    )
+{
+    return Adapter->NdisHandle;
 }
 
-//
-// Sets miniport registration attributes.
-//
-static NDIS_STATUS
-AdapterSetRegistrationAttributes (
-    IN  PADAPTER Adapter
+NTSTATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE                 NdisHandle,
+    OUT PXENNET_ADAPTER             *Adapter
     )
 {
-    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
-    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registrationAttributes;
-    NDIS_STATUS ndisStatus;
+    PDEVICE_OBJECT          DeviceObject;
+    NTSTATUS                status;
+    NDIS_SG_DMA_DESCRIPTION DmaDescription;
+    NDIS_STATUS             NdisStatus;
+
+    status = STATUS_NO_MEMORY;
+    *Adapter = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_ADAPTER), XENNET_POOL_TAG);
+    if (*Adapter == NULL)
+        goto fail1;
 
+    RtlZeroMemory(*Adapter, sizeof(XENNET_ADAPTER));
+    (*Adapter)->NdisHandle = NdisHandle;
+
+    DeviceObject = NULL;
+    NdisMGetDeviceProperty(NdisHandle,
+                           &DeviceObject,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
+
+    status = QUERY_INTERFACE(DeviceObject,
+                             XENVIF,
+                             VIF,
+                             XENVIF_VIF_INTERFACE_VERSION_MAX,
+                             (PINTERFACE)&(*Adapter)->VifInterface,
+                             sizeof ((*Adapter)->VifInterface),
+                             FALSE);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    NdisZeroMemory(&registrationAttributes, 
-                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+    status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    registrationAttributes.Header.Type = 
-                NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+    status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
+    if (!NT_SUCCESS(status))
+        goto fail4;
 
-    registrationAttributes.Header.Revision = 
-                NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+    status = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
-    registrationAttributes.Header.Size = 
-                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+    NdisStatus = AdapterGetAdvancedSettings(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail6;
 
-    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;
+    NdisStatus = AdapterSetRegistrationAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail7;
 
-    adapterAttributes = 
-                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
+    NdisStatus = AdapterSetGeneralAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail8;
 
-    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
-                                            adapterAttributes);
+    NdisStatus = AdapterSetOffloadAttributes(*Adapter);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        goto fail9;
 
-    return ndisStatus;
-}
+    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
+    DmaDescription.Header.Type      = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
+    DmaDescription.Header.Size      = sizeof(NDIS_SG_DMA_DESCRIPTION);
+    DmaDescription.Header.Revision  = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
+    DmaDescription.Flags            = NDIS_SG_DMA_64_BIT_ADDRESS;
+    DmaDescription.MaximumPhysicalMapping           = 65536;    
+    DmaDescription.ProcessSGListHandler             = AdapterProcessSGList;
+    DmaDescription.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
 
-//
-// Shuts down adapter.
-//
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
+    NdisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisHandle,
+                                               &DmaDescription,
+                                               &(*Adapter)->NdisDmaHandle);
+    if (NdisStatus != NDIS_STATUS_SUCCESS)
+        (*Adapter)->NdisDmaHandle = NULL;
 
-    UNREFERENCED_PARAMETER(ShutdownAction);
+    status = AdapterEnable(*Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail10;
 
-    if (ShutdownAction != NdisShutdownBugCheck)
-        AdapterStop(Adapter);
+    return STATUS_SUCCESS;
 
-    return;
+fail10:
+    Error("fail10 (%08x)\n", status);
+    if ((*Adapter)->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
+    (*Adapter)->NdisDmaHandle = NULL;
+fail9:
+    Error("fail9\n");
+fail8:
+    Error("fail8\n");
+fail7:
+    Error("fail7\n");
+fail6:
+    Error("fail6 (%08x)\n", NdisStatus);
+    if (NT_SUCCESS(status))
+        status = STATUS_UNSUCCESSFUL;
+    ReceiverTeardown((*Adapter)->Receiver);
+    (*Adapter)->Receiver = NULL;
+fail5:
+    Error("fail5\n");
+    TransmitterTeardown((*Adapter)->Transmitter);
+    (*Adapter)->Transmitter = NULL;
+fail4:
+    Error("fail4\n");
+    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
+fail3:
+    Error("fail3\n");
+    RtlZeroMemory(&(*Adapter)->VifInterface, sizeof(XENVIF_VIF_INTERFACE));
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Adapter, XENNET_POOL_TAG);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
-//
-// 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
-)
+VOID
+AdapterTeardown(
+    IN  PXENNET_ADAPTER             Adapter
+    )
 {
-    Trace("====>\n");
+    if (Adapter->NdisDmaHandle)
+        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
+    Adapter->NdisDmaHandle = NULL;
 
-    if (!Adapter->Enabled)
-        goto done;
+    ReceiverTeardown(Adapter->Receiver);
+    Adapter->Receiver = NULL;
 
-    XENVIF_VIF(Disable,
-               &Adapter->VifInterface);
+    TransmitterTeardown(Adapter->Transmitter);
+    Adapter->Transmitter = 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, XENNET_POOL_TAG);
 }
+
+//
+//#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)
+//
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
index e64e40d..a1f4b85 100644
--- a/src/xennet/adapter.h
+++ b/src/xennet/adapter.h
@@ -29,19 +29,20 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_ADAPTER_H_
+#define _XENNET_ADAPTER_H_
 
-#define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
+#define XENNET_INTERFACE_TYPE   NdisInterfaceInternal
 
-#define XENNET_MEDIA_TYPE               NdisMedium802_3
+#define XENNET_MEDIA_TYPE       NdisMedium802_3
 
-#define XENNET_MAC_OPTIONS              (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
-                                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
-                                         NDIS_MAC_OPTION_NO_LOOPBACK |          \
-                                         NDIS_MAC_OPTION_8021P_PRIORITY |       \
-                                         NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
+#define XENNET_MAC_OPTIONS      (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
+                                 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
+                                 NDIS_MAC_OPTION_NO_LOOPBACK |          \
+                                 NDIS_MAC_OPTION_8021P_PRIORITY |       \
+                                 NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
 
-typedef struct _PROPERTIES {
+typedef struct _XENNET_PROPERTIES {
     int ipv4_csum;
     int tcpv4_csum;
     int udpv4_csum;
@@ -52,122 +53,63 @@ typedef struct _PROPERTIES {
     int lsov6;
     int lrov4;
     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
-    );
-
-MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
-VOID 
-AdapterCancelSendNetBufferLists (
-    IN  NDIS_HANDLE NdisHandle,
-    IN  PVOID       CancelId
-    );
+} XENNET_PROPERTIES, *PXENNET_PROPERTIES;
 
-MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
-BOOLEAN 
-AdapterCheckForHang (
-    IN  NDIS_HANDLE NdisHandle
-    );
-
-VOID
-AdapterCleanup (
-    IN PADAPTER Adapter
-    );
+typedef struct _XENNET_ADAPTER  XENNET_ADAPTER, *PXENNET_ADAPTER;
 
-NDIS_STATUS 
-AdapterInitialize (
-    IN  PADAPTER    Adapter,
-    IN  NDIS_HANDLE AdapterHandle
+extern NDIS_STATUS
+AdapterOidRequest(
+    IN  PXENNET_ADAPTER             Adapter,
+    IN  PNDIS_OID_REQUEST           Request
     );
 
-MINIPORT_OID_REQUEST AdapterOidRequest;
-NDIS_STATUS 
-AdapterOidRequest (
-    IN  NDIS_HANDLE         NdisHandle,
-    IN  PNDIS_OID_REQUEST   NdisRequest
+extern NTSTATUS
+AdapterEnable(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_PAUSE AdapterPause;
-NDIS_STATUS 
-AdapterPause (
-    IN  NDIS_HANDLE                     NdisHandle,
-    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+extern BOOLEAN
+AdapterDisable(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
-VOID 
-AdapterPnPEventHandler (
-    IN  NDIS_HANDLE             NdisHandle,
-    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+extern VOID
+AdapterMediaStateChange(
+    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
+#include "transmitter.h"
+extern PXENNET_TRANSMITTER
+AdapterGetTransmitter(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
-VOID 
-AdapterReturnNetBufferLists (
-    IN  NDIS_HANDLE         MiniportAdapterContext,
-    IN  PNET_BUFFER_LIST    NetBufferLists,
-    IN  ULONG               ReturnFlags
+#include <vif_interface.h>
+extern PXENVIF_VIF_INTERFACE
+AdapterGetVifInterface(
+    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 NDIS_HANDLE
+AdapterGetHandle(
+    IN  PXENNET_ADAPTER             Adapter
     );
 
-NDIS_STATUS
-AdapterStop (
-    IN  PADAPTER    Adapter
-    );
-
-MINIPORT_SHUTDOWN AdapterShutdown;
-
-VOID 
-AdapterShutdown (
-    IN  NDIS_HANDLE             MiniportAdapterContext,
-    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+extern NTSTATUS
+AdapterInitialize(
+    IN  NDIS_HANDLE                 NdisHandle,
+    OUT PXENNET_ADAPTER             *Adapter
     );
 
 extern VOID
-ReceiverReceivePackets(
-    IN  PRECEIVER   Receiver,
-    IN  PLIST_ENTRY List
+AdapterTeardown(
+    IN  PXENNET_ADAPTER             Adapter
     );
+
+#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/driver.c b/src/xennet/driver.c
new file mode 100644
index 0000000..66aff1d
--- /dev/null
+++ b/src/xennet/driver.c
@@ -0,0 +1,550 @@
+/* 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 <ndis.h>
+#include <ntstrsafe.h>
+#include <version.h>
+
+#include "adapter.h"
+#include "transmitter.h"
+#include "receiver.h"
+#include "registry.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+extern PULONG InitSafeBootMode;
+
+typedef struct _XENNET_DRIVER {
+    PDRIVER_OBJECT              DriverObject;
+    NDIS_HANDLE                 MiniportHandle;
+    NTSTATUS                    (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
+} XENNET_DRIVER;
+
+static XENNET_DRIVER            Driver;
+
+MINIPORT_CANCEL_OID_REQUEST     DriverCancelOidRequest;
+VOID
+DriverCancelOidRequest(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PVOID                   RequestId
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(RequestId);
+}
+
+MINIPORT_CANCEL_SEND            DriverCancelSendNetBufferLists;
+VOID
+DriverCancelSendNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PVOID                   CancelId
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(CancelId);
+}
+
+MINIPORT_CHECK_FOR_HANG DriverCheckForHang;
+BOOLEAN
+DriverCheckForHang(
+    IN  NDIS_HANDLE             NdisHandle
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    return FALSE;
+}
+
+MINIPORT_DEVICE_PNP_EVENT_NOTIFY DriverPnPEventHandler;
+VOID
+DriverPnPEventHandler(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    UNREFERENCED_PARAMETER(NetDevicePnPEvent);
+}
+
+MINIPORT_RESET                  DriverReset;
+NDIS_STATUS
+DriverReset(
+    IN  NDIS_HANDLE             NdisHandle,
+    OUT PBOOLEAN                AddressingReset
+    )
+{
+    UNREFERENCED_PARAMETER(NdisHandle);
+    *AddressingReset = FALSE;
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_OID_REQUEST            DriverOidRequest;
+NDIS_STATUS
+DriverOidRequest(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNDIS_OID_REQUEST       NdisRequest
+    )
+{
+    return AdapterOidRequest((PXENNET_ADAPTER)NdisHandle, NdisRequest);
+}
+
+MINIPORT_PAUSE DriverPause;
+NDIS_STATUS
+DriverPause(
+    IN  NDIS_HANDLE                     NdisHandle,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+    )
+{
+    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+
+    if (AdapterDisable((PXENNET_ADAPTER)NdisHandle))
+        AdapterMediaStateChange((PXENNET_ADAPTER)NdisHandle);
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+MINIPORT_RESTART DriverRestart;
+NDIS_STATUS
+DriverRestart(
+    IN  NDIS_HANDLE                         NdisHandle,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+    )
+{
+    NTSTATUS    status;
+
+    UNREFERENCED_PARAMETER(MiniportRestartParameters);
+
+    status = AdapterEnable((PXENNET_ADAPTER)NdisHandle);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return NDIS_STATUS_FAILURE;
+}
+
+MINIPORT_RETURN_NET_BUFFER_LISTS DriverReturnNetBufferLists;
+VOID
+DriverReturnNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    PXENNET_RECEIVER            Receiver;
+    Receiver = AdapterGetReceiver((PXENNET_ADAPTER)NdisHandle);
+    ReceiverReturnNetBufferLists(Receiver,
+                                 NetBufferLists,
+                                 ReturnFlags);
+}
+
+MINIPORT_SEND_NET_BUFFER_LISTS  DriverSendNetBufferLists;
+VOID
+DriverSendNetBufferLists(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    PXENNET_TRANSMITTER         Transmitter;
+    Transmitter = AdapterGetTransmitter((PXENNET_ADAPTER)NdisHandle);
+    TransmitterSendNetBufferLists(Transmitter,
+                                  NetBufferList,
+                                  PortNumber,
+                                  SendFlags);
+}
+
+MINIPORT_SHUTDOWN DriverShutdown;
+VOID
+DriverShutdown(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+    )
+{
+    UNREFERENCED_PARAMETER(ShutdownAction);
+
+    if (ShutdownAction != NdisShutdownBugCheck)
+        (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
+}
+
+MINIPORT_INITIALIZE             DriverInitialize;
+NDIS_STATUS 
+DriverInitialize(
+    IN  NDIS_HANDLE                        NdisHandle,
+    IN  NDIS_HANDLE                        DriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     Parameters
+    )
+{
+    NTSTATUS            status;
+    PXENNET_ADAPTER     Adapter;
+
+    UNREFERENCED_PARAMETER(DriverContext);
+    UNREFERENCED_PARAMETER(Parameters);
+
+    status = AdapterInitialize(NdisHandle, &Adapter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return NDIS_STATUS_ADAPTER_NOT_FOUND;
+}
+
+MINIPORT_HALT                   DriverHalt;
+VOID 
+DriverHalt(
+    IN  NDIS_HANDLE             NdisHandle,
+    IN  NDIS_HALT_ACTION        HaltAction
+    )
+{
+    if (NdisHandle == NULL)
+        return;
+
+    UNREFERENCED_PARAMETER(HaltAction);
+
+    (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
+    AdapterTeardown((PXENNET_ADAPTER)NdisHandle);
+}
+
+typedef struct _XENNET_CONTEXT {
+    PDEVICE_CAPABILITIES    Capabilities;
+    PIO_COMPLETION_ROUTINE  CompletionRoutine;
+    PVOID                   CompletionContext;
+    UCHAR                   CompletionControl;
+} XENNET_CONTEXT, *PXENNET_CONTEXT;
+
+__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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
+
+    Trace("<====\n");
+
+    return status;    
+}
+
+_Dispatch_type_(IRP_MJ_PNP)
+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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
+        break;
+    }
+
+    return status;
+}
+
+_Dispatch_type_(IRP_MJ_CREATE)
+_Dispatch_type_(IRP_MJ_CLOSE)
+_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
+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
+    )
+{
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        goto done;
+
+    ASSERT3P(Driver.DriverObject, ==, DriverObject);
+    Driver.DriverObject = NULL;
+
+    if (Driver.MiniportHandle)
+        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+    Driver.NdisDispatchPnp = NULL;
+
+    RegistryTeardown();
+
+    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;
+    NTSTATUS                                status;
+
+    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+    Trace("====>\n");
+
+    if (*InitSafeBootMode > 0)
+        return NDIS_STATUS_SUCCESS;
+
+    ASSERT3P(Driver.DriverObject, ==, NULL);
+    Driver.DriverObject = DriverObject;
+
+    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    status = RegistryInitialize(RegistryPath);
+
+    ndisStatus = (NT_SUCCESS(status)) ?
+                 NDIS_STATUS_SUCCESS :
+                 NDIS_STATUS_FAILURE;
+
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
+
+    //
+    // Register miniport with NDIS.
+    //
+
+    RtlZeroMemory(&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     = DriverCancelOidRequest;
+    mpChars.CancelSendHandler           = DriverCancelSendNetBufferLists;
+    mpChars.CheckForHangHandlerEx       = DriverCheckForHang;
+    mpChars.InitializeHandlerEx         = DriverInitialize;
+    mpChars.HaltHandlerEx               = DriverHalt;
+    mpChars.OidRequestHandler           = DriverOidRequest;    
+    mpChars.PauseHandler                = DriverPause;      
+    mpChars.DevicePnPEventNotifyHandler = DriverPnPEventHandler;
+    mpChars.ResetHandlerEx              = DriverReset;
+    mpChars.RestartHandler              = DriverRestart;    
+    mpChars.ReturnNetBufferListsHandler = DriverReturnNetBufferLists;
+    mpChars.SendNetBufferListsHandler   = DriverSendNetBufferLists;
+    mpChars.ShutdownHandlerEx           = DriverShutdown;
+    mpChars.UnloadHandler               = DriverUnload;
+
+    Driver.MiniportHandle = NULL;
+    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
+                                             RegistryPath,
+                                             NULL,
+                                             &mpChars,
+                                             &Driver.MiniportHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail2;
+
+    RtlZeroMemory(&ConfigurationObject, sizeof(ConfigurationObject));
+    ConfigurationObject.Header.Type     = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    ConfigurationObject.Header.Size     = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.NdisHandle      = Driver.MiniportHandle;
+    ConfigurationObject.Flags           = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail3;
+
+    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);
+
+    Driver.NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
+    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+    if (FailCreateClose != 0) {
+        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
+    }
+
+    if (FailDeviceControl != 0) {
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
+    }
+
+    Trace("<====\n");
+    return NDIS_STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
+    Driver.MiniportHandle = NULL;
+
+fail2:
+    Error("fail2\n");
+
+    RegistryTeardown();
+
+fail1:
+    Error("fail1\n");
+
+    Driver.DriverObject = NULL;
+    return ndisStatus;
+}
+
diff --git a/src/xennet/main.c b/src/xennet/main.c
deleted file mode 100644
index 6622e82..0000000
--- a/src/xennet/main.c
+++ /dev/null
@@ -1,361 +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"
-#include "registry.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;
-    NTSTATUS status;
-
-    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);
-
-    status = RegistryInitialize(RegistryPath);
-
-    ndisStatus = (NT_SUCCESS(status)) ?
-                 NDIS_STATUS_SUCCESS :
-                 NDIS_STATUS_FAILURE;
-
-    if (ndisStatus != NDIS_STATUS_SUCCESS)
-        goto fail;
-
-    //
-    // 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);
-
-    RegistryTeardown();
-
-    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/miniport.c b/src/xennet/miniport.c
deleted file mode 100644
index a1d605f..0000000
--- a/src/xennet/miniport.c
+++ /dev/null
@@ -1,297 +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.
- */
-
-#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,
-    IN  ULONG           Size,
-    IN  BOOLEAN         Optional
-    )
-{
-    UNICODE_STRING      Unicode;
-    HANDLE              InterfacesKey;
-    HANDLE              SubscriberKey;
-    KEVENT              Event;
-    IO_STATUS_BLOCK     StatusBlock;
-    PIRP                Irp;
-    PIO_STACK_LOCATION  StackLocation;
-    NTSTATUS            status;
-
-    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));
-
-    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
-                                       DeviceObject,
-                                       NULL,
-                                       0,
-                                       NULL,
-                                       &Event,
-                                       &StatusBlock);
-
-    status = STATUS_UNSUCCESSFUL;
-    if (Irp == NULL)
-        goto fail4;
-
-    StackLocation = IoGetNextIrpStackLocation(Irp);
-    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
-
-    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;
-    }
-
-    if (!NT_SUCCESS(status)) {
-        if (status == STATUS_NOT_SUPPORTED && Optional)
-            goto done;
-
-        goto fail5;
-    }
-
-    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);
-
-    return status;
-}
-
-#define QUERY_INTERFACE(                                                                \
-    _DeviceObject,                                                                      \
-    _ProviderName,                                                                      \
-    _InterfaceName,                                                                     \
-    _Version,                                                                           \
-    _Interface,                                                                         \
-    _Size,                                                                              \
-    _Optional)                                                                          \
-    __QueryInterface((_DeviceObject),                                                   \
-                     L ## #_ProviderName,                                               \
-                     #_InterfaceName,                                                   \
-                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE,      \
-                     (_Version),                                                        \
-                     (_Interface),                                                      \
-                     (_Size),                                                           \
-                     (_Optional))
-
-NDIS_STATUS 
-MiniportInitialize (
-    IN  NDIS_HANDLE                        MiniportAdapterHandle,
-    IN  NDIS_HANDLE                        MiniportDriverContext,
-    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
-    )
-{
-    PADAPTER Adapter = NULL;
-    NDIS_STATUS ndisStatus;
-    PDEVICE_OBJECT DeviceObject;
-    NTSTATUS status;
-
-    UNREFERENCED_PARAMETER(MiniportDriverContext);
-    UNREFERENCED_PARAMETER(MiniportInitParameters);
-
-    Trace("====>\n");
-
-    status = AllocAdapter(&Adapter);
-
-    if (!NT_SUCCESS(status) || Adapter == NULL) {
-        ndisStatus = NDIS_STATUS_RESOURCES;
-        goto fail1;
-    }
-
-    RtlZeroMemory(Adapter, sizeof (ADAPTER));
-
-    DeviceObject = NULL;
-    NdisMGetDeviceProperty(MiniportAdapterHandle,
-                           &DeviceObject,
-                           NULL,
-                           NULL,
-                           NULL,
-                           NULL);
-
-    status = QUERY_INTERFACE(DeviceObject,
-                             XENVIF,
-                             VIF,
-                             XENVIF_VIF_INTERFACE_VERSION_MAX,
-                             (PINTERFACE)&Adapter->VifInterface,
-                             sizeof (Adapter->VifInterface),
-                             FALSE);
-
-    if (!NT_SUCCESS(status)) {
-        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
-        goto fail2;
-    }
-
-    ndisStatus = AdapterInitialize(Adapter, MiniportAdapterHandle);
-    if (ndisStatus != NDIS_STATUS_SUCCESS) {
-        goto fail3;
-    }
-
-    Trace("<====\n");
-    return ndisStatus;
-
-fail3:
-    Error("fail3\n");
-
-    RtlZeroMemory(&Adapter->VifInterface,
-                  sizeof (XENVIF_VIF_INTERFACE));
-
-fail2:
-    Error("fail2\n");
-
-    ExFreePool(Adapter);
-
-fail1:
-    Error("fail1\n");
-
-    return ndisStatus;
-}
-
-//
-// Stops adapter and frees all resources.
-//
-VOID 
-MiniportHalt (
-    IN  NDIS_HANDLE             MiniportAdapterHandle,
-    IN  NDIS_HALT_ACTION        HaltAction
-    )
-{
-    PADAPTER Adapter = (PADAPTER)MiniportAdapterHandle;
-
-    UNREFERENCED_PARAMETER(HaltAction);
-
-    if (Adapter == NULL)
-        return;
-
-    (VOID) AdapterStop(Adapter);
-
-    AdapterCleanup(Adapter);
-
-    RtlZeroMemory(&Adapter->VifInterface,
-                  sizeof (XENVIF_VIF_INTERFACE));
-
-    ExFreePool(Adapter);
-}
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..ee01a18 100644
--- a/src/xennet/receiver.c
+++ b/src/xennet/receiver.c
@@ -29,103 +29,38 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
-
-#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;
-}
+#include <ndis.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       'teNX'
+#define IN_NDIS_MAX 1024
 
-PNET_BUFFER_LIST
+static PNET_BUFFER_LIST
 ReceiverAllocateNetBufferList(
-    IN  PRECEIVER       Receiver,
-    IN  PMDL            Mdl,
-    IN  ULONG           Offset,
-    IN  ULONG           Length
+    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();
-
     NetBufferList = Receiver->GetList[Cpu];
 
     if (NetBufferList == NULL)
@@ -158,16 +93,16 @@ ReceiverAllocateNetBufferList(
     return NetBufferList;
 }        
 
-VOID
+static VOID
 ReceiverReleaseNetBufferList(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  BOOLEAN             Cache
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  BOOLEAN                 Cache
     )
 {
     if (Cache) {
-        PNET_BUFFER_LIST    Old;
-        PNET_BUFFER_LIST    New;
+        PNET_BUFFER_LIST        Old;
+        PNET_BUFFER_LIST        New;
 
         ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
@@ -182,72 +117,9 @@ ReceiverReleaseNetBufferList(
     }
 }
 
-static FORCEINLINE ULONG
-__ReceiverReturnNetBufferLists(
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  BOOLEAN             Cache
-    )
-{
-    PADAPTER                Adapter;
-    LIST_ENTRY              List;
-    ULONG                   Count;
-
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
-    InitializeListHead(&List);
-
-    Count = 0;
-    while (NetBufferList != NULL) {
-        PNET_BUFFER_LIST        Next;
-        PNET_BUFFER             NetBuffer;
-        PMDL                    Mdl;
-        PXENVIF_RECEIVER_PACKET Packet;
-
-        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
-        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
-
-        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
-        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
-
-        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
-
-        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
-
-        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
-
-        InsertTailList(&List, &Packet->ListEntry);
-
-        Count++;
-        NetBufferList = Next;
-    }
-
-    if (Count != 0)
-        XENVIF_VIF(ReceiverReturnPackets,
-                   &Adapter->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  PXENNET_RECEIVER                        Receiver,
     IN  PMDL                                    Mdl,
     IN  ULONG                                   Offset,
     IN  ULONG                                   Length,
@@ -255,11 +127,11 @@ ReceiverReceivePacket(
     IN  USHORT                                  TagControlInformation
     )
 {
-    PADAPTER                                    Adapter;
+    PXENNET_ADAPTER                             Adapter;
     PNET_BUFFER_LIST                            NetBufferList;
     NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    Adapter = Receiver->Adapter;
 
     NetBufferList = ReceiverAllocateNetBufferList(Receiver,
                                                   Mdl,
@@ -268,7 +140,7 @@ ReceiverReceivePacket(
     if (NetBufferList == NULL)
         goto fail1;
 
-    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
+    NetBufferList->SourceHandle = AdapterGetHandle(Adapter);
 
     csumInfo.Value = 0;
 
@@ -281,8 +153,8 @@ ReceiverReceivePacket(
     csumInfo.Receive.UdpChecksumSucceeded = Flags.UdpChecksumSucceeded;
     csumInfo.Receive.UdpChecksumFailed = Flags.UdpChecksumFailed;
 
-    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = (PVOID)(ULONG_PTR)csumInfo.Value;
-
+    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = 
+                                            (PVOID)(ULONG_PTR)csumInfo.Value;
     if (TagControlInformation != 0) {
         NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
 
@@ -306,20 +178,67 @@ fail1:
     return NULL;
 }
 
+static FORCEINLINE ULONG
+__ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  BOOLEAN                 Cache
+    )
+{
+    PXENNET_ADAPTER             Adapter;
+    LIST_ENTRY                  List;
+    ULONG                       Count;
+
+    Adapter = Receiver->Adapter;
+
+    InitializeListHead(&List);
+
+    Count = 0;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST        Next;
+        PNET_BUFFER             NetBuffer;
+        PMDL                    Mdl;
+        PXENVIF_RECEIVER_PACKET Packet;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
+
+        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
+
+        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
+
+        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
+
+        InsertTailList(&List, &Packet->ListEntry);
+
+        Count++;
+        NetBufferList = Next;
+    }
+
+    if (Count != 0) {
+        XENVIF_VIF(ReceiverReturnPackets,
+                   AdapterGetVifInterface(Adapter),
+                   &List);
+    }
+    return Count;
+}
+
 static VOID
 ReceiverPushPackets(
-    IN  PRECEIVER           Receiver,
+    IN  PXENNET_RECEIVER    Receiver,
     IN  PNET_BUFFER_LIST    NetBufferList,
     IN  ULONG               Count,
     IN  BOOLEAN             LowResources
     )
 {
-    PADAPTER                Adapter;
+    PXENNET_ADAPTER         Adapter;
     ULONG                   Flags;
     LONG                    InNDIS;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
-
+    Adapter = Receiver->Adapter;
     InNDIS = Receiver->InNDIS;
 
     Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
@@ -342,7 +261,7 @@ ReceiverPushPackets(
             break;
     }
 
-    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
+    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Adapter),
                                        NetBufferList,
                                        NDIS_DEFAULT_PORT_NUMBER,
                                        Count,
@@ -352,21 +271,34 @@ ReceiverPushPackets(
         (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
 }
 
-#define IN_NDIS_MAX 1024
+VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
+    )
+{
+    ULONG                   Count;
+
+    UNREFERENCED_PARAMETER(ReturnFlags);
+
+    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferLists, 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;
+    PXENNET_ADAPTER     Adapter;
     PNET_BUFFER_LIST    HeadNetBufferList;
     PNET_BUFFER_LIST    *TailNetBufferList;
     ULONG               Count;
     BOOLEAN             LowResources;
 
-    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    Adapter = Receiver->Adapter;
     LowResources = FALSE;
 
 again:
@@ -404,21 +336,26 @@ 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);
+                       AdapterGetVifInterface(Adapter),
+                       &PacketList);
         }
     }
 
@@ -434,3 +371,95 @@ again:
         goto again;
     }
 }
+
+PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER        Receiver
+    )
+{
+    return &Receiver->OffloadOptions;
+}
+
+NTSTATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_RECEIVER        *Receiver
+    )
+{
+    NTSTATUS                        status;
+    NET_BUFFER_LIST_POOL_PARAMETERS Pool;
+
+    status = STATUS_NO_MEMORY;
+    *Receiver = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_RECEIVER), RECEIVER_POOL_TAG);
+    if (*Receiver == NULL)
+        goto fail1;
+
+    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
+    (*Receiver)->Adapter = Adapter;
+
+    RtlZeroMemory(&Pool, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
+    Pool.Header.Type        = NDIS_OBJECT_TYPE_DEFAULT;
+    Pool.Header.Size        = sizeof(NET_BUFFER_LIST_POOL_PARAMETERS);
+    Pool.Header.Revision    = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    Pool.ProtocolId         = 0;
+    Pool.ContextSize        = 0;
+    Pool.fAllocateNetBuffer = TRUE;
+    Pool.PoolTag            = RECEIVER_POOL_TAG;
+
+    (*Receiver)->NetBufferListPool = NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
+                                                                   &Pool);
+    if ((*Receiver)->NetBufferListPool == NULL)
+        goto fail2;
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+    ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    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;
+
+    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
+}
+
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
index 1a58053..715f02e 100644
--- a/src/xennet/receiver.h
+++ b/src/xennet/receiver.h
@@ -29,49 +29,42 @@
  * 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;
+typedef struct _XENNET_RECEIVER     XENNET_RECEIVER, *PXENNET_RECEIVER;
 
-VOID
-ReceiverDebugDump (
-    IN PRECEIVER Receiver
-    );
+#include <vif_interface.h>
 
-VOID 
-ReceiverCleanup (
-    IN  PRECEIVER Receiver
+extern VOID
+ReceiverReturnNetBufferLists(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PNET_BUFFER_LIST        NetBufferLists,
+    IN  ULONG                   ReturnFlags
     );
 
-VOID
-ReceiverHandleNotification (
-    IN  PRECEIVER Receiver
+extern VOID
+ReceiverReceivePackets(
+    IN  PXENNET_RECEIVER        Receiver,
+    IN  PLIST_ENTRY             List
     );
 
-NDIS_STATUS
-ReceiverInitialize (
-    IN  PRECEIVER   Receiver
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+ReceiverOffloadOptions(
+    IN  PXENNET_RECEIVER        Receiver
     );
 
-VOID 
-ReceiverReturnNetBufferLists (
-    IN  PRECEIVER           Receiver,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  ULONG               ReturnFlags
+#include "adapter.h"
+extern NTSTATUS
+ReceiverInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_RECEIVER        *Receiver
     );
 
-VOID
-ReceiverWaitForPacketReturn(
-    IN  PRECEIVER   Receiver,
-    IN  BOOLEAN     Locked
+extern VOID
+ReceiverTeardown(
+    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..be07458 100644
--- a/src/xennet/transmitter.c
+++ b/src/xennet/transmitter.c
@@ -29,59 +29,18 @@
  * SUCH DAMAGE.
  */
 
-#include "common.h"
+#include <ndis.h>
+#include "transmitter.h"
+#include "adapter.h"
+#include "dbg_print.h"
+#include "assert.h"
 
-#pragma warning(disable:4711)
+struct _XENNET_TRANSMITTER {
+    PXENNET_ADAPTER             Adapter;
+    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
+};
 
-NDIS_STATUS
-TransmitterInitialize(
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
-    )
-{
-    Transmitter->Adapter = Adapter;
-
-    return NDIS_STATUS_SUCCESS;
-}
-
-VOID
-TransmitterEnable(
-    IN  PTRANSMITTER    Transmitter
-    )
-{
-    PADAPTER            Adapter = Transmitter->Adapter;
-
-    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
-                      &Adapter->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,
-                      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,
-                      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;
-    }
-}
+#define TRANSMITTER_POOL_TAG    'teNX'
 
 typedef struct _NET_BUFFER_LIST_RESERVED {
     LONG    Reference;
@@ -97,24 +56,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             NdisStatus
     )
 {
+    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
+
     ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_NOT_ACCEPTED;
+    if (NdisStatus == 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;
+    }
+    NET_BUFFER_LIST_STATUS(NetBufferList) = NdisStatus;
 
-    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+    NdisMSendNetBufferListsComplete(AdapterGetHandle(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                 NdisStatus
     )
 {
     while (Packet != NULL) {
@@ -135,21 +107,85 @@ TransmitterAbortPackets(
 
         ASSERT(ListReserved->Reference != 0);
         if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
+            TransmitterCompleteNetBufferList(Transmitter, NetBufferList, NdisStatus);
 
         Packet = Next;
     }
 }
+    
+static FORCEINLINE VOID
+__OffloadOptions(
+    IN  PNET_BUFFER_LIST            NetBufferList,
+    OUT PXENVIF_VIF_OFFLOAD_OPTIONS Offload,
+    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);
+
+    Offload->Value = 0;
+    *TagControlInformation = 0;
+    *MaximumSegmentSize = 0;
+
+    if (ChecksumInfo->Transmit.IsIPv4) {
+        if (ChecksumInfo->Transmit.IpHeaderChecksum)
+            Offload->OffloadIpVersion4HeaderChecksum = 1;
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            Offload->OffloadIpVersion4TcpChecksum = 1;
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            Offload->OffloadIpVersion4UdpChecksum = 1;
+    }
+
+    if (ChecksumInfo->Transmit.IsIPv6) {
+        if (ChecksumInfo->Transmit.TcpChecksum)
+            Offload->OffloadIpVersion6TcpChecksum = 1;
+        if (ChecksumInfo->Transmit.UdpChecksum)
+            Offload->OffloadIpVersion6UdpChecksum = 1;
+    }
+
+    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
+        Offload->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)
+            Offload->OffloadIpVersion4LargePacket = 1;
+        if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
+            Offload->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;
+    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
     PXENVIF_TRANSMITTER_PACKET  HeadPacket;
     PXENVIF_TRANSMITTER_PACKET  *TailPacket;
     KIRQL                       Irql;
@@ -158,21 +194,21 @@ TransmitterSendNetBufferLists(
 
     HeadPacket = NULL;
     TailPacket = &HeadPacket;
-
+ 
     if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
         ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
         NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
     } else {
         Irql = DISPATCH_LEVEL;
     }
-
+ 
     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;
+        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
+        USHORT                          TagControlInformation;
+        USHORT                          MaximumSegmentSize;
+        PNET_BUFFER                     NetBuffer;
 
         ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
         NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
@@ -180,12 +216,7 @@ TransmitterSendNetBufferLists(
         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);
+        __OffloadOptions(NetBufferList, &Options, &TagControlInformation, &MaximumSegmentSize);
 
         NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
         while (NetBuffer != NULL) {
@@ -199,50 +230,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   = Options.Value & Transmitter->OffloadOptions.Value;
+            Packet->Send.TagControlInformation  = TagControlInformation;
+            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
 
             ASSERT3P(Packet->Next, ==, NULL);
             *TailPacket = Packet;
@@ -258,65 +248,89 @@ TransmitterSendNetBufferLists(
         NTSTATUS    status; 
 
         status = XENVIF_VIF(TransmitterQueuePackets,
-                            &Adapter->VifInterface,
+                            AdapterGetVifInterface(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
+VOID
+TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     )
 {
-    PADAPTER                                            Adapter = Transmitter->Adapter;
-    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+    __TransmitterCompletePackets(Transmitter,
+                                 Packet,
+                                 NDIS_STATUS_SUCCESS);
+}
 
-    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter->Adapter);
 
-    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
-                                                                                             TcpLargeSendNetBufferListInfo);
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
-    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
-        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
 
-    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
+    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
+                      Vif,
+                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
+                      (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
+                      (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
+}
 
-    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
-                                    NetBufferList,
-                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
+PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    return &Transmitter->OffloadOptions;
 }
 
-VOID
-TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+NTSTATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_TRANSMITTER     *Transmitter
     )
 {
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
-        PNET_BUFFER_RESERVED        Reserved;
-        PNET_BUFFER_LIST            NetBufferList;
-        PNET_BUFFER_LIST_RESERVED   ListReserved;
+    NTSTATUS            status;
 
-        Next = Packet->Next;
-        Packet->Next = NULL;
+    status = STATUS_NO_MEMORY;
+    *Transmitter = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENNET_TRANSMITTER), TRANSMITTER_POOL_TAG);
+    if (*Transmitter == NULL)
+        goto fail1;
 
-        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
+    (*Transmitter)->Adapter = Adapter;
 
-        NetBufferList = Reserved->NetBufferList;
-        ASSERT(NetBufferList != NULL);
+    return STATUS_SUCCESS;
 
-        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 
-        ASSERT(ListReserved->Reference != 0);
-        if (InterlockedDecrement(&ListReserved->Reference) == 0)
-            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
+}
 
-        Packet = Next;
-    }
+VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER     Transmitter
+    )
+{
+    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
 }
+
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
index 8dc7e8d..f99ffd3 100644
--- a/src/xennet/transmitter.h
+++ b/src/xennet/transmitter.h
@@ -29,47 +29,48 @@
  * SUCH DAMAGE.
  */
 
-#pragma once
+#ifndef _XENNET_TRANSMITTER_H_
+#define _XENNET_TRANSMITTER_H_
 
-typedef struct _TRANSMITTER {
-    PADAPTER                    Adapter;
-    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
-} TRANSMITTER, *PTRANSMITTER;
+typedef struct _XENNET_TRANSMITTER  XENNET_TRANSMITTER, *PXENNET_TRANSMITTER;
 
-VOID 
-TransmitterCleanup (
-    IN OUT PTRANSMITTER* Transmitter
+#include <vif_interface.h>
+
+extern VOID
+TransmitterSendNetBufferLists(
+    IN  PXENNET_TRANSMITTER     Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
     );
 
-NDIS_STATUS
-TransmitterInitialize (
-    IN  PTRANSMITTER    Transmitter,
-    IN  PADAPTER        Adapter
+extern VOID
+TransmitterCompletePackets(
+    IN  PXENNET_TRANSMITTER         Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
     );
 
-VOID
-TransmitterEnable (
-    IN  PTRANSMITTER    Transmitter
+extern VOID
+TransmitterEnable(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-VOID 
-TransmitterDelete (
-    IN OUT PTRANSMITTER* Transmitter
+extern PXENVIF_VIF_OFFLOAD_OPTIONS
+TransmitterOffloadOptions(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-VOID
-TransmitterSendNetBufferLists (
-    IN  PTRANSMITTER        Transmitter,
-    IN  PNET_BUFFER_LIST    NetBufferList,
-    IN  NDIS_PORT_NUMBER    PortNumber,
-    IN  ULONG               SendFlags
+#include "adapter.h"
+extern NTSTATUS
+TransmitterInitialize(
+    IN  PXENNET_ADAPTER         Adapter,
+    OUT PXENNET_TRANSMITTER     *Transmitter
     );
 
-VOID
-TransmitterCompletePackets(
-    IN  PTRANSMITTER                Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+extern VOID
+TransmitterTeardown(
+    IN  PXENNET_TRANSMITTER     Transmitter
     );
 
-void TransmitterPause(PTRANSMITTER Transmitter);
-void TransmitterUnpause(PTRANSMITTER Transmitter);
+#endif // _XENNET_TRANSMITTER_H_
+
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index db07e9b..4b6e780 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -84,9 +84,8 @@
 	</ItemGroup>
 	<ItemGroup>
 		<ClCompile Include="../../src/xennet/registry.c" />
+		<ClCompile Include="../../src/xennet/driver.c" />
 		<ClCompile Include="../../src/xennet/adapter.c" />
-		<ClCompile Include="../../src/xennet/main.c" />
-		<ClCompile Include="../../src/xennet/miniport.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 908bc2d..d890878 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -115,9 +115,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="../../src/xennet/registry.c" />
+    <ClCompile Include="../../src/xennet/driver.c" />
     <ClCompile Include="../../src/xennet/adapter.c" />
-    <ClCompile Include="../../src/xennet/main.c" />
-    <ClCompile Include="../../src/xennet/miniport.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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UA-IX; Wed, 12 Nov 2014 16:39:21 +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 1Xoawx-0003Tt-L1
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:19 +0000
Received: from [193.109.254.147] by server-10.bemta-14.messagelabs.com id
	44/84-02696-63D83645; Wed, 12 Nov 2014 16:39:18 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5003 invoked from network); 12 Nov 2014 16:39:18 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032188"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:57 +0000
Message-ID: <1415810347-7152-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 00/10] Add multi-queue 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

This patch series implements multi-queue support.
A queue will be created per vCPU, and up to min(vCPUs, "multi-queue-max-queues") queues
will be used by default. If "multi-queue-max-queues" is not present, only 1 queue is used
which has the same behaviour as the previous protocol.
Note: without patches to xennet, the packet steering algorithm will deliver all packets to 
  queue 0

1: Add a new transmitter packet to the vif interface header and use this structure
   internally.
2: Bump the vif interface version to 2, add new calls and macros to access the extended
    interface methods.
3-9: Implement multi-queue behaviour, steering packets based on a supplied hash value
10: Reduce event channel usage by not creating event channels that would be unused

Owen Smith (10):
  Rework transmitter packet code to use an internal cache of objects
  Add VIF interface version 2
  Store maximum number of queues allowed
  Create a transmitter/receiver ring per max-queue
  Split notifier into a list of queues.
  Dont call through to inactive queues
  Write queue values under <frontend>/queue-<id> and "multi-queue-num-queues"
  Steer transmitter packets to queues
  Pin queue's DPC to appropriate vCPU when using multiple queues
  Only call EVTCHN:Open for rx and tx or single event channel, based on 
       "feature-split-event-channels"

 include/vif_interface.h  | 123 ++++++--
 src/xenvif/driver.c      |  36 +++
 src/xenvif/driver.h      |   5 +
 src/xenvif/frontend.c    |  91 +++++-
 src/xenvif/frontend.h    |  13 +
 src/xenvif/notifier.c    | 722 +++++++++++++++++++++++++++++++++-------------
 src/xenvif/notifier.h    |  12 +-
 src/xenvif/receiver.c    |  42 ++-
 src/xenvif/receiver.h    |   4 +-
 src/xenvif/transmitter.c | 724 ++++++++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h |  27 +-
 src/xenvif/vif.c         | 157 +++++++++-
 src/xenvif/vif.h         |  15 +-
 13 files changed, 1555 insertions(+), 416 deletions(-)

-- 
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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UA-IX; Wed, 12 Nov 2014 16:39:21 +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 1Xoawx-0003Tt-L1
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:19 +0000
Received: from [193.109.254.147] by server-10.bemta-14.messagelabs.com id
	44/84-02696-63D83645; Wed, 12 Nov 2014 16:39:18 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5003 invoked from network); 12 Nov 2014 16:39:18 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032188"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:57 +0000
Message-ID: <1415810347-7152-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 00/10] Add multi-queue 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

This patch series implements multi-queue support.
A queue will be created per vCPU, and up to min(vCPUs, "multi-queue-max-queues") queues
will be used by default. If "multi-queue-max-queues" is not present, only 1 queue is used
which has the same behaviour as the previous protocol.
Note: without patches to xennet, the packet steering algorithm will deliver all packets to 
  queue 0

1: Add a new transmitter packet to the vif interface header and use this structure
   internally.
2: Bump the vif interface version to 2, add new calls and macros to access the extended
    interface methods.
3-9: Implement multi-queue behaviour, steering packets based on a supplied hash value
10: Reduce event channel usage by not creating event channels that would be unused

Owen Smith (10):
  Rework transmitter packet code to use an internal cache of objects
  Add VIF interface version 2
  Store maximum number of queues allowed
  Create a transmitter/receiver ring per max-queue
  Split notifier into a list of queues.
  Dont call through to inactive queues
  Write queue values under <frontend>/queue-<id> and "multi-queue-num-queues"
  Steer transmitter packets to queues
  Pin queue's DPC to appropriate vCPU when using multiple queues
  Only call EVTCHN:Open for rx and tx or single event channel, based on 
       "feature-split-event-channels"

 include/vif_interface.h  | 123 ++++++--
 src/xenvif/driver.c      |  36 +++
 src/xenvif/driver.h      |   5 +
 src/xenvif/frontend.c    |  91 +++++-
 src/xenvif/frontend.h    |  13 +
 src/xenvif/notifier.c    | 722 +++++++++++++++++++++++++++++++++-------------
 src/xenvif/notifier.h    |  12 +-
 src/xenvif/receiver.c    |  42 ++-
 src/xenvif/receiver.h    |   4 +-
 src/xenvif/transmitter.c | 724 ++++++++++++++++++++++++++++++++++++-----------
 src/xenvif/transmitter.h |  27 +-
 src/xenvif/vif.c         | 157 +++++++++-
 src/xenvif/vif.h         |  15 +-
 13 files changed, 1555 insertions(+), 416 deletions(-)

-- 
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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UE-JV; Wed, 12 Nov 2014 16:39:21 +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 1Xoawy-0003Tu-6c
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:20 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	A2/84-02953-73D83645; Wed, 12 Nov 2014 16:39:19 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5053 invoked from network); 12 Nov 2014 16:39:18 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032189"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:00 +0000
Message-ID: <1415810347-7152-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 03/10] Store maximum number of queues allowed
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

Read "MultiQueueMaxQueues" from parameters key to determine in-guest
limit to multi-queue support.
The maximum number of queues used will be the smallest of;
  "HKLM/CurrentControlSet/Services/XENVIF/Parameters/MultiQueueMaxQueues",
  "device/vif/<number>/multi-queue-max-queues" and 
  number of guest vCPUs

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/driver.c | 36 ++++++++++++++++++++++++++++++++++++
 src/xenvif/driver.h |  5 +++++
 2 files changed, 41 insertions(+)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 6f81620..b1fbb79 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               QueueMax;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -123,6 +124,33 @@ DriverGetAddressesKey(
     return __DriverGetAddressesKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetQueueMax(
+    IN  ULONG       Count
+    )
+{
+    ULONG   Processors;
+
+    Processors = KeQueryActiveProcessorCount(NULL);
+    Driver.QueueMax = Count > Processors ? Processors : Count;
+}
+
+static FORCEINLINE ULONG
+__DriverGetQueueMax(
+    VOID
+    )
+{
+    return Driver.QueueMax;
+}
+
+ULONG
+DriverGetQueueMax(
+    VOID
+    )
+{
+    return __DriverGetQueueMax();
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -254,6 +282,7 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
+    ULONG               Queues;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
@@ -304,6 +333,13 @@ DriverEntry(
 
     __DriverSetAddressesKey(AddressesKey);
 
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "MultiQueueMaxQueues",
+                                     &Queues);
+    if (!NT_SUCCESS(status))
+        Queues = MAXIMUM_PROCESSORS;
+    __DriverSetQueueMax(Queues);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index cdef7d1..9375930 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,6 +52,11 @@ DriverGetAliasesKey(
     VOID
     );
 
+extern ULONG
+DriverGetQueueMax(
+    VOID
+    );
+
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
-- 
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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UE-JV; Wed, 12 Nov 2014 16:39:21 +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 1Xoawy-0003Tu-6c
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:20 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	A2/84-02953-73D83645; Wed, 12 Nov 2014 16:39:19 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5053 invoked from network); 12 Nov 2014 16:39:18 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:18 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032189"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:00 +0000
Message-ID: <1415810347-7152-4-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA1
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 03/10] Store maximum number of queues allowed
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

Read "MultiQueueMaxQueues" from parameters key to determine in-guest
limit to multi-queue support.
The maximum number of queues used will be the smallest of;
  "HKLM/CurrentControlSet/Services/XENVIF/Parameters/MultiQueueMaxQueues",
  "device/vif/<number>/multi-queue-max-queues" and 
  number of guest vCPUs

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/driver.c | 36 ++++++++++++++++++++++++++++++++++++
 src/xenvif/driver.h |  5 +++++
 2 files changed, 41 insertions(+)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 6f81620..b1fbb79 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               QueueMax;
 } XENVIF_DRIVER, *PXENVIF_DRIVER;
 
 static XENVIF_DRIVER    Driver;
@@ -123,6 +124,33 @@ DriverGetAddressesKey(
     return __DriverGetAddressesKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetQueueMax(
+    IN  ULONG       Count
+    )
+{
+    ULONG   Processors;
+
+    Processors = KeQueryActiveProcessorCount(NULL);
+    Driver.QueueMax = Count > Processors ? Processors : Count;
+}
+
+static FORCEINLINE ULONG
+__DriverGetQueueMax(
+    VOID
+    )
+{
+    return Driver.QueueMax;
+}
+
+ULONG
+DriverGetQueueMax(
+    VOID
+    )
+{
+    return __DriverGetQueueMax();
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -254,6 +282,7 @@ DriverEntry(
     HANDLE              ParametersKey;
     HANDLE              AddressesKey;
     ULONG               Index;
+    ULONG               Queues;
     NTSTATUS            status;
 
     ASSERT3P(__DriverGetDriverObject(), ==, NULL);
@@ -304,6 +333,13 @@ DriverEntry(
 
     __DriverSetAddressesKey(AddressesKey);
 
+    status = RegistryQueryDwordValue(ParametersKey,
+                                     "MultiQueueMaxQueues",
+                                     &Queues);
+    if (!NT_SUCCESS(status))
+        Queues = MAXIMUM_PROCESSORS;
+    __DriverSetQueueMax(Queues);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index cdef7d1..9375930 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,6 +52,11 @@ DriverGetAliasesKey(
     VOID
     );
 
+extern ULONG
+DriverGetQueueMax(
+    VOID
+    );
+
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
-- 
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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UV-Kw; Wed, 12 Nov 2014 16:39:21 +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 1Xoawz-0003U3-1H
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:21 +0000
Received: from [193.109.254.147] by server-6.bemta-14.messagelabs.com id
	CA/D4-03145-83D83645; Wed, 12 Nov 2014 16:39:20 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5133 invoked from network); 12 Nov 2014 16:39:19 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032193"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:05 +0000
Message-ID: <1415810347-7152-9-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 08/10] Stear transmitter packets to 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/transmitter.c | 109 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 92 insertions(+), 17 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index f1a3e9e..38e9c62 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3782,6 +3782,96 @@ fail1:
     return status;
 }
 
+static FORCEINLINE ULONG
+__TransmitterGetQueue(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    PXENVIF_FRONTEND    Frontend;
+
+    Frontend = Transmitter->Frontend;
+
+    // simplistic mod of hash value
+    // this should become a lookup operation using a shared table
+    return (ULONG)(Packet->HashValue % FrontendGetQueueCount(Frontend));
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_RING
+__TransmitterGetRing(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  ULONG                           Index
+    )
+{
+    PLIST_ENTRY     ListEntry;
+
+    ASSERT3U(Index, <, FrontendGetQueueCount(Transmitter->Frontend));
+
+    for (ListEntry = Transmitter->List.Flink;
+         ListEntry != &Transmitter->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_TRANSMITTER_RING    Ring;
+
+        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
+
+        return Ring;
+    }
+
+    // return queue-0
+    ListEntry = Transmitter->List.Flink;
+    return CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+}
+
+static FORCEINLINE VOID
+__TransmitterQueuePackets(
+    IN  PXENVIF_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
+    )
+{
+    PXENVIF_FRONTEND            Frontend;
+    PLIST_ENTRY                 ListEntry;
+    PXENVIF_TRANSMITTER_RING    Ring;
+
+    Frontend = Transmitter->Frontend;
+
+    if (FrontendGetQueueCount(Frontend) == 1) {
+        ListEntry = Transmitter->List.Flink;
+        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+
+        __TransmitterRingQueuePackets(Ring, List);
+    } else {
+        while (!IsListEmpty(List)) {
+            LIST_ENTRY                      SubList;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+            ULONG                           Queue;
+
+            InitializeListHead(&SubList);
+
+            Packet = CONTAINING_RECORD(List->Flink, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+            Queue = __TransmitterGetQueue(Transmitter, Packet);
+
+            ListEntry = RemoveHeadList(List);
+            ASSERT3U(ListEntry, !=, List);
+            InsertTailList(&SubList, ListEntry);
+
+            while (!IsListEmpty(List)) {
+                Packet = CONTAINING_RECORD(List->Flink, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+                if (__TransmitterGetQueue(Transmitter, Packet) != Queue)
+                    break;
+
+                ListEntry = RemoveHeadList(List);
+                ASSERT3U(ListEntry, !=, List);
+                InsertTailList(&SubList, ListEntry);
+            }
+
+            Ring = __TransmitterGetRing(Transmitter, Queue);
+            __TransmitterRingQueuePackets(Ring, &SubList);
+        }
+    }
+}
+
 VOID
 TransmitterQueuePacketsV1(
     IN  PXENVIF_TRANSMITTER             Transmitter,
@@ -3798,8 +3888,6 @@ TransmitterQueuePacketsV1(
          NULL)
 
     LIST_ENTRY                      List;
-    PLIST_ENTRY                     ListEntry;
-    PXENVIF_TRANSMITTER_RING        Ring;
 
     InitializeListHead(&List);
     while (HeadPacket != NULL) {
@@ -3828,12 +3916,7 @@ TransmitterQueuePacketsV1(
         HeadPacket = HeadPacket->Next;
     }
     
-    // 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);
-
-    __TransmitterRingQueuePackets(Ring, &List);
+    __TransmitterQueuePackets(Transmitter, &List);
 
     // if HeadPacket != NULL, errors occured and need returning
     if (HeadPacket != NULL) {
@@ -3861,15 +3944,7 @@ TransmitterQueuePacketsV2(
     IN  PLIST_ENTRY         List
     )
 {
-    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);
-
-    __TransmitterRingQueuePackets(Ring, List);
+    __TransmitterQueuePackets(Transmitter, List);
 }
 
 static BOOLEAN
-- 
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 Wed Nov 12 16:39:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoawz-0003UV-Kw; Wed, 12 Nov 2014 16:39:21 +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 1Xoawz-0003U3-1H
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:21 +0000
Received: from [193.109.254.147] by server-6.bemta-14.messagelabs.com id
	CA/D4-03145-83D83645; Wed, 12 Nov 2014 16:39:20 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5133 invoked from network); 12 Nov 2014 16:39:19 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032193"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:05 +0000
Message-ID: <1415810347-7152-9-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 08/10] Stear transmitter packets to 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/transmitter.c | 109 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 92 insertions(+), 17 deletions(-)

diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index f1a3e9e..38e9c62 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3782,6 +3782,96 @@ fail1:
     return status;
 }
 
+static FORCEINLINE ULONG
+__TransmitterGetQueue(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
+    )
+{
+    PXENVIF_FRONTEND    Frontend;
+
+    Frontend = Transmitter->Frontend;
+
+    // simplistic mod of hash value
+    // this should become a lookup operation using a shared table
+    return (ULONG)(Packet->HashValue % FrontendGetQueueCount(Frontend));
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_RING
+__TransmitterGetRing(
+    IN  PXENVIF_TRANSMITTER             Transmitter,
+    IN  ULONG                           Index
+    )
+{
+    PLIST_ENTRY     ListEntry;
+
+    ASSERT3U(Index, <, FrontendGetQueueCount(Transmitter->Frontend));
+
+    for (ListEntry = Transmitter->List.Flink;
+         ListEntry != &Transmitter->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_TRANSMITTER_RING    Ring;
+
+        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
+
+        return Ring;
+    }
+
+    // return queue-0
+    ListEntry = Transmitter->List.Flink;
+    return CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+}
+
+static FORCEINLINE VOID
+__TransmitterQueuePackets(
+    IN  PXENVIF_TRANSMITTER     Transmitter,
+    IN  PLIST_ENTRY             List
+    )
+{
+    PXENVIF_FRONTEND            Frontend;
+    PLIST_ENTRY                 ListEntry;
+    PXENVIF_TRANSMITTER_RING    Ring;
+
+    Frontend = Transmitter->Frontend;
+
+    if (FrontendGetQueueCount(Frontend) == 1) {
+        ListEntry = Transmitter->List.Flink;
+        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+
+        __TransmitterRingQueuePackets(Ring, List);
+    } else {
+        while (!IsListEmpty(List)) {
+            LIST_ENTRY                      SubList;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+            ULONG                           Queue;
+
+            InitializeListHead(&SubList);
+
+            Packet = CONTAINING_RECORD(List->Flink, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+            Queue = __TransmitterGetQueue(Transmitter, Packet);
+
+            ListEntry = RemoveHeadList(List);
+            ASSERT3U(ListEntry, !=, List);
+            InsertTailList(&SubList, ListEntry);
+
+            while (!IsListEmpty(List)) {
+                Packet = CONTAINING_RECORD(List->Flink, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+                if (__TransmitterGetQueue(Transmitter, Packet) != Queue)
+                    break;
+
+                ListEntry = RemoveHeadList(List);
+                ASSERT3U(ListEntry, !=, List);
+                InsertTailList(&SubList, ListEntry);
+            }
+
+            Ring = __TransmitterGetRing(Transmitter, Queue);
+            __TransmitterRingQueuePackets(Ring, &SubList);
+        }
+    }
+}
+
 VOID
 TransmitterQueuePacketsV1(
     IN  PXENVIF_TRANSMITTER             Transmitter,
@@ -3798,8 +3888,6 @@ TransmitterQueuePacketsV1(
          NULL)
 
     LIST_ENTRY                      List;
-    PLIST_ENTRY                     ListEntry;
-    PXENVIF_TRANSMITTER_RING        Ring;
 
     InitializeListHead(&List);
     while (HeadPacket != NULL) {
@@ -3828,12 +3916,7 @@ TransmitterQueuePacketsV1(
         HeadPacket = HeadPacket->Next;
     }
     
-    // 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);
-
-    __TransmitterRingQueuePackets(Ring, &List);
+    __TransmitterQueuePackets(Transmitter, &List);
 
     // if HeadPacket != NULL, errors occured and need returning
     if (HeadPacket != NULL) {
@@ -3861,15 +3944,7 @@ TransmitterQueuePacketsV2(
     IN  PLIST_ENTRY         List
     )
 {
-    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);
-
-    __TransmitterRingQueuePackets(Ring, List);
+    __TransmitterQueuePackets(Transmitter, List);
 }
 
 static BOOLEAN
-- 
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 Wed Nov 12 16:39:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:22 +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 1Xoax0-0003VJ-M4; Wed, 12 Nov 2014 16:39:22 +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 1Xoawz-0003U9-Tt
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	24/45-22777-93D83645; Wed, 12 Nov 2014 16:39:21 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415810357!10931411!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 11681 invoked from network); 12 Nov 2014 16:39:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032196"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:06 +0000
Message-ID: <1415810347-7152-10-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 09/10] Pin queue's DPC to appropriate vCPU
	when using 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/notifier.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 573ffaa..93f2395 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -295,6 +295,11 @@ NotifierQueueConnect(
         PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
         BOOLEAN             Pending;
 
+        if (FrontendGetQueueCount(Frontend) > 1) {
+            KeSetTargetProcessorDpc(&Queue->Dpc[Index],
+                                    (CCHAR)Queue->Index);
+        }
+
         Queue->Channel[Index] = XENBUS_EVTCHN(Open,
                                               &Notifier->EvtchnInterface,
                                               XENBUS_EVTCHN_TYPE_UNBOUND,
-- 
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 Wed Nov 12 16:39:22 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:22 +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 1Xoax0-0003VJ-M4; Wed, 12 Nov 2014 16:39:22 +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 1Xoawz-0003U9-Tt
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	24/45-22777-93D83645; Wed, 12 Nov 2014 16:39:21 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415810357!10931411!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 11681 invoked from network); 12 Nov 2014 16:39:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032196"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:06 +0000
Message-ID: <1415810347-7152-10-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 09/10] Pin queue's DPC to appropriate vCPU
	when using 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/notifier.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 573ffaa..93f2395 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -295,6 +295,11 @@ NotifierQueueConnect(
         PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
         BOOLEAN             Pending;
 
+        if (FrontendGetQueueCount(Frontend) > 1) {
+            KeSetTargetProcessorDpc(&Queue->Dpc[Index],
+                                    (CCHAR)Queue->Index);
+        }
+
         Queue->Channel[Index] = XENBUS_EVTCHN(Open,
                                               &Notifier->EvtchnInterface,
                                               XENBUS_EVTCHN_TYPE_UNBOUND,
-- 
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 Wed Nov 12 16:39:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax1-0003Vn-N5; Wed, 12 Nov 2014 16:39:23 +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 1Xoax0-0003U8-Is
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [193.109.254.147] by server-14.bemta-14.messagelabs.com id
	43/3C-02698-93D83645; Wed, 12 Nov 2014 16:39:21 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5408 invoked from network); 12 Nov 2014 16:39:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032195"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:01 +0000
Message-ID: <1415810347-7152-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 04/10] Create a transmitter/receiver ring per
	max-queue
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

Reads "multi-queue-max-queues" from xenstore for frontend to report.
Creates a transmitter and receiver ring per queue (queues above 0 are not used)

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c    | 57 ++++++++++++++++++++++++++++++++++++++----------
 src/xenvif/frontend.h    |  5 +++++
 src/xenvif/receiver.c    |  3 +--
 src/xenvif/receiver.h    |  1 -
 src/xenvif/transmitter.c |  3 +--
 src/xenvif/transmitter.h |  1 -
 6 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 305faaf..9a6cbde 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -64,6 +64,7 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
+    ULONG                       MultiQueueCount;
 
     PXENVIF_GRANTER             Granter;
     PXENVIF_NOTIFIER            Notifier;
@@ -203,6 +204,22 @@ FrontendGetBackendDomain(
     return __FrontendGetBackendDomain(Frontend);
 }
 
+static FORCEINLINE ULONG
+__FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->MultiQueueCount;
+}
+
+ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetQueueCount(Frontend);
+}
+
 #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
 static FORCEINLINE _Type                                \
 __FrontendGet ## _Function(                             \
@@ -1285,6 +1302,7 @@ __FrontendConnect(
     PCHAR                   Path = __FrontendGetBackendPath(Frontend);
     XenbusState             State;
     ULONG                   Attempt;
+    PCHAR                   Buffer;
     NTSTATUS                status;
 
     Trace("====>\n");
@@ -1302,6 +1320,21 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_STORE(Read,
+                          &Frontend->StoreInterface,
+                          NULL,
+                          __FrontendGetBackendPath(Frontend),
+                          "multi-queue-max-queues",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Frontend->MultiQueueCount = (ULONG)strtol(Buffer, NULL, 10);
+        XENBUS_STORE(Free,
+                     &Frontend->StoreInterface,
+                     Buffer);
+    } else {
+        Frontend->MultiQueueCount = 1;
+    }
+
     status = GranterConnect(__FrontendGetGranter(Frontend));
     if (!NT_SUCCESS(status))
         goto fail3;
@@ -1458,6 +1491,8 @@ __FrontendDisconnect(
     MacDisconnect(__FrontendGetMac(Frontend));
     GranterDisconnect(__FrontendGetGranter(Frontend));
 
+    Frontend->MultiQueueCount = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Frontend->DebugInterface,
                  Frontend->DebugCallback);
@@ -1894,19 +1929,19 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
+    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
+    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
+    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
         goto fail9;
 
-    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
+    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
         goto fail10;
 
@@ -1944,14 +1979,14 @@ fail10:
 fail9:
     Error("fail9\n");
 
-    MacTeardown(__FrontendGetMac(*Frontend));
-    (*Frontend)->Mac = NULL;
+    NotifierTeardown(__FrontendGetNotifier(*Frontend));
+    (*Frontend)->Notifier = NULL;
 
 fail8:
     Error("fail8\n");
 
-    NotifierTeardown(__FrontendGetNotifier(*Frontend));
-    (*Frontend)->Notifier = NULL;
+    MacTeardown(__FrontendGetMac(*Frontend));
+    (*Frontend)->Mac = NULL;
 
 fail7:
     Error("fail7\n");
@@ -2040,12 +2075,12 @@ FrontendTeardown(
     ReceiverTeardown(__FrontendGetReceiver(Frontend));
     Frontend->Receiver = NULL;
 
-    MacTeardown(__FrontendGetMac(Frontend));
-    Frontend->Mac = NULL;
-
     NotifierTeardown(__FrontendGetNotifier(Frontend));
     Frontend->Notifier = NULL;
 
+    MacTeardown(__FrontendGetMac(Frontend));
+    Frontend->Mac = NULL;
+
     GranterTeardown(__FrontendGetGranter(Frontend));
     Frontend->Granter = NULL;
 
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 60c085a..20cd390 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -112,6 +112,11 @@ FrontendGetBackendDomain(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
+extern ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
 #include "granter.h"
 
 extern PXENVIF_GRANTER
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 88ee07c..626feed 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2298,7 +2298,6 @@ ReceiverDebugCallback(
 NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     )
 {
@@ -2385,7 +2384,7 @@ ReceiverInitialize(
         goto fail2;
 
     Index = 0;
-    while (Index < Count) {
+    while (Index < DriverGetQueueMax()) {
         PXENVIF_RECEIVER_RING   Ring;
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 0497c5b..8009858 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 6fd542e..bea46f1 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3308,7 +3308,6 @@ TransmitterDebugCallback(
 NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     )
 {
@@ -3391,7 +3390,7 @@ TransmitterInitialize(
         goto fail4;
 
     Index = 0;
-    while (Index < Count) {
+    while (Index < DriverGetQueueMax()) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index c359c20..7e10603 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 Wed Nov 12 16:39:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax1-0003Vn-N5; Wed, 12 Nov 2014 16:39:23 +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 1Xoax0-0003U8-Is
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [193.109.254.147] by server-14.bemta-14.messagelabs.com id
	43/3C-02698-93D83645; Wed, 12 Nov 2014 16:39:21 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!4
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5408 invoked from network); 12 Nov 2014 16:39:20 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:20 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032195"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:01 +0000
Message-ID: <1415810347-7152-5-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 04/10] Create a transmitter/receiver ring per
	max-queue
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

Reads "multi-queue-max-queues" from xenstore for frontend to report.
Creates a transmitter and receiver ring per queue (queues above 0 are not used)

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c    | 57 ++++++++++++++++++++++++++++++++++++++----------
 src/xenvif/frontend.h    |  5 +++++
 src/xenvif/receiver.c    |  3 +--
 src/xenvif/receiver.h    |  1 -
 src/xenvif/transmitter.c |  3 +--
 src/xenvif/transmitter.h |  1 -
 6 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 305faaf..9a6cbde 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -64,6 +64,7 @@ struct _XENVIF_FRONTEND {
 
     PCHAR                       BackendPath;
     USHORT                      BackendDomain;
+    ULONG                       MultiQueueCount;
 
     PXENVIF_GRANTER             Granter;
     PXENVIF_NOTIFIER            Notifier;
@@ -203,6 +204,22 @@ FrontendGetBackendDomain(
     return __FrontendGetBackendDomain(Frontend);
 }
 
+static FORCEINLINE ULONG
+__FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return Frontend->MultiQueueCount;
+}
+
+ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    )
+{
+    return __FrontendGetQueueCount(Frontend);
+}
+
 #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
 static FORCEINLINE _Type                                \
 __FrontendGet ## _Function(                             \
@@ -1285,6 +1302,7 @@ __FrontendConnect(
     PCHAR                   Path = __FrontendGetBackendPath(Frontend);
     XenbusState             State;
     ULONG                   Attempt;
+    PCHAR                   Buffer;
     NTSTATUS                status;
 
     Trace("====>\n");
@@ -1302,6 +1320,21 @@ __FrontendConnect(
     if (!NT_SUCCESS(status))
         goto fail2;
 
+    status = XENBUS_STORE(Read,
+                          &Frontend->StoreInterface,
+                          NULL,
+                          __FrontendGetBackendPath(Frontend),
+                          "multi-queue-max-queues",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Frontend->MultiQueueCount = (ULONG)strtol(Buffer, NULL, 10);
+        XENBUS_STORE(Free,
+                     &Frontend->StoreInterface,
+                     Buffer);
+    } else {
+        Frontend->MultiQueueCount = 1;
+    }
+
     status = GranterConnect(__FrontendGetGranter(Frontend));
     if (!NT_SUCCESS(status))
         goto fail3;
@@ -1458,6 +1491,8 @@ __FrontendDisconnect(
     MacDisconnect(__FrontendGetMac(Frontend));
     GranterDisconnect(__FrontendGetGranter(Frontend));
 
+    Frontend->MultiQueueCount = 0;
+
     XENBUS_DEBUG(Deregister,
                  &Frontend->DebugInterface,
                  Frontend->DebugCallback);
@@ -1894,19 +1929,19 @@ FrontendInitialize(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
+    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
+    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
+    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
     if (!NT_SUCCESS(status))
         goto fail9;
 
-    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
+    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
     if (!NT_SUCCESS(status))
         goto fail10;
 
@@ -1944,14 +1979,14 @@ fail10:
 fail9:
     Error("fail9\n");
 
-    MacTeardown(__FrontendGetMac(*Frontend));
-    (*Frontend)->Mac = NULL;
+    NotifierTeardown(__FrontendGetNotifier(*Frontend));
+    (*Frontend)->Notifier = NULL;
 
 fail8:
     Error("fail8\n");
 
-    NotifierTeardown(__FrontendGetNotifier(*Frontend));
-    (*Frontend)->Notifier = NULL;
+    MacTeardown(__FrontendGetMac(*Frontend));
+    (*Frontend)->Mac = NULL;
 
 fail7:
     Error("fail7\n");
@@ -2040,12 +2075,12 @@ FrontendTeardown(
     ReceiverTeardown(__FrontendGetReceiver(Frontend));
     Frontend->Receiver = NULL;
 
-    MacTeardown(__FrontendGetMac(Frontend));
-    Frontend->Mac = NULL;
-
     NotifierTeardown(__FrontendGetNotifier(Frontend));
     Frontend->Notifier = NULL;
 
+    MacTeardown(__FrontendGetMac(Frontend));
+    Frontend->Mac = NULL;
+
     GranterTeardown(__FrontendGetGranter(Frontend));
     Frontend->Granter = NULL;
 
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 60c085a..20cd390 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -112,6 +112,11 @@ FrontendGetBackendDomain(
     IN  PXENVIF_FRONTEND    Frontend
     );
 
+extern ULONG
+FrontendGetQueueCount(
+    IN  PXENVIF_FRONTEND    Frontend
+    );
+
 #include "granter.h"
 
 extern PXENVIF_GRANTER
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 88ee07c..626feed 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2298,7 +2298,6 @@ ReceiverDebugCallback(
 NTSTATUS
 ReceiverInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_RECEIVER    *Receiver
     )
 {
@@ -2385,7 +2384,7 @@ ReceiverInitialize(
         goto fail2;
 
     Index = 0;
-    while (Index < Count) {
+    while (Index < DriverGetQueueMax()) {
         PXENVIF_RECEIVER_RING   Ring;
 
         status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 0497c5b..8009858 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 6fd542e..bea46f1 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3308,7 +3308,6 @@ TransmitterDebugCallback(
 NTSTATUS
 TransmitterInitialize(
     IN  PXENVIF_FRONTEND    Frontend,
-    IN  ULONG               Count,
     OUT PXENVIF_TRANSMITTER *Transmitter
     )
 {
@@ -3391,7 +3390,7 @@ TransmitterInitialize(
         goto fail4;
 
     Index = 0;
-    while (Index < Count) {
+    while (Index < DriverGetQueueMax()) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index c359c20..7e10603 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 Wed Nov 12 16:39:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax1-0003Vu-O9; Wed, 12 Nov 2014 16:39:23 +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 1Xoax0-0003VF-Lr
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id
	8C/5C-08051-A3D83645; Wed, 12 Nov 2014 16:39:22 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!5
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5536 invoked from network); 12 Nov 2014 16:39:21 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:21 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032197"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:03 +0000
Message-ID: <1415810347-7152-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 06/10] Dont call through to inactive 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

Queues where Index >= QueueCount are inactive, and should not
Connect, Disconnect, Enable, Disable or write to the store.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  2 ++
 src/xenvif/receiver.c    | 22 ++++++++++++++++++++++
 src/xenvif/transmitter.c | 26 ++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 4ce61c4..83e3846 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
     ULONG                                       Length;
     /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Hash value calculated from packet's headers */
+    ULONGLONG                                   HashValue;
     /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
     /*! Information passed up from subscriber for packet completion */
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 85ebcf9..4d7f19b 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2477,6 +2477,8 @@ ReceiverConnect(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -2509,6 +2511,8 @@ fail3:
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisconnect(Ring);
 
@@ -2668,6 +2672,8 @@ ReceiverStoreWrite(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -2714,6 +2720,8 @@ ReceiverEnable(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingEnable(Ring);
         if (!NT_SUCCESS(status))
@@ -2731,6 +2739,8 @@ fail1:
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2744,6 +2754,9 @@ ReceiverDisable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Receiver->Frontend;
 
     for (ListEntry = Receiver->List.Blink;
          ListEntry != &Receiver->List;
@@ -2751,6 +2764,8 @@ ReceiverDisable(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2777,6 +2792,8 @@ ReceiverDisconnect(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisconnect(Ring);
     }
@@ -2842,6 +2859,9 @@ ReceiverSetOffloadOptions(
     )
 {
     PLIST_ENTRY                     ListEntry;
+    PXENVIF_FRONTEND                Frontend;
+
+    Frontend = Receiver->Frontend;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -2855,6 +2875,8 @@ ReceiverSetOffloadOptions(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingSetOffloadOptions(Ring, Options);
     }    
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 477fecc..c5b05b3 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3494,6 +3494,8 @@ TransmitterConnect(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -3526,6 +3528,8 @@ fail3:
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisconnect(Ring);
 
@@ -3553,6 +3557,9 @@ TransmitterStoreWrite(
 {
     PLIST_ENTRY                     ListEntry;
     NTSTATUS                        status;
+    PXENVIF_FRONTEND                Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Flink;
          ListEntry != &Transmitter->List;
@@ -3560,6 +3567,8 @@ TransmitterStoreWrite(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __TransmitterRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -3580,6 +3589,9 @@ TransmitterEnable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Flink;
          ListEntry != &Transmitter->List;
@@ -3587,6 +3599,8 @@ TransmitterEnable(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingEnable(Ring);
     }    
@@ -3600,6 +3614,9 @@ TransmitterDisable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Blink;
          ListEntry != &Transmitter->List;
@@ -3607,6 +3624,8 @@ TransmitterDisable(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisable(Ring);
     }
@@ -3633,6 +3652,8 @@ TransmitterDisconnect(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3943,6 +3964,9 @@ TransmitterAbortPackets(
 {
     PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
@@ -3952,6 +3976,8 @@ TransmitterAbortPackets(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingAbortPackets(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 Wed Nov 12 16:39:23 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax1-0003Vu-O9; Wed, 12 Nov 2014 16:39:23 +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 1Xoax0-0003VF-Lr
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:22 +0000
Received: from [193.109.254.147] by server-5.bemta-14.messagelabs.com id
	8C/5C-08051-A3D83645; Wed, 12 Nov 2014 16:39:22 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!5
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5536 invoked from network); 12 Nov 2014 16:39:21 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:21 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032197"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:03 +0000
Message-ID: <1415810347-7152-7-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 06/10] Dont call through to inactive 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

Queues where Index >= QueueCount are inactive, and should not
Connect, Disconnect, Enable, Disable or write to the store.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  2 ++
 src/xenvif/receiver.c    | 22 ++++++++++++++++++++++
 src/xenvif/transmitter.c | 26 ++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 4ce61c4..83e3846 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
     ULONG                                       Length;
     /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Hash value calculated from packet's headers */
+    ULONGLONG                                   HashValue;
     /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
     /*! Information passed up from subscriber for packet completion */
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 85ebcf9..4d7f19b 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2477,6 +2477,8 @@ ReceiverConnect(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -2509,6 +2511,8 @@ fail3:
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisconnect(Ring);
 
@@ -2668,6 +2672,8 @@ ReceiverStoreWrite(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -2714,6 +2720,8 @@ ReceiverEnable(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __ReceiverRingEnable(Ring);
         if (!NT_SUCCESS(status))
@@ -2731,6 +2739,8 @@ fail1:
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2744,6 +2754,9 @@ ReceiverDisable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Receiver->Frontend;
 
     for (ListEntry = Receiver->List.Blink;
          ListEntry != &Receiver->List;
@@ -2751,6 +2764,8 @@ ReceiverDisable(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisable(Ring);
     }
@@ -2777,6 +2792,8 @@ ReceiverDisconnect(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingDisconnect(Ring);
     }
@@ -2842,6 +2859,9 @@ ReceiverSetOffloadOptions(
     )
 {
     PLIST_ENTRY                     ListEntry;
+    PXENVIF_FRONTEND                Frontend;
+
+    Frontend = Receiver->Frontend;
 
     if (Receiver->AllowGsoPackets == 0) {
         Warning("RECEIVER GSO DISALLOWED\n");
@@ -2855,6 +2875,8 @@ ReceiverSetOffloadOptions(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __ReceiverRingSetOffloadOptions(Ring, Options);
     }    
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 477fecc..c5b05b3 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -3494,6 +3494,8 @@ TransmitterConnect(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __TransmitterRingConnect(Ring);
         if (!NT_SUCCESS(status))
@@ -3526,6 +3528,8 @@ fail3:
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisconnect(Ring);
 
@@ -3553,6 +3557,9 @@ TransmitterStoreWrite(
 {
     PLIST_ENTRY                     ListEntry;
     NTSTATUS                        status;
+    PXENVIF_FRONTEND                Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Flink;
          ListEntry != &Transmitter->List;
@@ -3560,6 +3567,8 @@ TransmitterStoreWrite(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         status = __TransmitterRingStoreWrite(Ring, Transaction);
         if (!NT_SUCCESS(status))
@@ -3580,6 +3589,9 @@ TransmitterEnable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Flink;
          ListEntry != &Transmitter->List;
@@ -3587,6 +3599,8 @@ TransmitterEnable(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingEnable(Ring);
     }    
@@ -3600,6 +3614,9 @@ TransmitterDisable(
     )
 {
     PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     for (ListEntry = Transmitter->List.Blink;
          ListEntry != &Transmitter->List;
@@ -3607,6 +3624,8 @@ TransmitterDisable(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisable(Ring);
     }
@@ -3633,6 +3652,8 @@ TransmitterDisconnect(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingDisconnect(Ring);
     }
@@ -3943,6 +3964,9 @@ TransmitterAbortPackets(
 {
     PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
+    PXENVIF_FRONTEND        Frontend;
+
+    Frontend = Transmitter->Frontend;
 
     KeRaiseIrql(DISPATCH_LEVEL, &Irql);
 
@@ -3952,6 +3976,8 @@ TransmitterAbortPackets(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index >= FrontendGetQueueCount(Frontend))
+            continue;
 
         __TransmitterRingAbortPackets(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 Wed Nov 12 16:39:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax3-0003Wk-Q8; Wed, 12 Nov 2014 16:39:25 +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 1Xoax2-0003WU-TZ
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:25 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	DD/A4-02953-C3D83645; Wed, 12 Nov 2014 16:39:24 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!6
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5695 invoked from network); 12 Nov 2014 16:39:22 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:22 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032201"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:59 +0000
Message-ID: <1415810347-7152-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 02/10] Add VIF interface version 2
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  |  84 ++++++++++++++++++++++--
 src/xenvif/transmitter.c | 164 ++++++++++++++++++++++++++++++++++++++++-------
 src/xenvif/transmitter.h |  17 +++++
 src/xenvif/vif.c         | 145 +++++++++++++++++++++++++++++++++++++++--
 src/xenvif/vif.h         |  11 ++++
 5 files changed, 386 insertions(+), 35 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 8bde731..4ce61c4 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -116,6 +116,7 @@ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
     };
 };
 
+
 typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS, *PXENVIF_PACKET_CHECKSUM_FLAGS;
 
 #pragma warning(pop)
@@ -269,17 +270,25 @@ C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
     \brief Transmit-side packet structure
 */
 struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
     LIST_ENTRY                                  ListEntry;
+    /*! MDL referencing the packet's buffer */
     PMDL                                        Mdl;
+    /*! Offset of start of packet in MDL */
     ULONG                                       Offset;
+    /*! Total length of packet */
     ULONG                                       Length;
+    /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Information passed up from subscriber for packet completion */
     XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
 };
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
 
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET_V1 pointer
@@ -501,6 +510,34 @@ typedef NTSTATUS
     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_GET_PACKET_HEADERS
+    \brief Get a copy of the packet headers and each the offset of each
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
     \brief Query the available set of transmit side offload options
 
@@ -694,10 +731,6 @@ typedef NTSTATUS
 DEFINE_GUID(GUID_XENVIF_VIF_INTERFACE, 
 0x76f279cd, 0xca11, 0x418b, 0x92, 0xe8, 0xc5, 0x7f, 0x77, 0xde, 0xe, 0x2e);
 
-/*! \struct _XENVIF_VIF_INTERFACE_V1
-    \brief VIF interface version 1
-    \ingroup interfaces
-*/
 struct _XENVIF_VIF_INTERFACE_V1 {
     INTERFACE                                       Interface;
     XENVIF_VIF_ACQUIRE                              Acquire;
@@ -723,17 +756,54 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE_V1, *PXENVIF_VIF_INTERFACE_V1;
+
+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_SET_PACKET_OFFSET        TransmitterSetPacketOffset; // obsolete
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;    // obsolete
+    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;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePacketsV2;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2, *PXENVIF_VIF_INTERFACE_V2;
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
-    \brief Macro at assist in method invocation
+    \brief Macro to assist in method invocation
 */
 #define XENVIF_VIF(_Method, _Interface, ...)    \
     (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
 
+/*! \def XENVIF_VIF_VERSION
+    \brief Macro to assist in getting interface version in use
+*/
+#define XENVIF_VIF_VERSION(_Interface)          \
+    ((_Interface)->Interface.Version)
+
 #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 38e4cb2..6fd542e 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2386,33 +2386,44 @@ TransmitterReturnPackets(
     IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
+    PXENVIF_VIF_CONTEXT             Context;
+        
+    Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
 
-    HeadPacket = NULL;
-    NextPacket = NULL;
-    while (!IsListEmpty(List)) {
-        PLIST_ENTRY                     ListEntry;
-        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+    switch (VifGetVersion(Context)) {
+    case 1: {
+        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
 
-        ListEntry = RemoveTailList(List);
-        ASSERT3P(ListEntry, !=, List);
+        HeadPacket = NULL;
+        NextPacket = NULL;
+        while (!IsListEmpty(List)) {
+            PLIST_ENTRY                     ListEntry;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
-        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+            ListEntry = RemoveTailList(List);
+            ASSERT3P(ListEntry, !=, List);
 
-        HeadPacket = Packet->Cookie;
-        HeadPacket->Next = NextPacket;
-        HeadPacket->Completion = Packet->Completion;
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
 
-        __TransmitterPutPacket(Transmitter, Packet);
-        NextPacket = HeadPacket;
-    }
+            HeadPacket = Packet->Cookie;
+            HeadPacket->Next = NextPacket;
+            HeadPacket->Completion = Packet->Completion;
 
-    Frontend = Transmitter->Frontend;
+            __TransmitterPutPacket(Transmitter, Packet);
+            NextPacket = HeadPacket;
+        }
 
-    VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                HeadPacket);
+        VifTransmitterReturnPackets(Context, HeadPacket);
+        break;
+    }
+    case 2:
+        VifTransmitterReturnPacketsV2(Context, List);
+        break;
+    default:
+        ASSERT(FALSE);
+        break;
+    }
 }
 
 static FORCEINLINE BOOLEAN
@@ -3803,9 +3814,9 @@ TransmitterQueuePacketsV1(
     // if HeadPacket != NULL, errors occured and need returning
     if (HeadPacket != NULL) {
         PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-        PXENVIF_FRONTEND                Frontend;
+        PXENVIF_VIF_CONTEXT             Context;
 
-        Frontend = Transmitter->Frontend;
+        Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
 
         Packet = HeadPacket;
         while (Packet != NULL) {
@@ -3813,8 +3824,7 @@ TransmitterQueuePacketsV1(
             Packet = Packet->Next;
         }
 
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+        VifTransmitterReturnPackets(Context, HeadPacket);
     }
 
 #undef OFFSET
@@ -3822,6 +3832,112 @@ TransmitterQueuePacketsV1(
 }
 
 VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    )
+{
+    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);
+
+    __TransmitterRingQueuePackets(Ring, List);
+}
+
+static BOOLEAN
+TransmitterHeaderPullup(
+    IN  PVOID                   Argument,
+    IN  PUCHAR                  DestinationVa,
+    IN  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  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    )
+{
+    XENVIF_PACKET_PAYLOAD   Payload;
+    NTSTATUS                status;
+
+    UNREFERENCED_PARAMETER(Transmitter);
+
+    Payload.Mdl = Mdl;
+    Payload.Offset = Offset;
+    Payload.Length = Length;
+
+    status = ParsePacket(HeaderBuffer,
+                         TransmitterHeaderPullup,
+                         &HeaderLength,
+                         &Payload,
+                         Info);
+    return status;
+}
+
+VOID
 TransmitterAbortPackets(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 661eeae..c359c20 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -113,6 +113,23 @@ TransmitterQueuePacketsV1(
     );
 
 extern VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    );
+
+extern NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
+extern VOID
 TransmitterQueryOffloadOptions(
     IN  PXENVIF_TRANSMITTER         Transmitter,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index d6da258..8c1156a 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -46,6 +46,7 @@ struct _XENVIF_VIF_CONTEXT {
     PXENVIF_PDO                 Pdo;
     XENVIF_MRSW_LOCK            Lock;
     LONG                        References;
+    ULONG                       Version;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Enabled;    
     XENVIF_VIF_CALLBACK         Callback;
@@ -302,6 +303,75 @@ 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;
+
+    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context->Frontend),
+                              List);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
+static NTSTATUS
+VifTransmitterGetPacketHeaders(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    )
+{
+    PXENVIF_VIF_CONTEXT Context = Interface->Context;
+    NTSTATUS            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->Enabled == FALSE)
+        goto fail1;
+
+    status = TransmitterGetPacketHeaders(FrontendGetTransmitter(Context->Frontend),
+                                         Mdl,
+                                         Offset,
+                                         Length,
+                                         HeaderBuffer,
+                                         HeaderLength,
+                                         Info);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail2:
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
 static VOID
 VifTransmitterQueryOffloadOptions(
     IN  PINTERFACE                  Interface,
@@ -560,7 +630,9 @@ VifAcquire(
     if (Context->References++ != 0)
         goto done;
 
-    Trace("====>\n");
+    Trace("====> (%u)\n", Interface->Version);
+
+    Context->Version = Interface->Version;
 
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
@@ -577,7 +649,7 @@ VifAcquire(
 
     Context->Frontend = PdoGetFrontend(Context->Pdo);
 
-    Trace("<====\n");
+    Trace("<==== (%u)\n", Interface->Version);
 
 done:
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
@@ -612,7 +684,7 @@ VifRelease(
     if (--Context->References > 0)
         goto done;
 
-    Trace("====>\n");
+    Trace("====> (%u)\n", Interface->Version);
 
     ASSERT(!Context->Enabled);
 
@@ -625,7 +697,9 @@ VifRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Trace("<====\n");
+    Context->Version = 0;
+
+    Trace("<==== (%u)\n", Interface->Version);
 
 done:
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
@@ -656,6 +730,33 @@ 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,
+    VifTransmitterSetPacketOffset,
+    VifTransmitterQueuePackets,
+    VifTransmitterQueryOffloadOptions,
+    VifTransmitterQueryLargePacketSize,
+    VifTransmitterQueryRingSize,
+    VifMacQueryState,
+    VifMacQueryMaximumFrameSize,
+    VifMacQueryPermanentAddress,
+    VifMacQueryCurrentAddress,
+    VifMacQueryMulticastAddresses,
+    VifMacSetMulticastAddresses,
+    VifMacSetFilterLevel,
+    VifMacQueryFilterLevel,
+    VifTransmitterQueuePacketsV2,
+    VifTransmitterGetPacketHeaders
+};
+
 NTSTATUS
 VifInitialize(
     IN  PXENVIF_PDO         Pdo,
@@ -737,6 +838,23 @@ 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;
@@ -793,6 +911,25 @@ VifTransmitterReturnPackets(
                       Head);
 }
 
+VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    )
+{
+    Context->Callback(Context->Argument,
+                      XENVIF_TRANSMITTER_RETURN_PACKETS,
+                      List);
+}
+
+ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    )
+{
+    return Context->Version;
+}
+
 extern PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index 0ef6687..fe0f9e4 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -74,10 +74,21 @@ VifTransmitterReturnPackets(
     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 Wed Nov 12 16:39:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax3-0003Wk-Q8; Wed, 12 Nov 2014 16:39:25 +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 1Xoax2-0003WU-TZ
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:25 +0000
Received: from [193.109.254.147] by server-3.bemta-14.messagelabs.com id
	DD/A4-02953-C3D83645; Wed, 12 Nov 2014 16:39:24 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!6
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5695 invoked from network); 12 Nov 2014 16:39:22 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:22 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032201"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:59 +0000
Message-ID: <1415810347-7152-3-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 02/10] Add VIF interface version 2
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  |  84 ++++++++++++++++++++++--
 src/xenvif/transmitter.c | 164 ++++++++++++++++++++++++++++++++++++++++-------
 src/xenvif/transmitter.h |  17 +++++
 src/xenvif/vif.c         | 145 +++++++++++++++++++++++++++++++++++++++--
 src/xenvif/vif.h         |  11 ++++
 5 files changed, 386 insertions(+), 35 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 8bde731..4ce61c4 100644
--- a/include/vif_interface.h
+++ b/include/vif_interface.h
@@ -116,6 +116,7 @@ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
     };
 };
 
+
 typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 XENVIF_PACKET_CHECKSUM_FLAGS, *PXENVIF_PACKET_CHECKSUM_FLAGS;
 
 #pragma warning(pop)
@@ -269,17 +270,25 @@ C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
     \brief Transmit-side packet structure
 */
 struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    /*! List entry used for chaining packets together */
     LIST_ENTRY                                  ListEntry;
+    /*! MDL referencing the packet's buffer */
     PMDL                                        Mdl;
+    /*! Offset of start of packet in MDL */
     ULONG                                       Offset;
+    /*! Total length of packet */
     ULONG                                       Length;
+    /*! Opaque cookie used to store context information for packet return */
     PVOID                                       Cookie;
+    /*! Packet information passed down to subscriber */
     XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    /*! Information passed up from subscriber for packet completion */
     XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
 };
 
 typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
 
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
     XENVIF_TRANSMITTER_PACKET_V1 pointer
@@ -501,6 +510,34 @@ typedef NTSTATUS
     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_GET_PACKET_HEADERS
+    \brief Get a copy of the packet headers and each the offset of each
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
     \brief Query the available set of transmit side offload options
 
@@ -694,10 +731,6 @@ typedef NTSTATUS
 DEFINE_GUID(GUID_XENVIF_VIF_INTERFACE, 
 0x76f279cd, 0xca11, 0x418b, 0x92, 0xe8, 0xc5, 0x7f, 0x77, 0xde, 0xe, 0x2e);
 
-/*! \struct _XENVIF_VIF_INTERFACE_V1
-    \brief VIF interface version 1
-    \ingroup interfaces
-*/
 struct _XENVIF_VIF_INTERFACE_V1 {
     INTERFACE                                       Interface;
     XENVIF_VIF_ACQUIRE                              Acquire;
@@ -723,17 +756,54 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
 };
 
-typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE_V1, *PXENVIF_VIF_INTERFACE_V1;
+
+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_SET_PACKET_OFFSET        TransmitterSetPacketOffset; // obsolete
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;    // obsolete
+    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;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2         TransmitterQueuePacketsV2;
+    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS       TransmitterGetPacketHeaders;
+};
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2, *PXENVIF_VIF_INTERFACE_V2;
+
+typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
 
 /*! \def XENVIF_VIF
-    \brief Macro at assist in method invocation
+    \brief Macro to assist in method invocation
 */
 #define XENVIF_VIF(_Method, _Interface, ...)    \
     (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
 
+/*! \def XENVIF_VIF_VERSION
+    \brief Macro to assist in getting interface version in use
+*/
+#define XENVIF_VIF_VERSION(_Interface)          \
+    ((_Interface)->Interface.Version)
+
 #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 38e4cb2..6fd542e 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2386,33 +2386,44 @@ TransmitterReturnPackets(
     IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
+    PXENVIF_VIF_CONTEXT             Context;
+        
+    Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
 
-    HeadPacket = NULL;
-    NextPacket = NULL;
-    while (!IsListEmpty(List)) {
-        PLIST_ENTRY                     ListEntry;
-        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+    switch (VifGetVersion(Context)) {
+    case 1: {
+        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
 
-        ListEntry = RemoveTailList(List);
-        ASSERT3P(ListEntry, !=, List);
+        HeadPacket = NULL;
+        NextPacket = NULL;
+        while (!IsListEmpty(List)) {
+            PLIST_ENTRY                     ListEntry;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
-        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+            ListEntry = RemoveTailList(List);
+            ASSERT3P(ListEntry, !=, List);
 
-        HeadPacket = Packet->Cookie;
-        HeadPacket->Next = NextPacket;
-        HeadPacket->Completion = Packet->Completion;
+            Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
 
-        __TransmitterPutPacket(Transmitter, Packet);
-        NextPacket = HeadPacket;
-    }
+            HeadPacket = Packet->Cookie;
+            HeadPacket->Next = NextPacket;
+            HeadPacket->Completion = Packet->Completion;
 
-    Frontend = Transmitter->Frontend;
+            __TransmitterPutPacket(Transmitter, Packet);
+            NextPacket = HeadPacket;
+        }
 
-    VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                HeadPacket);
+        VifTransmitterReturnPackets(Context, HeadPacket);
+        break;
+    }
+    case 2:
+        VifTransmitterReturnPacketsV2(Context, List);
+        break;
+    default:
+        ASSERT(FALSE);
+        break;
+    }
 }
 
 static FORCEINLINE BOOLEAN
@@ -3803,9 +3814,9 @@ TransmitterQueuePacketsV1(
     // if HeadPacket != NULL, errors occured and need returning
     if (HeadPacket != NULL) {
         PXENVIF_TRANSMITTER_PACKET_V1   Packet;
-        PXENVIF_FRONTEND                Frontend;
+        PXENVIF_VIF_CONTEXT             Context;
 
-        Frontend = Transmitter->Frontend;
+        Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
 
         Packet = HeadPacket;
         while (Packet != NULL) {
@@ -3813,8 +3824,7 @@ TransmitterQueuePacketsV1(
             Packet = Packet->Next;
         }
 
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+        VifTransmitterReturnPackets(Context, HeadPacket);
     }
 
 #undef OFFSET
@@ -3822,6 +3832,112 @@ TransmitterQueuePacketsV1(
 }
 
 VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    )
+{
+    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);
+
+    __TransmitterRingQueuePackets(Ring, List);
+}
+
+static BOOLEAN
+TransmitterHeaderPullup(
+    IN  PVOID                   Argument,
+    IN  PUCHAR                  DestinationVa,
+    IN  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  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    )
+{
+    XENVIF_PACKET_PAYLOAD   Payload;
+    NTSTATUS                status;
+
+    UNREFERENCED_PARAMETER(Transmitter);
+
+    Payload.Mdl = Mdl;
+    Payload.Offset = Offset;
+    Payload.Length = Length;
+
+    status = ParsePacket(HeaderBuffer,
+                         TransmitterHeaderPullup,
+                         &HeaderLength,
+                         &Payload,
+                         Info);
+    return status;
+}
+
+VOID
 TransmitterAbortPackets(
     IN  PXENVIF_TRANSMITTER Transmitter
     )
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 661eeae..c359c20 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -113,6 +113,23 @@ TransmitterQueuePacketsV1(
     );
 
 extern VOID
+TransmitterQueuePacketsV2(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PLIST_ENTRY         List
+    );
+
+extern NTSTATUS
+TransmitterGetPacketHeaders(
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    );
+
+extern VOID
 TransmitterQueryOffloadOptions(
     IN  PXENVIF_TRANSMITTER         Transmitter,
     OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
index d6da258..8c1156a 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -46,6 +46,7 @@ struct _XENVIF_VIF_CONTEXT {
     PXENVIF_PDO                 Pdo;
     XENVIF_MRSW_LOCK            Lock;
     LONG                        References;
+    ULONG                       Version;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Enabled;    
     XENVIF_VIF_CALLBACK         Callback;
@@ -302,6 +303,75 @@ 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;
+
+    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context->Frontend),
+                              List);
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
+static NTSTATUS
+VifTransmitterGetPacketHeaders(
+    IN  PINTERFACE          Interface,
+    IN  PMDL                Mdl,
+    IN  ULONG               Offset,
+    IN  ULONG               Length,
+    OUT PVOID               HeaderBuffer,
+    IN  ULONG               HeaderLength,
+    OUT PXENVIF_PACKET_INFO Info
+    )
+{
+    PXENVIF_VIF_CONTEXT Context = Interface->Context;
+    NTSTATUS            status;
+
+    AcquireMrswLockShared(&Context->Lock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->Enabled == FALSE)
+        goto fail1;
+
+    status = TransmitterGetPacketHeaders(FrontendGetTransmitter(Context->Frontend),
+                                         Mdl,
+                                         Offset,
+                                         Length,
+                                         HeaderBuffer,
+                                         HeaderLength,
+                                         Info);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return STATUS_SUCCESS;
+
+fail2:
+fail1:
+    ReleaseMrswLockShared(&Context->Lock);
+
+    return status;
+}
+
 static VOID
 VifTransmitterQueryOffloadOptions(
     IN  PINTERFACE                  Interface,
@@ -560,7 +630,9 @@ VifAcquire(
     if (Context->References++ != 0)
         goto done;
 
-    Trace("====>\n");
+    Trace("====> (%u)\n", Interface->Version);
+
+    Context->Version = Interface->Version;
 
     status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
     if (!NT_SUCCESS(status))
@@ -577,7 +649,7 @@ VifAcquire(
 
     Context->Frontend = PdoGetFrontend(Context->Pdo);
 
-    Trace("<====\n");
+    Trace("<==== (%u)\n", Interface->Version);
 
 done:
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
@@ -612,7 +684,7 @@ VifRelease(
     if (--Context->References > 0)
         goto done;
 
-    Trace("====>\n");
+    Trace("====> (%u)\n", Interface->Version);
 
     ASSERT(!Context->Enabled);
 
@@ -625,7 +697,9 @@ VifRelease(
 
     XENBUS_SUSPEND(Release, &Context->SuspendInterface);
 
-    Trace("<====\n");
+    Context->Version = 0;
+
+    Trace("<==== (%u)\n", Interface->Version);
 
 done:
     ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
@@ -656,6 +730,33 @@ 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,
+    VifTransmitterSetPacketOffset,
+    VifTransmitterQueuePackets,
+    VifTransmitterQueryOffloadOptions,
+    VifTransmitterQueryLargePacketSize,
+    VifTransmitterQueryRingSize,
+    VifMacQueryState,
+    VifMacQueryMaximumFrameSize,
+    VifMacQueryPermanentAddress,
+    VifMacQueryCurrentAddress,
+    VifMacQueryMulticastAddresses,
+    VifMacSetMulticastAddresses,
+    VifMacSetFilterLevel,
+    VifMacQueryFilterLevel,
+    VifTransmitterQueuePacketsV2,
+    VifTransmitterGetPacketHeaders
+};
+
 NTSTATUS
 VifInitialize(
     IN  PXENVIF_PDO         Pdo,
@@ -737,6 +838,23 @@ 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;
@@ -793,6 +911,25 @@ VifTransmitterReturnPackets(
                       Head);
 }
 
+VOID
+VifTransmitterReturnPacketsV2(
+    IN  PXENVIF_VIF_CONTEXT Context,
+    IN  PLIST_ENTRY         List
+    )
+{
+    Context->Callback(Context->Argument,
+                      XENVIF_TRANSMITTER_RETURN_PACKETS,
+                      List);
+}
+
+ULONG
+VifGetVersion(
+    IN  PXENVIF_VIF_CONTEXT Context
+    )
+{
+    return Context->Version;
+}
+
 extern PXENVIF_THREAD
 VifGetMacThread(
     IN  PXENVIF_VIF_CONTEXT Context
diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
index 0ef6687..fe0f9e4 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -74,10 +74,21 @@ VifTransmitterReturnPackets(
     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 Wed Nov 12 16:39:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax3-0003Wq-RW; Wed, 12 Nov 2014 16:39:25 +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 1Xoax2-0003WT-Tk
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:25 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	0A/D5-22819-C3D83645; Wed, 12 Nov 2014 16:39:24 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415810357!10931411!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 11962 invoked from network); 12 Nov 2014 16:39:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032198"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:04 +0000
Message-ID: <1415810347-7152-8-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 07/10] Write queue values under
	<frontend>/queue-<id> and "multi-queue-num-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

When multi-queues are used, queue event-channel and ring-refs are written under
"device/vif/<number>/queue-<id>". When the number of active queues is 1, write
the event-channel and ring-refs inder "device/vif/<number>" as before.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c    | 34 ++++++++++++++++++++++++++++++++++
 src/xenvif/frontend.h    |  8 ++++++++
 src/xenvif/notifier.c    |  8 +++++++-
 src/xenvif/receiver.c    |  6 +++++-
 src/xenvif/transmitter.c |  6 +++++-
 5 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 9a6cbde..846b051 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -156,6 +156,30 @@ FrontendGetPath(
     return __FrontendGetPath(Frontend);
 }
 
+PCHAR
+FrontendGetQueuePath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index,
+    IN  PCHAR               Buffer,
+    IN  ULONG               Length
+    )
+{
+    if (Frontend->MultiQueueCount == 1) {
+        return __FrontendGetPath(Frontend);
+    } else {
+        NTSTATUS    status;
+
+        status = RtlStringCbPrintfA(Buffer,
+                                    Length,
+                                    "%s/queue-%u",
+                                    __FrontendGetPath(Frontend),
+                                    Index);
+        ASSERT(NT_SUCCESS(status));
+
+        return Buffer;
+    }
+}
+
 static FORCEINLINE PCHAR
 __FrontendGetPrefix(
     IN  PXENVIF_FRONTEND    Frontend
@@ -1380,6 +1404,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,
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 20cd390..75cb4a0 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -103,6 +103,14 @@ FrontendGetPath(
     );
 
 extern PCHAR
+FrontendGetQueuePath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index,
+    IN  PCHAR               Buffer,
+    IN  ULONG               Length
+    );
+
+extern PCHAR
 FrontendGetBackendPath(
     IN  PXENVIF_FRONTEND    Frontend
     );
diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 02a11d8..573ffaa 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -224,6 +224,8 @@ PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
 
 C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
 
+#define MAX_BUFFER      128
+
 static VOID
 NotifierQueueDebugCallback(
     IN  PXENVIF_NOTIFIER_QUEUE  Queue
@@ -346,6 +348,7 @@ NotifierQueueStoreWrite(
     for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
         PCHAR   Node;
         ULONG   Port;
+        CHAR    Buffer[MAX_BUFFER];
 
         switch (Index) {
         case XENVIF_NOTIFIER_EVTCHN_COMBINED:
@@ -383,7 +386,10 @@ NotifierQueueStoreWrite(
         status = XENBUS_STORE(Printf,
                               &Notifier->StoreInterface,
                               Transaction,
-                              FrontendGetPath(Frontend),
+                              FrontendGetQueuePath(Frontend,
+                                                   Queue->Index,
+                                                   Buffer,
+                                                   sizeof(Buffer)),
                               Node,
                               "%u",
                               Port);
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 4d7f19b..01ab248 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2101,6 +2101,7 @@ __ReceiverRingStoreWrite(
 {
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
+    CHAR                            Buffer[MAXNAMELEN];
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -2109,7 +2110,10 @@ __ReceiverRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          FrontendGetQueuePath(Frontend,
+                                               Ring->Index,
+                                               Buffer,
+                                               sizeof(Buffer)),
                           "rx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index c5b05b3..f1a3e9e 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2956,6 +2956,7 @@ __TransmitterRingStoreWrite(
 {
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
+    CHAR                            Buffer[MAXNAMELEN];
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -2964,7 +2965,10 @@ __TransmitterRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          FrontendGetQueuePath(Frontend,
+                                               Ring->Index,
+                                               Buffer,
+                                               sizeof(Buffer)),
                           "tx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
-- 
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 Wed Nov 12 16:39:25 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax3-0003Wq-RW; Wed, 12 Nov 2014 16:39:25 +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 1Xoax2-0003WT-Tk
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:25 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	0A/D5-22819-C3D83645; Wed, 12 Nov 2014 16:39:24 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-2.tower-206.messagelabs.com!1415810357!10931411!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 11962 invoked from network); 12 Nov 2014 16:39:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-2.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032198"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:04 +0000
Message-ID: <1415810347-7152-8-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 07/10] Write queue values under
	<frontend>/queue-<id> and "multi-queue-num-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

When multi-queues are used, queue event-channel and ring-refs are written under
"device/vif/<number>/queue-<id>". When the number of active queues is 1, write
the event-channel and ring-refs inder "device/vif/<number>" as before.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/frontend.c    | 34 ++++++++++++++++++++++++++++++++++
 src/xenvif/frontend.h    |  8 ++++++++
 src/xenvif/notifier.c    |  8 +++++++-
 src/xenvif/receiver.c    |  6 +++++-
 src/xenvif/transmitter.c |  6 +++++-
 5 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 9a6cbde..846b051 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -156,6 +156,30 @@ FrontendGetPath(
     return __FrontendGetPath(Frontend);
 }
 
+PCHAR
+FrontendGetQueuePath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index,
+    IN  PCHAR               Buffer,
+    IN  ULONG               Length
+    )
+{
+    if (Frontend->MultiQueueCount == 1) {
+        return __FrontendGetPath(Frontend);
+    } else {
+        NTSTATUS    status;
+
+        status = RtlStringCbPrintfA(Buffer,
+                                    Length,
+                                    "%s/queue-%u",
+                                    __FrontendGetPath(Frontend),
+                                    Index);
+        ASSERT(NT_SUCCESS(status));
+
+        return Buffer;
+    }
+}
+
 static FORCEINLINE PCHAR
 __FrontendGetPrefix(
     IN  PXENVIF_FRONTEND    Frontend
@@ -1380,6 +1404,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,
diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
index 20cd390..75cb4a0 100644
--- a/src/xenvif/frontend.h
+++ b/src/xenvif/frontend.h
@@ -103,6 +103,14 @@ FrontendGetPath(
     );
 
 extern PCHAR
+FrontendGetQueuePath(
+    IN  PXENVIF_FRONTEND    Frontend,
+    IN  ULONG               Index,
+    IN  PCHAR               Buffer,
+    IN  ULONG               Length
+    );
+
+extern PCHAR
 FrontendGetBackendPath(
     IN  PXENVIF_FRONTEND    Frontend
     );
diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 02a11d8..573ffaa 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -224,6 +224,8 @@ PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
 
 C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
 
+#define MAX_BUFFER      128
+
 static VOID
 NotifierQueueDebugCallback(
     IN  PXENVIF_NOTIFIER_QUEUE  Queue
@@ -346,6 +348,7 @@ NotifierQueueStoreWrite(
     for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
         PCHAR   Node;
         ULONG   Port;
+        CHAR    Buffer[MAX_BUFFER];
 
         switch (Index) {
         case XENVIF_NOTIFIER_EVTCHN_COMBINED:
@@ -383,7 +386,10 @@ NotifierQueueStoreWrite(
         status = XENBUS_STORE(Printf,
                               &Notifier->StoreInterface,
                               Transaction,
-                              FrontendGetPath(Frontend),
+                              FrontendGetQueuePath(Frontend,
+                                                   Queue->Index,
+                                                   Buffer,
+                                                   sizeof(Buffer)),
                               Node,
                               "%u",
                               Port);
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 4d7f19b..01ab248 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -2101,6 +2101,7 @@ __ReceiverRingStoreWrite(
 {
     PXENVIF_RECEIVER                Receiver;
     PXENVIF_FRONTEND                Frontend;
+    CHAR                            Buffer[MAXNAMELEN];
     NTSTATUS                        status;
 
     Receiver = Ring->Receiver;
@@ -2109,7 +2110,10 @@ __ReceiverRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Receiver->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          FrontendGetQueuePath(Frontend,
+                                               Ring->Index,
+                                               Buffer,
+                                               sizeof(Buffer)),
                           "rx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index c5b05b3..f1a3e9e 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2956,6 +2956,7 @@ __TransmitterRingStoreWrite(
 {
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
+    CHAR                            Buffer[MAXNAMELEN];
     NTSTATUS                        status;
 
     Transmitter = Ring->Transmitter;
@@ -2964,7 +2965,10 @@ __TransmitterRingStoreWrite(
     status = XENBUS_STORE(Printf,
                           &Transmitter->StoreInterface,
                           Transaction,
-                          FrontendGetPath(Frontend),
+                          FrontendGetQueuePath(Frontend,
+                                               Ring->Index,
+                                               Buffer,
+                                               sizeof(Buffer)),
                           "tx-ring-ref",
                           "%u",
                           GranterGetReference(FrontendGetGranter(Frontend),
-- 
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 Wed Nov 12 16:39:26 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:26 +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 1Xoax4-0003Xa-St; Wed, 12 Nov 2014 16:39:26 +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 1Xoax3-0003Wi-V3
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:26 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	C9/90-27785-D3D83645; Wed, 12 Nov 2014 16:39:25 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!7
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5865 invoked from network); 12 Nov 2014 16:39:24 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032203"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:02 +0000
Message-ID: <1415810347-7152-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 05/10] Split notifier into a list of 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

Move event channel registration to a list item, with 1 item per
max-queue.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/notifier.c    | 686 +++++++++++++++++++++++++++++++++--------------
 src/xenvif/notifier.h    |  12 +-
 src/xenvif/receiver.c    |  11 +-
 src/xenvif/receiver.h    |   3 +-
 src/xenvif/transmitter.c |   9 +-
 src/xenvif/transmitter.h |   3 +-
 6 files changed, 512 insertions(+), 212 deletions(-)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index fc6725a..02a11d8 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -52,19 +52,26 @@ typedef enum _XENVIF_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;
+    LIST_ENTRY                  List;
     XENBUS_STORE_INTERFACE      StoreInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
 };
 
+typedef struct _XENVIF_NOTIFIER_QUEUE {
+    PXENVIF_NOTIFIER            Notifier;
+    LIST_ENTRY                  ListEntry;
+    ULONG                       Index;
+    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];
+} XENVIF_NOTIFIER_QUEUE, *PXENVIF_NOTIFIER_QUEUE;
+
 #define XENVIF_NOTIFIER_TAG 'ITON'
 
 static FORCEINLINE PVOID
@@ -84,22 +91,24 @@ __NotifierFree(
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
+__NotifierQueueUnmask(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue,
     IN  XENVIF_NOTIFIER_EVTCHN  Index
     )
 {
+    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Pending;
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
 
-    Pending = (Notifier->Connected) ?
+    Pending = (Notifier->Connected && Queue->Channel[Index]) ?
               XENBUS_EVTCHN(Unmask,
                             &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
+                            Queue->Channel[Index],
                             FALSE) :
               FALSE;
 
@@ -114,14 +123,15 @@ __drv_minIRQL(DISPATCH_LEVEL)
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __drv_sameIRQL
 static VOID
-NotifierDpc(
+NotifierQueueDpc(
     IN  PKDPC               Dpc,
     IN  PVOID               Context,
     IN  PVOID               Argument1,
     IN  PVOID               Argument2
     )
 {
-    PXENVIF_NOTIFIER        Notifier = Context;
+    PXENVIF_NOTIFIER_QUEUE  Queue = Context;
+    PXENVIF_NOTIFIER        Notifier;
     XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
     PXENVIF_FRONTEND        Frontend;
     BOOLEAN                 Pending;
@@ -129,24 +139,25 @@ NotifierDpc(
     UNREFERENCED_PARAMETER(Dpc);
     UNREFERENCED_PARAMETER(Argument2);
 
-    ASSERT(Notifier != NULL);
+    ASSERT(Queue != NULL);
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     do {
         if (Notifier->Enabled) {
             switch (Index) {
             case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue->Index);
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             default:
@@ -155,88 +166,345 @@ NotifierDpc(
             }
         }
 
-        Pending = __NotifierUnmask(Notifier, Index);
+        Pending = __NotifierQueueUnmask(Queue, Index);
     } while (Pending);
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
+__NotifierQueueEvtchnCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  XENVIF_NOTIFIER_EVTCHN      Index
     )
 {
-    Notifier->Events[Index]++;
+    Queue->Events[Index]++;
 
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
+    if (KeInsertQueueDpc(&Queue->Dpc[Index],
                          (PVOID)(ULONG_PTR)Index,
                          NULL))
-        Notifier->Dpcs[Index]++;
+        Queue->Dpcs[Index]++;
 
     return TRUE;
 }
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)             \
                                                                         \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
+KSERVICE_ROUTINE    NotifierQueue ## _Type ## EvtchnCallback;           \
                                                                         \
 BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
+NotifierQueue ## _Type ## EvtchnCallback(                               \
     IN  PKINTERRUPT         InterruptObject,                            \
     IN  PVOID               Argument                                    \
     )                                                                   \
 {                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
+    PXENVIF_NOTIFIER_QUEUE  Queue = Argument;                           \
                                                                         \
     UNREFERENCED_PARAMETER(InterruptObject);                            \
                                                                         \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
+    ASSERT(Queue != NULL);                                              \
+    return __NotifierQueueEvtchnCallback(Queue,                         \
                                     XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
 }
 
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)   \
+    NotifierQueue ## _Type ## EvtchnCallback,
 
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 };
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
+C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
 
 static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
+NotifierQueueDebugCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
     )
 {
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
     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",
+                     "[%u][%s]: Events = %lu Dpcs = %lu\n",
+                     Queue->Index,
                      ((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]);
+                     Queue->Events[Index],
+                     Queue->Dpcs[Index]);
+}
+
+static NTSTATUS
+NotifierQueueInitialize(
+    IN  PXENVIF_NOTIFIER        Notifier,
+    IN  ULONG                   QueueIndex,
+    OUT PXENVIF_NOTIFIER_QUEUE  *Queue
+    )
+{
+    ULONG       Index;
+    NTSTATUS    status;
+
+    *Queue = __NotifierAllocate(sizeof (XENVIF_NOTIFIER_QUEUE));
+
+    status = STATUS_NO_MEMORY;
+    if (*Queue == NULL)
+        goto fail1;
+
+    (*Queue)->Notifier = Notifier;
+    (*Queue)->Index = QueueIndex;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
+        KeInitializeDpc(&(*Queue)->Dpc[Index],
+                        NotifierQueueDpc,
+                        *Queue);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueConnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER        Notifier;
+    PXENVIF_FRONTEND        Frontend;
+    LONG                    Index;
+    NTSTATUS                status;
+
+    Notifier = Queue->Notifier;
+    Frontend = Notifier->Frontend;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
+        PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
+        BOOLEAN             Pending;
+
+        Queue->Channel[Index] = XENBUS_EVTCHN(Open,
+                                              &Notifier->EvtchnInterface,
+                                              XENBUS_EVTCHN_TYPE_UNBOUND,
+                                              Callback,
+                                              Queue,
+                                              FrontendGetBackendDomain(Frontend),
+                                              TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Queue->Channel[Index] == NULL)
+            goto fail1;
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Notifier->EvtchnInterface,
+                                Queue->Channel[Index],
+                                FALSE);
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Notifier->EvtchnInterface,
+                          Queue->Channel[Index]);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (--Index >= 0) {
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueStoreWrite(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  PXENBUS_STORE_TRANSACTION   Transaction
+    )
+{
+    PXENVIF_NOTIFIER                Notifier = Queue->Notifier;
+    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,
+                             Queue->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;
+}
+
+static NTSTATUS
+NotifierQueueEnable(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    ULONG               Index;
+
+    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(&Queue->Dpc[Index],
+                             (PVOID)(ULONG_PTR)Index,
+                             NULL))
+            Queue->Dpcs[Index]++;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+NotifierQueueDisconnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    LONG                Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        if (Queue->Channel[Index] == NULL)
+            continue;
+
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+}
+
+static VOID
+NotifierQueueTeardown(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    LONG        Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        Queue->Dpcs[Index] = 0;
+        RtlZeroMemory(&Queue->Dpc[Index], sizeof (KDPC));
+    }
+
+    Queue->Notifier = NULL;
+    Queue->Index = 0;
+
+    ASSERT(IsZeroMemory(Queue, sizeof (XENVIF_NOTIFIER_QUEUE)));
+
+    __NotifierFree(Queue);
+}
+
+static VOID
+NotifierDebugCallback(
+    IN  PVOID           Argument,
+    IN  BOOLEAN         Crashing
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Argument;
+    PLIST_ENTRY         ListEntry;
+
+    UNREFERENCED_PARAMETER(Crashing);
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        NotifierQueueDebugCallback(Queue);
+    }
 }
 
 NTSTATUS
@@ -266,13 +534,41 @@ NotifierInitialize(
     (*Notifier)->Frontend = Frontend;
 
     KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
+    InitializeListHead(&(*Notifier)->List);
+
+    Index = 0;
+    while (Index < DriverGetQueueMax()) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        status = NotifierQueueInitialize(*Notifier, Index, &Queue);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        InsertTailList(&(*Notifier)->List, &Queue->ListEntry);
+        Index++;
+    }
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    while (!IsListEmpty(&(*Notifier)->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&(*Notifier)->List);
+        ASSERT3P(ListEntry, !=, &(*Notifier)->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
+        --Index;
+    }
+    ASSERT3U(Index, ==, 0);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -285,7 +581,7 @@ NotifierConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -308,32 +604,6 @@ NotifierConnect(
     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",
@@ -341,7 +611,7 @@ NotifierConnect(
                           Notifier,
                           &Notifier->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail4;
 
     status = XENBUS_STORE(Read,
                           &Notifier->StoreInterface,
@@ -359,6 +629,20 @@ NotifierConnect(
                      Buffer);
     }
 
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        status = NotifierQueueConnect(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail5;
+    }
+
     Notifier->Connected = TRUE;
     KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
 
@@ -367,20 +651,19 @@ NotifierConnect(
 fail5:
     Error("fail5\n");
 
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
 
-        Notifier->Events[Index] = 0;
+        NotifierQueueDisconnect(Queue);
     }
 
+fail4:
+    Error("fail4\n");
+
     XENBUS_STORE(Release, &Notifier->StoreInterface);
 
 fail3:
@@ -408,54 +691,20 @@ NotifierStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
+    PLIST_ENTRY                     ListEntry;
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
+        status = NotifierQueueStoreWrite(Queue,
+                                         Transaction);
         if (!NT_SUCCESS(status))
             goto fail1;
     }
@@ -473,44 +722,34 @@ NotifierEnable(
     IN  PXENVIF_NOTIFIER    Notifier
     )
 {   
-    ULONG                   Index;
+    PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+    NTSTATUS                status;
+
+    Frontend = Notifier->Frontend;
 
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            break;
-        }
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
+        status = NotifierQueueEnable(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail1;
     }
 
     return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
 VOID
@@ -528,7 +767,7 @@ NotifierDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
 
     Frontend = Notifier->Frontend;
 
@@ -544,14 +783,16 @@ NotifierDisconnect(
                  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;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-        Notifier->Events[Index] = 0;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        NotifierQueueDisconnect(Queue);
     }
 
     XENBUS_STORE(Release, &Notifier->StoreInterface);
@@ -568,15 +809,21 @@ 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));
+    while (!IsListEmpty(&Notifier->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&Notifier->List);
+        ASSERT3P(ListEntry, !=, &Notifier->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
     }
 
     Notifier->Frontend = NULL;
@@ -590,6 +837,7 @@ NotifierTeardown(
     RtlZeroMemory(&Notifier->EvtchnInterface,
                   sizeof (XENBUS_EVTCHN_INTERFACE));
 
+    RtlZeroMemory(&Notifier->List, sizeof(LIST_ENTRY));
     RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
 
     ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
@@ -600,85 +848,125 @@ NotifierTeardown(
 static FORCEINLINE VOID
 __NotifierSend(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Send,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 static FORCEINLINE VOID
 __NotifierTrigger(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Trigger,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
index 2f06a6f..fd28060 100644
--- a/src/xenvif/notifier.h
+++ b/src/xenvif/notifier.h
@@ -78,22 +78,26 @@ NotifierTeardown(
 
 extern VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 #endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 626feed..85ebcf9 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -1397,7 +1397,7 @@ __ReceiverRingReturnPacket(
             Receiver = Ring->Receiver;
             Frontend = Receiver->Frontend;
 
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            NotifierTriggerRx(FrontendGetNotifier(Frontend), Ring->Index);
         }
 
         if (!Locked)
@@ -1477,7 +1477,7 @@ __ReceiverRingPushRequests(
         Receiver = Ring->Receiver;
         Frontend = Receiver->Frontend;
 
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1869,7 +1869,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
             }
 
             KeMemoryBarrier();
@@ -2941,7 +2941,8 @@ ReceiverWaitForPackets(
 
 VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -2952,6 +2953,8 @@ ReceiverNotify(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __ReceiverRingNotify(Ring);
     }    
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 8009858..1505887 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,7 +79,8 @@ ReceiverTeardown(
 
 extern VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index bea46f1..477fecc 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2195,7 +2195,7 @@ __TransmitterRingPushRequests(
         Transmitter = Ring->Transmitter;
         Frontend = Transmitter->Frontend;
 
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2624,7 +2624,7 @@ TransmitterRingWatchdog(
                              Ring->DebugCallback);
 
                 // Try to move things along
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
                 TransmitterRingPoll(Ring);
             }
 
@@ -3972,7 +3972,8 @@ TransmitterQueryRingSize(
 
 VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -3983,6 +3984,8 @@ TransmitterNotify(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __TransmitterRingNotify(Ring);
     }    
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 7e10603..3e56b34 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,7 +79,8 @@ TransmitterTeardown(
 
 extern VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
-- 
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 Wed Nov 12 16:39:26 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39:26 +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 1Xoax4-0003Xa-St; Wed, 12 Nov 2014 16:39:26 +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 1Xoax3-0003Wi-V3
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:26 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	C9/90-27785-D3D83645; Wed, 12 Nov 2014 16:39:25 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-12.tower-27.messagelabs.com!1415810355!12113631!7
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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 5865 invoked from network); 12 Nov 2014 16:39:24 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-12.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:24 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032203"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:02 +0000
Message-ID: <1415810347-7152-6-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 05/10] Split notifier into a list of 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

Move event channel registration to a list item, with 1 item per
max-queue.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenvif/notifier.c    | 686 +++++++++++++++++++++++++++++++++--------------
 src/xenvif/notifier.h    |  12 +-
 src/xenvif/receiver.c    |  11 +-
 src/xenvif/receiver.h    |   3 +-
 src/xenvif/transmitter.c |   9 +-
 src/xenvif/transmitter.h |   3 +-
 6 files changed, 512 insertions(+), 212 deletions(-)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index fc6725a..02a11d8 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -52,19 +52,26 @@ typedef enum _XENVIF_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;
+    LIST_ENTRY                  List;
     XENBUS_STORE_INTERFACE      StoreInterface;
     XENBUS_DEBUG_INTERFACE      DebugInterface;
     PXENBUS_DEBUG_CALLBACK      DebugCallback;
 };
 
+typedef struct _XENVIF_NOTIFIER_QUEUE {
+    PXENVIF_NOTIFIER            Notifier;
+    LIST_ENTRY                  ListEntry;
+    ULONG                       Index;
+    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];
+} XENVIF_NOTIFIER_QUEUE, *PXENVIF_NOTIFIER_QUEUE;
+
 #define XENVIF_NOTIFIER_TAG 'ITON'
 
 static FORCEINLINE PVOID
@@ -84,22 +91,24 @@ __NotifierFree(
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierUnmask(
-    IN  PXENVIF_NOTIFIER        Notifier,
+__NotifierQueueUnmask(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue,
     IN  XENVIF_NOTIFIER_EVTCHN  Index
     )
 {
+    PXENVIF_NOTIFIER            Notifier;
     PXENVIF_FRONTEND            Frontend;
     BOOLEAN                     Pending;
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
 
-    Pending = (Notifier->Connected) ?
+    Pending = (Notifier->Connected && Queue->Channel[Index]) ?
               XENBUS_EVTCHN(Unmask,
                             &Notifier->EvtchnInterface,
-                            Notifier->Channel[Index],
+                            Queue->Channel[Index],
                             FALSE) :
               FALSE;
 
@@ -114,14 +123,15 @@ __drv_minIRQL(DISPATCH_LEVEL)
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __drv_sameIRQL
 static VOID
-NotifierDpc(
+NotifierQueueDpc(
     IN  PKDPC               Dpc,
     IN  PVOID               Context,
     IN  PVOID               Argument1,
     IN  PVOID               Argument2
     )
 {
-    PXENVIF_NOTIFIER        Notifier = Context;
+    PXENVIF_NOTIFIER_QUEUE  Queue = Context;
+    PXENVIF_NOTIFIER        Notifier;
     XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
     PXENVIF_FRONTEND        Frontend;
     BOOLEAN                 Pending;
@@ -129,24 +139,25 @@ NotifierDpc(
     UNREFERENCED_PARAMETER(Dpc);
     UNREFERENCED_PARAMETER(Argument2);
 
-    ASSERT(Notifier != NULL);
+    ASSERT(Queue != NULL);
 
+    Notifier = Queue->Notifier;
     Frontend = Notifier->Frontend;
 
     do {
         if (Notifier->Enabled) {
             switch (Index) {
             case XENVIF_NOTIFIER_EVTCHN_TX:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_RX:
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             case XENVIF_NOTIFIER_EVTCHN_COMBINED:
-                TransmitterNotify(FrontendGetTransmitter(Frontend));
-                ReceiverNotify(FrontendGetReceiver(Frontend));
+                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue->Index);
+                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
                 break;
 
             default:
@@ -155,88 +166,345 @@ NotifierDpc(
             }
         }
 
-        Pending = __NotifierUnmask(Notifier, Index);
+        Pending = __NotifierQueueUnmask(Queue, Index);
     } while (Pending);
 }
 
 static FORCEINLINE BOOLEAN
-__NotifierEvtchnCallback(
-    IN  PXENVIF_NOTIFIER    Notifier,
-    IN  XENVIF_NOTIFIER_EVTCHN     Index
+__NotifierQueueEvtchnCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  XENVIF_NOTIFIER_EVTCHN      Index
     )
 {
-    Notifier->Events[Index]++;
+    Queue->Events[Index]++;
 
-    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
+    if (KeInsertQueueDpc(&Queue->Dpc[Index],
                          (PVOID)(ULONG_PTR)Index,
                          NULL))
-        Notifier->Dpcs[Index]++;
+        Queue->Dpcs[Index]++;
 
     return TRUE;
 }
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)             \
                                                                         \
-KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
+KSERVICE_ROUTINE    NotifierQueue ## _Type ## EvtchnCallback;           \
                                                                         \
 BOOLEAN                                                                 \
-Notifier ## _Type ## EvtchnCallback(                                    \
+NotifierQueue ## _Type ## EvtchnCallback(                               \
     IN  PKINTERRUPT         InterruptObject,                            \
     IN  PVOID               Argument                                    \
     )                                                                   \
 {                                                                       \
-    PXENVIF_NOTIFIER        Notifier = Argument;                        \
+    PXENVIF_NOTIFIER_QUEUE  Queue = Argument;                           \
                                                                         \
     UNREFERENCED_PARAMETER(InterruptObject);                            \
                                                                         \
-    ASSERT(Notifier != NULL);                                           \
-    return __NotifierEvtchnCallback(Notifier,                           \
+    ASSERT(Queue != NULL);                                              \
+    return __NotifierQueueEvtchnCallback(Queue,                         \
                                     XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
 }
 
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
-    Notifier ## _Type ## EvtchnCallback,
+#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)   \
+    NotifierQueue ## _Type ## EvtchnCallback,
 
-PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
-    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
+PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
+    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
 };
 
-#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
+#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
 
-C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
+C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) == XENVIF_NOTIFIER_EVTCHN_COUNT);
 
 static VOID
-NotifierDebugCallback(
-    IN  PVOID           Argument,
-    IN  BOOLEAN         Crashing
+NotifierQueueDebugCallback(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
     )
 {
-    PXENVIF_NOTIFIER    Notifier = Argument;
-    PXENVIF_FRONTEND    Frontend;
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
     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",
+                     "[%u][%s]: Events = %lu Dpcs = %lu\n",
+                     Queue->Index,
                      ((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]);
+                     Queue->Events[Index],
+                     Queue->Dpcs[Index]);
+}
+
+static NTSTATUS
+NotifierQueueInitialize(
+    IN  PXENVIF_NOTIFIER        Notifier,
+    IN  ULONG                   QueueIndex,
+    OUT PXENVIF_NOTIFIER_QUEUE  *Queue
+    )
+{
+    ULONG       Index;
+    NTSTATUS    status;
+
+    *Queue = __NotifierAllocate(sizeof (XENVIF_NOTIFIER_QUEUE));
+
+    status = STATUS_NO_MEMORY;
+    if (*Queue == NULL)
+        goto fail1;
+
+    (*Queue)->Notifier = Notifier;
+    (*Queue)->Index = QueueIndex;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
+        KeInitializeDpc(&(*Queue)->Dpc[Index],
+                        NotifierQueueDpc,
+                        *Queue);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueConnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER        Notifier;
+    PXENVIF_FRONTEND        Frontend;
+    LONG                    Index;
+    NTSTATUS                status;
+
+    Notifier = Queue->Notifier;
+    Frontend = Notifier->Frontend;
+
+    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
+        PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
+        BOOLEAN             Pending;
+
+        Queue->Channel[Index] = XENBUS_EVTCHN(Open,
+                                              &Notifier->EvtchnInterface,
+                                              XENBUS_EVTCHN_TYPE_UNBOUND,
+                                              Callback,
+                                              Queue,
+                                              FrontendGetBackendDomain(Frontend),
+                                              TRUE);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (Queue->Channel[Index] == NULL)
+            goto fail1;
+
+        Pending = XENBUS_EVTCHN(Unmask,
+                                &Notifier->EvtchnInterface,
+                                Queue->Channel[Index],
+                                FALSE);
+        if (Pending)
+            XENBUS_EVTCHN(Trigger,
+                          &Notifier->EvtchnInterface,
+                          Queue->Channel[Index]);
+    }
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    while (--Index >= 0) {
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+
+    return status;
+}
+
+static NTSTATUS
+NotifierQueueStoreWrite(
+    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
+    IN  PXENBUS_STORE_TRANSACTION   Transaction
+    )
+{
+    PXENVIF_NOTIFIER                Notifier = Queue->Notifier;
+    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,
+                             Queue->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;
+}
+
+static NTSTATUS
+NotifierQueueEnable(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    ULONG               Index;
+
+    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(&Queue->Dpc[Index],
+                             (PVOID)(ULONG_PTR)Index,
+                             NULL))
+            Queue->Dpcs[Index]++;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static VOID
+NotifierQueueDisconnect(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
+    LONG                Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        if (Queue->Channel[Index] == NULL)
+            continue;
+
+        XENBUS_EVTCHN(Close,
+                      &Notifier->EvtchnInterface,
+                      Queue->Channel[Index]);
+        Queue->Channel[Index] = NULL;
+
+        Queue->Events[Index] = 0;
+    }
+}
+
+static VOID
+NotifierQueueTeardown(
+    IN  PXENVIF_NOTIFIER_QUEUE  Queue
+    )
+{
+    LONG        Index;
+
+    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    while (--Index >= 0) {
+        Queue->Dpcs[Index] = 0;
+        RtlZeroMemory(&Queue->Dpc[Index], sizeof (KDPC));
+    }
+
+    Queue->Notifier = NULL;
+    Queue->Index = 0;
+
+    ASSERT(IsZeroMemory(Queue, sizeof (XENVIF_NOTIFIER_QUEUE)));
+
+    __NotifierFree(Queue);
+}
+
+static VOID
+NotifierDebugCallback(
+    IN  PVOID           Argument,
+    IN  BOOLEAN         Crashing
+    )
+{
+    PXENVIF_NOTIFIER    Notifier = Argument;
+    PLIST_ENTRY         ListEntry;
+
+    UNREFERENCED_PARAMETER(Crashing);
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        NotifierQueueDebugCallback(Queue);
+    }
 }
 
 NTSTATUS
@@ -266,13 +534,41 @@ NotifierInitialize(
     (*Notifier)->Frontend = Frontend;
 
     KeInitializeSpinLock(&(*Notifier)->Lock);
-    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
-        KeInitializeDpc(&(*Notifier)->Dpc[Index],
-                        NotifierDpc,
-                        *Notifier);
+    InitializeListHead(&(*Notifier)->List);
+
+    Index = 0;
+    while (Index < DriverGetQueueMax()) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        status = NotifierQueueInitialize(*Notifier, Index, &Queue);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+
+        InsertTailList(&(*Notifier)->List, &Queue->ListEntry);
+        Index++;
+    }
 
     return STATUS_SUCCESS;
 
+fail2:
+    Error("fail2\n");
+
+    while (!IsListEmpty(&(*Notifier)->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&(*Notifier)->List);
+        ASSERT3P(ListEntry, !=, &(*Notifier)->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
+        --Index;
+    }
+    ASSERT3U(Index, ==, 0);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -285,7 +581,7 @@ NotifierConnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
     PCHAR                   Buffer;
     NTSTATUS                status;
 
@@ -308,32 +604,6 @@ NotifierConnect(
     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",
@@ -341,7 +611,7 @@ NotifierConnect(
                           Notifier,
                           &Notifier->DebugCallback);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail4;
 
     status = XENBUS_STORE(Read,
                           &Notifier->StoreInterface,
@@ -359,6 +629,20 @@ NotifierConnect(
                      Buffer);
     }
 
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        status = NotifierQueueConnect(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail5;
+    }
+
     Notifier->Connected = TRUE;
     KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
 
@@ -367,20 +651,19 @@ NotifierConnect(
 fail5:
     Error("fail5\n");
 
-    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-fail4:
-    Error("fail4\n");
-
-    while (--Index >= 0) {
-        XENBUS_EVTCHN(Close,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel[Index]);
-        Notifier->Channel[Index] = NULL;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
 
-        Notifier->Events[Index] = 0;
+        NotifierQueueDisconnect(Queue);
     }
 
+fail4:
+    Error("fail4\n");
+
     XENBUS_STORE(Release, &Notifier->StoreInterface);
 
 fail3:
@@ -408,54 +691,20 @@ NotifierStoreWrite(
     )
 {
     PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
-    ULONG                           Index;
+    PLIST_ENTRY                     ListEntry;
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            Node = "";
-            break;
-        }
-
-        Port = XENBUS_EVTCHN(GetPort,
-                             &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
-
-        status = XENBUS_STORE(Printf,
-                              &Notifier->StoreInterface,
-                              Transaction,
-                              FrontendGetPath(Frontend),
-                              Node,
-                              "%u",
-                              Port);
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
+        status = NotifierQueueStoreWrite(Queue,
+                                         Transaction);
         if (!NT_SUCCESS(status))
             goto fail1;
     }
@@ -473,44 +722,34 @@ NotifierEnable(
     IN  PXENVIF_NOTIFIER    Notifier
     )
 {   
-    ULONG                   Index;
+    PLIST_ENTRY             ListEntry;
+    PXENVIF_FRONTEND        Frontend;
+    NTSTATUS                status;
+
+    Frontend = Notifier->Frontend;
 
     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);
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-            break;
-        }
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index > FrontendGetQueueCount(Frontend))
+            continue;
 
-        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
-                             (PVOID)(ULONG_PTR)Index,
-                             NULL))
-            Notifier->Dpcs[Index]++;
+        status = NotifierQueueEnable(Queue);
+        if (!NT_SUCCESS(status))
+            goto fail1;
     }
 
     return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+    return status;
 }
 
 VOID
@@ -528,7 +767,7 @@ NotifierDisconnect(
     )
 {
     PXENVIF_FRONTEND        Frontend;
-    LONG                    Index;
+    PLIST_ENTRY             ListEntry;
 
     Frontend = Notifier->Frontend;
 
@@ -544,14 +783,16 @@ NotifierDisconnect(
                  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;
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
 
-        Notifier->Events[Index] = 0;
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+
+        NotifierQueueDisconnect(Queue);
     }
 
     XENBUS_STORE(Release, &Notifier->StoreInterface);
@@ -568,15 +809,21 @@ 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));
+    while (!IsListEmpty(&Notifier->List)) {
+        PLIST_ENTRY             ListEntry;
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        ListEntry = RemoveTailList(&Notifier->List);
+        ASSERT3P(ListEntry, !=, &Notifier->List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+
+        NotifierQueueTeardown(Queue);
     }
 
     Notifier->Frontend = NULL;
@@ -590,6 +837,7 @@ NotifierTeardown(
     RtlZeroMemory(&Notifier->EvtchnInterface,
                   sizeof (XENBUS_EVTCHN_INTERFACE));
 
+    RtlZeroMemory(&Notifier->List, sizeof(LIST_ENTRY));
     RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
 
     ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
@@ -600,85 +848,125 @@ NotifierTeardown(
 static FORCEINLINE VOID
 __NotifierSend(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Send,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 static FORCEINLINE VOID
 __NotifierTrigger(
     IN  PXENVIF_NOTIFIER    Notifier,
-    IN  ULONG               Index
+    IN  ULONG               Index,
+    IN  ULONG               QueueIndex
     )
 {
     PXENVIF_FRONTEND        Frontend;
+    PLIST_ENTRY             ListEntry;
     KIRQL                   Irql;
 
     Frontend = Notifier->Frontend;
 
     KeAcquireSpinLock(&Notifier->Lock, &Irql);
 
-    if (Notifier->Connected)
+    if (!Notifier->Connected)
+        goto done;
+
+    for (ListEntry = Notifier->List.Flink;
+         ListEntry != &Notifier->List;
+         ListEntry = ListEntry->Flink) {
+        PXENVIF_NOTIFIER_QUEUE  Queue;
+
+        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE, ListEntry);
+        if (Queue->Index >= FrontendGetQueueCount(Frontend))
+            continue;
+        if (Queue->Index != QueueIndex)
+            continue;
+
         (VOID) XENBUS_EVTCHN(Trigger,
                              &Notifier->EvtchnInterface,
-                             Notifier->Channel[Index]);
+                             Queue->Channel[Index]);
+        break;
+    }
 
+done:
     KeReleaseSpinLock(&Notifier->Lock, Irql);
 }
 
 VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
 
 VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     )
 {
     if (Notifier->Split)
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
     else
-        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
+        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED, Queue);
 }
diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
index 2f06a6f..fd28060 100644
--- a/src/xenvif/notifier.h
+++ b/src/xenvif/notifier.h
@@ -78,22 +78,26 @@ NotifierTeardown(
 
 extern VOID
 NotifierSendTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierSendRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerTx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 extern VOID
 NotifierTriggerRx(
-    IN  PXENVIF_NOTIFIER    Notifier
+    IN  PXENVIF_NOTIFIER    Notifier,
+    IN  ULONG               Queue
     );
 
 #endif  // _XENVIF_NOTIFIER_H
diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
index 626feed..85ebcf9 100644
--- a/src/xenvif/receiver.c
+++ b/src/xenvif/receiver.c
@@ -1397,7 +1397,7 @@ __ReceiverRingReturnPacket(
             Receiver = Ring->Receiver;
             Frontend = Receiver->Frontend;
 
-            NotifierTriggerRx(FrontendGetNotifier(Frontend));
+            NotifierTriggerRx(FrontendGetNotifier(Frontend), Ring->Index);
         }
 
         if (!Locked)
@@ -1477,7 +1477,7 @@ __ReceiverRingPushRequests(
         Receiver = Ring->Receiver;
         Frontend = Receiver->Frontend;
 
-        NotifierSendRx(FrontendGetNotifier(Frontend));
+        NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -1869,7 +1869,7 @@ ReceiverRingWatchdog(
 
                 // Try to move things along
                 ReceiverRingPoll(Ring);
-                NotifierSendRx(FrontendGetNotifier(Frontend));
+                NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
             }
 
             KeMemoryBarrier();
@@ -2941,7 +2941,8 @@ ReceiverWaitForPackets(
 
 VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -2952,6 +2953,8 @@ ReceiverNotify(
         PXENVIF_RECEIVER_RING   Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __ReceiverRingNotify(Ring);
     }    
diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
index 8009858..1505887 100644
--- a/src/xenvif/receiver.h
+++ b/src/xenvif/receiver.h
@@ -79,7 +79,8 @@ ReceiverTeardown(
 
 extern VOID
 ReceiverNotify(
-    IN  PXENVIF_RECEIVER    Receiver
+    IN  PXENVIF_RECEIVER    Receiver,
+    IN  ULONG               Index
     );
 
 extern VOID
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index bea46f1..477fecc 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -2195,7 +2195,7 @@ __TransmitterRingPushRequests(
         Transmitter = Ring->Transmitter;
         Frontend = Transmitter->Frontend;
 
-        NotifierSendTx(FrontendGetNotifier(Frontend));
+        NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
     }
 
     Ring->RequestsPushed = Ring->RequestsPosted;
@@ -2624,7 +2624,7 @@ TransmitterRingWatchdog(
                              Ring->DebugCallback);
 
                 // Try to move things along
-                NotifierSendTx(FrontendGetNotifier(Frontend));
+                NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
                 TransmitterRingPoll(Ring);
             }
 
@@ -3972,7 +3972,8 @@ TransmitterQueryRingSize(
 
 VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     )
 {
     PLIST_ENTRY             ListEntry;
@@ -3983,6 +3984,8 @@ TransmitterNotify(
         PXENVIF_TRANSMITTER_RING    Ring;
 
         Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING, ListEntry);
+        if (Ring->Index != Index)
+            continue;
 
         __TransmitterRingNotify(Ring);
     }    
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 7e10603..3e56b34 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -79,7 +79,8 @@ TransmitterTeardown(
 
 extern VOID
 TransmitterNotify(
-    IN  PXENVIF_TRANSMITTER Transmitter
+    IN  PXENVIF_TRANSMITTER Transmitter,
+    IN  ULONG               Index
     );
 
 extern VOID
-- 
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 Wed Nov 12 16:39:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax4-0003Xq-Ur; Wed, 12 Nov 2014 16:39:26 +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 1Xoax3-0003Wj-WF
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:26 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	C0/22-09842-D3D83645; Wed, 12 Nov 2014 16:39:25 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-5.tower-21.messagelabs.com!1415810360!12226299!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17999 invoked from network); 12 Nov 2014 16:39:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032202"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:58 +0000
Message-ID: <1415810347-7152-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 01/10] Rework transmitter packet code to use
	an internal cache of objects
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 XENVIF_TRANSMITTER_PACKET_V2 for queueing packets, with a
translation on entry and exit through the interface (for v1)
Renames XENVIF_TRANSMITTER_PACKET to XENVIF_TRANSMITTER_PACKET_V1
XENVIF_TRANSMITTER_PACKET_V2 is allocated from a cache and not
included inline in the miniport reserved area of a NET_BUFFER, like 
XENVIF_TRANSMITTER_PACKET_V1.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  37 ++--
 src/xenvif/transmitter.c | 477 ++++++++++++++++++++++++++++++++---------------
 src/xenvif/transmitter.h |   6 +-
 src/xenvif/vif.c         |  12 +-
 src/xenvif/vif.h         |   4 +-
 5 files changed, 368 insertions(+), 168 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..8bde731 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,9 +265,24 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
+    \brief Transmit-side packet structure
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    LIST_ENTRY                                  ListEntry;
+    PMDL                                        Mdl;
+    ULONG                                       Offset;
+    ULONG                                       Length;
+    PVOID                                       Cookie;
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
-    XENVIF_TRANSMITTER_PACKET pointer
+    XENVIF_TRANSMITTER_PACKET_V1 pointer
 
     Because the transmit side packet structure is limited to 3 pointer
     types in size, not all information about the packet can be passed in
@@ -380,10 +395,10 @@ typedef VOID
     \param ... Additional paramaters required by \a Type
 
     \b XENVIF_TRANSMITTER_RETURN_PACKETS:
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
 
     \b XENVIF_RECEIVER_QUEUE_PACKETS:
-    \param List List of XENVIF_TRANSMITTER_PACKET
+    \param List List of XENVIF_RECEIVER_PACKET
 
     \b XENVIF_MAC_STATE_CHANGE:
     No additional arguments
@@ -459,7 +474,7 @@ typedef VOID
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
     \brief Set byte offset of packet information relative to
-    XENVIF_TRANSMITTER_PACKET pointer.
+    XENVIF_TRANSMITTER_PACKET_V1 pointer.
 
     See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
 
@@ -474,16 +489,16 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
-/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
     \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
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -694,7 +709,7 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
     XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
     XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET        TransmitterSetPacketOffset;
-    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS            TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;
     XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
     XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
     XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..38e4cb2 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -88,7 +88,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_V2       Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -100,8 +100,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;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
 } XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
 
 typedef struct _XENVIF_TRANSMITTER_RING {
@@ -118,7 +118,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
-    PXENVIF_TRANSMITTER_PACKET      Lock;
+    PLIST_ENTRY                     Lock;
     PKTHREAD                        LockThread;
     XENVIF_TRANSMITTER_PACKET_LIST  Queued;
     XENVIF_TRANSMITTER_STATE        State;
@@ -133,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;
@@ -146,6 +146,7 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
+    PXENBUS_CACHE               PacketCache;
     LIST_ENTRY                  List;
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
     ULONG                       DisableIpVersion4Gso;
@@ -362,7 +363,7 @@ __TransmitterGetFragment(
                         TRUE);
 }
 
-static FORCEINLINE
+static FORCEINLINE VOID
 __TransmitterPutFragment(
     IN  PXENVIF_TRANSMITTER_RING        Ring,
     IN  PXENVIF_TRANSMITTER_FRAGMENT    Fragment
@@ -387,6 +388,67 @@ __TransmitterPutFragment(
                  TRUE);
 }
 
+static NTSTATUS
+TransmitterPacketCtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
+    return STATUS_SUCCESS;
+}
+
+static VOID
+TransmitterPacketDtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+TransmitterPacketLock(
+    IN  PVOID                       Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static VOID
+TransmitterPacketUnlock(
+    IN  PVOID                       Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
+__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_V2   Packet
+    )
+{
+    XENBUS_CACHE(Put,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 TRUE);
+}
+
 static VOID
 TransmitterRingDebugCallback(
     IN  PVOID                   Argument,
@@ -523,25 +585,25 @@ fail1:
     return FALSE;
 }
 
-#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            (*Reference)++;                                         \
+#define INCREMENT_PACKET_REFERENCE(_Packet)                                 \
+        do {                                                                \
+            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->ListEntry.Flink; \
+                                                                            \
+            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);                                         \
+#define DECREMENT_PACKET_REFERENCE(_Packet)                                 \
+        do {                                                                \
+            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->ListEntry.Flink; \
+                                                                            \
+            ASSERT(Packet != NULL);                                         \
+            ASSERT(*Reference != 0);                                        \
+            --(*Reference);                                                 \
         } while (FALSE)
 
-#define PACKET_REFERENCE(_Packet)                                   \
-        (*(PULONG_PTR)&(_Packet)->Next)
+#define PACKET_REFERENCE(_Packet)                                           \
+        (*(PULONG_PTR)&(_Packet)->ListEntry.Flink)
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingCopyPayload(
@@ -551,7 +613,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -698,7 +760,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -845,7 +907,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -1122,7 +1184,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET      Packet;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
         --State->Count;
 
@@ -1178,19 +1240,10 @@ __TransmitterRingUnprepareFragments(
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   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;
@@ -1198,7 +1251,7 @@ __TransmitterRingPreparePacket(
     NTSTATUS                        status;
 
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
-    ASSERT3P(Packet->Next, ==, NULL);
+    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
 
     Transmitter = Ring->Transmitter;
 
@@ -1211,16 +1264,9 @@ __TransmitterRingPreparePacket(
 
     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);
@@ -1325,18 +1371,15 @@ fail1:
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
 
     return status;
-
-#undef  OFFSET
-#undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1695,7 +1738,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1920,8 +1963,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_V2   Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -1980,9 +2023,9 @@ __TransmitterRingCompletePacket(
         }
     }
 
-    *Ring->Completed.TailPacket = Packet;
-    ASSERT3P(Packet->Next, ==, NULL);
-    Ring->Completed.TailPacket = &Packet->Next;
+    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
+    ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
+    InsertTailList(&Ring->Completed, &Packet->ListEntry);
 
     Ring->PacketsCompleted++;
 }
@@ -2019,7 +2062,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET      Packet;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2164,30 +2207,30 @@ __TransmitterRingPushRequests(
 
 static FORCEINLINE ULONG
 __TransmitterReversePacketList(
-    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
+    IN  PLIST_ENTRY                 *Entry
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
+    PLIST_ENTRY                     HeadEntry;
     ULONG                           Count;
 
-    HeadPacket = NULL;
+    HeadEntry = NULL;
     Count = 0;
 
-    while (*Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+    while (*Entry != NULL) {
+        PLIST_ENTRY     Next;
 
-        ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
+        ASSERT(((ULONG_PTR)*Entry & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
 
-        Next = (*Packet)->Next;
+        Next = (*Entry)->Flink;
 
-        (*Packet)->Next = HeadPacket;
-        HeadPacket = *Packet;
+        (*Entry)->Flink = HeadEntry;
+        HeadEntry = *Entry;
 
-        *Packet = Next;
+        *Entry = Next;
         Count++;
     }
 
-    *Packet = HeadPacket;
+    *Entry = HeadEntry;
 
     return Count;
 }
@@ -2199,8 +2242,8 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
@@ -2209,21 +2252,21 @@ TransmitterRingSwizzle(
     Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock, (PVOID)New);
 
     ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
-    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+    HeadEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
 
-    if (HeadPacket == NULL)
+    if (HeadEntry == 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);
+    TailEntry = &HeadEntry->Flink;
+    Count = __TransmitterReversePacketList(&HeadEntry);
+    ASSERT3P(*TailEntry, ==, NULL);
 
-    *(Ring->Queued.TailPacket) = HeadPacket;
-    Ring->Queued.TailPacket = TailPacket;
+    *(Ring->Queued.TailEntry) = HeadEntry;
+    Ring->Queued.TailEntry = TailEntry;
     Ring->PacketsQueued += Count;
 }
 
@@ -2240,8 +2283,9 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET  Packet;
-        NTSTATUS                    status;
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+        NTSTATUS                        status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2290,19 +2334,20 @@ TransmitterRingSchedule(
             continue;
         }
 
-        Packet = Ring->Queued.HeadPacket;
-
-        if (Packet == NULL)
+        ListEntry = Ring->Queued.HeadEntry;
+        if (ListEntry == NULL)
             break;
 
-        if (Packet->Next == NULL) {
-            Ring->Queued.HeadPacket = NULL;
-            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
+        if (ListEntry->Flink == NULL) {
+            Ring->Queued.HeadEntry = NULL;
+            Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
         } else {
-            Ring->Queued.HeadPacket = Packet->Next;
-            Packet->Next = NULL;
+            Ring->Queued.HeadEntry = ListEntry->Flink;
+            ListEntry->Flink = NULL;
         }
 
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
         status = __TransmitterRingPreparePacket(Ring, Packet);
         if (!NT_SUCCESS(status)) {
             PXENVIF_TRANSMITTER Transmitter;
@@ -2330,11 +2375,46 @@ TransmitterRingSchedule(
         ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
     }
 
-    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring->Queued.TailPacket == &Ring->Queued.HeadPacket));
+    ASSERT(IMPLY(Ring->Queued.HeadEntry == NULL, Ring->Queued.TailEntry == &Ring->Queued.HeadEntry));
 
     __TransmitterRingPushRequests(Ring);
 }
 
+static VOID
+TransmitterReturnPackets(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PLIST_ENTRY                 List
+    )
+{
+    PXENVIF_FRONTEND                Frontend;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
+
+    HeadPacket = NULL;
+    NextPacket = NULL;
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+        ListEntry = RemoveTailList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
+        HeadPacket = Packet->Cookie;
+        HeadPacket->Next = NextPacket;
+        HeadPacket->Completion = Packet->Completion;
+
+        __TransmitterPutPacket(Transmitter, Packet);
+        NextPacket = HeadPacket;
+    }
+
+    Frontend = Transmitter->Frontend;
+
+    VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                HeadPacket);
+}
+
 static FORCEINLINE BOOLEAN
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingTryAcquireLock(
@@ -2427,16 +2507,29 @@ __TransmitterRingTryReleaseLock(
 }
 
 static FORCEINLINE VOID
+__AppendTailList(
+    IN OUT PLIST_ENTRY              List,
+    IN OUT PLIST_ENTRY              Apendee
+    )
+{
+    PLIST_ENTRY HeadEntry = Apendee->Flink;
+
+    if (!IsListEmpty(Apendee)) {
+        RemoveEntryList(Apendee);
+        InitializeListHead(Apendee);
+        AppendTailList(List, HeadEntry);
+    }
+}
+
+static FORCEINLINE VOID
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
-    
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    LIST_ENTRY          List;
+
+    InitializeListHead(&List);
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
@@ -2449,22 +2542,11 @@ __TransmitterRingReleaseLock(
         TransmitterRingSwizzle(Ring);
         TransmitterRingSchedule(Ring);
 
-        *TailPacket = Ring->Completed.HeadPacket;
-        TailPacket = Ring->Completed.TailPacket;
-
-        Ring->Completed.HeadPacket = NULL;
-        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
+        __AppendTailList(&List, &Ring->Completed);
     } while (!__TransmitterRingTryReleaseLock(Ring));
 
-    if (HeadPacket != NULL) {
-        PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
-
-        Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
-
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+    if (!IsListEmpty(&List)) {
+        TransmitterReturnPackets(Ring->Transmitter, &List);
     }
 }
 
@@ -2624,8 +2706,8 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
-    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
-    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    (*Ring)->Queued.TailEntry = &(*Ring)->Queued.HeadEntry;
+    InitializeListHead(&(*Ring)->Completed);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -2756,8 +2838,8 @@ fail3:
 fail2:
     Error("fail2\n");
 
-    (*Ring)->Queued.TailPacket = NULL;
-    (*Ring)->Completed.TailPacket = NULL;
+    (*Ring)->Queued.TailEntry = NULL;
+    RtlZeroMemory(&(*Ring)->Completed, sizeof(LIST_ENTRY));
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -2910,7 +2992,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -2929,14 +3011,15 @@ __TransmitterRingDisable(
 
     // Put any packet back on the head of the queue
     if (Packet != NULL) {
-        ASSERT3P(Packet->Next, ==, NULL);
+        ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
+        ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
 
-        Packet->Next = Ring->Queued.HeadPacket;
+        Packet->ListEntry.Flink = Ring->Queued.HeadEntry;
 
-        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
-            Ring->Queued.TailPacket = &Packet->Next;
+        if (Ring->Queued.TailEntry == &Ring->Queued.HeadEntry)
+            Ring->Queued.TailEntry = &Packet->ListEntry.Flink;
 
-        Ring->Queued.HeadPacket = Packet;
+        Ring->Queued.HeadEntry = &Packet->ListEntry;
     }
 
     Ring->AddressIndex = 0;
@@ -3076,11 +3159,11 @@ __TransmitterRingTeardown(
                  Ring->BufferCache);
     Ring->BufferCache = NULL;
 
-    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
-    Ring->Queued.TailPacket = NULL;
+    ASSERT3P(Ring->Queued.TailEntry, ==, &Ring->Queued.HeadEntry);
+    Ring->Queued.TailEntry = NULL;
 
-    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;
@@ -3092,24 +3175,40 @@ __TransmitterRingTeardown(
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+    IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PLIST_ENTRY                     ListEntry;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
 
-    TailPacket = &HeadPacket->Next;
-    (VOID) __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
+    ListEntry = RemoveTailList(List);
+    ASSERT3P(ListEntry, !=, List);
+
+    ListEntry->Flink = NULL;
+    ListEntry->Blink = NULL;
+    HeadEntry = ListEntry;
+
+    TailEntry = &ListEntry->Flink;
+    while (!IsListEmpty(List)) {
+        ListEntry = RemoveTailList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        ListEntry->Flink = HeadEntry;
+        ListEntry->Blink = NULL;
+        HeadEntry = ListEntry;
+    }
+    ASSERT3P(*TailEntry, ==, NULL);
 
     do {
         Old = (ULONG_PTR)Ring->Lock;
         LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
 
-        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
-        New = (ULONG_PTR)HeadPacket;
+        *TailEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+        New = (ULONG_PTR)HeadEntry;
         ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
         New |= LockBit;
     } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock, (PVOID)New, (PVOID)Old) != Old);
@@ -3128,33 +3227,35 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PLIST_ENTRY                     ListEntry;
 
     __TransmitterRingAcquireLock(Ring);
 
     TransmitterRingSwizzle(Ring);
 
-    Packet = Ring->Queued.HeadPacket;
+    ListEntry = Ring->Queued.HeadEntry;
 
-    Ring->Queued.HeadPacket = NULL;
-    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
+    Ring->Queued.HeadEntry = NULL;
+    Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
 
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+    while (ListEntry != NULL) {
+        PLIST_ENTRY                     Next;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
         
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        Next = ListEntry->Flink;
+        ListEntry->Flink = NULL;
 
         // Fake that we prapared and sent this packet
         Ring->PacketsPrepared++;
         Ring->PacketsSent++;
         Ring->PacketsFaked++;
 
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
         Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
 
         __TransmitterRingCompletePacket(Ring, Packet);
 
-        Packet = Next;
+        ListEntry = Next;
     }
 
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
@@ -3264,13 +3365,27 @@ TransmitterInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_CACHE(Create,
+                          &(*Transmitter)->CacheInterface,
+                          "packet_cache",
+                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
+                          0,
+                          TransmitterPacketCtor,
+                          TransmitterPacketDtor,
+                          TransmitterPacketLock,
+                          TransmitterPacketUnlock,
+                          *Transmitter,
+                          &(*Transmitter)->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     Index = 0;
     while (Index < Count) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail5;
 
         InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
         Index++;
@@ -3278,8 +3393,8 @@ TransmitterInitialize(
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
+fail5:
+    Error("fail5\n");
 
     while (!IsListEmpty(&(*Transmitter)->List)) {
         PLIST_ENTRY                 ListEntry;
@@ -3297,6 +3412,14 @@ fail4:
     }
     ASSERT3U(Index, ==, 0);
 
+    XENBUS_CACHE(Destroy,
+                 &(*Transmitter)->CacheInterface,
+                 (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
     XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
 
 fail3:
@@ -3530,6 +3653,11 @@ TransmitterTeardown(
         __TransmitterRingTeardown(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
     XENBUS_CACHE(Release, &Transmitter->CacheInterface);
 
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
@@ -3620,20 +3748,77 @@ fail1:
 }
 
 VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+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;
     PLIST_ENTRY                     ListEntry;
     PXENVIF_TRANSMITTER_RING        Ring;
 
+    InitializeListHead(&List);
+    while (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+        Packet = __TransmitterGetPacket(Transmitter);
+        if (Packet == NULL) {
+            Warning("Out-of-cached-packets\n");
+            break;
+        }
+
+        Packet->Cookie = HeadPacket;
+        RtlCopyMemory(&Packet->Send, &HeadPacket->Send, sizeof(Packet->Send));
+        RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
+
+        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;
+    }
+    
     // 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);
 
-    __TransmitterRingQueuePackets(Ring, HeadPacket);
+    __TransmitterRingQueuePackets(Ring, &List);
+
+    // if HeadPacket != NULL, errors occured and need returning
+    if (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        PXENVIF_FRONTEND                Frontend;
+
+        Frontend = Transmitter->Frontend;
+
+        Packet = HeadPacket;
+        while (Packet != NULL) {
+            Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
+            Packet = Packet->Next;
+        }
+
+        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                    HeadPacket);
+    }
+
+#undef OFFSET
+#undef OFFSET_EXISTS
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 5ffb590..661eeae 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -107,9 +107,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..d6da258 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -276,8 +276,8 @@ VifReceiverReturnPackets(
 
 static NTSTATUS
 VifTransmitterQueuePackets(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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);
 
@@ -784,8 +784,8 @@ VifReceiverQueuePackets(
 
 VOID
 VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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..0ef6687 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -70,8 +70,8 @@ VifReceiverQueuePackets(
 
 extern VOID
 VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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 Wed Nov 12 16:39:27 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:39: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 1Xoax4-0003Xq-Ur; Wed, 12 Nov 2014 16:39:26 +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 1Xoax3-0003Wj-WF
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:39:26 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	C0/22-09842-D3D83645; Wed, 12 Nov 2014 16:39:25 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-5.tower-21.messagelabs.com!1415810360!12226299!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17999 invoked from network); 12 Nov 2014 16:39:23 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:39:23 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192032202"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:58 +0000
Message-ID: <1415810347-7152-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 01/10] Rework transmitter packet code to use
	an internal cache of objects
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 XENVIF_TRANSMITTER_PACKET_V2 for queueing packets, with a
translation on entry and exit through the interface (for v1)
Renames XENVIF_TRANSMITTER_PACKET to XENVIF_TRANSMITTER_PACKET_V1
XENVIF_TRANSMITTER_PACKET_V2 is allocated from a cache and not
included inline in the miniport reserved area of a NET_BUFFER, like 
XENVIF_TRANSMITTER_PACKET_V1.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 include/vif_interface.h  |  37 ++--
 src/xenvif/transmitter.c | 477 ++++++++++++++++++++++++++++++++---------------
 src/xenvif/transmitter.h |   6 +-
 src/xenvif/vif.c         |  12 +-
 src/xenvif/vif.h         |   4 +-
 5 files changed, 368 insertions(+), 168 deletions(-)

diff --git a/include/vif_interface.h b/include/vif_interface.h
index 498ed8f..8bde731 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,9 +265,24 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET, *PXENVIF
 
 C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
 
+/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
+    \brief Transmit-side packet structure
+*/
+struct _XENVIF_TRANSMITTER_PACKET_V2 {
+    LIST_ENTRY                                  ListEntry;
+    PMDL                                        Mdl;
+    ULONG                                       Offset;
+    ULONG                                       Length;
+    PVOID                                       Cookie;
+    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
+    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
+};
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_V2 XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
+
 /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
     \brief Offsets of packet metadata relative to
-    XENVIF_TRANSMITTER_PACKET pointer
+    XENVIF_TRANSMITTER_PACKET_V1 pointer
 
     Because the transmit side packet structure is limited to 3 pointer
     types in size, not all information about the packet can be passed in
@@ -380,10 +395,10 @@ typedef VOID
     \param ... Additional paramaters required by \a Type
 
     \b XENVIF_TRANSMITTER_RETURN_PACKETS:
-    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
+    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
 
     \b XENVIF_RECEIVER_QUEUE_PACKETS:
-    \param List List of XENVIF_TRANSMITTER_PACKET
+    \param List List of XENVIF_RECEIVER_PACKET
 
     \b XENVIF_MAC_STATE_CHANGE:
     No additional arguments
@@ -459,7 +474,7 @@ typedef VOID
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
     \brief Set byte offset of packet information relative to
-    XENVIF_TRANSMITTER_PACKET pointer.
+    XENVIF_TRANSMITTER_PACKET_V1 pointer.
 
     See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
 
@@ -474,16 +489,16 @@ typedef NTSTATUS
     IN  LONG_PTR                            Value
     );
 
-/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
+/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
     \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
+(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
+    IN  PINTERFACE                      Interface,
+    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
     );
 
 /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
@@ -694,7 +709,7 @@ struct _XENVIF_VIF_INTERFACE_V1 {
     XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS         ReceiverSetOffloadOptions;
     XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
     XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET        TransmitterSetPacketOffset;
-    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS            TransmitterQueuePackets;
+    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1         TransmitterQueuePackets;
     XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS    TransmitterQueryOffloadOptions;
     XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE  TransmitterQueryLargePacketSize;
     XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE          TransmitterQueryRingSize;
diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
index 8125a5a..38e4cb2 100644
--- a/src/xenvif/transmitter.c
+++ b/src/xenvif/transmitter.c
@@ -88,7 +88,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_V2       Packet;
     XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
     PUCHAR                              StartVa;
     XENVIF_PACKET_INFO                  Info;
@@ -100,8 +100,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;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
 } XENVIF_TRANSMITTER_PACKET_LIST, *PXENVIF_TRANSMITTER_PACKET_LIST;
 
 typedef struct _XENVIF_TRANSMITTER_RING {
@@ -118,7 +118,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
     BOOLEAN                         Connected;
     BOOLEAN                         Enabled;
     BOOLEAN                         Stopped;
-    PXENVIF_TRANSMITTER_PACKET      Lock;
+    PLIST_ENTRY                     Lock;
     PKTHREAD                        LockThread;
     XENVIF_TRANSMITTER_PACKET_LIST  Queued;
     XENVIF_TRANSMITTER_STATE        State;
@@ -133,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;
@@ -146,6 +146,7 @@ struct _XENVIF_TRANSMITTER {
     PXENVIF_FRONTEND            Frontend;
     XENBUS_CACHE_INTERFACE      CacheInterface;
     XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
+    PXENBUS_CACHE               PacketCache;
     LIST_ENTRY                  List;
     LONG_PTR                    Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
     ULONG                       DisableIpVersion4Gso;
@@ -362,7 +363,7 @@ __TransmitterGetFragment(
                         TRUE);
 }
 
-static FORCEINLINE
+static FORCEINLINE VOID
 __TransmitterPutFragment(
     IN  PXENVIF_TRANSMITTER_RING        Ring,
     IN  PXENVIF_TRANSMITTER_FRAGMENT    Fragment
@@ -387,6 +388,67 @@ __TransmitterPutFragment(
                  TRUE);
 }
 
+static NTSTATUS
+TransmitterPacketCtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
+    return STATUS_SUCCESS;
+}
+
+static VOID
+TransmitterPacketDtor(
+    IN  PVOID                       Argument,
+    IN  PVOID                       Object
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+    UNREFERENCED_PARAMETER(Object);
+}
+
+static VOID
+TransmitterPacketLock(
+    IN  PVOID                       Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static VOID
+TransmitterPacketUnlock(
+    IN  PVOID                       Argument
+    )
+{
+    UNREFERENCED_PARAMETER(Argument);
+}
+
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
+__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_V2   Packet
+    )
+{
+    XENBUS_CACHE(Put,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache,
+                 Packet,
+                 TRUE);
+}
+
 static VOID
 TransmitterRingDebugCallback(
     IN  PVOID                   Argument,
@@ -523,25 +585,25 @@ fail1:
     return FALSE;
 }
 
-#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
-        do {                                                        \
-            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
-                                                                    \
-            ASSERT(Packet != NULL);                                 \
-            (*Reference)++;                                         \
+#define INCREMENT_PACKET_REFERENCE(_Packet)                                 \
+        do {                                                                \
+            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->ListEntry.Flink; \
+                                                                            \
+            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);                                         \
+#define DECREMENT_PACKET_REFERENCE(_Packet)                                 \
+        do {                                                                \
+            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->ListEntry.Flink; \
+                                                                            \
+            ASSERT(Packet != NULL);                                         \
+            ASSERT(*Reference != 0);                                        \
+            --(*Reference);                                                 \
         } while (FALSE)
 
-#define PACKET_REFERENCE(_Packet)                                   \
-        (*(PULONG_PTR)&(_Packet)->Next)
+#define PACKET_REFERENCE(_Packet)                                           \
+        (*(PULONG_PTR)&(_Packet)->ListEntry.Flink)
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingCopyPayload(
@@ -551,7 +613,7 @@ __TransmitterRingCopyPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     XENVIF_PACKET_PAYLOAD           Payload;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
     PXENVIF_TRANSMITTER_BUFFER      Buffer;
@@ -698,7 +760,7 @@ __TransmitterRingGrantPayload(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PMDL                            Mdl;
     ULONG                           Offset;
@@ -845,7 +907,7 @@ __TransmitterRingPrepareHeader(
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_MAC                     Mac;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     PXENVIF_PACKET_INFO             Info;
     PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
@@ -1122,7 +1184,7 @@ __TransmitterRingUnprepareFragments(
     while (State->Count != 0) {
         PLIST_ENTRY                     ListEntry;
         PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-        PXENVIF_TRANSMITTER_PACKET      Packet;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
         --State->Count;
 
@@ -1178,19 +1240,10 @@ __TransmitterRingUnprepareFragments(
 
 static FORCEINLINE NTSTATUS
 __TransmitterRingPreparePacket(
-    IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    IN  PXENVIF_TRANSMITTER_RING        Ring,
+    IN  PXENVIF_TRANSMITTER_PACKET_V2   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;
@@ -1198,7 +1251,7 @@ __TransmitterRingPreparePacket(
     NTSTATUS                        status;
 
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
-    ASSERT3P(Packet->Next, ==, NULL);
+    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
 
     Transmitter = Ring->Transmitter;
 
@@ -1211,16 +1264,9 @@ __TransmitterRingPreparePacket(
 
     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);
@@ -1325,18 +1371,15 @@ fail1:
     ASSERT(IsZeroMemory(&Ring->State, sizeof (XENVIF_TRANSMITTER_STATE)));
 
     return status;
-
-#undef  OFFSET
-#undef  OFFSET_EXISTS
 }
 
-static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
+static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
 __TransmitterRingUnpreparePacket(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
     State = &Ring->State;
     Packet = State->Packet;
@@ -1695,7 +1738,7 @@ __TransmitterRingPostFragments(
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
     PXENVIF_TRANSMITTER_STATE       State;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PXENVIF_PACKET_PAYLOAD          Payload;
     RING_IDX                        req_prod;
     RING_IDX                        rsp_cons;
@@ -1920,8 +1963,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_V2   Packet
     )
 {
     PXENVIF_TRANSMITTER             Transmitter;
@@ -1980,9 +2023,9 @@ __TransmitterRingCompletePacket(
         }
     }
 
-    *Ring->Completed.TailPacket = Packet;
-    ASSERT3P(Packet->Next, ==, NULL);
-    Ring->Completed.TailPacket = &Packet->Next;
+    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
+    ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
+    InsertTailList(&Ring->Completed, &Packet->ListEntry);
 
     Ring->PacketsCompleted++;
 }
@@ -2019,7 +2062,7 @@ TransmitterRingPoll(
             netif_tx_response_t             *rsp;
             uint16_t                        id;
             PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
-            PXENVIF_TRANSMITTER_PACKET      Packet;
+            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
 
             rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
             rsp_cons++;
@@ -2164,30 +2207,30 @@ __TransmitterRingPushRequests(
 
 static FORCEINLINE ULONG
 __TransmitterReversePacketList(
-    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
+    IN  PLIST_ENTRY                 *Entry
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
+    PLIST_ENTRY                     HeadEntry;
     ULONG                           Count;
 
-    HeadPacket = NULL;
+    HeadEntry = NULL;
     Count = 0;
 
-    while (*Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+    while (*Entry != NULL) {
+        PLIST_ENTRY     Next;
 
-        ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
+        ASSERT(((ULONG_PTR)*Entry & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
 
-        Next = (*Packet)->Next;
+        Next = (*Entry)->Flink;
 
-        (*Packet)->Next = HeadPacket;
-        HeadPacket = *Packet;
+        (*Entry)->Flink = HeadEntry;
+        HeadEntry = *Entry;
 
-        *Packet = Next;
+        *Entry = Next;
         Count++;
     }
 
-    *Packet = HeadPacket;
+    *Entry = HeadEntry;
 
     return Count;
 }
@@ -2199,8 +2242,8 @@ TransmitterRingSwizzle(
 {
     ULONG_PTR                       Old;
     ULONG_PTR                       New;
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
     ULONG                           Count;
 
     ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
@@ -2209,21 +2252,21 @@ TransmitterRingSwizzle(
     Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock, (PVOID)New);
 
     ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
-    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+    HeadEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
 
-    if (HeadPacket == NULL)
+    if (HeadEntry == 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);
+    TailEntry = &HeadEntry->Flink;
+    Count = __TransmitterReversePacketList(&HeadEntry);
+    ASSERT3P(*TailEntry, ==, NULL);
 
-    *(Ring->Queued.TailPacket) = HeadPacket;
-    Ring->Queued.TailPacket = TailPacket;
+    *(Ring->Queued.TailEntry) = HeadEntry;
+    Ring->Queued.TailEntry = TailEntry;
     Ring->PacketsQueued += Count;
 }
 
@@ -2240,8 +2283,9 @@ TransmitterRingSchedule(
     State = &Ring->State;
 
     for (;;) {
-        PXENVIF_TRANSMITTER_PACKET  Packet;
-        NTSTATUS                    status;
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+        NTSTATUS                        status;
 
         if (State->Count != 0) {
             status = __TransmitterRingPostFragments(Ring);
@@ -2290,19 +2334,20 @@ TransmitterRingSchedule(
             continue;
         }
 
-        Packet = Ring->Queued.HeadPacket;
-
-        if (Packet == NULL)
+        ListEntry = Ring->Queued.HeadEntry;
+        if (ListEntry == NULL)
             break;
 
-        if (Packet->Next == NULL) {
-            Ring->Queued.HeadPacket = NULL;
-            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
+        if (ListEntry->Flink == NULL) {
+            Ring->Queued.HeadEntry = NULL;
+            Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
         } else {
-            Ring->Queued.HeadPacket = Packet->Next;
-            Packet->Next = NULL;
+            Ring->Queued.HeadEntry = ListEntry->Flink;
+            ListEntry->Flink = NULL;
         }
 
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
         status = __TransmitterRingPreparePacket(Ring, Packet);
         if (!NT_SUCCESS(status)) {
             PXENVIF_TRANSMITTER Transmitter;
@@ -2330,11 +2375,46 @@ TransmitterRingSchedule(
         ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring->PacketsGranted + Ring->PacketsFaked);
     }
 
-    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring->Queued.TailPacket == &Ring->Queued.HeadPacket));
+    ASSERT(IMPLY(Ring->Queued.HeadEntry == NULL, Ring->Queued.TailEntry == &Ring->Queued.HeadEntry));
 
     __TransmitterRingPushRequests(Ring);
 }
 
+static VOID
+TransmitterReturnPackets(
+    IN  PXENVIF_TRANSMITTER         Transmitter,
+    IN  PLIST_ENTRY                 List
+    )
+{
+    PXENVIF_FRONTEND                Frontend;
+    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
+
+    HeadPacket = NULL;
+    NextPacket = NULL;
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+        ListEntry = RemoveTailList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
+
+        HeadPacket = Packet->Cookie;
+        HeadPacket->Next = NextPacket;
+        HeadPacket->Completion = Packet->Completion;
+
+        __TransmitterPutPacket(Transmitter, Packet);
+        NextPacket = HeadPacket;
+    }
+
+    Frontend = Transmitter->Frontend;
+
+    VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                HeadPacket);
+}
+
 static FORCEINLINE BOOLEAN
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingTryAcquireLock(
@@ -2427,16 +2507,29 @@ __TransmitterRingTryReleaseLock(
 }
 
 static FORCEINLINE VOID
+__AppendTailList(
+    IN OUT PLIST_ENTRY              List,
+    IN OUT PLIST_ENTRY              Apendee
+    )
+{
+    PLIST_ENTRY HeadEntry = Apendee->Flink;
+
+    if (!IsListEmpty(Apendee)) {
+        RemoveEntryList(Apendee);
+        InitializeListHead(Apendee);
+        AppendTailList(List, HeadEntry);
+    }
+}
+
+static FORCEINLINE VOID
 __drv_requiresIRQL(DISPATCH_LEVEL)
 __TransmitterRingReleaseLock(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
-    
-    HeadPacket = NULL;
-    TailPacket = &HeadPacket;
+    LIST_ENTRY          List;
+
+    InitializeListHead(&List);
 
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
@@ -2449,22 +2542,11 @@ __TransmitterRingReleaseLock(
         TransmitterRingSwizzle(Ring);
         TransmitterRingSchedule(Ring);
 
-        *TailPacket = Ring->Completed.HeadPacket;
-        TailPacket = Ring->Completed.TailPacket;
-
-        Ring->Completed.HeadPacket = NULL;
-        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
+        __AppendTailList(&List, &Ring->Completed);
     } while (!__TransmitterRingTryReleaseLock(Ring));
 
-    if (HeadPacket != NULL) {
-        PXENVIF_TRANSMITTER Transmitter;
-        PXENVIF_FRONTEND    Frontend;
-
-        Transmitter = Ring->Transmitter;
-        Frontend = Transmitter->Frontend;
-
-        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
-                                    HeadPacket);
+    if (!IsListEmpty(&List)) {
+        TransmitterReturnPackets(Ring->Transmitter, &List);
     }
 }
 
@@ -2624,8 +2706,8 @@ __TransmitterRingInitialize(
 
     (*Ring)->Transmitter = Transmitter;
     (*Ring)->Index = Index;
-    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
-    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
+    (*Ring)->Queued.TailEntry = &(*Ring)->Queued.HeadEntry;
+    InitializeListHead(&(*Ring)->Completed);
 
     status = RtlStringCbPrintfA(Name,
                                 sizeof (Name),
@@ -2756,8 +2838,8 @@ fail3:
 fail2:
     Error("fail2\n");
 
-    (*Ring)->Queued.TailPacket = NULL;
-    (*Ring)->Completed.TailPacket = NULL;
+    (*Ring)->Queued.TailEntry = NULL;
+    RtlZeroMemory(&(*Ring)->Completed, sizeof(LIST_ENTRY));
     (*Ring)->Index = 0;
     (*Ring)->Transmitter = NULL;
 
@@ -2910,7 +2992,7 @@ __TransmitterRingDisable(
 {    
     PXENVIF_TRANSMITTER             Transmitter;
     PXENVIF_FRONTEND                Frontend;
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
     PCHAR                           Buffer;
     XenbusState                     State;
     ULONG                           Attempt;
@@ -2929,14 +3011,15 @@ __TransmitterRingDisable(
 
     // Put any packet back on the head of the queue
     if (Packet != NULL) {
-        ASSERT3P(Packet->Next, ==, NULL);
+        ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
+        ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
 
-        Packet->Next = Ring->Queued.HeadPacket;
+        Packet->ListEntry.Flink = Ring->Queued.HeadEntry;
 
-        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
-            Ring->Queued.TailPacket = &Packet->Next;
+        if (Ring->Queued.TailEntry == &Ring->Queued.HeadEntry)
+            Ring->Queued.TailEntry = &Packet->ListEntry.Flink;
 
-        Ring->Queued.HeadPacket = Packet;
+        Ring->Queued.HeadEntry = &Packet->ListEntry;
     }
 
     Ring->AddressIndex = 0;
@@ -3076,11 +3159,11 @@ __TransmitterRingTeardown(
                  Ring->BufferCache);
     Ring->BufferCache = NULL;
 
-    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
-    Ring->Queued.TailPacket = NULL;
+    ASSERT3P(Ring->Queued.TailEntry, ==, &Ring->Queued.HeadEntry);
+    Ring->Queued.TailEntry = NULL;
 
-    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;
@@ -3092,24 +3175,40 @@ __TransmitterRingTeardown(
 static FORCEINLINE VOID
 __TransmitterRingQueuePackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+    IN  PLIST_ENTRY                 List
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
+    PLIST_ENTRY                     ListEntry;
+    PLIST_ENTRY                     HeadEntry;
+    PLIST_ENTRY                     *TailEntry;
     ULONG_PTR                       Old;
     ULONG_PTR                       LockBit;
     ULONG_PTR                       New;
 
-    TailPacket = &HeadPacket->Next;
-    (VOID) __TransmitterReversePacketList(&HeadPacket);
-    ASSERT3P(*TailPacket, ==, NULL);
+    ListEntry = RemoveTailList(List);
+    ASSERT3P(ListEntry, !=, List);
+
+    ListEntry->Flink = NULL;
+    ListEntry->Blink = NULL;
+    HeadEntry = ListEntry;
+
+    TailEntry = &ListEntry->Flink;
+    while (!IsListEmpty(List)) {
+        ListEntry = RemoveTailList(List);
+        ASSERT3P(ListEntry, !=, List);
+
+        ListEntry->Flink = HeadEntry;
+        ListEntry->Blink = NULL;
+        HeadEntry = ListEntry;
+    }
+    ASSERT3P(*TailEntry, ==, NULL);
 
     do {
         Old = (ULONG_PTR)Ring->Lock;
         LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
 
-        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
-        New = (ULONG_PTR)HeadPacket;
+        *TailEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
+        New = (ULONG_PTR)HeadEntry;
         ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
         New |= LockBit;
     } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock, (PVOID)New, (PVOID)Old) != Old);
@@ -3128,33 +3227,35 @@ __TransmitterRingAbortPackets(
     IN  PXENVIF_TRANSMITTER_RING    Ring
     )
 {
-    PXENVIF_TRANSMITTER_PACKET      Packet;
+    PLIST_ENTRY                     ListEntry;
 
     __TransmitterRingAcquireLock(Ring);
 
     TransmitterRingSwizzle(Ring);
 
-    Packet = Ring->Queued.HeadPacket;
+    ListEntry = Ring->Queued.HeadEntry;
 
-    Ring->Queued.HeadPacket = NULL;
-    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
+    Ring->Queued.HeadEntry = NULL;
+    Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
 
-    while (Packet != NULL) {
-        PXENVIF_TRANSMITTER_PACKET  Next;
+    while (ListEntry != NULL) {
+        PLIST_ENTRY                     Next;
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
         
-        Next = Packet->Next;
-        Packet->Next = NULL;
+        Next = ListEntry->Flink;
+        ListEntry->Flink = NULL;
 
         // Fake that we prapared and sent this packet
         Ring->PacketsPrepared++;
         Ring->PacketsSent++;
         Ring->PacketsFaked++;
 
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
         Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
 
         __TransmitterRingCompletePacket(Ring, Packet);
 
-        Packet = Next;
+        ListEntry = Next;
     }
 
     ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring->PacketsUnprepared);
@@ -3264,13 +3365,27 @@ TransmitterInitialize(
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = XENBUS_CACHE(Create,
+                          &(*Transmitter)->CacheInterface,
+                          "packet_cache",
+                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
+                          0,
+                          TransmitterPacketCtor,
+                          TransmitterPacketDtor,
+                          TransmitterPacketLock,
+                          TransmitterPacketUnlock,
+                          *Transmitter,
+                          &(*Transmitter)->PacketCache);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     Index = 0;
     while (Index < Count) {
         PXENVIF_TRANSMITTER_RING    Ring;
 
         status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail5;
 
         InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
         Index++;
@@ -3278,8 +3393,8 @@ TransmitterInitialize(
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
+fail5:
+    Error("fail5\n");
 
     while (!IsListEmpty(&(*Transmitter)->List)) {
         PLIST_ENTRY                 ListEntry;
@@ -3297,6 +3412,14 @@ fail4:
     }
     ASSERT3U(Index, ==, 0);
 
+    XENBUS_CACHE(Destroy,
+                 &(*Transmitter)->CacheInterface,
+                 (*Transmitter)->PacketCache);
+    (*Transmitter)->PacketCache = NULL;
+
+fail4:
+    Error("fail4\n");
+
     XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
 
 fail3:
@@ -3530,6 +3653,11 @@ TransmitterTeardown(
         __TransmitterRingTeardown(Ring);
     }
 
+    XENBUS_CACHE(Destroy,
+                 &Transmitter->CacheInterface,
+                 Transmitter->PacketCache);
+    Transmitter->PacketCache = NULL;
+
     XENBUS_CACHE(Release, &Transmitter->CacheInterface);
 
     XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
@@ -3620,20 +3748,77 @@ fail1:
 }
 
 VOID
-TransmitterQueuePackets(
-    IN  PXENVIF_TRANSMITTER         Transmitter,
-    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
+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;
     PLIST_ENTRY                     ListEntry;
     PXENVIF_TRANSMITTER_RING        Ring;
 
+    InitializeListHead(&List);
+    while (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
+
+        Packet = __TransmitterGetPacket(Transmitter);
+        if (Packet == NULL) {
+            Warning("Out-of-cached-packets\n");
+            break;
+        }
+
+        Packet->Cookie = HeadPacket;
+        RtlCopyMemory(&Packet->Send, &HeadPacket->Send, sizeof(Packet->Send));
+        RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
+
+        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;
+    }
+    
     // 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);
 
-    __TransmitterRingQueuePackets(Ring, HeadPacket);
+    __TransmitterRingQueuePackets(Ring, &List);
+
+    // if HeadPacket != NULL, errors occured and need returning
+    if (HeadPacket != NULL) {
+        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
+        PXENVIF_FRONTEND                Frontend;
+
+        Frontend = Transmitter->Frontend;
+
+        Packet = HeadPacket;
+        while (Packet != NULL) {
+            Packet->Completion.Status = XENVIF_TRANSMITTER_PACKET_DROPPED;
+            Packet = Packet->Next;
+        }
+
+        VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend)),
+                                    HeadPacket);
+    }
+
+#undef OFFSET
+#undef OFFSET_EXISTS
 }
 
 VOID
diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
index 5ffb590..661eeae 100644
--- a/src/xenvif/transmitter.h
+++ b/src/xenvif/transmitter.h
@@ -107,9 +107,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..d6da258 100644
--- a/src/xenvif/vif.c
+++ b/src/xenvif/vif.c
@@ -276,8 +276,8 @@ VifReceiverReturnPackets(
 
 static NTSTATUS
 VifTransmitterQueuePackets(
-    IN  PINTERFACE                  Interface,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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);
 
@@ -784,8 +784,8 @@ VifReceiverQueuePackets(
 
 VOID
 VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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..0ef6687 100644
--- a/src/xenvif/vif.h
+++ b/src/xenvif/vif.h
@@ -70,8 +70,8 @@ VifReceiverQueuePackets(
 
 extern VOID
 VifTransmitterReturnPackets(
-    IN  PXENVIF_VIF_CONTEXT         Context,
-    IN  PXENVIF_TRANSMITTER_PACKET  Head
+    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 Wed Nov 12 16:44:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:44: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 1Xob1p-0003ib-FV; Wed, 12 Nov 2014 16:44:21 +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 1Xob1o-0003iW-Jg
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:44:20 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	DB/9D-29352-36E83645; Wed, 12 Nov 2014 16:44:19 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1415810656!6823167!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19466 invoked from network); 12 Nov 2014 16:44:19 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:44:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="190581200"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:46 +0000
Message-ID: <1415810330-1152-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/4] Add multi-queue 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

This patch series adds multi-queue support to the frontend.
Note: this relies on patches to xenvif for vif interface version 2,
  though should still function on an older xenvif using interface version 1.

1: Refactor the source to a coding style that is consistent with other 
   Xen PV drivers
2: Update the VIF interface header to version 2, and use interface version 2
   if possible.
3: Pullup the packet headers and calculate a simple hash over IP addresses/ports
4: Improve the handleing of the pullup call

Owen Smith (4):
  Refactor for maintainability/coding style
  Add VIF interface version 2
  Pullup headers and calculate hash over IP addresses and Ports
  Use a cache for header buffers, to fix a 'function uses too much
    stack' warning     Tweak GetPacketHeaders interface call to pass
    less parameters.

 include/cache_interface.h    |  232 +++
 include/vif_interface.h      |  458 ++++-
 src/xennet/adapter.c         | 3886 +++++++++++++++++++-----------------------
 src/xennet/adapter.h         |  156 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  550 ++++++
 src/xennet/main.c            |  361 ----
 src/xennet/miniport.c        |  297 ----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  401 +++--
 src/xennet/receiver.h        |   59 +-
 src/xennet/std.h             |   45 -
 src/xennet/toeplitzhash.h    |   71 +
 src/xennet/transmitter.c     |  783 +++++++--
 src/xennet/transmitter.h     |   67 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 17 files changed, 4040 insertions(+), 3434 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/miniport.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/std.h
 create mode 100644 src/xennet/toeplitzhash.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 Wed Nov 12 16:44:21 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:44: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 1Xob1p-0003ib-FV; Wed, 12 Nov 2014 16:44:21 +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 1Xob1o-0003iW-Jg
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:44:20 +0000
Received: from [85.158.139.211] by server-16.bemta-5.messagelabs.com id
	DB/9D-29352-36E83645; Wed, 12 Nov 2014 16:44:19 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-11.tower-206.messagelabs.com!1415810656!6823167!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19466 invoked from network); 12 Nov 2014 16:44:19 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-11.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:44:19 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="190581200"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:38:46 +0000
Message-ID: <1415810330-1152-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 0/4] Add multi-queue 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

This patch series adds multi-queue support to the frontend.
Note: this relies on patches to xenvif for vif interface version 2,
  though should still function on an older xenvif using interface version 1.

1: Refactor the source to a coding style that is consistent with other 
   Xen PV drivers
2: Update the VIF interface header to version 2, and use interface version 2
   if possible.
3: Pullup the packet headers and calculate a simple hash over IP addresses/ports
4: Improve the handleing of the pullup call

Owen Smith (4):
  Refactor for maintainability/coding style
  Add VIF interface version 2
  Pullup headers and calculate hash over IP addresses and Ports
  Use a cache for header buffers, to fix a 'function uses too much
    stack' warning     Tweak GetPacketHeaders interface call to pass
    less parameters.

 include/cache_interface.h    |  232 +++
 include/vif_interface.h      |  458 ++++-
 src/xennet/adapter.c         | 3886 +++++++++++++++++++-----------------------
 src/xennet/adapter.h         |  156 +-
 src/xennet/common.h          |   36 -
 src/xennet/driver.c          |  550 ++++++
 src/xennet/main.c            |  361 ----
 src/xennet/miniport.c        |  297 ----
 src/xennet/project.h         |   66 -
 src/xennet/receiver.c        |  401 +++--
 src/xennet/receiver.h        |   59 +-
 src/xennet/std.h             |   45 -
 src/xennet/toeplitzhash.h    |   71 +
 src/xennet/transmitter.c     |  783 +++++++--
 src/xennet/transmitter.h     |   67 +-
 vs2012/xennet/xennet.vcxproj |    3 +-
 vs2013/xennet/xennet.vcxproj |    3 +-
 17 files changed, 4040 insertions(+), 3434 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/miniport.c
 delete mode 100644 src/xennet/project.h
 delete mode 100644 src/xennet/std.h
 create mode 100644 src/xennet/toeplitzhash.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 Wed Nov 12 16:47:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:47: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 1Xob5I-0003jR-Om; Wed, 12 Nov 2014 16:47:56 +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 1Xob5H-0003jM-Vm
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:47:56 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	F3/9B-24532-B3F83645; Wed, 12 Nov 2014 16:47:55 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1415810872!12264549!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22088 invoked from network); 12 Nov 2014 16:47:54 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:47:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192036339"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:07 +0000
Message-ID: <1415810347-7152-11-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 10/10] Only call EVTCHN:Open for rx and tx or
	single event channel, based on "feature-split-event-channels"
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/notifier.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 93f2395..e9972d2 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -295,6 +295,27 @@ NotifierQueueConnect(
         PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
         BOOLEAN             Pending;
 
+        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 (FrontendGetQueueCount(Frontend) > 1) {
             KeSetTargetProcessorDpc(&Queue->Dpc[Index],
                                     (CCHAR)Queue->Index);
@@ -328,6 +349,9 @@ fail1:
     Error("fail1 (%08x)\n", status);
 
     while (--Index >= 0) {
+        if (Queue->Channel[Index] == NULL)
+            continue;
+
         XENBUS_EVTCHN(Close,
                       &Notifier->EvtchnInterface,
                       Queue->Channel[Index]);
@@ -384,6 +408,7 @@ NotifierQueueStoreWrite(
             break;
         }
 
+        ASSERT(Queue->Channel[Index] != NULL);
         Port = XENBUS_EVTCHN(GetPort,
                              &Notifier->EvtchnInterface,
                              Queue->Channel[Index]);
-- 
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 Wed Nov 12 16:47:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Wed, 12 Nov 2014 16:47: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 1Xob5I-0003jR-Om; Wed, 12 Nov 2014 16:47:56 +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 1Xob5H-0003jM-Vm
	for win-pv-devel@lists.xenproject.org; Wed, 12 Nov 2014 16:47:56 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	F3/9B-24532-B3F83645; Wed, 12 Nov 2014 16:47:55 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1415810872!12264549!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22088 invoked from network); 12 Nov 2014 16:47:54 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	12 Nov 2014 16:47:54 -0000
X-IronPort-AV: E=Sophos;i="5.07,369,1413244800"; d="scan'208";a="192036339"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Wed, 12 Nov 2014 16:39:07 +0000
Message-ID: <1415810347-7152-11-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 10/10] Only call EVTCHN:Open for rx and tx or
	single event channel, based on "feature-split-event-channels"
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/notifier.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
index 93f2395..e9972d2 100644
--- a/src/xenvif/notifier.c
+++ b/src/xenvif/notifier.c
@@ -295,6 +295,27 @@ NotifierQueueConnect(
         PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
         BOOLEAN             Pending;
 
+        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 (FrontendGetQueueCount(Frontend) > 1) {
             KeSetTargetProcessorDpc(&Queue->Dpc[Index],
                                     (CCHAR)Queue->Index);
@@ -328,6 +349,9 @@ fail1:
     Error("fail1 (%08x)\n", status);
 
     while (--Index >= 0) {
+        if (Queue->Channel[Index] == NULL)
+            continue;
+
         XENBUS_EVTCHN(Close,
                       &Notifier->EvtchnInterface,
                       Queue->Channel[Index]);
@@ -384,6 +408,7 @@ NotifierQueueStoreWrite(
             break;
         }
 
+        ASSERT(Queue->Channel[Index] != NULL);
         Port = XENBUS_EVTCHN(GetPort,
                              &Notifier->EvtchnInterface,
                              Queue->Channel[Index]);
-- 
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 Nov 13 14:19:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:19: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 1XovFJ-000416-Sw; Thu, 13 Nov 2014 14:19:37 +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 1XovFH-000411-AD
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:19:36 +0000
Received: from [85.158.139.211] by server-5.bemta-5.messagelabs.com id
	D1/45-27584-6FDB4645; Thu, 13 Nov 2014 14:19:34 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415888373!11171953!1
X-Originating-IP: [74.125.82.44]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15577 invoked from network); 13 Nov 2014 14:19:33 -0000
Received: from mail-wg0-f44.google.com (HELO mail-wg0-f44.google.com)
	(74.125.82.44)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:19:33 -0000
Received: by mail-wg0-f44.google.com with SMTP id x12so17011726wgg.17
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 13 Nov 2014 06:19:33 -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
	:subject:content-type;
	bh=5I4QI8lp+nGlTOR38rXHV5IgGHGIhW20aZIJi9XPVkI=;
	b=fvcWXcaMrp6vUx7EbPWIUOrj1H98+iVSSKAyOH4GUP0WXFVHpBV83uU+tCfalki4yS
	PA2VKdT00Qb25Z6/q13NxQkvt8e+dJ5dQRkWrxVMSbw9WH1ZAAFRd5bM9RTzHpZ6DpP6
	z4UwH8AY5Q8ijz+3hnz0mV1a49nWyPVs19QDHdSbbr+nzpE4iqYatCrwesSko/fPXsjf
	E6/zthdeKl/fTDbNDEnpoUmQhYDKHaZRxLLRIlknSLEl7B6sIzgJy2Lox+m7vau9Cu6E
	J1asa+Z8NsNjVZRuJLJuT1I408Ir8IaQIOoN86XPuev3vM5HsobSXLP91FqO7bynHSdq
	yqvw==
X-Gm-Message-State: ALoCoQmY90UkQAXaTBwb8wdmA0LR4UUk7NO79CUjHb1amUN+WcHqEHBjPbjWKPosD+l4+g5mJTzP
X-Received: by 10.180.109.17 with SMTP id ho17mr4303299wib.4.1415888373176;
	Thu, 13 Nov 2014 06:19:33 -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
	bj7sm35711415wjc.33.2014.11.13.06.19.24 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 13 Nov 2014 06:19:32 -0800 (PST)
Message-ID: <5464BDF4.1090103@m2r.biz>
Date: Thu, 13 Nov 2014 15:19:32 +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.2.0
MIME-Version: 1.0
To: win-pv-devel@lists.xenproject.org, 
	"paul.durrant@citrix.com >> Paul Durrant" <paul.durrant@citrix.com>
Content-Type: multipart/mixed; boundary="------------070603040901030901050202"
Subject: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------070603040901030901050202
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

I did a new build of winpv drivers and tested on one windows 7 64 bit 
domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu 
id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2 
from spice git:
https://github.com/Fantu/Xen/commits/rebase/m2r-staging

After restore windows showed blue screen with stop 1e, I open the dump 
with "BlueScreenView" and showed that cause is xennet driver.
I attached the dump, if you need more informations/tests tell me and 
I'll post them.

Thanks for any reply and sorry for my bad english.

--------------070603040901030901050202
Content-Type: application/octet-stream;
 name="111314-16707-01.dmp"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="111314-16707-01.dmp"

UEFHRURVNjQPAAAAsR0AAABwGAAAAAAAeDLQAgD4//+QmMkCAPj//5C1xwIA+P//ZIYAAAIA
AAAeAAAAUEFHRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0WgUMQCAPj//1BBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAA
AAAAAICN5gKA+P//WLPBAgD4///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC
5gKA+P//4HvmAoD4//+wjeYCgPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//
AAAAAAAAAACQu6wCAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAUAAAD/////aIMjodF/AAAFAAAAAAAAAAAAAAAAAAAAAPBFodF/AADyuY+h0X8AAAAA
AAAA8EWh0X8AAPK5j6EAAAAAAAAAAAD/////AP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAwAAgAEAAAAAAAAAAAAAAJC7rAIA+P//AAAAAFBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UEAAAA
UEFHRQgbBAAAAAAA8DjYAkn/zwFQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRQBOMcYAAAAA/wwAAFBB
R0UBAAAAEAEAAAAAAABQAEdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UAAQAAAAAEAPz/AwBIAwAA
AA8AAIAgAADQIAAA8CEAAPBuAADAcwAAaHgAAAAQAACoiwAAjwAAABjcAADoLwAAAAAAAP//
///oeuYCgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaIgAAEADAAAADAEA
DwAAAAEAAABQAAAAAAAAAAAAAAAAAAAAAAAAAHh5BQAAAAAAIhgAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArJEDAAAAAABCwAYAAAAAAHT+HQAAAAAABQAAAAAAAAAYABgAAAAAAAAAAAAAAAAA
YwByAGEAcwBoAGQAbQBwAC4AcwB5AHMAAFCcAYD4//8AMJ0BgPj//xgAGAAAAAAAAAAAAAAA
AABkAHUAbQBwAF8AcwB0AG8AcgBwAG8AcgAAMJ0BgPj//wDQnQGA+P//GAAYAAAAAAAAAAAA
AAAAAGQAdQBtAHAAXwB4AGUAbgBjAHIAcwBoAAAwoQOA+P//ANCkA4D4//8YABgAAAAAAAAA
AAAAAAAAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AAACAAYD4//8AwIIBgPj//xgAGAAAAAAA
AAAAAAAAAABkAHUAbQBwAF8AZAB1AG0AcABmAHYAZQAA0KQDgPj//wAApgOA+P//gB8AAAEA
AABAr+QCgPj//wAAAAAAAAAAQK/kAoD4//8BAAAAAQAAALCN5gKA+P//AAAAAAAAAAAAAAAA
AAAAADEABYAAAAAAAPAbAqD4//8AcBgAAAAAAPgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADwD///AAAAAAAEAAAAAAAAAAAAAAAAfwDAtOQCgPj//wAAAAAAAP8P
QLXkAoD4//9AAAAAgB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAAAAAAAICN5gKA+P//WLPBAgD4
///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC5gKA+P//4HvmAoD4//+wjeYC
gPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//AAAAAAAAAACQu6wCAPj//wAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAA/////2iDI6HRfwAA
BQAAAAAAAAAAAAAAAAAAAADwRaHRfwAA8rmPodF/AAAAAAAAAPBFodF/AADyuY+hAAAAAAAA
AAAA/////wD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAGAQUeZAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAAIQAuD///9AAAAAAAAAAAAAAAACAAAAAgAAAAAA
AAAAAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBn0AIA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgGfQAgD4//8AAAAAAAAAAABq0AIA+P//AAAAAAAA
AACAatACAPj//wAAAAAAAAAAgGnQAgD4//8AAAAAAAAAAABp0AIA+P//AAAAAAAAAABAatAC
APj//wAAAAAAAAAAwGjQAgD4//8AAAAAAAAAAIBo0AIA+P//AAAAAAAAAABAadACAPj//wAA
AAAAAAAAAGfQAgD4//8AAAAAAAAAAMBm0AIA+P//AAAAAAAAAADAadACAPj//wAAAAAAAAAA
QGfQAgD4//8AAAAAAAAAAAAAAAAAAAAAkPF8AYD6//8ACMUCAPj//xDxfAGA+v//gAjFAgD4
//+Q8HwBgPr//wAJxQIA+P//EPJ8AYD6//+AB8UCAPj//9DXdgGA+v//AI3FAgD4//+g9nUB
gPr//4CMxQIA+P//8A53AYD6//+A/cQCAPj//xDwfAGA+v//gAnFAgD4///QZ3YBgPr//8DG
xQIA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAAAAABQb29M
EAAAABD8vwIA+P//0PC/AgD4//9AFuQCgPj//+COxAIA+P//AAAAAAAAAAAAAAAAAAAAABUA
FBsAAAAAEWx2AoD6//8LAAABJ2MAAP8aAAC1GwAAFBsAAAAAAABQb29MIAAAABD8vwIA+P//
0PC/AgD4//+gFuQCgPj//0AW5AKA+P//J2MAAP8aAAAAAAAAAAAAABIAEh8AAAAA0RqIAoD6
//+VAAABY24AAAAfAACEHwAAEh8AAAAAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//8AF+QC
gPj//6AW5AKA+P//XG4AAPkeAAAAAAAAAAAAADQAcBYAAAAAAQlHA4D6//8EAAABk2cAADwW
AAAqGgAAcBYAAAAAAABQb29MQAAAABD8vwIA+P//0PC/AgD4//9gF+QCgPj//wAX5AKA+P//
kWcAADoWAAAAAAAAAAAAAGMAEzoAAAAAMTKFA4D6//9RAAABKl0AALA5AADSOgAAEzoAAAAA
AABQb29MUAAAABD8vwIA+P//0PC/AgD4///AF+QCgPj//2AX5AKA+P//KV0AAK85AAAAAAAA
AAAAADIAwC4AAAAAEfyZAYD6//8oAAABN2sAAI4uAAAsMAAAwC4AAAAAAABQb29MYAAAABD8
vwIA+P//0PC/AgD4//8gGOQCgPj//8AX5AKA+P//N2sAAI4uAAAAAAAAAAAAAAEA0gQAAAAA
8WByA4D6//8EAAABPSAAANEEAACPBgAA0gQAAAAAAABQb29McAAAABD8vwIA+P//0PC/AgD4
//+AGOQCgPj//yAY5AKA+P//PSAAANEEAAAAAAAAAAAAANAADzMAAAAA4UeOA4D6///SAAAB
mZQAAD8yAACoNAAADzMAAAAAAABQb29MgAAAABD8vwIA+P//0PC/AgD4///gGOQCgPj//4AY
5AKA+P//hJQAACoyAAAAAAAAAAAAADUAhKUAAAAAIayWA4D6///4AAABMf0AAE+lAACZygAA
hKUAAAAAAABQb29MkAAAABD8vwIA+P//0PC/AgD4//9AGeQCgPj//+AY5AKA+P//L/0AAE2l
AAAAAAAAAAAAAJ8AGisAAAAAkfe7AYD6//+XAAABskgAAHsqAAC0KwAAGisAAAAAAABQb29M
oAAAABD8vwIA+P//0PC/AgD4//+gGeQCgPj//0AZ5AKA+P//sEgAAHkqAAAAAAAAAAAAAAQA
2AQAAAAAEW6YAYD6//8EAAAB6wsAANQEAADfBAAA2AQAAAAAAABQb29MsAAAABD8vwIA+P//
0PC/AgD4//8AGuQCgPj//6AZ5AKA+P//6wsAANQEAAAAAAAAAAAAAHQA0AgAAAAAIdmAAoD6
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
AAAtAAAALQAAAAAAAABQb29M8AEAABD8vwIA+P//0PC/AgD4//+AIeQCgPj//yAh5AKA+P//
hwAAAC0AAAAAAAAAAAAAAAMAIgAAAAAAAXFnA4D6//8EAAABswAAAB8AAAAlAAAAIgAAAAAA
AABQb29MAAIAABD8vwIA+P//0PC/AgD4///gIeQCgPj//4Ah5AKA+P//swAAAB8AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MEAAAABD8
vwIA+P//0PC/AgD4//+gCuQCgPj//0AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAQA3gMAAAAA
YUofAaD4//8EAAABiAYAANoDAABlBAAA3gMAAAEAAABQb29MIAAAABD8vwIA+P//0PC/AgD4
//8AC+QCgPj//6AK5AKA+P//hgYAANgDAAAAAAAAAAAAANUALjsAAAAAkfE/AKD4///dAAAB
eFMAAFk6AAAoRQAALjsAAAEAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//9gC+QCgPj//wAL
5AKA+P//aVMAAEo6AAAAAAAAAAAAANcAuCkAAAAAUZXyAKD4///cAAABGzwAAOEoAAAbMgAA
uCkAAAEAAABQb29MQAAAABD8vwIA+P//0PC/AgD4///AC+QCgPj//2AL5AKA+P//DzwAANUo
AAAAAAAAAAAAACQAiSIBAAAAoXN9AKD4//9WAAABgCYBAGUiAQD9JAEAiSIBAAEAAABQb29M
UAAAABD8vwIA+P//0PC/AgD4//8gDOQCgPj//8AL5AKA+P//dyYBAFwiAQAAAAAAAAAAAIsA
XyMAAAAAMa29AKD4//+GAAABBScAANQiAACAJgAAXyMAAAEAAABQb29MYAAAABD8vwIA+P//
0PC/AgD4//+ADOQCgPj//yAM5AKA+P//AicAANEiAAAAAAAAAAAAADgAZnMAAAAAYbSBAKD4
//+TAAABQYEAAC5zAAAAdAAAZnMAAAEAAABQb29McAAAABD8vwIA+P//0PC/AgD4///gDOQC
gPj//4AM5AKA+P//QYEAAC5zAAAAAAAAAAAAAHsAbWMAAAAAQd4sAaD4//+gAAABP28AAPJi
AACfYwAAbWMAAAEAAABQb29MgAAAABD8vwIA+P//0PC/AgD4//9ADeQCgPj//+AM5AKA+P//
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
MJyTA4D6//8wnJMDgPr//2A4wNgAAAAAAAAAAAAAAADgo5EDgPr//+CjkQOA+v//gLd6ygAA
AAAAAAAAAAAAAEDRsQGA+v//QNGxAYD6//8gm27pAAAAAAAAAAAAAAAAqCfkAoD4//+oJ+QC
gPj//0BX4cz/////AAAAAAAAAAAgykYDgPr//yDKRgOA+v//4LpEzwAAAAAAAAAAAAAAAOgn
5AKA+P//6CfkAoD4//+g7Be1/////wAAAAAAAAAACCjkAoD4//8IKOQCgPj//6CA2ev/////
AAAAAAAAAAAwbEcDgPr//zBsRwOA+v//AN9LzwAAAAAAAAAAAAAAAEgo5AKA+P//SCjkAoD4
//9wh2fD/////wAAAAAAAAAAMOyKAYD6//8w7IoBgPr//6DQW+IAAAAAAAAAAAAAAACIKOQC
gPj//4go5AKA+P//YAuovv////8AAAAAAAAAAKgo5AKA+P//qCjkAoD4//9gUw3B/////wAA
AAAAAAAAyCjkAoD4///IKOQCgPj//yDOrL7/////AAAAAAAAAADoKOQCgPj//+go5AKA+P//
INzTxf////8AAAAAAAAAAAgp5AKA+P//CCnkAoD4///g0O65/////wAAAAAAAAAAICWtA4D6
//8gJa0DgPr//wAKg9YAAAAAAAAAAAAAAABIKeQCgPj//0gp5AKA+P//YK5H2/////8AAAAA
AAAAAGgp5AKA+P//aCnkAoD4//8AbPe5/////wAAAAAAAAAAiCnkAoD4//+IKeQCgPj//yBR
M+f/////AAAAAAAAAACoKeQCgPj//6gp5AKA+P//AC7jxf////8AAAAAAAAAAFCSewGA+v//
UJJ7AYD6//8AiEXIAAAAAAAAAAAAAAAAQLF7A4D6//9AsXsDgPr//6DCC80AAAAAAAAAAAAA
AAAIKuQCgPj//wgq5AKA+P//AEQnwf////8AAAAAAAAAACgq5AKA+P//KCrkAoD4///g4ynB
/////wAAAAAAAAAASCrkAoD4//9IKuQCgPj//wAmIa7/////AAAAAAAAAABoKuQCgPj//2gq
5AKA+P//YGcKuv////8AAAAAAAAAAIgq5AKA+P//iCrkAoD4///gVkq1/////wAAAAAAAAAA
qCrkAoD4//+oKuQCgPj//2BpM8H/////AAAAAAAAAAAgqZMDgPr//6AYjgOA+v//4J66ygAA
AAAAAAAAAAAAAKDLvwGA+v//oMu/AYD6//9A4K7pAAAAAAAAAAAAAAAACCvkAoD4//8IK+QC
gPj//4D22hD/////AAAAAAAAAAAAZ18DgPr//zC8NwOA+v//AMPBygAAAAAAAAAAAAAAADBF
jAGA+v//MEWMAYD6//8gy6YIAQAAAAAAAAAAAAAAaCvkAoD4//9oK+QCgPj//8Cl9eT/////
AAAAAAAAAACIK+QCgPj//4gr5AKA+P//IMev1v////8AAAAAAAAAAKgr5AKA+P//qCvkAoD4
//9AgyK6/////wAAAAAAAAAAyCvkAoD4///IK+QCgPj//wBVqsP/////AAAAAAAAAAAAZFID
gPr//wBkUgOA+v//ENBwcQEAAAAAAAAAAAAAAAgs5AKA+P//CCzkAoD4///AoK3D/////wAA
AAAAAAAAKCzkAoD4//8oLOQCgPj//8Bojbz/////AAAAAAAAAABILOQCgPj//0gs5AKA+P//
YA++1v////8AAAAAAAAAAGgs5AKA+P//aCzkAoD4///AcMvp/////wAAAAAAAAAAiCzkAoD4
//+ILOQCgPj//yCShdv/////AAAAAAAAAACoLOQCgPj//6gs5AKA+P//QE74vv////8AAAAA
AAAAAMgs5AKA+P//yCzkAoD4///glMfW/////wAAAAAAAAAAQCGpAYD6//9AIakBgPr//0BW
NuwAAAAAAAAAAAAAAAAILeQCgPj//wgt5AKA+P//oHfw3f////8AAAAAAAAAAECBSQOA+v//
4LMoA4D6//+gUSaUIQAAAAAAAAAAAAAASC3kAoD4//9ILeQCgPj//2Aa0db/////AAAAAAAA
AABoLeQCgPj//2gt5AKA+P//YOikvP////8AAAAAAAAAADCImwOA+v//MIibA4D6//8gXVvg
AAAAAAAAAAAAAAAAqC3kAoD4//+oLeQCgPj//0AZzsP/////AAAAAAAAAACANjEDgPr//zB8
VwOA+v//4B9VzQAAAAAAAAAAAAAAAOgt5AKA+P//6C3kAoD4//+Axm/B/////wAAAAAAAAAA
CC7kAoD4//8ILuQCgPj//6BCxuL/////AAAAAAAAAAAoLuQCgPj//ygu5AKA+P//wP44xv//
//8AAAAAAAAAAEgu5AKA+P//SC7kAoD4//9A0c6w/////wAAAAAAAAAAaC7kAoD4//9oLuQC
gPj//2CzesH/////AAAAAAAAAACILuQCgPj//4gu5AKA+P//ICgx5f////8AAAAAAAAAAMAo
JgOA+v//wCgmA4D6//+AyWXNAAAAAAAAAAAAAAAAyC7kAoD4///ILuQCgPj//6BFpsj/////
AAAAAAAAAADoLuQCgPj//+gu5AKA+P//4HjBvP////8AAAAAAAAAAAgv5AKA+P//CC/kAoD4
//9A+ufD/////wAAAAAAAAAAMMwnA4D6//8wzCcDgPr//1C4ORcBAAAAAAAAAAAAAABIL+QC
gPj//0gv5AKA+P//ICsRy/////8AAAAAAAAAAGgv5AKA+P//aC/kAoD4//9gXiy//////wAA
AAAAAAAAgKiuAYD6//+AqK4BgPr//yBTaOwAAAAAAAAAAAAAAACgJjEDgPr//6AmMQOA+v//
gFQJ6gAAAAAAAAAAAAAAAMgv5AKA+P//yC/kAoD4//8AwTO//////wAAAAAAAAAAQPGtAYD6
//8ginoDgPr//0BXS+UAAAAAAAAAAAAAAACIczUCgPr//4hzNQKA+v//4EAdywAAAAAAAAAA
AAAAAKAHMgOA+v//oAcyA4D6//+w+VzGAAAAAAAAAAAAAAAASDDkAoD4//9IMOQCgPj//2A7
Ctf/////AAAAAAAAAABoMOQCgPj//2gw5AKA+P//ADkCxP////8AAAAAAAAAAIgw5AKA+P//
iDDkAoD4///g2366/////wAAAAAAAAAAqDDkAoD4//+oMOQCgPj//+DppcH/////AAAAAAAA
AADIMOQCgPj//8gw5AKA+P//4EMIxP////8AAAAAAAAAAIC+SQOA+v//oEYmA4D6//+gcmzG
AAAAAAAAAAAAAAAACDHkAoD4//8IMeQCgPj//+DCJrj/////AAAAAAAAAAAoMeQCgPj//ygx
5AKA+P//AIW51P////8AAAAAAAAAAEgx5AKA+P//SDHkAoD4//9gBuDb/////wAAAAAAAAAA
aDHkAoD4//9oMeQCgPj//4ACkLr/////AAAAAAAAAACIMeQCgPj//4gx5AKA+P//IKnL5///
//8AAAAAAAAAADCVfgGA+v//MJV+AYD6//9gFiXXAAAAAAAAAAAAAAAAkOaiAYD6//+Q5qIB
gPr//4DEe8YAAAAAAAAAAAAAAADoMeQCgPj//+gx5AKA+P//AEvhyP////8AAAAAAAAAAAgy
5AKA+P//CDLkAoD4///AfL/B/////wAAAAAAAAAAKDLkAoD4//8oMuQCgPj//wDwLdf/////
AAAAAAAAAABIMuQCgPj//0gy5AKA+P//QGbGE/////8AAAAAAAAAACCqXQOA+v//IKpdA4D6
///AkhnjAAAAAAAAAAAAAAAAiDLkAoD4//+IMuQCgPj//yCUuuD/////AAAAAAAAAACoMuQC
gPj//6gy5AKA+P//QBDltf////8AAAAAAAAAAMgy5AKA+P//yDLkAoD4//+gcee1/////wAA
AAAAAAAA6DLkAoD4///oMuQCgPj//yBN0hP/////AAAAAAAAAAAIM+QCgPj//wgz5AKA+P//
oHkl4/////8AAAAAAAAAACgz5AKA+P//KDPkAoD4//9A+hG9/////wAAAAAAAAAASDPkAoD4
//9IM+QCgPj//2DcyOD/////AAAAAAAAAABoM+QCgPj//2gz5AKA+P//IM5TuP////8AAAAA
AAAAAJCdOgOA+v//kJ06A4D6//8gX5DlAAAAAAAAAAAAAAAAqDPkAoD4//+oM+QCgPj//4CA
Stf/////AAAAAAAAAADIM+QCgPj//8gz5AKA+P//oDy9uv////8AAAAAAAAAAOgz5AKA+P//
6DPkAoD4//8g+IMR/////wAAAAAAAAAACDTkAoD4//8INOQCgPj//6BE++f/////AAAAAAAA
AAAoNOQCgPj//yg05AKA+P//AGa12f////8AAAAAAAAAAEg05AKA+P//SDTkAoD4//8gIii9
/////wAAAAAAAAAAaDTkAoD4//9oNOQCgPj//8AIltL/////AAAAAAAAAACINOQCgPj//4g0
5AKA+P//ICpm6v////8AAAAAAAAAAKg05AKA+P//qDTkAoD4//+Ai2jq/////wAAAAAAAAAA
yDTkAoD4///INOQCgPj//+Dpz7r/////AAAAAAAAAADoNOQCgPj//+g05AKA+P//gA3rrv//
//8AAAAAAAAAAAg15AKA+P//CDXkAoD4//+gD9Hs/////wAAAAAAAAAAKDXkAoD4//8oNeQC
gPj//yBfXMT/////AAAAAAAAAABINeQCgPj//0g15AKA+P//oDH9wf////8AAAAAAAAAAEAx
cwOA+v//QDFzA4D6//+Ar7qhZAAAAAAAAAAAAAAAiDXkAoD4//+INeQCgPj//8ChP73/////
AAAAAAAAAACoNeQCgPj//6g15AKA+P//gBb24P////8AAAAAAAAAAMg15AKA+P//yDXkAoD4
//+g0mjE/////wAAAAAAAAAAQCFEA4D6//8Ai4oBgPr//0AZONwAAAAAAAAAAAAAAAAINuQC
gPj//wg25AKA+P//4N9rxP////8AAAAAAAAAACg25AKA+P//KDbkAoD4///A2dDG/////wAA
AAAAAAAASDbkAoD4//9INuQCgPj//yC408b/////AAAAAAAAAABoNuQCgPj//2g25AKA+P//
oC2NuP////8AAAAAAAAAAIg25AKA+P//iDbkAoD4///ATPG6/////wAAAAAAAAAAqDbkAoD4
//+oNuQCgPj//yDOF8L/////AAAAAAAAAABQYzIDgPr//1BjMgOA+v//4L/D0gAAAAAAAAAA
AAAAAOg25AKA+P//6DbkAoD4//8A/0DJ/////wAAAAAAAAAAIGc1A4D6//8wDEUDgPr//zCR
4MYAAAAAAAAAAAAAAAAwPF4DgPr//zA8XgOA+v//ACeN1wAAAAAAAAAAAAAAAEg35AKA+P//
SDfkAoD4//9AFGG9/////wAAAAAAAAAAQDFMAoD6//9AMUwCgPr//4Cn6MYAAAAAAAAAAAAA
AACIN+QCgPj//4g35AKA+P//wBfHv/////8AAAAAAAAAAKg35AKA+P//qDfkAoD4//9ggSnC
/////wAAAAAAAAAAyDfkAoD4///IN+QCgPj//+ANpOr/////AAAAAAAAAADoN+QCgPj//+g3
5AKA+P//gHHxxv////8AAAAAAAAAAAg45AKA+P//CDjkAoD4//9A/THC/////wAAAAAAAAAA
KDjkAoD4//8oOOQCgPj//6BeNML/////AAAAAAAAAABIOOQCgPj//0g45AKA+P//YPMO7f//
//8AAAAAAAAAAGg45AKA+P//aDjkAoD4//9gZPCz/////wAAAAAAAAAAcPd+A4D6//9w934D
gPr//6Da49IAAAAAAAAAAAAAAACoOOQCgPj//6g45AKA+P//YO9OGv////8AAAAAAAAAAMg4
5AKA+P//yDjkAoD4//8gPqDE/////wAAAAAAAAAA6DjkAoD4///oOOQCgPj//yCvosT/////
AAAAAAAAAAAIOeQCgPj//wg55AKA+P//4Lpdtv////8AAAAAAAAAACg55AKA+P//KDnkAoD4
//8A3Vzo/////wAAAAAAAAAASDnkAoD4//9IOeQCgPj//2BeeNz/////AAAAAAAAAABoOeQC
gPj//2g55AKA+P//wH894f////8AAAAAAAAAAIg55AKA+P//iDnkAoD4//8ATe2//////wAA
AAAAAAAAwCY7A4D6///AJjsDgPr//8DHouMAAAAAAAAAAAAAAABQYngBgPr//1DSfAGA+v//
AFsUxwAAAAAAAAAAAAAAAOg55AKA+P//6DnkAoD4//9AxQnm/////wAAAAAAAAAACDrkAoD4
//8IOuQCgPj//0DzM7v/////AAAAAAAAAAAoOuQCgPj//yg65AKA+P//oPTUuP////8AAAAA
AAAAAEg65AKA+P//SDrkAoD4//8g5BS0/////wAAAAAAAAAAaDrkAoD4//9oOuQCgPj//+CV
eLb/////AAAAAAAAAACIOuQCgPj//4g65AKA+P//gN+rnv////8AAAAAAAAAAKg65AKA+P//
qDrkAoD4//+ATVXh/////wAAAAAAAAAAMNx8A4D6//8w3HwDgPr//yCXk9wAAAAAAAAAAAAA
AADoOuQCgPj//+g65AKA+P//QHClvf////8AAAAAAAAAAAg75AKA+P//CDvkAoD4///gmb+x
/////wAAAAAAAAAAKDvkAoD4//8oO+QCgPj//wAzwOP/////AAAAAAAAAABIO+QCgPj//0g7
5AKA+P//oHNvwv////8AAAAAAAAAADC8SwOA+v//MLxLA4D6//+gKn8nAgAAAAAAAAAAAAAA
iDvkAoD4//+IO+QCgPj//2A/7bj/////AAAAAAAAAAAwnJQBgPr//0CxnwGA+v//gHiB1QAA
AAAAAAAAAAAAAEDRTQOA+v//QNFNA4D6//+AN0puCAAAAAAAAAAAAAAA6DvkAoD4///oO+QC
gPj//wC/k7b/////AAAAAAAAAAAw9EsDgPr//zD0SwOA+v//YC7NTwQAAAAAAAAAAAAAACg8
5AKA+P//KDzkAoD4//+gioDC/////wAAAAAAAAAASDzkAoD4//9IPOQCgPj//2AfUNr/////
AAAAAAAAAABoPOQCgPj//2g85AKA+P//gNvCvf////8AAAAAAAAAAIg85AKA+P//iDzkAoD4
//8gYs/Q/////wAAAAAAAAAAqDzkAoD4//+oPOQCgPj//4DjAOv/////AAAAAAAAAADIPOQC
gPj//8g85AKA+P//oIjIvf////8AAAAAAAAAAOg85AKA+P//6DzkAoD4//9ARo7C/////wAA
AAAAAAAAQEGTA4D6//9AQZMDgPr//yBJ5YwBAAAAAAAAAAAAAAAoPeQCgPj//yg95AKA+P//
AMlr7f////8AAAAAAAAAAEg95AKA+P//SD3kAoD4//+gKTTA/////wAAAAAAAAAAaD3kAoD4
//9oPeQCgPj//4CmmML/////AAAAAAAAAABAAVADgPr//wBIkwGA+v//II0G2AAAAAAAAAAA
AAAAALAzWAOA+v//sDNYA4D6//+ALlHmAAAAAAAAAAAAAAAAyD3kAoD4///IPeQCgPj//+DP
kOH/////AAAAAAAAAADoPeQCgPj//+g95AKA+P//AIwDxf////8AAAAAAAAAAAg+5AKA+P//
CD7kAoD4//+AZ+MP/////wAAAAAAAAAAkDVqA4D6//+QNWoDgPr//0D5Z8cAAAAAAAAAAAAA
AAAwrG8DgPr//zCsbwOA+v//YJXX3AAAAAAAAAAAAAAAAGg+5AKA+P//aD7kAoD4//+AcW7H
/////wAAAAAAAAAAiD7kAoD4//+IPuQCgPj//yAeiLv/////AAAAAAAAAACoPuQCgPj//6g+
5AKA+P//IAaMu/////8AAAAAAAAAAOCVdgOA+v//4JV2A4D6//8g4HPHAAAAAAAAAAAAAAAA
6D7kAoD4///oPuQCgPj//6CvhKj/////AAAAAAAAAAAIP+QCgPj//wg/5AKA+P//YLjbyf//
//8AAAAAAAAAAABKagOA+v//AEpqA4D6//8APGPTAAAAAAAAAAAAAAAASD/kAoD4//9IP+QC
gPj//wBtHcX/////AAAAAAAAAABoP+QCgPj//2g/5AKA+P//wIFy5v////8AAAAAAAAAAEAh
VQOA+v//QCFVA4D6///gnUbMAAAAAAAAAAAAAAAAqD/kAoD4//+oP+QCgPj//+ARw8L/////
AAAAAAAAAAAAKlgDgPr//wAqWAOA+v//QFaJcAEAAAAAAAAAAAAAADBYtAGA+v//MFi0AYD6
//9Axz7rAAAAAAAAAAAAAAAAIGdLA4D6//8gZ0sDgPr//4DdahICAAAAAAAAAAAAAAAoQOQC
gPj//yhA5AKA+P//oLbMwv////8AAAAAAAAAAEhA5AKA+P//SEDkAoD4//9g6y/F/////wAA
AAAAAAAAQEGXA4D6//9AYZsDgPr//8Csqe0AAAAAAAAAAAAAAAAwPJoBgPr//zA8mgGA+v//
IE7p6AAAAAAAAAAAAAAAAKhA5AKA+P//qEDkAoD4//8gnDfF/////wAAAAAAAAAAyEDkAoD4
///IQOQCgPj//6CRdsD/////AAAAAAAAAAAwjKYDgPr//zCMpgOA+v//gFecxwAAAAAAAAAA
AAAAADBIpQOA+v//MEilA4D6//+g0/LoAAAAAAAAAAAAAAAAKEHkAoD4//8oQeQCgPj//wA1
6tX/////AAAAAAAAAABIQeQCgPj//0hB5AKA+P//YFav2v////8AAAAAAAAAAAC8HgOA+v//
MLM6A4D6///A19XhAAAAAAAAAAAAAAAAiEHkAoD4//+IQeQCgPj//4DjhcD/////AAAAAAAA
AACoQeQCgPj//6hB5AKA+P//gHrB7f////8AAAAAAAAAALAoqAOA+v//QHGwAYD6//+A8azH
AAAAAAAAAAAAAAAA6EHkAoD4///oQeQCgPj//0C9NdH/////AAAAAAAAAAAIQuQCgPj//whC
5AKA+P//oN761f////8AAAAAAAAAAChC5AKA+P//KELkAoD4//9grfLC/////wAAAAAAAAAA
SELkAoD4//9IQuQCgPj//2Ahhd//////AAAAAAAAAAAAZoYDgPr//wBmhgOA+v//4O+Sdg0A
AAAAAAAAAAAAAIhC5AKA+P//iELkAoD4///AkI2t/////wAAAAAAAAAAqELkAoD4//+oQuQC
gPj//4DFEen/////AAAAAAAAAADIQuQCgPj//8hC5AKA+P//QJT+wv////8AAAAAAAAAABDp
PAOA+v//EOk8A4D6///Ar6I3AQAAAAAAAAAAAAAACEPkAoD4//8IQ+QCgPj//+CIfbn/////
AAAAAAAAAAAoQ+QCgPj//yhD5AKA+P//AEsb6f////8AAAAAAAAAAEhD5AKA+P//SEPkAoD4
//+ga6bA/////wAAAAAAAAAAgPBWA4D6//+A8FYDgPr//wCnViMCAAAAAAAAAAAAAACIQ+QC
gPj//4hD5AKA+P//IK9f5P////8AAAAAAAAAADC8rgOA+v//8McxA4D6//+AMHvYAAAAAAAA
AAAAAAAAyEPkAoD4///IQ+QCgPj//0CfEcP/////AAAAAAAAAADoQ+QCgPj//+hD5AKA+P//
oOr5wP////8AAAAAAAAAADDMAAOA+v//MClCAoD6//+g8ZvMAAAAAAAAAAAAAAAAKETkAoD4
//8oROQCgPj//6BCesX/////AAAAAAAAAAAQqbgBgPr//xCpuAGA+v//YLcl1gAAAAAAAAAA
AAAAAGhE5AKA+P//aETkAoD4///A2Ora/////wAAAAAAAAAAiETkAoD4//+IROQCgPj//+CU
Xb7/////AAAAAAAAAACoROQCgPj//6hE5AKA+P//gNss1v////8AAAAAAAAAAMhE5AKA+P//
yETkAoD4///gnJvr/////wAAAAAAAAAA6ETkAoD4///oROQCgPj//0C+Vd3/////AAAAAAAA
AAAIReQCgPj//whF5AKA+P//YHrIwP////8AAAAAAAAAAChF5AKA+P//KEXkAoD4//8AYTbW
/////wAAAAAAAAAAQPFoA4D6//9A8WgDgPr//2CCBu4AAAAAAAAAAAAAAABA4Z4DgPr//8Bt
bAOA+v//wIOc2AAAAAAHAQYAAAAAAEgheAGA+v//SCF4AYD6//8AAAAAAAAAABMCAQEAAAAA
ACPkAoD4//8AI+QCgPj//zATtgIA+P//AAAAAAAAAAAAHG4DgPj//wgcbgOA+P//AAAAAAAA
AAABAAAAAGQAAAAAAAAAAAAAJ8ABAAAAAAAAAAAAAAAAAPDnmwGA+v//APFoA4D6//8AAAAA
AAAAAAAAAAABAAAAEwEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAQH6/AgD4//8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gEbkAoD4//+ARuQCgPj//5BG5AKA+P//kEbkAoD4//+gRuQCgPj//6BG5AKA+P//sEbkAoD4
//+wRuQCgPj//8BG5AKA+P//wEbkAoD4///QRuQCgPj//9BG5AKA+P//4EbkAoD4///gRuQC
gPj///BG5AKA+P//8EbkAoD4//8AR+QCgPj//wBH5AKA+P//EEfkAoD4//8QR+QCgPj//yBH
5AKA+P//IEfkAoD4//8wR+QCgPj//zBH5AKA+P//QEfkAoD4//9AR+QCgPj//1BH5AKA+P//
UEfkAoD4//9gR+QCgPj//2BH5AKA+P//cEfkAoD4//9wR+QCgPj//4BH5AKA+P//gEfkAoD4
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
gPj//7hxrQIA+P//AHgAAAAAAACJeAMBgB8AAAAAAAAAAAAA4BDGAgD4///gEMYCAPj//0tE
QkdAAwAAAGClAgD4///wOawCAPj//wAAAAAAAAAA6AHYAAAAAQAQMqwCAPj//wAAAAAAAAAA
kJjJAgD4//+QtccCAPj//8i1xwIA+P//UBTHAgD4//8wOtACAPj//3gw0AIA+P//lDDQAgD4
//8AxcwCAPj//4BjzAIA+P//8ArNAgD4///QwccCAPj//+jBxwIA+P//AAAAAAAAAAAAAAAA
AAAAAABr0AIA+P//eDLQAgD4//8AAAAAAAAAAAAAAAAAAAAA+DnQAgD4//8kL8gCAPj///gy
0AIA+P//CDHQAgD4//9gMNACAPj//+Ay0AIA+P//AAAAAAAAAAC4MNACAPj//wAAAAAAAAAA
AAAAAAAAAACgMdACAPj//9A40AIA+P//ABAAAAAAAACQNNACAPj//xgfyAIA+P//IB/IAgD4
///A0sYCAPj//yiZyQIA+P//8B7IAgD4//9gH8gCAPj//wAAAAAAAAAAAGXQAgD4///AatAC
APj//8Br0AIA+P//wGLQAgD4//9gTMQCAPj//8D7xAIA+P//APzEAgD4//9oGscCAPj//4C1
xQIA+P//EDDQAgD4//8AMdACAPj//wAw0AIA+P//cM/FAgD4//9w38UCAPj//7hPxAIA+P//
ZM/FAgD4///woMkCAPj//6CrwAIA+P//AAAAAAAAAABAPNACAPj//+gx0AIA+P//iJjJAgD4
///InMcCAPj//9Qw0AIA+P//yP7GAgD4///gnMkCAPj//xA0yAIA+P//UB/IAgD4//8oH8gC
APj//5wtzQIA+P//ODDQAgD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwA
uAA4ACgAcABkAQAAAADQBDgDkAIoAABN2iEIAPQF8AW4SyABJACoBAAAAAAAAJBQxAIA+P//
mFDEAgD4//9A1cwCAPj//4BOGAAgAIABAAAAAAAAAAAAAEAAEAAYAAAAMwArAAAAAABAACMA
UwAABs0CAPj//wACzQIA+P//AAAAAAAAAABIG8gCAPj//0QbyAIA+P//gGfAAgD4///YSwAA
AAAAABjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAGClAgD4//8AAAAAAAAAAABQXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuG5VAAAAAABz8LlTAAAAAGDcAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCgAgD4//8AAAAA
AAAAAACQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAwwQEAAAAAABpxudMAAAAAKDcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOC6AAD4//8AAAAAAAAAAACgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm/UAAAAAAABhgE1N
AAAAAOjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAODIAID4//8AAAAAAAAAAADwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfvkEAAAAAAA3x+dMAAAAAFDdAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDNAID4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAYvcAAAAAAAAn4FtKAAAAAJjdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDPAID4//8AAAAAAAAAAADgBQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARlwGAAAAAAAdwVtK
AAAAANjdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPDUAID4//8AAAAAAAAAAABQBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlWUHAAAAAAAl0axTAAAAABjeAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDuAID4//8AAAAA
AAAAAAAgDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAyskMAAAAAABBFsVRAAAAAHDeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABD7AID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX2oBAAAAAABwqxBQ
AAAAAMjeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAADgAID4//8AAAAAAAAAAABwBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9qwFAAAAAACUkudMAAAAABjfAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDlAID4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAB1AAAAAAAAAXwVtKAAAAAHDfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmAID4//8AAAAAAAAAAACgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADTIBAAAAAAD+wFtK
AAAAAMjfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKDmAID4//8AAAAAAAAAAAAwAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUDEDAAAAAACPkudMAAAAABjgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDpAID4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAS8AAAAAAAADbyltKAAAAAHDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDqAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJwBAAAAAAD8dWRU
AAAAAMjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKDrAID4//8AAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADaoBAAAAAADxdWRUAAAAABjhAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABD8AID4//8AAAAA
AAAAAABQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFdYCAAAAAAAcdmRUAAAAAHDhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGD+AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyN8BAAAAAADBG2RP
AAAAAMjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADDtAID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcp8BAAAAAACgkudMAAAAACDiAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAID4//8AAAAA
AAAAAADABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHjiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDFAID4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqRABAAAAAAAUwVtK
AAAAANDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEDGAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxZwBAAAAAAAUwVtKAAAAACjjAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDHAID4//8AAAAA
AAAAAACgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAISYCAAAAAACZkudMAAAAAIDjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDcAID4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu2UAAAAAAAATwVtK
AAAAANjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANDcAID4//8AAAAAAAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVgsDAAAAAAC1+f5RAAAAADDkAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIACAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAAIjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAFAYD4//8AAAAAAAAAAABABgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlb4DAAAAAAAyRPBS
AAAAAODkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAIALAYD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNUAAAAADjlAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjikBAAAAAAA+YGNUAAAAAJDlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQAYD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt5IAAAAAAADKo6NL
AAAAAOjlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANAQAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALUUFAAAAAACckudMAAAAAEDmAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAVAYD4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAARFYBAAAAAACBxFtKAAAAAJjmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAkAYD4//8AAAAAAAAAAACQGgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXfIZAAAAAACKvuFS
AAAAAOjmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANAWAYD4//8AAAAAAAAAAADgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDnAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAYD4//8AAAAA
AAAAAACwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAqfcBAAAAAAAOkkhTAAAAAJjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBPAYD4//8AAAAAAAAAAAAgBwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhV4HAAAAAAC3TxlQ
AAAAAOjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEBWAYD4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXksBAAAAAAD/wFtKAAAAADjoAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBXAYD4//8AAAAA
AAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAYD4//8AAAAAAAAAAAAgDwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEYsOAAAAAACy9jRQ
AAAAAODoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPBXAYD4//8AAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPkMGAAAAAAANdpRSAAAAADjpAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAcAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAfD4DAAAAAACQdzxUAAAAAJDpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAYD4//8AAAAAAAAAAADwHwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARV8dAAAAAADUWz9T
AAAAAOjpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADCEAYD4//8AAAAAAAAAAACQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsjgFAAAAAAAJWz9TAAAAAEDqAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCIAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCJAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ScFAAAAAADIkudM
AAAAAPDqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAICOAYD4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6eAAAAAAAAC7WAhKAAAAAEjrAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPAYD4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVnMDAAAAAAAumOdMAAAAAKDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCSAYD4//8AAAAAAAAAAAAgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/V0BAAAAAAABwltK
AAAAAPDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMCTAYD4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9NkAAAAAAAB+kudMAAAAAEjsAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCUAYD4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAQSEEAAAAAABcpgBRAAAAAKDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPCXAYD4//8AAAAAAAAAAABgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHf8BAAAAAAAdwVtK
AAAAAPDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCzA4D4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVWIBAAAAAAA+k+dMAAAAAIjxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC0A4D4//8AAAAAAAAAAACQCAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ukHAAAAAAAcKYhT
AAAAANjxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKAGBID4//8AAAAAAAAAAABQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBEEAAAAAACGk+dMAAAAADDyAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAKBID4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAe7EAAAAAAAC2zFtKAAAAAIjyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIALBID4//8AAAAAAAAAAABgAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzw0CAAAAAABiqOdM
AAAAAODyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAOANBID4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaBYBAAAAAAC2zFtKAAAAADjzAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAOBID4//8AAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxrcDAAAAAACCG05SAAAAAIAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHA5BID4//8AAAAA
AAAAAAAgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAT2cCAAAAAAD+JE5SAAAAANAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA7BID4//8AAAAAAAAAAABSAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkq8AAAAAAACTyltK
AAAAACgBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPA7BID4//8AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfekAAAAAAAARZWNUAAAAAIABAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALA8BID4//8AAAAA
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAx3gBAAAAAAC9yltKAAAAANgBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA9BID4//8AAAAAAAAAAACgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTQBAAAAAAAZRPBS
AAAAAEACAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAgBID4//8AAAAAAAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoH8CAAAAAABUYGNUAAAAAKACAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgA4D4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjsEDAAAAAAAzYGNUAAAAAAADAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA+BID4//8AAAAAAAAAAAAwAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6g0BAAAAAACPwVtK
AAAAAGADAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAABAGD5//8AAAAAAAAAAAAgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKgDAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAiBID4//8AAAAA
AAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjkEBAAAAAAB0xVtKAAAAAAAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHAGD5//8AAAAAAAAAAADgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABvAGD5//8AAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJgEAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGAGD5//8AAAAA
AAAAAABwAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCjA4D4//8AAAAAAAAAAAAwAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8XsCAAAAAACVwltK
AAAAADgFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACAAYD4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnRABAAAAAACSzFtKAAAAAJAFAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCBAYD4//8AAAAA
AAAAAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAa2UBAAAAAACSzFtKAAAAAOgFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBtAoD4//8AAAAAAAAAAACQDAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7lYMAAAAAADOk+dM
AAAAADgGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFB6AoD4//8AAAAAAAAAAADgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOC0CAAAAAAAok2RNAAAAAJAGAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADB8AoD4//8AAAAA
AAAAAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApR8EAAAAAAAxJcdT
AAAAAFALAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKBDA4D4//8AAAAAAAAAAAAQBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCIHAAAAAAB6XghKAAAAAKgLAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBKA4D4//8AAAAA
AAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAKmgAAAAAAADlzFtKAAAAACEAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABuAHQAbwBzAGsAcgBuAGwALgBlAHgAZQAAABwAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABoAGEAbAAuAGQAbABsAAAAAAAeAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAawBkAGMAbwBtAC4A
ZABsAGwAAAAAAAAAAAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAbQBjAHUAcABkAGEAdABlAF8ARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwALgBkAGwA
bAAAAAAAAAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABQAFMASABFAEQALgBkAGwAbAAAAAAAAAAAAB0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABDAEwARgBTAC4AUwBZAFMAAAAbAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAQwBJAC4AZABsAGwAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABXAGQAZgAwADEAMAAwADAALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBEAEYATABEAFIALgBTAFkA
UwAAAAAAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAEEAQwBQAEkALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBNAEkATABJAEIA
LgBTAFkAUwAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAG0AcwBpAHMAYQBkAHIAdgAuAHMAeQBzAAAAJAAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABwAGMAaQAuAHMAeQBzAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAZAByAHYAcgBvAG8AdAAuAHMAeQBzAAAA
KAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAB4AGUAbgBmAGkAbAB0AC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4ALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAB4AGUAbgBiAHUAcwAuAHMAeQBzAAAAAAAAACgAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABhAHIA
dABtAGcAcgAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAbwBsAG0AZwByAC4AcwB5AHMAAAAAAAAA
KAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXAB2AG8AbABtAGcAcgB4AC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaQBuAHQAZQBsAGkA
ZABlAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAFAAQwBJAEkARABFAFgALgBTAFkAUwAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABtAG8AdQBuAHQAbQBnAHIALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAYQB0AGEAcABpAC4AcwB5AHMA
AAAAAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAGEAdABhAHAAbwByAHQALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgB2AGIAZAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwB0AG8AcgBwAG8AcgB0AC4AcwB5AHMA
AAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBkAGkA
cwBrAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAYQBtAGQAeABhAHQAYQAuAHMAeQBzAAAAAAAnAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAGYAbAB0AG0AZwByAC4AcwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABmAGkAbABlAGkAbgBmAG8A
LgBzAHkAcwAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAHIAaQB2AGUAcgBzAFwATgB0AGYAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABtAHMAcgBwAGMA
LgBzAHkAcwAAAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBkAGQALgBzAHkAcwAAAAAAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIA
cwBcAGMAbgBnAC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABjAHcALgBzAHkAcwAAAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMA
XABGAHMAXwBSAGUAYwAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbgBkAGkAcwAuAHMAeQBzAAAA
JgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXABOAEUAVABJAE8ALgBTAFkAUwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBwAGsA
ZwAuAHMAeQBzAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHQAYwBwAGkAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABmAHcAcABrAGMAbABuAHQALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAdgBtAHMAdABvAHIAZgBsAC4A
cwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHYAbwBsAHMAbgBhAHAALgBzAHkAcwAAAAAAJgAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAHAA
bABkAHIALgBzAHkAcwAAAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHkAYgBvAG8AcwB0AC4AcwB5AHMA
AAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkA
dgBlAHIAcwBcAG0AdQBwAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaAB3AHAAbwBsAGkAYwB5AC4A
cwB5AHMAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAGYAdgBlAHYAbwBsAC4AcwB5AHMAAAAAAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABkAGkA
cwBrAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAEMATABBAFMAUwBQAE4AUAAuAFMAWQBTAAAAJgAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABjAGQAcgBvAG0ALgBzAHkAcwAAAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwATgB1AGwAbAAuAFMAWQBTAAAA
JQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYA
ZQByAHMAXABCAGUAZQBwAC4AUwBZAFMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
UwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAZwBhAC4AcwB5AHMAAAAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwAVgBJAEQARQBPAFAAUgBUAC4AUwBZAFMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHcAYQB0AGMAaABkAG8A
ZwAuAHMAeQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABSAEQAUABDAEQARAAuAHMAeQBzAAAAAAAAACkAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwA
cgBkAHAAZQBuAGMAZABkAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHIAZABwAHIAZQBmAG0AcAAuAHMA
eQBzAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQA
cgBpAHYAZQByAHMAXABNAHMAZgBzAC4AUwBZAFMAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAE4AcABmAHMALgBTAFkA
UwAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAdABkAHgALgBzAHkAcwAAAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABUAEQASQAuAFMAWQBTAAAA
AAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAGEAZgBkAC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgB0AC4AcwB5AHMA
AAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAHcAZgBwAGwAdwBmAC4AcwB5AHMAAAAAAAAAJgAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABwAGEA
YwBlAHIALgBzAHkAcwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgBpAG8AcwAuAHMAeQBzAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHcAYQBuAGEAcgBwAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AGUAcgBtAGQA
ZAAuAHMAeQBzAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAcgBkAGIAcwBzAC4AcwB5AHMAAAAAAAAAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAG4AcwBpAHAAcgBvAHgAeQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAHMAcwBtAGIAaQBvAHMA
LgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAZABpAHMAYwBhAGMAaABlAC4AcwB5AHMAAAAkAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGMA
cwBjAC4AcwB5AHMAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZABmAHMAYwAuAHMAeQBzAAAAKQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAGwA
YgBkAHIAaQB2AGUALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdAB1AG4AbgBlAGwALgBzAHkAcwAAAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAGkAOAAwADQAMgBwAHIAdAAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAG8AdQBjAGwA
YQBzAHMALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAawBiAGQAYwBsAGEAcwBzAC4AcwB5AHMAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAGYAZABjAC4AcwB5AHMAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4AdgBpAGYALgBzAHkAcwAAAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHgAZQBuAGkAZgBhAGMAZQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABIAEQAQQB1AGQA
QgB1AHMALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAdgBpAG8AcwBlAHIALgBzAHkAcwAAAAAAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAHEAeABsAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdQBzAGIAdQBoAGMAaQAuAHMAeQBzAAAA
AAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAFUAUwBCAFAATwBSAFQALgBTAFkAUwAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB1AHMAYgBlAGgA
YwBpAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAaQBuAHQAZQBsAHAAcABtAC4AcwB5AHMAAAAtAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAEMAbwBtAHAAbwBzAGkAdABlAEIAdQBzAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAEEAZwBpAGwA
ZQBWAHAAbgAuAHMAeQBzAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAByAGEAcwBsADIAdABwAC4AcwB5AHMAAAAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAbgBkAGkAcwB0AGEAcABpAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAG4AZABpAHMAdwBhAG4A
LgBzAHkAcwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXAByAGEAcwBwAHAAcABvAGUALgBzAHkAcwAAACgAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwA
cgBhAHMAcABwAHQAcAAuAHMAeQBzAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAHMAcwB0AHAALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAByAGQAcABiAHUAcwAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwB3AGUA
bgB1AG0ALgBzAHkAcwAAAAAAAAAjAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGsAcwAuAHMAeQBzAAAAAAAAACYAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwA
dQBtAGIAdQBzAC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHUAcwBiAGgAdQBiAC4AcwB5AHMA
AAAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQA
cgBpAHYAZQByAHMAXABOAEQAUAByAG8AeAB5AC4AUwBZAFMAAAAAACgAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABkAEEA
dQBkAGkAbwAuAHMAeQBzAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHAAbwByAHQAYwBsAHMALgBzAHkAcwAAAAAA
JQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXABkAHIAbQBrAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGsAcwB0AGgAdQBuAGsALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAB4AGUAbgBuAGUAdAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAYwByAGEA
cwBoAGQAbQBwAC4AcwB5AHMAAAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMA
dABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAGQAdQBtAHAAXwBkAGkAcwBrAGQAdQBtAHAA
LgBzAHkAcwAAAAAAAAAAACwAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AcwB5AHMA
AAAAAC0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIA
aQB2AGUAcgBzAFwAZAB1AG0AcABfAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAC0AAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwA
ZAB1AG0AcABfAGQAdQBtAHAAZgB2AGUALgBzAHkAcwAAAB8AAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXAB3AGkAbgAzADIAawAuAHMAeQBzAAAAAAAAACYA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwARAB4AGEAcABpAC4AcwB5AHMAAAAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGQAeABnAC4AcwB5AHMA
AAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABUAFMA
RABEAEQALgBkAGwAbAAAAAAAAAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABxAHgAbABkAGQALgBkAGwAbAAAAAAAAAAAACYAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbAB1AGEA
ZgB2AC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGwAbAB0AGQAaQBvAC4AcwB5AHMAAAAAAAAA
JwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAByAHMAcABuAGQAcgAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABUAFQAUAAuAHMA
eQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXABiAG8AdwBzAGUAcgAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbQBwAHMA
ZAByAHYALgBzAHkAcwAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAG0AcgB4AHMAbQBiAC4AcwB5AHMAAAAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXABtAHIAeABzAG0AYgAxADAALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbQByAHgAcwBtAGIA
MgAwAC4AcwB5AHMAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHAAZQBhAHUAdABoAC4AcwB5AHMAAAAAAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMA
XABzAGUAYwBkAHIAdgAuAFMAWQBTAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwByAHYAbgBlAHQALgBzAHkA
cwAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHQAYwBwAGkAcAByAGUAZwAuAHMAeQBzAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHIA
dgAyAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwARABSAEkAVgBFAFIAUwBcAHMAcgB2AC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAA
ZAByAC4AcwB5AHMAAAAAAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHQAZAB0AGMAcAAuAHMAeQBzAAAAAAAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAB0AHMAcwBlAGMAcwByAHYALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAUgBEAFAAVwBEAC4A
UwBZAFMAAAAAAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHMAcABzAHkAcwAuAHMAeQBzAAAAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABhAHMAeQBuAGMAbQBhAGMALgBzAHkAcwAAAOCcyQIA+P//8AwBAJwAAABIG8gCAPj//4wN
AQAEAAAARBvIAgD4//+QDQEABAAAAKCrwAIA+P//lA0BAAABAAAABs0CAPj//5QOAQAEAAAA
AALNAgD4//+YDgEAUAAAAHww0AIA+P//6A4BAAQAAABoMNACAPj//+wOAQAEAAAAANCJAYD6
///wDgEAeAkAAIDSxgIA+P//aBgBAAgAAACI0sYCAPj//3AYAQAIAAAAALDBAgD4//94GAEA
ABAAAABgpQIA+P//eCgBAAAQAAAAgOYCgPj//3g4AQAAEAAAALCsAgD4//94SAEAABAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
NzYwMS4xODUyNi5hbWQ2NGZyZS53aW43c3AxX2dkci4xNDA3MDYtMTUwNgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABhMDVlNTg1NC1hMDAxLTRjMjItODg1MS1kZDc4NWUxMAUAAAB8MNACAPj//4Aw
0AIA+P//aDDQAgD4//9sMNACAPj//wDQiQGA+v//eNmJAYD6//+A0sYCAPj//4jSxgIA+P//
iNLGAgD4//+Q0sYCAPj//0cAAAAAAAAAABAAAAAAAAB4CQAADwAAAAAAAAAAAAAAxgEAAAAA
AAAAAAAAAAAAAAAIAgABAAAAAAAAAAAAAADgkagDgPr//zhAigGA+v//AgARwDgAIALGOzHB
BAAAAKECMcEEAAAAACQbAAAAAABQP1A/AQAAAEBhaQOg+P//dAoAAAAgAAACABHAOAAgAu+W
b8EEAAAA7ZNvwQQAAAAAAHwCAAAAAAAAOAqA+f//8OYcAKD4//90CgAAABAAAAIAEcA4ACAC
MqB7wQQAAACwJnDBBAAAAABQgAAAAAAAoCgWAgAAAADQwxIDgPr//3QKAAAAAAEAAgARwDgA
IALYqH/BBAAAAFulf8EEAAAAAAAAAAAAAAAAANkBAAAAAHBs1wCg+P//dAoAAACAAAACABHA
OAAgAvLRtsEEAAAA9cF/wQQAAAAAQIAAAAAAAGAUFgIAAAAA0MMSA4D6//90CgAAABAAAAIA
EcA4ACACsXHHwQQAAABMbcfBBAAAAAAAAAAAAAAAAADZAQAAAACgsw4BoPj//3QKAAAAgAAA
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
AQEBAAECAAABAQEAAQIAAAEBAQABAgAAARkCABlSFQIBBwIABwGnAAEEAQAEQgAAGQQBAARC
AABw7AEAAAAAAAAAAAABBAEABEIAABkEAQAEQgAAwD8CAAAAAAAAAAAAAQQBAARCAAAZBAEA
BEIAAPBFCAAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABAUQIAAAAAAAAAAAABBAEABEIAABkE
AQAEQgAAYPwHAAAAAAAAAAAAAQQBAARCAAAZBAEABEIAADAZDAAAAAAAAAAAAAEEAQAEQgAA
GQQBAARCAACw3gAAAAAAAAAAAAABBAEABEIAABkEAQAEQgAA8BkMAAAAAAAAAAAAAQQBAARC
AAAZBAEABEIAALAaDAAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABwGwwAAAAAAAAAAAABFAaF
FFMMASsABVAEAgAKARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBXyQAX/QmAFvk
JQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXICQAwuAgAK6gHACWYBgAfiAUA
GXgEABRoAwAHAScAARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsA
BVAEAgAKARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBEAWFEFMIASsAAVAAGgAA
ARQGhRRTDAErAAVQBAIACgEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARAFhRBT
CAErAAFQABoAAAEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARQGhRRTDAErAAVQ
BAIACgEQBYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKAV8kAF/0JgBb5CUAV9QkAFPE
IwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMA
BwEnAAEUBoUUUwwBKwAFUAQCAAoBGQaFGVMRASsAClAJAgUKARgGhRhTEAErAAlQCAIECgE7
BoU7UzMBKwAsUCsCJwoBBAEABGIAAAEpDIUpZCoAInQpABs0KAAUUwwBKwAFUAQCAAoZUAyF
UGQqAEl0KQBCNCgAO1MzASsALFArAicKQEoHAAAAAAAAAAAAAV8kAF/0JgBb5CUAV9QkAFPE
IwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMA
BwEnAAFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAARPgMAD/oCwA62AoANcgJADC4
CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBOwABBAEABEIAAAGfJACfNC4Al2QwAI90LwCH9DQA
f+QzAHfUMgBvxDEAZ/gTAF7oEgBV2BEATMgQAEO4DwA6qA4AMZgNACiIDAAfeAsAF2gKAA8B
NQABBAEABEIAAAF/HgB/9DQAd+QzAG/UMgBnxDEAX/gTAFboEgBN2BEARMgQADu4DwAyqA4A
KZgNACCIDAAXeAsAD2gKAAcBNQABBAEABEIAAAEEAQAEwgAAAZckAJc0LgCPZDAAh3QvAH/0
NAB35DMAb9QyAGfEMQBf+BMAVugSAE3YEQBEyBAAO7gPADKoDgApmA0AIIgMABd4CwAPaAoA
BwE1AAEGAwAGQgJQATAAAAEFAgAFMgFQAQYDAAZiAlABMAAAAQUCAAVSAVABBwQABzIDYAJQ
ATABBwQABzIDcAJgAVABBQIABZIBUAEGAwAGggJQATAAAAEJBQAJYgXQA3ACUAEwAAABBQIA
BXIBUAEIBAAIUgTgAlABMAEHAwAHYgPQAVAAAAEHBAAHMgNwAlABMAEHAwAHQgPgAVAAAAEI
BAAIcgTQAnABUAEHAwAHggPwAVAAAAEJBAAJkgXgA8ABUAEOCAAOUgrgCNAGwARwA2ACUAEw
ARAJABCCDPAK4AjQBsAEcANgAlABMAAAAQcEAAdSA3ACUAEwAQgFAAhiBHADYAJQATAAACEA
BAAAdAAAAGQDAKCjBACkowQAMNgbACEAAACgYQsA8GELAFjJGwAhAAAAnJcEAOSXBADg0hsA
IQAAACzdAQDf3QEAvNQbACEAAAC80wkAMNQJAFjJGwAhAAAAgNIJAEzTCQAkyRsAIQAAACRT
BAAIVAQA4NIbACEAAAD0RQAAKUYAAEw7HAAhAAAA5OUEAMTmBADsKhwAIQAAAPwxAQDsMwEA
MD4cACEAAACkQQAAGEMAAOgfHAAhAAAAQD8EAJA/BAAgyhsAIQAAAACJAQCgigEA7CocACEA
AADgrwEAdLABAHzJGwAhAAgAAPQDAAB0BAAAVAUAADQGAMBWAgD6VgIA/D8cACEAEAAA9AQA
AOQFAADUBgAAxAcAAHQIAABkDQAAVAwAADQLAOA8BQD5PAUA/OgbACEAAAAgPgUALT4FAGDI
GwAhAAYAAHQEAABkBwAANAYAl6QMAKGkDAC8XRwAIQAAAMRDBQBsRAUAIMobACEAAgAANAAA
gO4JALLuCQAw2BsAIQAAAMQ+AwAcPwMAnDgcACEAAADQZggA7WYIADDYGwAhAAAAAAQEAJwE
BAAgyhsAIQAAADgABADwAAQAIMobACEAAACYNwMAcDgDANTQGwAhAAAAUEAKAIVACgBY2hsA
IQAAAHCqBABQqwQAXDMcACEAAACgwwQAQMQEALzUGwAhAAAAoMIEAATDBACMIxwAIQAAAFAG
AgBsBgIAkMkbACEAAACw0QgA4NIIALzUGwAhAAAAwC4FABwvBQA4OhwAIQACAABUCADqqwwA
9asMALxeHAAhAAAA6qsMAPWrDAC8XhwAIQAAABAQAACwEAAAJMkbACEAAAAs+QEA0PkBAODh
GwAhAAAAyMQFAFDFBQDg4RsAIQAAAIBmCQCUZwkA6D8cACEAAACkOwIAwDsCAGDIGwAhAAAA
EAAFAGwABQAkyRsAIQAAAAyxCgBMsgoA9N0bACEAAADAywUAQMwFAGDIGwAhAAAAIMsFAMDL
BQCUzhsAIQAAAAC7CABsuwgAkMkbACEAAAA4ygUAIMsFALA0HAAhAAAAcOILAHDjCwAkzBsA
IQAAAMDJBQA4ygUAMMwbACEAAABw4wsAoOMLAJjJGwAhAAAAUDwEALA9BAAkyRsAIQAAAIg7
BQAgPAUAlM4bACEAAADU5QEABOYBAJDJGwBNWpAAAwAAAAQAAAD//wAAuAAAAAAAAABAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoAAAADh+6DgC0Cc0huAFMzSFUaGlz
IHByb2dyYW0gY2Fubm90IGJlIHJ1biBpbiBET1MgbW9kZS4NDQokAAAAAAAAAPjLo8a8qs2V
vKrNlbyqzZW10k6V2KrNlbXSXpW3qs2VvKrMldCqzZW10liVgarNlbXSQ5Xlqc2VtdJJlaaq
zZW10l+VvarNlbXSWZW9qs2VtdJclb2qzZVSaWNovKrNlQAAAAAAAAAAUEUAAGSGGABz8LlT
AAAAAAAAAADwACIACwIJAACkRwAA/gwAADQAAPA2KwAAEAAAAAAAQAEAAAAAEAAAAAIAAAYA
AQAGAAEABgABAAAAAAAAUF4AAAYAALhuVQABAAAAAAAIAAAAAAAAIAAAAAAAAAAAEAAAAAAA
ABAAAAAAAAAAAAAAEAAAAAAAUwC8CQEA3KdaAHgAAAAAwFoAPF8DAADQJwBI/QIAAJhUALgb
AAAAIF4AdCAAACAfGgA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAADAGgCAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAACBDxoAABAAAAAQ
GgAABgAAAAAAAAAAAAAAAAAAIAAAaElOSVRLREJHsDkAAAAgGgAAOgAAABYaAAAAAAAAAAAA
AAAAACAAAGhQT09MTUkAAB0cAAAAYBoAAB4AAABQGgAAAAAAAAAAAAAAAAAgAABoUE9PTENP
REUbLgAAAIAaAAAwAAAAbhoAAAAAAAAAAAAAAAAAIAAAaFJXRVhFQwAAABAAAACwGgAAAAAA
AAAAAAAAAAAAAAAAAAAAAKAAAOgucmRhdGEAAKTWAwAAwBoAANgDAACeGgAAAAAAAAAAAAAA
AABAAABILmRhdGEAAACoLgkAAKAeAAD+AAAAdh4AAAAAAAAAAAAAAAAAQAAAyC5wZGF0YQAA
SP0CAADQJwAA/gIAAHQfAAAAAAAAAAAAAAAAAEAAAEhBTE1PU1RSTzAjAAAA0CoAAAgAAABy
IgAAAAAAAAAAAAAAAABAAADIU1BJTkxPQ0vAHQAAAAArAAAMAAAAeiIAAAAAAAAAAAAAAAAA
QAAAyFBBR0VMSwAAO04BAAAgKwAAUAEAAIYiAACA0AIA+P//AAAAACAAAGBQQUdFAAAAAJ4+
IwAAcCwAAEAjAADWIwAAAAAAAAAAAAAAAAAgAABgUEFHRUtEAADySwAAALBPAABMAAAAFkcA
AAAAAAAAAAAAAAAAIAAAYFBBR0VWUkZZuxYCAAAAUAAAGAIAAGJHAAAAAAAAAAAAAAAAACAA
AGBQQUdFSERMU9cnAAAAIFIAACgAAAB6SQAAAAAAAAAAAAAAAAAgAABgUEFHRUJHRlhMZgAA
AFBSAABoAAAAokkAALD3AgD4//8AAAAAIAAAYFBBR0VWUkZCADQAAADAUgAAAAAAAAAAAAAA
AAAAAAAAAAAAAIAAAMAuZWRhdGEAALwJAQAAAFMAAAoBAAAKSgAAAAAAAAAAAAAAAABAAABA
UEFHRURBVEEA3QAAABBUAABMAAAAFEsAAAAAAAAAAAAAAAAAQAAAwFBBR0VWUkZDHikAAADw
VAAAKgAAAGBLAAAAAAAAAAAAAAAAAEAAAEBQQUdFVlJGRFASAAAAIFUAABQAAACKSwAAAAAA
AAAAAAAAAABAAADASU5JVAAAAABcdgUAAEBVAAB4BQAAnksAAAAAAAAAAAAAAAAAIAAA4i5y
c3JjAAAAPF8DAADAWgAAYAMAABZRAAAAAAAAAAAAAAAAAEAAAEAucmVsb2MAAHQgAAAAIF4A
ACIAAAB2VAAAAAAAAAAAAAAAAABAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAPvDg/8gdVuJRYBIiU2ISIlVkEyJRZhMiU2g6JGE//8LwItFgEiLTYhIi1WQ
TItFmEyLTaBIiaPYAQAAD4Sx/P//SI09WIkjAIt3EEiLPzvGcxBIjTy3D74EOAvAD475/f//
uBwAAMDp7/3//7lKAAAARTPJRQ8gwEULwHUUuQEAAABFD7aD8AEAAEWLi8QBAABIi5XoAAAA
TIvV6GAAAABIg+xQSIlMJCBIiVQkKEyJRCQwTIlMJDhMiVQkQEmLyuhryA4ASItMJCBIi1Qk
KEyLRCQwTItMJDhMi1QkQEiDxFBB/9JIiUWwSIvI6N/HDgBIi0Ww6Vn9//9mDx9EAABIgew4
AQAASI2EJAABAAAPKXQkMA8pfCRARA8pRCRQRA8pTCRgRA8pVCRwRA8pWIBEDylgkEQPKWig
RA8pcLBEDyl4wEiJGEiJeAhIiXAQTIlgGEyJaCBMiXAoTIl4MEyJVCQg6FcKAACQZmZmZmZm
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
AAAAQYmQnAAAAIsNQHUjAA8yQYmAkAAAAEGJkJQAAAC52QEAAA8yg+D8DzDCAADMzMzMzMwP
HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVFJHRER1bXBCbG9iEAAAALEdAPAgAAAAQFp1ZUbx
6kOMkTa4Vyj9NQAAAAAAAAAAAAAAACAAAACPAFy8Oh7XRJiNhvaITGdYYQEAAAAAAAAHAAAA
AAIEJFkBAAAAGAAAAQIA6AMAgAAIAAAAAAAABAQF//9YZW4ANC41LjAtcmMAMTEvMTMvMjAx
NAAAARsAAQECAwQAAAAAAAAAAAAAAAAAAAAABgAAWGVuAEhWTSBkb21VADQuNS4wLXJjACAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAAw0AAwEBAAAAAwMDAlhlbgAA
BBoBBAEDAQLlBgEA//uJFwAAAABkCmQKQQFDUFUgMQBJbnRlbAAABBoCBAEDAQLlBgEA//uJ
FwAAAABkCmQKQQFDUFUgMgBJbnRlbAAACwUACwFYZW4AABAPABABAwYAAB4A/v8BAAAAERUA
EQAQAABAAEAAgAcJAAEABwAARElNTSAwAAATDwATAAAAAP//HQAAEAEAABQTABQAAAAA//8d
AAARABMBAAAAACALACAAAAAAAAAAAAB/BAB/AAAAAAAAAAAAIAAAAInDemwTQ9xHnzSogAoP
tWxuAgAAAAAAAAIAAAAKAAAAfgBNAEgAegAAAAQAAAAEAAAAbQoAACwAAABDAG8AbQBwAG8A
bgBlAG4AdAAgAEkAbgBmAG8AcgBtAGEAdABpAG8AbgAAAAMAAAAQAAAAAAAAAAAAAAAAAAAA
AAAAACYAAABDAG8AbgBmAGkAZwB1AHIAYQB0AGkAbwBuACAARABhAHQAYQAAAAkAAAAQAAAA
//////////8AAAAAAAAAABYAAABJAGQAZQBuAHQAaQBmAGkAZQByAAAAAQAAAEoAAABJAG4A
dABlAGwANgA0ACAARgBhAG0AaQBsAHkAIAA2ACAATQBvAGQAZQBsACAAMwAwACAAUwB0AGUA
cABwAGkAbgBnACAANQAAACgAAABQAHIAbwBjAGUAcwBzAG8AcgBOAGEAbQBlAFMAdAByAGkA
bgBnAAAAAQAAAGAAAABJAG4AdABlAGwAKABSACkAIABYAGUAbwBuACgAUgApACAAQwBQAFUA
IAAgACAAIAAgACAAIAAgACAAIAAgAFgAMwA0ADUAMAAgACAAQAAgADIALgA2ADcARwBIAHoA
AAAiAAAAVQBwAGQAYQB0AGUAIABTAGkAZwBuAGEAdAB1AHIAZQAAAAMAAAAIAAAAAAAAAAcA
AAAcAAAAVQBwAGQAYQB0AGUAIABTAHQAYQB0AHUAcwAAAAQAAAAEAAAABwAAACIAAABWAGUA
bgBkAG8AcgBJAGQAZQBuAHQAaQBmAGkAZQByAAAAAQAAABoAAABHAGUAbgB1AGkAbgBlAEkA
bgB0AGUAbAAAAAwAAABNAFMAUgA4AEIAAAALAAAACAAAAAAAAAAHAAAAAAAgAAAAb8A90I7Y
xUS6KvrgNRctGZgDAAAAAAAAAAAAAAAAAAAAAAAACwAAAEdlbnVudGVsaW5lSQsAAABHZW51
bnRlbGluZUkAAAAAAQAAAOUGAQAACCACASK4gf/7ixflBgEAAAggAgEiuIH/+4sXAAAAAAIA
AAABWgNV5LLwAAAAAAAsIcoJAVoDVeSy8AAAAAAALCHKCQAAAAAEAAAAAAAABAAAAAAAAAAA
AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAKAAAAAAAAB0QAAAAAAAAAAAAAAAAAAAdEAAAAAAAAAAAAAAAAAAAACwAAAAAA
AAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAQAAABcAAAAAAAAAAAAEAAAAAAAAAAAA
AAAAAAAABAAAAAAAAAAAAAEAAACLAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAA
AAABAAAAgAAAwAENAAAAAAAAAAAAAAAAAAABDQAAAAAAAAAAAAAAAAAAAAAAAAAAAIAIAACA
AAAAAAAAAAAAAAAACAAAgAAAAAAAAAAAAAAAAAAAAAABAACAAAAAAAAAAAABAAAAAAgQKAAA
AAAAAAAAAQAAAAAIECgAAAAAAgAAgEludGVsKFIpIFhlb24oUilJbnRlbChSKSBYZW9uKFIp
AAAAAAMAAIAgQ1BVICAgICAgICAgICBYIENQVSAgICAgICAgICAgWAAAAAAEAACAMzQ1MCAg
QCAyLjY3R0h6ADM0NTAgIEAgMi42N0dIegAAAAAABQAAgAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAYAAIAAAAAAAAAAAEBgAAEAAAAAAAAAAAAAAABAYAABAAAAAAAA
AAAHAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAgCQwAAAAAAAA
AAAAAAAAAAAkMAAAAAAAAAAAAAAAAAAAIAAAANJAO+igsEJIq+pxyeNGPdFAAAAAAAAAAAAA
AABBUElDYAQAAAKwWGVuAAAARkFDUPQAAAAEQFhlbgAAAFdBRVQoAAAAAVZYZW4AAABIUEVU
OAAAAAHSWGVuAAAAIAAAAIhIyFTRAR5MvtYoLJgkEwMAEAAAAAAAAAAAAACdTE1ULJTVRr9Q
31zZUkpQSBCNAoD6//+4DwAAJAnoCDMAAABjZHJvbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAExKfvihxS9Nv/DV3mOl
5MNoAgAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAAAAAAAAFdkZjAxMDAwAGgAAAkAAAABAAAA
AAAAAM7PAAAoAAAABAAAAEBCawKA+v//AQAAAAkAAACwHQAAbXNpc2FkcnYAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAACgEAQG4SAoD6//8BAAAACQAAALAdAAB2ZHJ2cm9vdAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAM7PAABAnjgCgPr//wEAAAAFAAAAcBcAAHN0b3JmbHQAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA8Ag/AAAZjAKA+v//AQAAAAkAAACwHQAAY2Ryb20AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAQAaTAoD6//8BAAAABwAAAHEXAABIREF1ZEJ1cwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAABAOpMCgPr//wEAAAAJAAAAsB0AAFZpcnRpb1Nl
cmlhbAAAAAAAAAAAAAAAAAAAAAAAAAAAvAIAAEBOlgKA+v//AQAAAAkAAACwHQAAaW50ZWxw
cG0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPzwAAUKyXAoD6//8BAAAACQAAALAdAABDb21w
b3NpdGVCdXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAWUQAQoJsCgPr//wEAAAAJAAAAsB0AAHVt
YnVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABBAUwOA+v//AQAAAAcAAABxFwAA
UEVBVVRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
--------------070603040901030901050202
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Thu Nov 13 14:19:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:19: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 1XovFJ-000416-Sw; Thu, 13 Nov 2014 14:19:37 +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 1XovFH-000411-AD
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:19:36 +0000
Received: from [85.158.139.211] by server-5.bemta-5.messagelabs.com id
	D1/45-27584-6FDB4645; Thu, 13 Nov 2014 14:19:34 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-13.tower-206.messagelabs.com!1415888373!11171953!1
X-Originating-IP: [74.125.82.44]
X-SpamReason: No, hits=0.0 required=7.0 tests=
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15577 invoked from network); 13 Nov 2014 14:19:33 -0000
Received: from mail-wg0-f44.google.com (HELO mail-wg0-f44.google.com)
	(74.125.82.44)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:19:33 -0000
Received: by mail-wg0-f44.google.com with SMTP id x12so17011726wgg.17
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 13 Nov 2014 06:19:33 -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
	:subject:content-type;
	bh=5I4QI8lp+nGlTOR38rXHV5IgGHGIhW20aZIJi9XPVkI=;
	b=fvcWXcaMrp6vUx7EbPWIUOrj1H98+iVSSKAyOH4GUP0WXFVHpBV83uU+tCfalki4yS
	PA2VKdT00Qb25Z6/q13NxQkvt8e+dJ5dQRkWrxVMSbw9WH1ZAAFRd5bM9RTzHpZ6DpP6
	z4UwH8AY5Q8ijz+3hnz0mV1a49nWyPVs19QDHdSbbr+nzpE4iqYatCrwesSko/fPXsjf
	E6/zthdeKl/fTDbNDEnpoUmQhYDKHaZRxLLRIlknSLEl7B6sIzgJy2Lox+m7vau9Cu6E
	J1asa+Z8NsNjVZRuJLJuT1I408Ir8IaQIOoN86XPuev3vM5HsobSXLP91FqO7bynHSdq
	yqvw==
X-Gm-Message-State: ALoCoQmY90UkQAXaTBwb8wdmA0LR4UUk7NO79CUjHb1amUN+WcHqEHBjPbjWKPosD+l4+g5mJTzP
X-Received: by 10.180.109.17 with SMTP id ho17mr4303299wib.4.1415888373176;
	Thu, 13 Nov 2014 06:19:33 -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
	bj7sm35711415wjc.33.2014.11.13.06.19.24 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 13 Nov 2014 06:19:32 -0800 (PST)
Message-ID: <5464BDF4.1090103@m2r.biz>
Date: Thu, 13 Nov 2014 15:19:32 +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.2.0
MIME-Version: 1.0
To: win-pv-devel@lists.xenproject.org, 
	"paul.durrant@citrix.com >> Paul Durrant" <paul.durrant@citrix.com>
Content-Type: multipart/mixed; boundary="------------070603040901030901050202"
Subject: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------070603040901030901050202
Content-Type: text/plain; charset=iso-8859-15; format=flowed
Content-Transfer-Encoding: 7bit

I did a new build of winpv drivers and tested on one windows 7 64 bit 
domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu 
id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2 
from spice git:
https://github.com/Fantu/Xen/commits/rebase/m2r-staging

After restore windows showed blue screen with stop 1e, I open the dump 
with "BlueScreenView" and showed that cause is xennet driver.
I attached the dump, if you need more informations/tests tell me and 
I'll post them.

Thanks for any reply and sorry for my bad english.

--------------070603040901030901050202
Content-Type: application/octet-stream;
 name="111314-16707-01.dmp"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="111314-16707-01.dmp"

UEFHRURVNjQPAAAAsR0AAABwGAAAAAAAeDLQAgD4//+QmMkCAPj//5C1xwIA+P//ZIYAAAIA
AAAeAAAAUEFHRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0WgUMQCAPj//1BBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAA
AAAAAICN5gKA+P//WLPBAgD4///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC
5gKA+P//4HvmAoD4//+wjeYCgPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//
AAAAAAAAAACQu6wCAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAUAAAD/////aIMjodF/AAAFAAAAAAAAAAAAAAAAAAAAAPBFodF/AADyuY+h0X8AAAAA
AAAA8EWh0X8AAPK5j6EAAAAAAAAAAAD/////AP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAwAAgAEAAAAAAAAAAAAAAJC7rAIA+P//AAAAAFBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UEAAAA
UEFHRQgbBAAAAAAA8DjYAkn/zwFQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRQBOMcYAAAAA/wwAAFBB
R0UBAAAAEAEAAAAAAABQAEdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UAAQAAAAAEAPz/AwBIAwAA
AA8AAIAgAADQIAAA8CEAAPBuAADAcwAAaHgAAAAQAACoiwAAjwAAABjcAADoLwAAAAAAAP//
///oeuYCgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaIgAAEADAAAADAEA
DwAAAAEAAABQAAAAAAAAAAAAAAAAAAAAAAAAAHh5BQAAAAAAIhgAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArJEDAAAAAABCwAYAAAAAAHT+HQAAAAAABQAAAAAAAAAYABgAAAAAAAAAAAAAAAAA
YwByAGEAcwBoAGQAbQBwAC4AcwB5AHMAAFCcAYD4//8AMJ0BgPj//xgAGAAAAAAAAAAAAAAA
AABkAHUAbQBwAF8AcwB0AG8AcgBwAG8AcgAAMJ0BgPj//wDQnQGA+P//GAAYAAAAAAAAAAAA
AAAAAGQAdQBtAHAAXwB4AGUAbgBjAHIAcwBoAAAwoQOA+P//ANCkA4D4//8YABgAAAAAAAAA
AAAAAAAAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AAACAAYD4//8AwIIBgPj//xgAGAAAAAAA
AAAAAAAAAABkAHUAbQBwAF8AZAB1AG0AcABmAHYAZQAA0KQDgPj//wAApgOA+P//gB8AAAEA
AABAr+QCgPj//wAAAAAAAAAAQK/kAoD4//8BAAAAAQAAALCN5gKA+P//AAAAAAAAAAAAAAAA
AAAAADEABYAAAAAAAPAbAqD4//8AcBgAAAAAAPgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADwD///AAAAAAAEAAAAAAAAAAAAAAAAfwDAtOQCgPj//wAAAAAAAP8P
QLXkAoD4//9AAAAAgB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAAAAAAAICN5gKA+P//WLPBAgD4
///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC5gKA+P//4HvmAoD4//+wjeYC
gPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//AAAAAAAAAACQu6wCAPj//wAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAA/////2iDI6HRfwAA
BQAAAAAAAAAAAAAAAAAAAADwRaHRfwAA8rmPodF/AAAAAAAAAPBFodF/AADyuY+hAAAAAAAA
AAAA/////wD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAGAQUeZAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAAIQAuD///9AAAAAAAAAAAAAAAACAAAAAgAAAAAA
AAAAAAAAAgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBn0AIA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgGfQAgD4//8AAAAAAAAAAABq0AIA+P//AAAAAAAA
AACAatACAPj//wAAAAAAAAAAgGnQAgD4//8AAAAAAAAAAABp0AIA+P//AAAAAAAAAABAatAC
APj//wAAAAAAAAAAwGjQAgD4//8AAAAAAAAAAIBo0AIA+P//AAAAAAAAAABAadACAPj//wAA
AAAAAAAAAGfQAgD4//8AAAAAAAAAAMBm0AIA+P//AAAAAAAAAADAadACAPj//wAAAAAAAAAA
QGfQAgD4//8AAAAAAAAAAAAAAAAAAAAAkPF8AYD6//8ACMUCAPj//xDxfAGA+v//gAjFAgD4
//+Q8HwBgPr//wAJxQIA+P//EPJ8AYD6//+AB8UCAPj//9DXdgGA+v//AI3FAgD4//+g9nUB
gPr//4CMxQIA+P//8A53AYD6//+A/cQCAPj//xDwfAGA+v//gAnFAgD4///QZ3YBgPr//8DG
xQIA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAAAAABQb29M
EAAAABD8vwIA+P//0PC/AgD4//9AFuQCgPj//+COxAIA+P//AAAAAAAAAAAAAAAAAAAAABUA
FBsAAAAAEWx2AoD6//8LAAABJ2MAAP8aAAC1GwAAFBsAAAAAAABQb29MIAAAABD8vwIA+P//
0PC/AgD4//+gFuQCgPj//0AW5AKA+P//J2MAAP8aAAAAAAAAAAAAABIAEh8AAAAA0RqIAoD6
//+VAAABY24AAAAfAACEHwAAEh8AAAAAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//8AF+QC
gPj//6AW5AKA+P//XG4AAPkeAAAAAAAAAAAAADQAcBYAAAAAAQlHA4D6//8EAAABk2cAADwW
AAAqGgAAcBYAAAAAAABQb29MQAAAABD8vwIA+P//0PC/AgD4//9gF+QCgPj//wAX5AKA+P//
kWcAADoWAAAAAAAAAAAAAGMAEzoAAAAAMTKFA4D6//9RAAABKl0AALA5AADSOgAAEzoAAAAA
AABQb29MUAAAABD8vwIA+P//0PC/AgD4///AF+QCgPj//2AX5AKA+P//KV0AAK85AAAAAAAA
AAAAADIAwC4AAAAAEfyZAYD6//8oAAABN2sAAI4uAAAsMAAAwC4AAAAAAABQb29MYAAAABD8
vwIA+P//0PC/AgD4//8gGOQCgPj//8AX5AKA+P//N2sAAI4uAAAAAAAAAAAAAAEA0gQAAAAA
8WByA4D6//8EAAABPSAAANEEAACPBgAA0gQAAAAAAABQb29McAAAABD8vwIA+P//0PC/AgD4
//+AGOQCgPj//yAY5AKA+P//PSAAANEEAAAAAAAAAAAAANAADzMAAAAA4UeOA4D6///SAAAB
mZQAAD8yAACoNAAADzMAAAAAAABQb29MgAAAABD8vwIA+P//0PC/AgD4///gGOQCgPj//4AY
5AKA+P//hJQAACoyAAAAAAAAAAAAADUAhKUAAAAAIayWA4D6///4AAABMf0AAE+lAACZygAA
hKUAAAAAAABQb29MkAAAABD8vwIA+P//0PC/AgD4//9AGeQCgPj//+AY5AKA+P//L/0AAE2l
AAAAAAAAAAAAAJ8AGisAAAAAkfe7AYD6//+XAAABskgAAHsqAAC0KwAAGisAAAAAAABQb29M
oAAAABD8vwIA+P//0PC/AgD4//+gGeQCgPj//0AZ5AKA+P//sEgAAHkqAAAAAAAAAAAAAAQA
2AQAAAAAEW6YAYD6//8EAAAB6wsAANQEAADfBAAA2AQAAAAAAABQb29MsAAAABD8vwIA+P//
0PC/AgD4//8AGuQCgPj//6AZ5AKA+P//6wsAANQEAAAAAAAAAAAAAHQA0AgAAAAAIdmAAoD6
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
AAAtAAAALQAAAAAAAABQb29M8AEAABD8vwIA+P//0PC/AgD4//+AIeQCgPj//yAh5AKA+P//
hwAAAC0AAAAAAAAAAAAAAAMAIgAAAAAAAXFnA4D6//8EAAABswAAAB8AAAAlAAAAIgAAAAAA
AABQb29MAAIAABD8vwIA+P//0PC/AgD4///gIeQCgPj//4Ah5AKA+P//swAAAB8AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MEAAAABD8
vwIA+P//0PC/AgD4//+gCuQCgPj//0AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAQA3gMAAAAA
YUofAaD4//8EAAABiAYAANoDAABlBAAA3gMAAAEAAABQb29MIAAAABD8vwIA+P//0PC/AgD4
//8AC+QCgPj//6AK5AKA+P//hgYAANgDAAAAAAAAAAAAANUALjsAAAAAkfE/AKD4///dAAAB
eFMAAFk6AAAoRQAALjsAAAEAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//9gC+QCgPj//wAL
5AKA+P//aVMAAEo6AAAAAAAAAAAAANcAuCkAAAAAUZXyAKD4///cAAABGzwAAOEoAAAbMgAA
uCkAAAEAAABQb29MQAAAABD8vwIA+P//0PC/AgD4///AC+QCgPj//2AL5AKA+P//DzwAANUo
AAAAAAAAAAAAACQAiSIBAAAAoXN9AKD4//9WAAABgCYBAGUiAQD9JAEAiSIBAAEAAABQb29M
UAAAABD8vwIA+P//0PC/AgD4//8gDOQCgPj//8AL5AKA+P//dyYBAFwiAQAAAAAAAAAAAIsA
XyMAAAAAMa29AKD4//+GAAABBScAANQiAACAJgAAXyMAAAEAAABQb29MYAAAABD8vwIA+P//
0PC/AgD4//+ADOQCgPj//yAM5AKA+P//AicAANEiAAAAAAAAAAAAADgAZnMAAAAAYbSBAKD4
//+TAAABQYEAAC5zAAAAdAAAZnMAAAEAAABQb29McAAAABD8vwIA+P//0PC/AgD4///gDOQC
gPj//4AM5AKA+P//QYEAAC5zAAAAAAAAAAAAAHsAbWMAAAAAQd4sAaD4//+gAAABP28AAPJi
AACfYwAAbWMAAAEAAABQb29MgAAAABD8vwIA+P//0PC/AgD4//9ADeQCgPj//+AM5AKA+P//
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
MJyTA4D6//8wnJMDgPr//2A4wNgAAAAAAAAAAAAAAADgo5EDgPr//+CjkQOA+v//gLd6ygAA
AAAAAAAAAAAAAEDRsQGA+v//QNGxAYD6//8gm27pAAAAAAAAAAAAAAAAqCfkAoD4//+oJ+QC
gPj//0BX4cz/////AAAAAAAAAAAgykYDgPr//yDKRgOA+v//4LpEzwAAAAAAAAAAAAAAAOgn
5AKA+P//6CfkAoD4//+g7Be1/////wAAAAAAAAAACCjkAoD4//8IKOQCgPj//6CA2ev/////
AAAAAAAAAAAwbEcDgPr//zBsRwOA+v//AN9LzwAAAAAAAAAAAAAAAEgo5AKA+P//SCjkAoD4
//9wh2fD/////wAAAAAAAAAAMOyKAYD6//8w7IoBgPr//6DQW+IAAAAAAAAAAAAAAACIKOQC
gPj//4go5AKA+P//YAuovv////8AAAAAAAAAAKgo5AKA+P//qCjkAoD4//9gUw3B/////wAA
AAAAAAAAyCjkAoD4///IKOQCgPj//yDOrL7/////AAAAAAAAAADoKOQCgPj//+go5AKA+P//
INzTxf////8AAAAAAAAAAAgp5AKA+P//CCnkAoD4///g0O65/////wAAAAAAAAAAICWtA4D6
//8gJa0DgPr//wAKg9YAAAAAAAAAAAAAAABIKeQCgPj//0gp5AKA+P//YK5H2/////8AAAAA
AAAAAGgp5AKA+P//aCnkAoD4//8AbPe5/////wAAAAAAAAAAiCnkAoD4//+IKeQCgPj//yBR
M+f/////AAAAAAAAAACoKeQCgPj//6gp5AKA+P//AC7jxf////8AAAAAAAAAAFCSewGA+v//
UJJ7AYD6//8AiEXIAAAAAAAAAAAAAAAAQLF7A4D6//9AsXsDgPr//6DCC80AAAAAAAAAAAAA
AAAIKuQCgPj//wgq5AKA+P//AEQnwf////8AAAAAAAAAACgq5AKA+P//KCrkAoD4///g4ynB
/////wAAAAAAAAAASCrkAoD4//9IKuQCgPj//wAmIa7/////AAAAAAAAAABoKuQCgPj//2gq
5AKA+P//YGcKuv////8AAAAAAAAAAIgq5AKA+P//iCrkAoD4///gVkq1/////wAAAAAAAAAA
qCrkAoD4//+oKuQCgPj//2BpM8H/////AAAAAAAAAAAgqZMDgPr//6AYjgOA+v//4J66ygAA
AAAAAAAAAAAAAKDLvwGA+v//oMu/AYD6//9A4K7pAAAAAAAAAAAAAAAACCvkAoD4//8IK+QC
gPj//4D22hD/////AAAAAAAAAAAAZ18DgPr//zC8NwOA+v//AMPBygAAAAAAAAAAAAAAADBF
jAGA+v//MEWMAYD6//8gy6YIAQAAAAAAAAAAAAAAaCvkAoD4//9oK+QCgPj//8Cl9eT/////
AAAAAAAAAACIK+QCgPj//4gr5AKA+P//IMev1v////8AAAAAAAAAAKgr5AKA+P//qCvkAoD4
//9AgyK6/////wAAAAAAAAAAyCvkAoD4///IK+QCgPj//wBVqsP/////AAAAAAAAAAAAZFID
gPr//wBkUgOA+v//ENBwcQEAAAAAAAAAAAAAAAgs5AKA+P//CCzkAoD4///AoK3D/////wAA
AAAAAAAAKCzkAoD4//8oLOQCgPj//8Bojbz/////AAAAAAAAAABILOQCgPj//0gs5AKA+P//
YA++1v////8AAAAAAAAAAGgs5AKA+P//aCzkAoD4///AcMvp/////wAAAAAAAAAAiCzkAoD4
//+ILOQCgPj//yCShdv/////AAAAAAAAAACoLOQCgPj//6gs5AKA+P//QE74vv////8AAAAA
AAAAAMgs5AKA+P//yCzkAoD4///glMfW/////wAAAAAAAAAAQCGpAYD6//9AIakBgPr//0BW
NuwAAAAAAAAAAAAAAAAILeQCgPj//wgt5AKA+P//oHfw3f////8AAAAAAAAAAECBSQOA+v//
4LMoA4D6//+gUSaUIQAAAAAAAAAAAAAASC3kAoD4//9ILeQCgPj//2Aa0db/////AAAAAAAA
AABoLeQCgPj//2gt5AKA+P//YOikvP////8AAAAAAAAAADCImwOA+v//MIibA4D6//8gXVvg
AAAAAAAAAAAAAAAAqC3kAoD4//+oLeQCgPj//0AZzsP/////AAAAAAAAAACANjEDgPr//zB8
VwOA+v//4B9VzQAAAAAAAAAAAAAAAOgt5AKA+P//6C3kAoD4//+Axm/B/////wAAAAAAAAAA
CC7kAoD4//8ILuQCgPj//6BCxuL/////AAAAAAAAAAAoLuQCgPj//ygu5AKA+P//wP44xv//
//8AAAAAAAAAAEgu5AKA+P//SC7kAoD4//9A0c6w/////wAAAAAAAAAAaC7kAoD4//9oLuQC
gPj//2CzesH/////AAAAAAAAAACILuQCgPj//4gu5AKA+P//ICgx5f////8AAAAAAAAAAMAo
JgOA+v//wCgmA4D6//+AyWXNAAAAAAAAAAAAAAAAyC7kAoD4///ILuQCgPj//6BFpsj/////
AAAAAAAAAADoLuQCgPj//+gu5AKA+P//4HjBvP////8AAAAAAAAAAAgv5AKA+P//CC/kAoD4
//9A+ufD/////wAAAAAAAAAAMMwnA4D6//8wzCcDgPr//1C4ORcBAAAAAAAAAAAAAABIL+QC
gPj//0gv5AKA+P//ICsRy/////8AAAAAAAAAAGgv5AKA+P//aC/kAoD4//9gXiy//////wAA
AAAAAAAAgKiuAYD6//+AqK4BgPr//yBTaOwAAAAAAAAAAAAAAACgJjEDgPr//6AmMQOA+v//
gFQJ6gAAAAAAAAAAAAAAAMgv5AKA+P//yC/kAoD4//8AwTO//////wAAAAAAAAAAQPGtAYD6
//8ginoDgPr//0BXS+UAAAAAAAAAAAAAAACIczUCgPr//4hzNQKA+v//4EAdywAAAAAAAAAA
AAAAAKAHMgOA+v//oAcyA4D6//+w+VzGAAAAAAAAAAAAAAAASDDkAoD4//9IMOQCgPj//2A7
Ctf/////AAAAAAAAAABoMOQCgPj//2gw5AKA+P//ADkCxP////8AAAAAAAAAAIgw5AKA+P//
iDDkAoD4///g2366/////wAAAAAAAAAAqDDkAoD4//+oMOQCgPj//+DppcH/////AAAAAAAA
AADIMOQCgPj//8gw5AKA+P//4EMIxP////8AAAAAAAAAAIC+SQOA+v//oEYmA4D6//+gcmzG
AAAAAAAAAAAAAAAACDHkAoD4//8IMeQCgPj//+DCJrj/////AAAAAAAAAAAoMeQCgPj//ygx
5AKA+P//AIW51P////8AAAAAAAAAAEgx5AKA+P//SDHkAoD4//9gBuDb/////wAAAAAAAAAA
aDHkAoD4//9oMeQCgPj//4ACkLr/////AAAAAAAAAACIMeQCgPj//4gx5AKA+P//IKnL5///
//8AAAAAAAAAADCVfgGA+v//MJV+AYD6//9gFiXXAAAAAAAAAAAAAAAAkOaiAYD6//+Q5qIB
gPr//4DEe8YAAAAAAAAAAAAAAADoMeQCgPj//+gx5AKA+P//AEvhyP////8AAAAAAAAAAAgy
5AKA+P//CDLkAoD4///AfL/B/////wAAAAAAAAAAKDLkAoD4//8oMuQCgPj//wDwLdf/////
AAAAAAAAAABIMuQCgPj//0gy5AKA+P//QGbGE/////8AAAAAAAAAACCqXQOA+v//IKpdA4D6
///AkhnjAAAAAAAAAAAAAAAAiDLkAoD4//+IMuQCgPj//yCUuuD/////AAAAAAAAAACoMuQC
gPj//6gy5AKA+P//QBDltf////8AAAAAAAAAAMgy5AKA+P//yDLkAoD4//+gcee1/////wAA
AAAAAAAA6DLkAoD4///oMuQCgPj//yBN0hP/////AAAAAAAAAAAIM+QCgPj//wgz5AKA+P//
oHkl4/////8AAAAAAAAAACgz5AKA+P//KDPkAoD4//9A+hG9/////wAAAAAAAAAASDPkAoD4
//9IM+QCgPj//2DcyOD/////AAAAAAAAAABoM+QCgPj//2gz5AKA+P//IM5TuP////8AAAAA
AAAAAJCdOgOA+v//kJ06A4D6//8gX5DlAAAAAAAAAAAAAAAAqDPkAoD4//+oM+QCgPj//4CA
Stf/////AAAAAAAAAADIM+QCgPj//8gz5AKA+P//oDy9uv////8AAAAAAAAAAOgz5AKA+P//
6DPkAoD4//8g+IMR/////wAAAAAAAAAACDTkAoD4//8INOQCgPj//6BE++f/////AAAAAAAA
AAAoNOQCgPj//yg05AKA+P//AGa12f////8AAAAAAAAAAEg05AKA+P//SDTkAoD4//8gIii9
/////wAAAAAAAAAAaDTkAoD4//9oNOQCgPj//8AIltL/////AAAAAAAAAACINOQCgPj//4g0
5AKA+P//ICpm6v////8AAAAAAAAAAKg05AKA+P//qDTkAoD4//+Ai2jq/////wAAAAAAAAAA
yDTkAoD4///INOQCgPj//+Dpz7r/////AAAAAAAAAADoNOQCgPj//+g05AKA+P//gA3rrv//
//8AAAAAAAAAAAg15AKA+P//CDXkAoD4//+gD9Hs/////wAAAAAAAAAAKDXkAoD4//8oNeQC
gPj//yBfXMT/////AAAAAAAAAABINeQCgPj//0g15AKA+P//oDH9wf////8AAAAAAAAAAEAx
cwOA+v//QDFzA4D6//+Ar7qhZAAAAAAAAAAAAAAAiDXkAoD4//+INeQCgPj//8ChP73/////
AAAAAAAAAACoNeQCgPj//6g15AKA+P//gBb24P////8AAAAAAAAAAMg15AKA+P//yDXkAoD4
//+g0mjE/////wAAAAAAAAAAQCFEA4D6//8Ai4oBgPr//0AZONwAAAAAAAAAAAAAAAAINuQC
gPj//wg25AKA+P//4N9rxP////8AAAAAAAAAACg25AKA+P//KDbkAoD4///A2dDG/////wAA
AAAAAAAASDbkAoD4//9INuQCgPj//yC408b/////AAAAAAAAAABoNuQCgPj//2g25AKA+P//
oC2NuP////8AAAAAAAAAAIg25AKA+P//iDbkAoD4///ATPG6/////wAAAAAAAAAAqDbkAoD4
//+oNuQCgPj//yDOF8L/////AAAAAAAAAABQYzIDgPr//1BjMgOA+v//4L/D0gAAAAAAAAAA
AAAAAOg25AKA+P//6DbkAoD4//8A/0DJ/////wAAAAAAAAAAIGc1A4D6//8wDEUDgPr//zCR
4MYAAAAAAAAAAAAAAAAwPF4DgPr//zA8XgOA+v//ACeN1wAAAAAAAAAAAAAAAEg35AKA+P//
SDfkAoD4//9AFGG9/////wAAAAAAAAAAQDFMAoD6//9AMUwCgPr//4Cn6MYAAAAAAAAAAAAA
AACIN+QCgPj//4g35AKA+P//wBfHv/////8AAAAAAAAAAKg35AKA+P//qDfkAoD4//9ggSnC
/////wAAAAAAAAAAyDfkAoD4///IN+QCgPj//+ANpOr/////AAAAAAAAAADoN+QCgPj//+g3
5AKA+P//gHHxxv////8AAAAAAAAAAAg45AKA+P//CDjkAoD4//9A/THC/////wAAAAAAAAAA
KDjkAoD4//8oOOQCgPj//6BeNML/////AAAAAAAAAABIOOQCgPj//0g45AKA+P//YPMO7f//
//8AAAAAAAAAAGg45AKA+P//aDjkAoD4//9gZPCz/////wAAAAAAAAAAcPd+A4D6//9w934D
gPr//6Da49IAAAAAAAAAAAAAAACoOOQCgPj//6g45AKA+P//YO9OGv////8AAAAAAAAAAMg4
5AKA+P//yDjkAoD4//8gPqDE/////wAAAAAAAAAA6DjkAoD4///oOOQCgPj//yCvosT/////
AAAAAAAAAAAIOeQCgPj//wg55AKA+P//4Lpdtv////8AAAAAAAAAACg55AKA+P//KDnkAoD4
//8A3Vzo/////wAAAAAAAAAASDnkAoD4//9IOeQCgPj//2BeeNz/////AAAAAAAAAABoOeQC
gPj//2g55AKA+P//wH894f////8AAAAAAAAAAIg55AKA+P//iDnkAoD4//8ATe2//////wAA
AAAAAAAAwCY7A4D6///AJjsDgPr//8DHouMAAAAAAAAAAAAAAABQYngBgPr//1DSfAGA+v//
AFsUxwAAAAAAAAAAAAAAAOg55AKA+P//6DnkAoD4//9AxQnm/////wAAAAAAAAAACDrkAoD4
//8IOuQCgPj//0DzM7v/////AAAAAAAAAAAoOuQCgPj//yg65AKA+P//oPTUuP////8AAAAA
AAAAAEg65AKA+P//SDrkAoD4//8g5BS0/////wAAAAAAAAAAaDrkAoD4//9oOuQCgPj//+CV
eLb/////AAAAAAAAAACIOuQCgPj//4g65AKA+P//gN+rnv////8AAAAAAAAAAKg65AKA+P//
qDrkAoD4//+ATVXh/////wAAAAAAAAAAMNx8A4D6//8w3HwDgPr//yCXk9wAAAAAAAAAAAAA
AADoOuQCgPj//+g65AKA+P//QHClvf////8AAAAAAAAAAAg75AKA+P//CDvkAoD4///gmb+x
/////wAAAAAAAAAAKDvkAoD4//8oO+QCgPj//wAzwOP/////AAAAAAAAAABIO+QCgPj//0g7
5AKA+P//oHNvwv////8AAAAAAAAAADC8SwOA+v//MLxLA4D6//+gKn8nAgAAAAAAAAAAAAAA
iDvkAoD4//+IO+QCgPj//2A/7bj/////AAAAAAAAAAAwnJQBgPr//0CxnwGA+v//gHiB1QAA
AAAAAAAAAAAAAEDRTQOA+v//QNFNA4D6//+AN0puCAAAAAAAAAAAAAAA6DvkAoD4///oO+QC
gPj//wC/k7b/////AAAAAAAAAAAw9EsDgPr//zD0SwOA+v//YC7NTwQAAAAAAAAAAAAAACg8
5AKA+P//KDzkAoD4//+gioDC/////wAAAAAAAAAASDzkAoD4//9IPOQCgPj//2AfUNr/////
AAAAAAAAAABoPOQCgPj//2g85AKA+P//gNvCvf////8AAAAAAAAAAIg85AKA+P//iDzkAoD4
//8gYs/Q/////wAAAAAAAAAAqDzkAoD4//+oPOQCgPj//4DjAOv/////AAAAAAAAAADIPOQC
gPj//8g85AKA+P//oIjIvf////8AAAAAAAAAAOg85AKA+P//6DzkAoD4//9ARo7C/////wAA
AAAAAAAAQEGTA4D6//9AQZMDgPr//yBJ5YwBAAAAAAAAAAAAAAAoPeQCgPj//yg95AKA+P//
AMlr7f////8AAAAAAAAAAEg95AKA+P//SD3kAoD4//+gKTTA/////wAAAAAAAAAAaD3kAoD4
//9oPeQCgPj//4CmmML/////AAAAAAAAAABAAVADgPr//wBIkwGA+v//II0G2AAAAAAAAAAA
AAAAALAzWAOA+v//sDNYA4D6//+ALlHmAAAAAAAAAAAAAAAAyD3kAoD4///IPeQCgPj//+DP
kOH/////AAAAAAAAAADoPeQCgPj//+g95AKA+P//AIwDxf////8AAAAAAAAAAAg+5AKA+P//
CD7kAoD4//+AZ+MP/////wAAAAAAAAAAkDVqA4D6//+QNWoDgPr//0D5Z8cAAAAAAAAAAAAA
AAAwrG8DgPr//zCsbwOA+v//YJXX3AAAAAAAAAAAAAAAAGg+5AKA+P//aD7kAoD4//+AcW7H
/////wAAAAAAAAAAiD7kAoD4//+IPuQCgPj//yAeiLv/////AAAAAAAAAACoPuQCgPj//6g+
5AKA+P//IAaMu/////8AAAAAAAAAAOCVdgOA+v//4JV2A4D6//8g4HPHAAAAAAAAAAAAAAAA
6D7kAoD4///oPuQCgPj//6CvhKj/////AAAAAAAAAAAIP+QCgPj//wg/5AKA+P//YLjbyf//
//8AAAAAAAAAAABKagOA+v//AEpqA4D6//8APGPTAAAAAAAAAAAAAAAASD/kAoD4//9IP+QC
gPj//wBtHcX/////AAAAAAAAAABoP+QCgPj//2g/5AKA+P//wIFy5v////8AAAAAAAAAAEAh
VQOA+v//QCFVA4D6///gnUbMAAAAAAAAAAAAAAAAqD/kAoD4//+oP+QCgPj//+ARw8L/////
AAAAAAAAAAAAKlgDgPr//wAqWAOA+v//QFaJcAEAAAAAAAAAAAAAADBYtAGA+v//MFi0AYD6
//9Axz7rAAAAAAAAAAAAAAAAIGdLA4D6//8gZ0sDgPr//4DdahICAAAAAAAAAAAAAAAoQOQC
gPj//yhA5AKA+P//oLbMwv////8AAAAAAAAAAEhA5AKA+P//SEDkAoD4//9g6y/F/////wAA
AAAAAAAAQEGXA4D6//9AYZsDgPr//8Csqe0AAAAAAAAAAAAAAAAwPJoBgPr//zA8mgGA+v//
IE7p6AAAAAAAAAAAAAAAAKhA5AKA+P//qEDkAoD4//8gnDfF/////wAAAAAAAAAAyEDkAoD4
///IQOQCgPj//6CRdsD/////AAAAAAAAAAAwjKYDgPr//zCMpgOA+v//gFecxwAAAAAAAAAA
AAAAADBIpQOA+v//MEilA4D6//+g0/LoAAAAAAAAAAAAAAAAKEHkAoD4//8oQeQCgPj//wA1
6tX/////AAAAAAAAAABIQeQCgPj//0hB5AKA+P//YFav2v////8AAAAAAAAAAAC8HgOA+v//
MLM6A4D6///A19XhAAAAAAAAAAAAAAAAiEHkAoD4//+IQeQCgPj//4DjhcD/////AAAAAAAA
AACoQeQCgPj//6hB5AKA+P//gHrB7f////8AAAAAAAAAALAoqAOA+v//QHGwAYD6//+A8azH
AAAAAAAAAAAAAAAA6EHkAoD4///oQeQCgPj//0C9NdH/////AAAAAAAAAAAIQuQCgPj//whC
5AKA+P//oN761f////8AAAAAAAAAAChC5AKA+P//KELkAoD4//9grfLC/////wAAAAAAAAAA
SELkAoD4//9IQuQCgPj//2Ahhd//////AAAAAAAAAAAAZoYDgPr//wBmhgOA+v//4O+Sdg0A
AAAAAAAAAAAAAIhC5AKA+P//iELkAoD4///AkI2t/////wAAAAAAAAAAqELkAoD4//+oQuQC
gPj//4DFEen/////AAAAAAAAAADIQuQCgPj//8hC5AKA+P//QJT+wv////8AAAAAAAAAABDp
PAOA+v//EOk8A4D6///Ar6I3AQAAAAAAAAAAAAAACEPkAoD4//8IQ+QCgPj//+CIfbn/////
AAAAAAAAAAAoQ+QCgPj//yhD5AKA+P//AEsb6f////8AAAAAAAAAAEhD5AKA+P//SEPkAoD4
//+ga6bA/////wAAAAAAAAAAgPBWA4D6//+A8FYDgPr//wCnViMCAAAAAAAAAAAAAACIQ+QC
gPj//4hD5AKA+P//IK9f5P////8AAAAAAAAAADC8rgOA+v//8McxA4D6//+AMHvYAAAAAAAA
AAAAAAAAyEPkAoD4///IQ+QCgPj//0CfEcP/////AAAAAAAAAADoQ+QCgPj//+hD5AKA+P//
oOr5wP////8AAAAAAAAAADDMAAOA+v//MClCAoD6//+g8ZvMAAAAAAAAAAAAAAAAKETkAoD4
//8oROQCgPj//6BCesX/////AAAAAAAAAAAQqbgBgPr//xCpuAGA+v//YLcl1gAAAAAAAAAA
AAAAAGhE5AKA+P//aETkAoD4///A2Ora/////wAAAAAAAAAAiETkAoD4//+IROQCgPj//+CU
Xb7/////AAAAAAAAAACoROQCgPj//6hE5AKA+P//gNss1v////8AAAAAAAAAAMhE5AKA+P//
yETkAoD4///gnJvr/////wAAAAAAAAAA6ETkAoD4///oROQCgPj//0C+Vd3/////AAAAAAAA
AAAIReQCgPj//whF5AKA+P//YHrIwP////8AAAAAAAAAAChF5AKA+P//KEXkAoD4//8AYTbW
/////wAAAAAAAAAAQPFoA4D6//9A8WgDgPr//2CCBu4AAAAAAAAAAAAAAABA4Z4DgPr//8Bt
bAOA+v//wIOc2AAAAAAHAQYAAAAAAEgheAGA+v//SCF4AYD6//8AAAAAAAAAABMCAQEAAAAA
ACPkAoD4//8AI+QCgPj//zATtgIA+P//AAAAAAAAAAAAHG4DgPj//wgcbgOA+P//AAAAAAAA
AAABAAAAAGQAAAAAAAAAAAAAJ8ABAAAAAAAAAAAAAAAAAPDnmwGA+v//APFoA4D6//8AAAAA
AAAAAAAAAAABAAAAEwEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAQH6/AgD4//8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gEbkAoD4//+ARuQCgPj//5BG5AKA+P//kEbkAoD4//+gRuQCgPj//6BG5AKA+P//sEbkAoD4
//+wRuQCgPj//8BG5AKA+P//wEbkAoD4///QRuQCgPj//9BG5AKA+P//4EbkAoD4///gRuQC
gPj///BG5AKA+P//8EbkAoD4//8AR+QCgPj//wBH5AKA+P//EEfkAoD4//8QR+QCgPj//yBH
5AKA+P//IEfkAoD4//8wR+QCgPj//zBH5AKA+P//QEfkAoD4//9AR+QCgPj//1BH5AKA+P//
UEfkAoD4//9gR+QCgPj//2BH5AKA+P//cEfkAoD4//9wR+QCgPj//4BH5AKA+P//gEfkAoD4
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
gPj//7hxrQIA+P//AHgAAAAAAACJeAMBgB8AAAAAAAAAAAAA4BDGAgD4///gEMYCAPj//0tE
QkdAAwAAAGClAgD4///wOawCAPj//wAAAAAAAAAA6AHYAAAAAQAQMqwCAPj//wAAAAAAAAAA
kJjJAgD4//+QtccCAPj//8i1xwIA+P//UBTHAgD4//8wOtACAPj//3gw0AIA+P//lDDQAgD4
//8AxcwCAPj//4BjzAIA+P//8ArNAgD4///QwccCAPj//+jBxwIA+P//AAAAAAAAAAAAAAAA
AAAAAABr0AIA+P//eDLQAgD4//8AAAAAAAAAAAAAAAAAAAAA+DnQAgD4//8kL8gCAPj///gy
0AIA+P//CDHQAgD4//9gMNACAPj//+Ay0AIA+P//AAAAAAAAAAC4MNACAPj//wAAAAAAAAAA
AAAAAAAAAACgMdACAPj//9A40AIA+P//ABAAAAAAAACQNNACAPj//xgfyAIA+P//IB/IAgD4
///A0sYCAPj//yiZyQIA+P//8B7IAgD4//9gH8gCAPj//wAAAAAAAAAAAGXQAgD4///AatAC
APj//8Br0AIA+P//wGLQAgD4//9gTMQCAPj//8D7xAIA+P//APzEAgD4//9oGscCAPj//4C1
xQIA+P//EDDQAgD4//8AMdACAPj//wAw0AIA+P//cM/FAgD4//9w38UCAPj//7hPxAIA+P//
ZM/FAgD4///woMkCAPj//6CrwAIA+P//AAAAAAAAAABAPNACAPj//+gx0AIA+P//iJjJAgD4
///InMcCAPj//9Qw0AIA+P//yP7GAgD4///gnMkCAPj//xA0yAIA+P//UB/IAgD4//8oH8gC
APj//5wtzQIA+P//ODDQAgD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwA
uAA4ACgAcABkAQAAAADQBDgDkAIoAABN2iEIAPQF8AW4SyABJACoBAAAAAAAAJBQxAIA+P//
mFDEAgD4//9A1cwCAPj//4BOGAAgAIABAAAAAAAAAAAAAEAAEAAYAAAAMwArAAAAAABAACMA
UwAABs0CAPj//wACzQIA+P//AAAAAAAAAABIG8gCAPj//0QbyAIA+P//gGfAAgD4///YSwAA
AAAAABjcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANDpAID4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAS8AAAAAAAADbyltKAAAAAHDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKDqAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJwBAAAAAAD8dWRU
AAAAAMjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKDrAID4//8AAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADaoBAAAAAADxdWRUAAAAABjhAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABD8AID4//8AAAAA
AAAAAABQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFdYCAAAAAAAcdmRUAAAAAHDhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGD+AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyN8BAAAAAADBG2RP
AAAAAMjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADDtAID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcp8BAAAAAACgkudMAAAAACDiAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAID4//8AAAAA
AAAAAADABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHjiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDFAID4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqRABAAAAAAAUwVtK
AAAAANDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEDGAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxZwBAAAAAAAUwVtKAAAAACjjAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDHAID4//8AAAAA
AAAAAACgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAISYCAAAAAACZkudMAAAAAIDjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDcAID4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu2UAAAAAAAATwVtK
AAAAANjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANDcAID4//8AAAAAAAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVgsDAAAAAAC1+f5RAAAAADDkAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIACAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAAIjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAFAYD4//8AAAAAAAAAAABABgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlb4DAAAAAAAyRPBS
AAAAAODkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAIALAYD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNUAAAAADjlAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjikBAAAAAAA+YGNUAAAAAJDlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQAYD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt5IAAAAAAADKo6NL
AAAAAOjlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANAQAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALUUFAAAAAACckudMAAAAAEDmAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAVAYD4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAARFYBAAAAAACBxFtKAAAAAJjmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAkAYD4//8AAAAAAAAAAACQGgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXfIZAAAAAACKvuFS
AAAAAOjmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANAWAYD4//8AAAAAAAAAAADgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDnAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAYD4//8AAAAA
AAAAAACwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAqfcBAAAAAAAOkkhTAAAAAJjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBPAYD4//8AAAAAAAAAAAAgBwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhV4HAAAAAAC3TxlQ
AAAAAOjnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEBWAYD4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXksBAAAAAAD/wFtKAAAAADjoAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBXAYD4//8AAAAA
AAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAYD4//8AAAAAAAAAAAAgDwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEYsOAAAAAACy9jRQ
AAAAAODoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPBXAYD4//8AAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPkMGAAAAAAANdpRSAAAAADjpAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAcAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAfD4DAAAAAACQdzxUAAAAAJDpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAYD4//8AAAAAAAAAAADwHwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARV8dAAAAAADUWz9T
AAAAAOjpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADCEAYD4//8AAAAAAAAAAACQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsjgFAAAAAAAJWz9TAAAAAEDqAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCIAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJjqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCJAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ScFAAAAAADIkudM
AAAAAPDqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAICOAYD4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6eAAAAAAAAC7WAhKAAAAAEjrAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPAYD4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVnMDAAAAAAAumOdMAAAAAKDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCSAYD4//8AAAAAAAAAAAAgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/V0BAAAAAAABwltK
AAAAAPDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMCTAYD4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9NkAAAAAAAB+kudMAAAAAEjsAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCUAYD4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAQSEEAAAAAABcpgBRAAAAAKDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPCXAYD4//8AAAAAAAAAAABgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHf8BAAAAAAAdwVtK
AAAAAPDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCzA4D4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVWIBAAAAAAA+k+dMAAAAAIjxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC0A4D4//8AAAAAAAAAAACQCAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ukHAAAAAAAcKYhT
AAAAANjxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKAGBID4//8AAAAAAAAAAABQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBEEAAAAAACGk+dMAAAAADDyAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAKBID4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAe7EAAAAAAAC2zFtKAAAAAIjyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIALBID4//8AAAAAAAAAAABgAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzw0CAAAAAABiqOdM
AAAAAODyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAOANBID4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaBYBAAAAAAC2zFtKAAAAADjzAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAOBID4//8AAAAA
AAAAAACwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAzHwBAAAAAAB0qOdMAAAAAJDzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAQBID4//8AAAAAAAAAAABAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFZ4BAAAAAAAMq+dM
AAAAAOjzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMARBID4//8AAAAAAAAAAAAQBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAb9cEAAAAAACXlOdMAAAAAED0AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAWBID4//8AAAAA
AAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA1T4BAAAAAABewVtKAAAAAJj0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAXBID4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdPQAAAAAAAC+w1tK
AAAAAPD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEAYBID4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP18BAAAAAAAuxVtKAAAAAEj1AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAlA4D4//8AAAAA
AAAAAAAwCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAnVEIAAAAAABwlOdMAAAAAJj1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAtA4D4//8AAAAAAAAAAADgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR9YBAAAAAABHlOdM
AAAAAOj1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAHAvA4D4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZ5UBAAAAAADfxFtKAAAAAED2AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAwA4D4//8AAAAA
AAAAAABgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAls0CAAAAAABGqOdMAAAAAJj2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAyA4D4//8AAAAAAAAAAADgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKV4CAAAAAAAdwVtK
AAAAAPD2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMA0A4D4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3uUAAAAAAAAWwVtKAAAAAEj3AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALA1A4D4//8AAAAA
AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAxbQBAAAAAAAWwVtKAAAAAKD3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKA2A4D4//8AAAAAAAAAAADQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+5YAAAAAAAC2yltK
AAAAAPD3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAHA3A4D4//8AAAAAAAAAAACAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOeECAAAAAABeiyJUAAAAAEj4AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA5A4D4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAwWQBAAAAAAC38TRUAAAAAKD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA7A4D4//8AAAAAAAAAAABAAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq78CAAAAAABepudM
AAAAAPj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAHA9A4D4//8AAAAAAAAAAAAwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8X0BAAAAAAAwsV9TAAAAAFD5AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKA+A4D4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAuJIAAAAAAADYDudRAAAAAKD5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA/A4D4//8AAAAAAAAAAADQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUSsBAAAAAACxTZVS
AAAAAPj5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAgA4D4//8AAAAAAAAAAABgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKkAFAAAAAAC3TZVSAAAAAFD6AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAZBID4//8AAAAA
AAAAAAAgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjkYBAAAAAAC3TZVSAAAAAKj6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAaBID4//8AAAAAAAAAAABgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7PQAAAAAAAD9wFtK
AAAAAAD7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAALAbBID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO5gAAAAAAADto+dMAAAAAGD7AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALAcBID4//8AAAAA
AAAAAABgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAvpIBAAAAAADwzFtKAAAAALj7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABID4//8AAAAAAAAAAABAAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo8wCAAAAAAByqOdM
AAAAABD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEACBID4//8AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6mMAAAAAAADYzFtKAAAAAGj8AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBID4//8AAAAA
AAAAAADwAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAgbsCAAAAAABwqOdMAAAAAMD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAeBID4//8AAAAAAAAAAACwAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJoBAAAAAADpzFtK
AAAAABj9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMC8A4D4//8AAAAAAAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy1ECAAAAAABvqOdMAAAAAHD9AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCdAYD4//8AAAAA
AAAAAACgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAASycCAAAAAADxzFtKAAAAAMj9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAFBID4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArcMAAAAAAACqzltK
AAAAACD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMAfBID4//8AAAAAAAAAAIAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATpMAAAAAAACSyltKAAAAAHj+AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAjBID4//8AAAAA
AAAAAAAwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAiFUEAAAAAADzo+dMAAAAAMj+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAnBID4//8AAAAAAAAAAAAgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWK8BAAAAAACVpudM
AAAAACD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPAoBID4//8AAAAAAAAAAACgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK/UFAAAAAADQTZVSAAAAAHj/AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAuBID4//8AAAAA
AAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAKJQBAAAAAABkqOdMAAAAAND/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAvBID4//8AAAAAAAAAAADABQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2pgFAAAAAACHpudM
AAAAACgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKA1BID4//8AAAAAAAAAAADQAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxrcDAAAAAACCG05SAAAAAIAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHA5BID4//8AAAAA
AAAAAAAgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAT2cCAAAAAAD+JE5SAAAAANAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA7BID4//8AAAAAAAAAAABSAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkq8AAAAAAACTyltK
AAAAACgBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAPA7BID4//8AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfekAAAAAAAARZWNUAAAAAIABAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALA8BID4//8AAAAA
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAx3gBAAAAAAC9yltKAAAAANgBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJA9BID4//8AAAAAAAAAAACgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTQBAAAAAAAZRPBS
AAAAAEACAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAgBID4//8AAAAAAAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoH8CAAAAAABUYGNUAAAAAKACAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgA4D4//8AAAAA
AAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjsEDAAAAAAAzYGNUAAAAAAADAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA+BID4//8AAAAAAAAAAAAwAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6g0BAAAAAACPwVtK
AAAAAGADAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAABAGD5//8AAAAAAAAAAAAgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKgDAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAiBID4//8AAAAA
AAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjkEBAAAAAAB0xVtKAAAAAAAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABHAGD5//8AAAAAAAAAAADgAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAFAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABvAGD5//8AAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJgEAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGAGD5//8AAAAA
AAAAAABwAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKCjA4D4//8AAAAAAAAAAAAwAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8XsCAAAAAACVwltK
AAAAADgFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACAAYD4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnRABAAAAAACSzFtKAAAAAJAFAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCBAYD4//8AAAAA
AAAAAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAa2UBAAAAAACSzFtKAAAAAOgFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBtAoD4//8AAAAAAAAAAACQDAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7lYMAAAAAADOk+dM
AAAAADgGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFB6AoD4//8AAAAAAAAAAADgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOC0CAAAAAAAok2RNAAAAAJAGAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADB8AoD4//8AAAAA
AAAAAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApR8EAAAAAAAxJcdT
AAAAAFALAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAKBDA4D4//8AAAAAAAAAAAAQBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCIHAAAAAAB6XghKAAAAAKgLAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALBKA4D4//8AAAAA
AAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAKmgAAAAAAADlzFtKAAAAACEAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABuAHQAbwBzAGsAcgBuAGwALgBlAHgAZQAAABwAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABoAGEAbAAuAGQAbABsAAAAAAAeAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAawBkAGMAbwBtAC4A
ZABsAGwAAAAAAAAAAAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAbQBjAHUAcABkAGEAdABlAF8ARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwALgBkAGwA
bAAAAAAAAAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABQAFMASABFAEQALgBkAGwAbAAAAAAAAAAAAB0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABDAEwARgBTAC4AUwBZAFMAAAAbAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAQwBJAC4AZABsAGwAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABXAGQAZgAwADEAMAAwADAALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBEAEYATABEAFIALgBTAFkA
UwAAAAAAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAEEAQwBQAEkALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBNAEkATABJAEIA
LgBTAFkAUwAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAG0AcwBpAHMAYQBkAHIAdgAuAHMAeQBzAAAAJAAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABwAGMAaQAuAHMAeQBzAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAZAByAHYAcgBvAG8AdAAuAHMAeQBzAAAA
KAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAB4AGUAbgBmAGkAbAB0AC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4ALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAB4AGUAbgBiAHUAcwAuAHMAeQBzAAAAAAAAACgAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABhAHIA
dABtAGcAcgAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAbwBsAG0AZwByAC4AcwB5AHMAAAAAAAAA
KAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXAB2AG8AbABtAGcAcgB4AC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaQBuAHQAZQBsAGkA
ZABlAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAFAAQwBJAEkARABFAFgALgBTAFkAUwAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABtAG8AdQBuAHQAbQBnAHIALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAYQB0AGEAcABpAC4AcwB5AHMA
AAAAAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAGEAdABhAHAAbwByAHQALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgB2AGIAZAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwB0AG8AcgBwAG8AcgB0AC4AcwB5AHMA
AAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBkAGkA
cwBrAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAYQBtAGQAeABhAHQAYQAuAHMAeQBzAAAAAAAnAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAGYAbAB0AG0AZwByAC4AcwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABmAGkAbABlAGkAbgBmAG8A
LgBzAHkAcwAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAHIAaQB2AGUAcgBzAFwATgB0AGYAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABtAHMAcgBwAGMA
LgBzAHkAcwAAAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBkAGQALgBzAHkAcwAAAAAAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIA
cwBcAGMAbgBnAC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABjAHcALgBzAHkAcwAAAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMA
XABGAHMAXwBSAGUAYwAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbgBkAGkAcwAuAHMAeQBzAAAA
JgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXABOAEUAVABJAE8ALgBTAFkAUwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBwAGsA
ZwAuAHMAeQBzAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHQAYwBwAGkAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMA
XABmAHcAcABrAGMAbABuAHQALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAdgBtAHMAdABvAHIAZgBsAC4A
cwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHYAbwBsAHMAbgBhAHAALgBzAHkAcwAAAAAAJgAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAHAA
bABkAHIALgBzAHkAcwAAAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHkAYgBvAG8AcwB0AC4AcwB5AHMA
AAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkA
dgBlAHIAcwBcAG0AdQBwAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaAB3AHAAbwBsAGkAYwB5AC4A
cwB5AHMAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAGYAdgBlAHYAbwBsAC4AcwB5AHMAAAAAAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABkAGkA
cwBrAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAEMATABBAFMAUwBQAE4AUAAuAFMAWQBTAAAAJgAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABjAGQAcgBvAG0ALgBzAHkAcwAAAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwATgB1AGwAbAAuAFMAWQBTAAAA
JQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYA
ZQByAHMAXABCAGUAZQBwAC4AUwBZAFMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
UwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYAZwBhAC4AcwB5AHMAAAAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwAVgBJAEQARQBPAFAAUgBUAC4AUwBZAFMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHcAYQB0AGMAaABkAG8A
ZwAuAHMAeQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABSAEQAUABDAEQARAAuAHMAeQBzAAAAAAAAACkAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwA
cgBkAHAAZQBuAGMAZABkAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHIAZABwAHIAZQBmAG0AcAAuAHMA
eQBzAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQA
cgBpAHYAZQByAHMAXABNAHMAZgBzAC4AUwBZAFMAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAE4AcABmAHMALgBTAFkA
UwAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAdABkAHgALgBzAHkAcwAAAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABUAEQASQAuAFMAWQBTAAAA
AAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAGEAZgBkAC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgB0AC4AcwB5AHMA
AAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAHcAZgBwAGwAdwBmAC4AcwB5AHMAAAAAAAAAJgAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABwAGEA
YwBlAHIALgBzAHkAcwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgBpAG8AcwAuAHMAeQBzAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHcAYQBuAGEAcgBwAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AGUAcgBtAGQA
ZAAuAHMAeQBzAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAcgBkAGIAcwBzAC4AcwB5AHMAAAAAAAAAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAG4AcwBpAHAAcgBvAHgAeQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAHMAcwBtAGIAaQBvAHMA
LgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAZABpAHMAYwBhAGMAaABlAC4AcwB5AHMAAAAkAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGMA
cwBjAC4AcwB5AHMAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZABmAHMAYwAuAHMAeQBzAAAAKQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAGwA
YgBkAHIAaQB2AGUALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdAB1AG4AbgBlAGwALgBzAHkAcwAAAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAGkAOAAwADQAMgBwAHIAdAAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAG8AdQBjAGwA
YQBzAHMALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAawBiAGQAYwBsAGEAcwBzAC4AcwB5AHMAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAGYAZABjAC4AcwB5AHMAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4AdgBpAGYALgBzAHkAcwAAAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAHgAZQBuAGkAZgBhAGMAZQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABIAEQAQQB1AGQA
QgB1AHMALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAdgBpAG8AcwBlAHIALgBzAHkAcwAAAAAAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAHEAeABsAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdQBzAGIAdQBoAGMAaQAuAHMAeQBzAAAA
AAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAFUAUwBCAFAATwBSAFQALgBTAFkAUwAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB1AHMAYgBlAGgA
YwBpAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAaQBuAHQAZQBsAHAAcABtAC4AcwB5AHMAAAAtAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAEMAbwBtAHAAbwBzAGkAdABlAEIAdQBzAC4AcwB5AHMAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAEEAZwBpAGwA
ZQBWAHAAbgAuAHMAeQBzAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAByAGEAcwBsADIAdABwAC4AcwB5AHMAAAAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAbgBkAGkAcwB0AGEAcABpAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAG4AZABpAHMAdwBhAG4A
LgBzAHkAcwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXAByAGEAcwBwAHAAcABvAGUALgBzAHkAcwAAACgAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwA
cgBhAHMAcABwAHQAcAAuAHMAeQBzAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAHMAcwB0AHAALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAByAGQAcABiAHUAcwAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwB3AGUA
bgB1AG0ALgBzAHkAcwAAAAAAAAAjAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGsAcwAuAHMAeQBzAAAAAAAAACYAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwA
dQBtAGIAdQBzAC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHUAcwBiAGgAdQBiAC4AcwB5AHMA
AAAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQA
cgBpAHYAZQByAHMAXABOAEQAUAByAG8AeAB5AC4AUwBZAFMAAAAAACgAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABkAEEA
dQBkAGkAbwAuAHMAeQBzAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHAAbwByAHQAYwBsAHMALgBzAHkAcwAAAAAA
JQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYA
ZQByAHMAXABkAHIAbQBrAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGsAcwB0AGgAdQBuAGsALgBzAHkA
cwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXAB4AGUAbgBuAGUAdAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAYwByAGEA
cwBoAGQAbQBwAC4AcwB5AHMAAAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMA
dABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAGQAdQBtAHAAXwBkAGkAcwBrAGQAdQBtAHAA
LgBzAHkAcwAAAAAAAAAAACwAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AcwB5AHMA
AAAAAC0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIA
aQB2AGUAcgBzAFwAZAB1AG0AcABfAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAC0AAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwA
ZAB1AG0AcABfAGQAdQBtAHAAZgB2AGUALgBzAHkAcwAAAB8AAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXAB3AGkAbgAzADIAawAuAHMAeQBzAAAAAAAAACYA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwARAB4AGEAcABpAC4AcwB5AHMAAAAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGQAeABnAC4AcwB5AHMA
AAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABUAFMA
RABEAEQALgBkAGwAbAAAAAAAAAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABxAHgAbABkAGQALgBkAGwAbAAAAAAAAAAAACYAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbAB1AGEA
ZgB2AC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGwAbAB0AGQAaQBvAC4AcwB5AHMAAAAAAAAA
JwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAByAHMAcABuAGQAcgAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABUAFQAUAAuAHMA
eQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQA
UgBJAFYARQBSAFMAXABiAG8AdwBzAGUAcgAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbQBwAHMA
ZAByAHYALgBzAHkAcwAAAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAG0AcgB4AHMAbQBiAC4AcwB5AHMAAAAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXABtAHIAeABzAG0AYgAxADAALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbQByAHgAcwBtAGIA
MgAwAC4AcwB5AHMAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHAAZQBhAHUAdABoAC4AcwB5AHMAAAAAAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMA
XABzAGUAYwBkAHIAdgAuAFMAWQBTAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcwByAHYAbgBlAHQALgBzAHkA
cwAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHQAYwBwAGkAcAByAGUAZwAuAHMAeQBzAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHIA
dgAyAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwARABSAEkAVgBFAFIAUwBcAHMAcgB2AC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAA
ZAByAC4AcwB5AHMAAAAAAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHQAZAB0AGMAcAAuAHMAeQBzAAAAAAAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXAB0AHMAcwBlAGMAcwByAHYALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAUgBEAFAAVwBEAC4A
UwBZAFMAAAAAAAAAAAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHMAcABzAHkAcwAuAHMAeQBzAAAAAAAAAAAAKQAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABhAHMAeQBuAGMAbQBhAGMALgBzAHkAcwAAAOCcyQIA+P//8AwBAJwAAABIG8gCAPj//4wN
AQAEAAAARBvIAgD4//+QDQEABAAAAKCrwAIA+P//lA0BAAABAAAABs0CAPj//5QOAQAEAAAA
AALNAgD4//+YDgEAUAAAAHww0AIA+P//6A4BAAQAAABoMNACAPj//+wOAQAEAAAAANCJAYD6
///wDgEAeAkAAIDSxgIA+P//aBgBAAgAAACI0sYCAPj//3AYAQAIAAAAALDBAgD4//94GAEA
ABAAAABgpQIA+P//eCgBAAAQAAAAgOYCgPj//3g4AQAAEAAAALCsAgD4//94SAEAABAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
NzYwMS4xODUyNi5hbWQ2NGZyZS53aW43c3AxX2dkci4xNDA3MDYtMTUwNgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABhMDVlNTg1NC1hMDAxLTRjMjItODg1MS1kZDc4NWUxMAUAAAB8MNACAPj//4Aw
0AIA+P//aDDQAgD4//9sMNACAPj//wDQiQGA+v//eNmJAYD6//+A0sYCAPj//4jSxgIA+P//
iNLGAgD4//+Q0sYCAPj//0cAAAAAAAAAABAAAAAAAAB4CQAADwAAAAAAAAAAAAAAxgEAAAAA
AAAAAAAAAAAAAAAIAgABAAAAAAAAAAAAAADgkagDgPr//zhAigGA+v//AgARwDgAIALGOzHB
BAAAAKECMcEEAAAAACQbAAAAAABQP1A/AQAAAEBhaQOg+P//dAoAAAAgAAACABHAOAAgAu+W
b8EEAAAA7ZNvwQQAAAAAAHwCAAAAAAAAOAqA+f//8OYcAKD4//90CgAAABAAAAIAEcA4ACAC
MqB7wQQAAACwJnDBBAAAAABQgAAAAAAAoCgWAgAAAADQwxIDgPr//3QKAAAAAAEAAgARwDgA
IALYqH/BBAAAAFulf8EEAAAAAAAAAAAAAAAAANkBAAAAAHBs1wCg+P//dAoAAACAAAACABHA
OAAgAvLRtsEEAAAA9cF/wQQAAAAAQIAAAAAAAGAUFgIAAAAA0MMSA4D6//90CgAAABAAAAIA
EcA4ACACsXHHwQQAAABMbcfBBAAAAAAAAAAAAAAAAADZAQAAAACgsw4BoPj//3QKAAAAgAAA
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
AQEBAAECAAABAQEAAQIAAAEBAQABAgAAARkCABlSFQIBBwIABwGnAAEEAQAEQgAAGQQBAARC
AABw7AEAAAAAAAAAAAABBAEABEIAABkEAQAEQgAAwD8CAAAAAAAAAAAAAQQBAARCAAAZBAEA
BEIAAPBFCAAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABAUQIAAAAAAAAAAAABBAEABEIAABkE
AQAEQgAAYPwHAAAAAAAAAAAAAQQBAARCAAAZBAEABEIAADAZDAAAAAAAAAAAAAEEAQAEQgAA
GQQBAARCAACw3gAAAAAAAAAAAAABBAEABEIAABkEAQAEQgAA8BkMAAAAAAAAAAAAAQQBAARC
AAAZBAEABEIAALAaDAAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABwGwwAAAAAAAAAAAABFAaF
FFMMASsABVAEAgAKARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBXyQAX/QmAFvk
JQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXICQAwuAgAK6gHACWYBgAfiAUA
GXgEABRoAwAHAScAARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsA
BVAEAgAKARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBEAWFEFMIASsAAVAAGgAA
ARQGhRRTDAErAAVQBAIACgEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARAFhRBT
CAErAAFQABoAAAEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARQGhRRTDAErAAVQ
BAIACgEQBYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKAV8kAF/0JgBb5CUAV9QkAFPE
IwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMA
BwEnAAEUBoUUUwwBKwAFUAQCAAoBGQaFGVMRASsAClAJAgUKARgGhRhTEAErAAlQCAIECgE7
BoU7UzMBKwAsUCsCJwoBBAEABGIAAAEpDIUpZCoAInQpABs0KAAUUwwBKwAFUAQCAAoZUAyF
UGQqAEl0KQBCNCgAO1MzASsALFArAicKQEoHAAAAAAAAAAAAAV8kAF/0JgBb5CUAV9QkAFPE
IwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMA
BwEnAAFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAARPgMAD/oCwA62AoANcgJADC4
CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBOwABBAEABEIAAAGfJACfNC4Al2QwAI90LwCH9DQA
f+QzAHfUMgBvxDEAZ/gTAF7oEgBV2BEATMgQAEO4DwA6qA4AMZgNACiIDAAfeAsAF2gKAA8B
NQABBAEABEIAAAF/HgB/9DQAd+QzAG/UMgBnxDEAX/gTAFboEgBN2BEARMgQADu4DwAyqA4A
KZgNACCIDAAXeAsAD2gKAAcBNQABBAEABEIAAAEEAQAEwgAAAZckAJc0LgCPZDAAh3QvAH/0
NAB35DMAb9QyAGfEMQBf+BMAVugSAE3YEQBEyBAAO7gPADKoDgApmA0AIIgMABd4CwAPaAoA
BwE1AAEGAwAGQgJQATAAAAEFAgAFMgFQAQYDAAZiAlABMAAAAQUCAAVSAVABBwQABzIDYAJQ
ATABBwQABzIDcAJgAVABBQIABZIBUAEGAwAGggJQATAAAAEJBQAJYgXQA3ACUAEwAAABBQIA
BXIBUAEIBAAIUgTgAlABMAEHAwAHYgPQAVAAAAEHBAAHMgNwAlABMAEHAwAHQgPgAVAAAAEI
BAAIcgTQAnABUAEHAwAHggPwAVAAAAEJBAAJkgXgA8ABUAEOCAAOUgrgCNAGwARwA2ACUAEw
ARAJABCCDPAK4AjQBsAEcANgAlABMAAAAQcEAAdSA3ACUAEwAQgFAAhiBHADYAJQATAAACEA
BAAAdAAAAGQDAKCjBACkowQAMNgbACEAAACgYQsA8GELAFjJGwAhAAAAnJcEAOSXBADg0hsA
IQAAACzdAQDf3QEAvNQbACEAAAC80wkAMNQJAFjJGwAhAAAAgNIJAEzTCQAkyRsAIQAAACRT
BAAIVAQA4NIbACEAAAD0RQAAKUYAAEw7HAAhAAAA5OUEAMTmBADsKhwAIQAAAPwxAQDsMwEA
MD4cACEAAACkQQAAGEMAAOgfHAAhAAAAQD8EAJA/BAAgyhsAIQAAAACJAQCgigEA7CocACEA
AADgrwEAdLABAHzJGwAhAAgAAPQDAAB0BAAAVAUAADQGAMBWAgD6VgIA/D8cACEAEAAA9AQA
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
UEFHRURBVEEA3QAAABBUAABMAAAAFEsAAAAAAAAAAAAAAAAAQAAAwFBBR0VWUkZDHikAAADw
VAAAKgAAAGBLAAAAAAAAAAAAAAAAAEAAAEBQQUdFVlJGRFASAAAAIFUAABQAAACKSwAAAAAA
AAAAAAAAAABAAADASU5JVAAAAABcdgUAAEBVAAB4BQAAnksAAAAAAAAAAAAAAAAAIAAA4i5y
c3JjAAAAPF8DAADAWgAAYAMAABZRAAAAAAAAAAAAAAAAAEAAAEAucmVsb2MAAHQgAAAAIF4A
ACIAAAB2VAAAAAAAAAAAAAAAAABAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAACAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAPvDg/8gdVuJRYBIiU2ISIlVkEyJRZhMiU2g6JGE//8LwItFgEiLTYhIi1WQ
TItFmEyLTaBIiaPYAQAAD4Sx/P//SI09WIkjAIt3EEiLPzvGcxBIjTy3D74EOAvAD475/f//
uBwAAMDp7/3//7lKAAAARTPJRQ8gwEULwHUUuQEAAABFD7aD8AEAAEWLi8QBAABIi5XoAAAA
TIvV6GAAAABIg+xQSIlMJCBIiVQkKEyJRCQwTIlMJDhMiVQkQEmLyuhryA4ASItMJCBIi1Qk
KEyLRCQwTItMJDhMi1QkQEiDxFBB/9JIiUWwSIvI6N/HDgBIi0Ww6Vn9//9mDx9EAABIgew4
AQAASI2EJAABAAAPKXQkMA8pfCRARA8pRCRQRA8pTCRgRA8pVCRwRA8pWIBEDylgkEQPKWig
RA8pcLBEDyl4wEiJGEiJeAhIiXAQTIlgGEyJaCBMiXAoTIl4MEyJVCQg6FcKAACQZmZmZmZm
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
AAAAQYmQnAAAAIsNQHUjAA8yQYmAkAAAAEGJkJQAAAC52QEAAA8yg+D8DzDCAADMzMzMzMwP
HwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVFJHRER1bXBCbG9iEAAAALEdAPAgAAAAQFp1ZUbx
6kOMkTa4Vyj9NQAAAAAAAAAAAAAAACAAAACPAFy8Oh7XRJiNhvaITGdYYQEAAAAAAAAHAAAA
AAIEJFkBAAAAGAAAAQIA6AMAgAAIAAAAAAAABAQF//9YZW4ANC41LjAtcmMAMTEvMTMvMjAx
NAAAARsAAQECAwQAAAAAAAAAAAAAAAAAAAAABgAAWGVuAEhWTSBkb21VADQuNS4wLXJjACAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAAw0AAwEBAAAAAwMDAlhlbgAA
BBoBBAEDAQLlBgEA//uJFwAAAABkCmQKQQFDUFUgMQBJbnRlbAAABBoCBAEDAQLlBgEA//uJ
FwAAAABkCmQKQQFDUFUgMgBJbnRlbAAACwUACwFYZW4AABAPABABAwYAAB4A/v8BAAAAERUA
EQAQAABAAEAAgAcJAAEABwAARElNTSAwAAATDwATAAAAAP//HQAAEAEAABQTABQAAAAA//8d
AAARABMBAAAAACALACAAAAAAAAAAAAB/BAB/AAAAAAAAAAAAIAAAAInDemwTQ9xHnzSogAoP
tWxuAgAAAAAAAAIAAAAKAAAAfgBNAEgAegAAAAQAAAAEAAAAbQoAACwAAABDAG8AbQBwAG8A
bgBlAG4AdAAgAEkAbgBmAG8AcgBtAGEAdABpAG8AbgAAAAMAAAAQAAAAAAAAAAAAAAAAAAAA
AAAAACYAAABDAG8AbgBmAGkAZwB1AHIAYQB0AGkAbwBuACAARABhAHQAYQAAAAkAAAAQAAAA
//////////8AAAAAAAAAABYAAABJAGQAZQBuAHQAaQBmAGkAZQByAAAAAQAAAEoAAABJAG4A
dABlAGwANgA0ACAARgBhAG0AaQBsAHkAIAA2ACAATQBvAGQAZQBsACAAMwAwACAAUwB0AGUA
cABwAGkAbgBnACAANQAAACgAAABQAHIAbwBjAGUAcwBzAG8AcgBOAGEAbQBlAFMAdAByAGkA
bgBnAAAAAQAAAGAAAABJAG4AdABlAGwAKABSACkAIABYAGUAbwBuACgAUgApACAAQwBQAFUA
IAAgACAAIAAgACAAIAAgACAAIAAgAFgAMwA0ADUAMAAgACAAQAAgADIALgA2ADcARwBIAHoA
AAAiAAAAVQBwAGQAYQB0AGUAIABTAGkAZwBuAGEAdAB1AHIAZQAAAAMAAAAIAAAAAAAAAAcA
AAAcAAAAVQBwAGQAYQB0AGUAIABTAHQAYQB0AHUAcwAAAAQAAAAEAAAABwAAACIAAABWAGUA
bgBkAG8AcgBJAGQAZQBuAHQAaQBmAGkAZQByAAAAAQAAABoAAABHAGUAbgB1AGkAbgBlAEkA
bgB0AGUAbAAAAAwAAABNAFMAUgA4AEIAAAALAAAACAAAAAAAAAAHAAAAAAAgAAAAb8A90I7Y
xUS6KvrgNRctGZgDAAAAAAAAAAAAAAAAAAAAAAAACwAAAEdlbnVudGVsaW5lSQsAAABHZW51
bnRlbGluZUkAAAAAAQAAAOUGAQAACCACASK4gf/7ixflBgEAAAggAgEiuIH/+4sXAAAAAAIA
AAABWgNV5LLwAAAAAAAsIcoJAVoDVeSy8AAAAAAALCHKCQAAAAAEAAAAAAAABAAAAAAAAAAA
AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAKAAAAAAAAB0QAAAAAAAAAAAAAAAAAAAdEAAAAAAAAAAAAAAAAAAAACwAAAAAA
AAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAQAAABcAAAAAAAAAAAAEAAAAAAAAAAAA
AAAAAAAABAAAAAAAAAAAAAEAAACLAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAA
AAABAAAAgAAAwAENAAAAAAAAAAAAAAAAAAABDQAAAAAAAAAAAAAAAAAAAAAAAAAAAIAIAACA
AAAAAAAAAAAAAAAACAAAgAAAAAAAAAAAAAAAAAAAAAABAACAAAAAAAAAAAABAAAAAAgQKAAA
AAAAAAAAAQAAAAAIECgAAAAAAgAAgEludGVsKFIpIFhlb24oUilJbnRlbChSKSBYZW9uKFIp
AAAAAAMAAIAgQ1BVICAgICAgICAgICBYIENQVSAgICAgICAgICAgWAAAAAAEAACAMzQ1MCAg
QCAyLjY3R0h6ADM0NTAgIEAgMi42N0dIegAAAAAABQAAgAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAYAAIAAAAAAAAAAAEBgAAEAAAAAAAAAAAAAAABAYAABAAAAAAAA
AAAHAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAgCQwAAAAAAAA
AAAAAAAAAAAkMAAAAAAAAAAAAAAAAAAAIAAAANJAO+igsEJIq+pxyeNGPdFAAAAAAAAAAAAA
AABBUElDYAQAAAKwWGVuAAAARkFDUPQAAAAEQFhlbgAAAFdBRVQoAAAAAVZYZW4AAABIUEVU
OAAAAAHSWGVuAAAAIAAAAIhIyFTRAR5MvtYoLJgkEwMAEAAAAAAAAAAAAACdTE1ULJTVRr9Q
31zZUkpQSBCNAoD6//+4DwAAJAnoCDMAAABjZHJvbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAExKfvihxS9Nv/DV3mOl
5MNoAgAAAAAAAAAAAAAAAAAAAAAAAAEAAAALAAAAAAAAAFdkZjAxMDAwAGgAAAkAAAABAAAA
AAAAAM7PAAAoAAAABAAAAEBCawKA+v//AQAAAAkAAACwHQAAbXNpc2FkcnYAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAACgEAQG4SAoD6//8BAAAACQAAALAdAAB2ZHJ2cm9vdAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAM7PAABAnjgCgPr//wEAAAAFAAAAcBcAAHN0b3JmbHQAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA8Ag/AAAZjAKA+v//AQAAAAkAAACwHQAAY2Ryb20AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAQAaTAoD6//8BAAAABwAAAHEXAABIREF1ZEJ1cwAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAABAOpMCgPr//wEAAAAJAAAAsB0AAFZpcnRpb1Nl
cmlhbAAAAAAAAAAAAAAAAAAAAAAAAAAAvAIAAEBOlgKA+v//AQAAAAkAAACwHQAAaW50ZWxw
cG0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADPzwAAUKyXAoD6//8BAAAACQAAALAdAABDb21w
b3NpdGVCdXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAWUQAQoJsCgPr//wEAAAAJAAAAsB0AAHVt
YnVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAABBAUwOA+v//AQAAAAcAAABxFwAA
UEVBVVRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
--------------070603040901030901050202
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Thu Nov 13 14:26:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:26: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 1XovLf-0004Ea-JX; Thu, 13 Nov 2014 14:26:11 +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 1XovLf-0004EV-68
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:26:11 +0000
Received: from [193.109.254.147] by server-9.bemta-14.messagelabs.com id
	F8/9C-02712-28FB4645; Thu, 13 Nov 2014 14:26:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1415888769!12340331!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6667 invoked from network); 13 Nov 2014 14:26:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:26:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,377,1413244800"; d="scan'208";a="26821000"
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: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ
Date: Thu, 13 Nov 2014 14:26:08 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
In-Reply-To: <5464BDF4.1090103@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
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 13 November 2014 14:20
> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> Subject: Windows 7 64 bit blue screen with stop 1e after restore with new
> build of win pv drivers
> 
> I did a new build of winpv drivers and tested on one windows 7 64 bit
> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> from spice git:
> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> 
> After restore windows showed blue screen with stop 1e, I open the dump
> with "BlueScreenView" and showed that cause is xennet driver.
> I attached the dump, if you need more informations/tests tell me and
> I'll post them.
> 

I've been testing with win7 32-bit and seen no problems. The minidump doesn't tell me much unfortunately do you have a full dump, plus the QEMU log?

  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

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 13 14:26:11 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:26: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 1XovLf-0004Ea-JX; Thu, 13 Nov 2014 14:26:11 +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 1XovLf-0004EV-68
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:26:11 +0000
Received: from [193.109.254.147] by server-9.bemta-14.messagelabs.com id
	F8/9C-02712-28FB4645; Thu, 13 Nov 2014 14:26:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1415888769!12340331!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6667 invoked from network); 13 Nov 2014 14:26:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:26:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,377,1413244800"; d="scan'208";a="26821000"
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: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ
Date: Thu, 13 Nov 2014 14:26:08 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
In-Reply-To: <5464BDF4.1090103@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
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 13 November 2014 14:20
> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> Subject: Windows 7 64 bit blue screen with stop 1e after restore with new
> build of win pv drivers
> 
> I did a new build of winpv drivers and tested on one windows 7 64 bit
> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> from spice git:
> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> 
> After restore windows showed blue screen with stop 1e, I open the dump
> with "BlueScreenView" and showed that cause is xennet driver.
> I attached the dump, if you need more informations/tests tell me and
> I'll post them.
> 

I've been testing with win7 32-bit and seen no problems. The minidump doesn't tell me much unfortunately do you have a full dump, plus the QEMU log?

  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

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 13 14:38:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:38: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 1XovXO-0004Qa-HI; Thu, 13 Nov 2014 14:38:18 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XovXN-0004QV-M9
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:38:17 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	58/3A-09842-952C4645; Thu, 13 Nov 2014 14:38:17 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415889495!12518338!1
X-Originating-IP: [209.85.212.172]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 24042 invoked from network); 13 Nov 2014 14:38:15 -0000
Received: from mail-wi0-f172.google.com (HELO mail-wi0-f172.google.com)
	(209.85.212.172)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:38:15 -0000
Received: by mail-wi0-f172.google.com with SMTP id bs8so8518049wib.5
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 13 Nov 2014 06:38:15 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=hbKebf2OywLo4rIMvjS0Sv7lbB5Nb2LL9hp5Z61nqDI=;
	b=RiZb3pwuggJSF8AVwz/dQvfGWnfWHmSr07xjfE3/OQNnvGXAs8ATdJlQrUAMa8ZSHi
	2vpj1BfvCrh14fKvIK7wDENbxEuxJDzmflQVzacuwOZIrudttUqDzdXLSJ9Ez2fFZPIO
	dMCsXuCiHb4Kb0bNrLH5P4qpJQWgUXqZuPo0AOFtSvCPb9bRd7Lrz/XSlBVe6LY+XhWj
	wUObH2fGuILt5ykEtWjC1UuSKaJe7U53jh/Amt6wEgQIfwcSGt6qeHAXpNtkZ1tlzdVc
	MwY0o6aMSXlrwDI5/p5Uv9SXi9nWNjBIHh6eoiS3CNEvSJJrabdSuxku5+Rk1gDW9iZK
	5RHQ==
X-Gm-Message-State: ALoCoQnFekpDvOkH0Ei9jAfONwrE0wdTfTHWDsSEaBbqpeh5sa9kkIrOxRHz/5Gq8tbVyX70Qh2R
X-Received: by 10.194.205.103 with SMTP id lf7mr4447698wjc.134.1415889494877; 
	Thu, 13 Nov 2014 06:38:14 -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
	dm10sm18267893wib.18.2014.11.13.06.38.13 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 13 Nov 2014 06:38:13 -0800 (PST)
Message-ID: <5464C25D.6070200@m2r.biz>
Date: Thu, 13 Nov 2014 15:38:21 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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

Il 13/11/2014 15:26, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 13 November 2014 14:20
>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
>> Subject: Windows 7 64 bit blue screen with stop 1e after restore with new
>> build of win pv drivers
>>
>> I did a new build of winpv drivers and tested on one windows 7 64 bit
>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
>> from spice git:
>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>>
>> After restore windows showed blue screen with stop 1e, I open the dump
>> with "BlueScreenView" and showed that cause is xennet driver.
>> I attached the dump, if you need more informations/tests tell me and
>> I'll post them.
>>
> I've been testing with win7 32-bit and seen no problems. The minidump doesn't tell me much unfortunately do you have a full dump, plus the QEMU log?
>
>    Paul

Thanks for reply.
qemu log was without errors or warning related, I changed windows option 
for full memory dump and enable qemu trace of xen and retried to reproce 
the problem but this time after restore on same domU not had the blue 
screen.

>
>> 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 Thu Nov 13 14:38:19 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 13 Nov 2014 14:38: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 1XovXO-0004Qa-HI; Thu, 13 Nov 2014 14:38:18 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XovXN-0004QV-M9
	for win-pv-devel@lists.xenproject.org; Thu, 13 Nov 2014 14:38:17 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	58/3A-09842-952C4645; Thu, 13 Nov 2014 14:38:17 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-8.tower-21.messagelabs.com!1415889495!12518338!1
X-Originating-IP: [209.85.212.172]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 24042 invoked from network); 13 Nov 2014 14:38:15 -0000
Received: from mail-wi0-f172.google.com (HELO mail-wi0-f172.google.com)
	(209.85.212.172)
	by server-8.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	13 Nov 2014 14:38:15 -0000
Received: by mail-wi0-f172.google.com with SMTP id bs8so8518049wib.5
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 13 Nov 2014 06:38:15 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=hbKebf2OywLo4rIMvjS0Sv7lbB5Nb2LL9hp5Z61nqDI=;
	b=RiZb3pwuggJSF8AVwz/dQvfGWnfWHmSr07xjfE3/OQNnvGXAs8ATdJlQrUAMa8ZSHi
	2vpj1BfvCrh14fKvIK7wDENbxEuxJDzmflQVzacuwOZIrudttUqDzdXLSJ9Ez2fFZPIO
	dMCsXuCiHb4Kb0bNrLH5P4qpJQWgUXqZuPo0AOFtSvCPb9bRd7Lrz/XSlBVe6LY+XhWj
	wUObH2fGuILt5ykEtWjC1UuSKaJe7U53jh/Amt6wEgQIfwcSGt6qeHAXpNtkZ1tlzdVc
	MwY0o6aMSXlrwDI5/p5Uv9SXi9nWNjBIHh6eoiS3CNEvSJJrabdSuxku5+Rk1gDW9iZK
	5RHQ==
X-Gm-Message-State: ALoCoQnFekpDvOkH0Ei9jAfONwrE0wdTfTHWDsSEaBbqpeh5sa9kkIrOxRHz/5Gq8tbVyX70Qh2R
X-Received: by 10.194.205.103 with SMTP id lf7mr4447698wjc.134.1415889494877; 
	Thu, 13 Nov 2014 06:38:14 -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
	dm10sm18267893wib.18.2014.11.13.06.38.13 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 13 Nov 2014 06:38:13 -0800 (PST)
Message-ID: <5464C25D.6070200@m2r.biz>
Date: Thu, 13 Nov 2014 15:38:21 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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

Il 13/11/2014 15:26, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 13 November 2014 14:20
>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
>> Subject: Windows 7 64 bit blue screen with stop 1e after restore with new
>> build of win pv drivers
>>
>> I did a new build of winpv drivers and tested on one windows 7 64 bit
>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
>> from spice git:
>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>>
>> After restore windows showed blue screen with stop 1e, I open the dump
>> with "BlueScreenView" and showed that cause is xennet driver.
>> I attached the dump, if you need more informations/tests tell me and
>> I'll post them.
>>
> I've been testing with win7 32-bit and seen no problems. The minidump doesn't tell me much unfortunately do you have a full dump, plus the QEMU log?
>
>    Paul

Thanks for reply.
qemu log was without errors or warning related, I changed windows option 
for full memory dump and enable qemu trace of xen and retried to reproce 
the problem but this time after restore on same domU not had the blue 
screen.

>
>> 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 Fri Nov 14 16:02:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 16:02: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 1XpJKT-00008z-3T; Fri, 14 Nov 2014 16:02:33 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XpJKR-00008q-5q
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 16:02:31 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	12/C0-24532-69726645; Fri, 14 Nov 2014 16:02:30 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-21.messagelabs.com!1415980948!12814314!1
X-Originating-IP: [74.125.82.52]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19885 invoked from network); 14 Nov 2014 16:02:28 -0000
Received: from mail-wg0-f52.google.com (HELO mail-wg0-f52.google.com)
	(74.125.82.52)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 16:02:28 -0000
Received: by mail-wg0-f52.google.com with SMTP id b13so19721608wgh.39
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 14 Nov 2014 08:02:28 -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
	:subject:references:in-reply-to:content-type;
	bh=HiO5oLpS+84oYxf7fRidHIHPFZDE7AQCd4TCsBm9c1U=;
	b=DnKvdW1qT0IjdsMA8ld4/lqYYbxF/JuOwe+AxGFsswmHXmGFzjXfCklrEmH/8Yg+5v
	HvLMULzc58Rzs7RDbrr6RTquSQ7D4YIWi8517RAqMWf+27HbPiH5PW2gAPHGpofLIbki
	fH1VD3qUUPGYLzCK1pfQWY5jHELikWhaamZ4cvQ99oJb9WQxtn973jkvKoV2uKYXGrii
	0U2giB4fb+O8ogvzRz4zHmcOu3z/ucs8UbmIvmGYo6f7/zm4dUTqANn0jg94ABUnETuW
	SqdUYK+gq2+U8hBNlHG+99Qq+mAVT8bO0HNS8bdHLX2GuDZv89Q33Jv9Sa7ThNdPtHrt
	4Fqw==
X-Gm-Message-State: ALoCoQnU2iBAuBxOow7vhlZ8CJpSGJZYqkLcw7GSix4bGn+cA4KOxamratT8xbj0/bYWq72ddJ68
X-Received: by 10.194.57.81 with SMTP id g17mr15695484wjq.12.1415980948093;
	Fri, 14 Nov 2014 08:02:28 -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 ce1sm40159934wjc.2.2014.11.14.08.02.25
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 14 Nov 2014 08:02:27 -0800 (PST)
Message-ID: <5466279C.207@m2r.biz>
Date: Fri, 14 Nov 2014 17:02: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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz>
In-Reply-To: <5464C25D.6070200@m2r.biz>
Content-Type: multipart/mixed; boundary="------------080400030902010507010701"
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit

Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> Il 13/11/2014 15:26, Paul Durrant ha scritto:
>>> -----Original Message-----
>>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>>> Sent: 13 November 2014 14:20
>>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
>>> Subject: Windows 7 64 bit blue screen with stop 1e after restore 
>>> with new
>>> build of win pv drivers
>>>
>>> I did a new build of winpv drivers and tested on one windows 7 64 bit
>>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
>>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
>>> from spice git:
>>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>>>
>>> After restore windows showed blue screen with stop 1e, I open the dump
>>> with "BlueScreenView" and showed that cause is xennet driver.
>>> I attached the dump, if you need more informations/tests tell me and
>>> I'll post them.
>>>
>> I've been testing with win7 32-bit and seen no problems. The minidump 
>> doesn't tell me much unfortunately do you have a full dump, plus the 
>> QEMU log?
>>
>>    Paul
>
> Thanks for reply.
> qemu log was without errors or warning related, I changed windows 
> option for full memory dump and enable qemu trace of xen and retried 
> to reproduce the problem but this time after restore on same domU not 
> had the blue screen.

Blue screen re-happen, in attachment qemu logs (before and after 
restore) with xen trace.
Also memory.dmp full this time but there is a problem, is 1,87 gb and my 
connection is max 256kbps of upload :(
If is really needed tell me and I'll try to load it in my webserver 
tomorrow.

>
>>
>>> Thanks for any reply and sorry for my bad english.
>



--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252;
 name="qemu-dm-W7-02.log"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="qemu-dm-W7-02.log"

xen_ram_alloc: do not alloc 78000000 bytes of ram at 0 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 4000000 bytes of ram at 78000000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 2000 bytes of ram at 7c000000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 4000000 bytes of ram at 7c002000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 10000 bytes of ram at 80002000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 40000 bytes of ram at 80012000 when runstate is INMIGRATE
red_dispatcher_loadvm_commands: 
qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

xen_platform_log xen platform: SUSPEND: SCHEDOP_shutdown:SHUTDOWN_suspend <==== (00000000)
xen_platform_log xen platform: XEN: HYPERCALL PAGE 0 @ 00000000.036a8000
xen_platform_log xen platform: SHARED_INFO: MAP XENMAPSPACE_shared_info @ 00000000.f8000000
xen_platform_log xen platform: XENCRSH|CRASH|XencrshEntryPoint:8.0.0.0 (12/11/2014)
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen be: qdisk-768: error: unknown operation (2)
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
main_channel_link: add main channel client
main_channel_handle_parsed: agent start
main_channel_handle_parsed: net test: latency 4.645000 ms, bitrate 2491484184 bps (2376.064476 Mbps)
inputs_connect: inputs channel client create
red_dispatcher_set_cursor_peer: 

--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252;
 name="qemu-dm-W7-02.log.1"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="qemu-dm-W7-02.log.1"

main_channel_link: add main channel client
main_channel_handle_parsed: net test: latency 6.002000 ms, bitrate 1035912999 bps (987.923621 Mbps)
red_dispatcher_set_cursor_peer: 
inputs_connect: inputs channel client create
xen_platform_log xen platform: XEN|DllInitialize: XEN 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XEN|SystemGetStartOptions:  TESTSIGNING  NOEXECUTE=OPTIN
xen_platform_log xen platform: XEN|SystemGetVersionInformation: KERNEL: 6.1 (BUILD 7601) PLATFORM WIN32_NT (x64)
xen_platform_log xen platform: XEN|SystemGetVersionInformation: SP: 1.0 ()
xen_platform_log xen platform: XEN|SystemGetVersionInformation: SUITES:
xen_platform_log xen platform: XEN|SystemGetVersionInformation: - TERMINAL
xen_platform_log xen platform: XEN|SystemGetVersionInformation: - SINGLEUSERTS
xen_platform_log xen platform: XEN|SystemGetVersionInformation: TYPE: WORKSTATION
xen_platform_log xen platform: XEN|SystemGetMemoryInformation: RANGE[0] 00000000.00001000 - 00000000.0009efff
xen_platform_log xen platform: XEN|SystemGetMemoryInformation: RANGE[1] 00000000.00100000 - 00000000.77ffefff
xen_platform_log xen platform: XEN|SystemCpuInformation: ====> (0)
xen_platform_log xen platform: XEN|SystemCpuInformation: Manufacturer: GenuineIntel
xen_platform_log xen platform: XEN|SystemCpuInformation: Local APIC ID: 00
xen_platform_log xen platform: XEN|SystemCpuInformation: <==== (0)
xen_platform_log xen platform: XEN|SystemCpuInformation: ====> (1)
xen_platform_log xen platform: XEN|SystemCpuInformation: Manufacturer: GenuineIntel
xen_platform_log xen platform: XEN|SystemCpuInformation: Local APIC ID: 02
xen_platform_log xen platform: XEN|SystemCpuInformation: <==== (1)
xen_platform_log xen platform: XEN: HYPERCALL PAGE 0 @ 00000000.036a8000
xen_platform_log xen platform: XEN: 4.5.0-rc
xen_platform_log xen platform: XENFILT|DriverEntry: XENFILT 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XENFILT|DriverSetActiveDeviceInstance: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01/10
xen_platform_log xen platform: XENFILT|UnplugCheckForPVDisks: PRESENT
xen_platform_log xen platform: XENFILT|UnplugCheckForPVNics: PRESENT
xen_platform_log xen platform: UNPLUG: PRE-AMBLE (DRIVERS NOT BLACKLISTED)
xen_platform_log xen platform: UNPLUG: DISKS
xen_platform_log xen platform: UNPLUG: NICS
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA80020F5040 (ACPI\PNP0A03\0)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80020F3040 (PCI\VEN_8086&DEV_1237&SUBSYS_11001AF4&REV_02\00)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214DAC0 (PCI\VEN_8086&DEV_7000&SUBSYS_11001AF4&REV_00\08)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214EAC0 (PCI\VEN_8086&DEV_7010&SUBSYS_11001AF4&REV_00\09)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214FAC0 (PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002150AC0 (PCI\VEN_8086&DEV_2668&SUBSYS_11001AF4&REV_01\18)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002151AC0 (PCI\VEN_1AF4&DEV_1003&SUBSYS_00031AF4&REV_00\20)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002152AC0 (PCI\VEN_1B36&DEV_0100&SUBSYS_11001AF4&REV_04\28)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80021535D0 (PCI\VEN_8086&DEV_2934&SUBSYS_11001AF4&REV_03\E8)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80021545D0 (PCI\VEN_8086&DEV_2935&SUBSYS_11001AF4&REV_03\E9)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002156040 (PCI\VEN_8086&DEV_2936&SUBSYS_11001AF4&REV_03\EA)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002157040 (PCI\VEN_8086&DEV_293A&SUBSYS_11001AF4&REV_03\EF)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002158040 (ACPI\PNP0103\0)
xen_platform_log xen platform: XENBUS|DriverEntry: XENBUS 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XENFILT|PdoQueryInterface: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10: UNPLUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|FdoCreate: FFFFFA80016F6D40 (XS0001 XENBUS) [ACTIVE]
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016EF9F8: Shared LevelSensitive CPU 0 VECTOR 51
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016F9A68: DeviceExclusive Latched CPU 0 VECTOR b0
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016F9878: DeviceExclusive Latched CPU 1 VECTOR b0
xen_platform_log xen platform: XENBUS|FdoScan: ====>
xen_platform_log xen platform: XENBUS|FdoCreateIoSpace: 00000000.f8000000 - 00000000.f8ffffff
xen_platform_log xen platform: XENBUS|FdoSuspend: ====>
xen_platform_log xen platform: SHARED_INFO: MAP XENMAPSPACE_shared_info @ 00000000.f8000000
xen_platform_log xen platform: XENBUS|FdoBalloon: ====>
xen_platform_log xen platform: EVTCHN_FIFO: CONTROLBLOCK[0] @ 00000000.25853000
xen_platform_log xen platform: EVTCHN_FIFO: CONTROLBLOCK[1] @ 00000000.25854000
xen_platform_log xen platform: XENBUS|EvtchnAbiAcquire: FIFO
xen_platform_log xen platform: STORE: PAGE @ 00000000.feffc000
xen_platform_log xen platform: STORE: EVTCHN 1
xen_platform_log xen platform: EVTCHN_FIFO: EVENTARRAY[0] @ 00000000.25855000
xen_platform_log xen platform: XENBUS|EvtchnFifoExpand: added ports [00000000 - 000003ff]
xen_platform_log xen platform: XENBUS|EvtchnInterruptEnable: CPU 0
xen_platform_log xen platform: XENBUS|EvtchnInterruptEnable: CPU 1
xen_platform_log xen platform: XENBUS|EvtchnBind: [1]: CPU 1
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000004)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000004)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000004)
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA8002113AC0 (PCIIDE\IDEChannel\0)
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA8002115AC0 (PCIIDE\IDEChannel\1)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002127630 (IDE\CdRomQEMU_QEMU_DVD-ROM_______________________2.1.____\0.1.0)
xen_platform_log xen platform: XENVBD|DriverEntry:8.0.0.0 (12/11/2014)
xen_platform_log xen platform: XENVBD|__DriverParseParameterKey:DriverParameters: 
xen_platform_log xen platform: XENDISK|DriverEntry:XENDISK 8.0.0 (0) (12.11.2014)
xen_platform_log xen platform: XENDISK|FdoCreate:FFFFFA800212CD40
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Version = 0
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Master = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: ScatterGather = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DemandMode = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: AutoInitialize = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma32BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: IgnoreCount = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma64BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: BusNumber = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaChannel = ffffffff
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: InterfaceType = Internal
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaWidth = 8Bits
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaSpeed = Compatible
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: MaximumLength = 000b0000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaPort = ffffffff
xen_platform_log xen platform: XENBUS|DmaGetAdapter: no interception
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: EVTCHN_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: GNTTAB_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: DEBUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: EMULATED_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENFILT|PdoQueryInterface: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10: EMULATED_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVBD|__FdoSetDevicePowerState:POWER D3 to D0
xen_platform_log xen platform: XENVBD|__FdoD3ToD0:D3->D0
xen_platform_log xen platform: XENVBD|__FdoIsPdoUnplugged:Target[0] : (vbd/768) Emulated NOT_PRESENT
xen_platform_log xen platform: XENVBD|PdoCreate:Target[0] : Creating (PV)
xen_platform_log xen platform: XENVBD|PdoSetDevicePowerState:Target[0] : POWER D3 to D0
xen_platform_log xen platform: XENVBD|PdoD3ToD0:Target[0] : D3->D0 (PV)
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : INITIALIZED ----> ENABLED
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state CLOSED
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|PdoReadInquiryData:Target[0] : Failed to get Page80 data
xen_platform_log xen platform: XENVBD|PdoReadInquiryData:Target[0] : Failed to get Page83 data
xen_platform_log xen platform: XENVBD|PdoUpdateInquiryData:Target[0] : VDI-UUID = {00000000-0000-0000-0000-000000000000}
xen_platform_log xen platform: XENVBD|FrontendPrepare:Target[0] : BackendId 0 (/local/domain/0/backend/qdisk/2/768)
xen_platform_log xen platform: XENVBD|FrontendReadFeatures:Target[0] : Features: PERSISTENT 
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state PREPARED
xen_platform_log xen platform: XENBUS|RangeSetPop: fail1 (c000009a)
xen_platform_log xen platform: GNTTAB: MAP XENMAPSPACE_grant_table[0] @ 00000000.f8001000
xen_platform_log xen platform: XENBUS|GnttabExpand: added references [00000009 - 000001ff]
xen_platform_log xen platform: XENVBD|__ReadDiskInfo:Target[0] : 102400000 sectors of 512 bytes (512)
xen_platform_log xen platform: XENVBD|__ReadDiskInfo:Target[0] : 48 GB (00000000) 
xen_platform_log xen platform: XENVBD|FrontendReadDiskInfo:Target[0] : Features: FLUSH DISCARD 
xen_platform_log xen platform: XENVBD|FrontendReadDiskInfo:Target[0] : DISCARD 0/0
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state CONNECTED
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state ENABLED
xen_platform_log xen platform: XENVBD|PdoCreate:Target[0] : Created (PV)
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread ===>
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread : Target[0] = 0xFFFFFA8002122C70 (present)
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread <===
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENVBD|__HandlePage83:Target[0] : INQUIRY Using Fake Page83 Data
xen_platform_log xen platform: XENVBD|__HandlePage80:Target[0] : INQUIRY Using Fake Page80 Data
xen_platform_log xen platform: XENDISK|PdoCreate:FFFFFA8002295740
xen_platform_log xen platform: XENVBD|PdoSetDeviceObject:Target[0] : Setting DeviceObject = 0xFFFFFA8002295060
xen_platform_log xen platform: XENVBD|FdoMapDeviceObjectToPdo:0xFFFFFA8002295060 --> Target 0 (000000)
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 13:QUERY_ID -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 15:QUERY_BUS_INFORMATION -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 19:UNKNOWN -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 18:UNKNOWN -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 0d:FILTER_RESOURCE_REQUIREMENTS -> c00000bb
xen_platform_log xen platform: XENVBD|PdoSetDevicePnpState:Target[0] : PNP Present to Started
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 07:QUERY_DEVICE_RELATIONS -> c00000bb
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENVIF|DriverEntry: XENVIF 8.0.0 (0) (24.09.2014)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: DEBUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: EVTCHN_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: RANGE_SET_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: CACHE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: GNTTAB_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVIF|FdoCreate: FFFFFA800288DD40 (XS0001 XENVIF)
xen_platform_log xen platform: XENIFACE|DriverEntry: 8.0.0.0 (8/10/2014)
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423D5B0 FFFFFA80028A1D90
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423C630 FFFFFA80028A1DA0
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: SHARED_INFO_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENIFACE|FdoInitialiseXSRegistryEntries: no such xenstore key
xen_platform_log xen platform: XENIFACE|FdoInitialiseXSRegistryEntries: Failed to initialise registry (c0000022)
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423D08C FFFFFA80028A1FB0
xen_platform_log xen platform: XENIFACE|FdoCreate: FFFFFA80028A1040 (IFACE)
xen_platform_log xen platform: XENBUS|RangeSetPop: fail1 (c000009a)
xen_platform_log xen platform: GNTTAB: MAP XENMAPSPACE_grant_table[1] @ 00000000.f8002000
xen_platform_log xen platform: XENBUS|GnttabExpand: added references [00000200 - 000003ff]
xen_platform_log xen platform: XENVIF|__PdoSetPermanentAddress: 0 00:16:3E:3E:00:77
xen_platform_log xen platform: XENVIF|__PdoSetContainerID: 0 {98381abd-649b-5822-b5c8-1de77941b503}
xen_platform_log xen platform: XENVIF|PdoCreate: FFFFFA8002FC71D0 (0 00000001)
xen_platform_log xen platform: XENNET|DriverEntry: XENNET 8.0.0 (0) (12.11.2014)
xen_platform_log xen platform: XENIFACE|WmiInit: DRV: XenIface WMI Initialisation
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:NotifyUnicastIpAddressChange (00F9) @ FFFFF880015DB850
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:GetUnicastIpAddressTable (0044) @ FFFFF880015DB900
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:FreeMibTable (0022) @ FFFFF880015C3FD0
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:CancelMibChangeNotify2 (0000) @ FFFFF880015D0D30
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:GetIfTable2 (0035) @ FFFFF880015D7270
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:FreeMibTable (0022) @ FFFFF880015C3FD0
xen_platform_log xen platform: XENVIF|PdoQueryInterface: 0: VIF_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.IpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Receive.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Receive.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.IpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Transmit.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Transmit.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: LsoV2.IPv4.MaxOffLoadSize = 65201
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: LsoV2.IPv6.MaxOffLoadSize = 65201
xen_platform_log xen platform: XENVIF|PdoQueryInterface: 0: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Version = 2
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Master = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: ScatterGather = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DemandMode = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: AutoInitialize = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma32BitAddresses = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: IgnoreCount = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma64BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: BusNumber = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaChannel = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: InterfaceType = Internal
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaWidth = 8Bits
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaSpeed = Compatible
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: MaximumLength = 00020000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaPort = 00000000
xen_platform_log xen platform: XENBUS|DmaGetAdapter: no interception
xen_platform_log xen platform: XENNET|AdapterMediaStateChange: LINK: UP: SPEED=1000000000 DUPLEX=FULL
xen_platform_log xen platform: XENNET|AdapterMediaStateChange: LINK: UP: SPEED=1000000000 DUPLEX=FULL
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : DUMP NOT_HIBER PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
main_channel_handle_parsed: agent start
main_channel_handle_parsed: agent start
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Guest agent lite main loop starting
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Set time to XenTime
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: hosttimeIsUTC: Open Registry Key
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Time is now  2014.11.14 15:23:39.612
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Set time to 2014.11.14 15:23:39.475
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to add feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Establish watch control/shutdown
xen_platform_log xen platform: XENIFACE|StartWatch: Start Watch FFFFFA8003610C60
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to advertise features
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:MethodExec Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SessionStart Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SetVValue Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SetVPath Failed 
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Failed to advertise shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to kick xapi 
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent going to sleep
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent woke up for 3
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Fire 000000000024EC10
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: fire feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Check if we need to shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: No need to shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: fired feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent going to sleep
xen_platform_log xen platform: SUSPEND: ====>
xen_platform_log xen platform: SUSPEND: SCHEDOP_shutdown:SHUTDOWN_suspend ====>
qemu: terminating on signal 1 from pid 5818
red_channel_client_disconnect_dummy: rcc=0x7f756b1fe800 (channel=0x7f756b2c2330 type=5 id=0)
snd_channel_put: SndChannel=0x7f756b4286c0 freed
red_channel_client_disconnect_dummy: rcc=0x7f756b533020 (channel=0x7f756b2c2560 type=6 id=0)
snd_channel_put: SndChannel=0x7f756b5227e0 freed

--------------080400030902010507010701
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Fri Nov 14 16:02:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 16:02: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 1XpJKT-00008z-3T; Fri, 14 Nov 2014 16:02:33 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XpJKR-00008q-5q
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 16:02:31 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	12/C0-24532-69726645; Fri, 14 Nov 2014 16:02:30 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-21.messagelabs.com!1415980948!12814314!1
X-Originating-IP: [74.125.82.52]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 19885 invoked from network); 14 Nov 2014 16:02:28 -0000
Received: from mail-wg0-f52.google.com (HELO mail-wg0-f52.google.com)
	(74.125.82.52)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 16:02:28 -0000
Received: by mail-wg0-f52.google.com with SMTP id b13so19721608wgh.39
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 14 Nov 2014 08:02:28 -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
	:subject:references:in-reply-to:content-type;
	bh=HiO5oLpS+84oYxf7fRidHIHPFZDE7AQCd4TCsBm9c1U=;
	b=DnKvdW1qT0IjdsMA8ld4/lqYYbxF/JuOwe+AxGFsswmHXmGFzjXfCklrEmH/8Yg+5v
	HvLMULzc58Rzs7RDbrr6RTquSQ7D4YIWi8517RAqMWf+27HbPiH5PW2gAPHGpofLIbki
	fH1VD3qUUPGYLzCK1pfQWY5jHELikWhaamZ4cvQ99oJb9WQxtn973jkvKoV2uKYXGrii
	0U2giB4fb+O8ogvzRz4zHmcOu3z/ucs8UbmIvmGYo6f7/zm4dUTqANn0jg94ABUnETuW
	SqdUYK+gq2+U8hBNlHG+99Qq+mAVT8bO0HNS8bdHLX2GuDZv89Q33Jv9Sa7ThNdPtHrt
	4Fqw==
X-Gm-Message-State: ALoCoQnU2iBAuBxOow7vhlZ8CJpSGJZYqkLcw7GSix4bGn+cA4KOxamratT8xbj0/bYWq72ddJ68
X-Received: by 10.194.57.81 with SMTP id g17mr15695484wjq.12.1415980948093;
	Fri, 14 Nov 2014 08:02:28 -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 ce1sm40159934wjc.2.2014.11.14.08.02.25
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 14 Nov 2014 08:02:27 -0800 (PST)
Message-ID: <5466279C.207@m2r.biz>
Date: Fri, 14 Nov 2014 17:02: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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz>
In-Reply-To: <5464C25D.6070200@m2r.biz>
Content-Type: multipart/mixed; boundary="------------080400030902010507010701"
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit

Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> Il 13/11/2014 15:26, Paul Durrant ha scritto:
>>> -----Original Message-----
>>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>>> Sent: 13 November 2014 14:20
>>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
>>> Subject: Windows 7 64 bit blue screen with stop 1e after restore 
>>> with new
>>> build of win pv drivers
>>>
>>> I did a new build of winpv drivers and tested on one windows 7 64 bit
>>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with vcpu
>>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
>>> from spice git:
>>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>>>
>>> After restore windows showed blue screen with stop 1e, I open the dump
>>> with "BlueScreenView" and showed that cause is xennet driver.
>>> I attached the dump, if you need more informations/tests tell me and
>>> I'll post them.
>>>
>> I've been testing with win7 32-bit and seen no problems. The minidump 
>> doesn't tell me much unfortunately do you have a full dump, plus the 
>> QEMU log?
>>
>>    Paul
>
> Thanks for reply.
> qemu log was without errors or warning related, I changed windows 
> option for full memory dump and enable qemu trace of xen and retried 
> to reproduce the problem but this time after restore on same domU not 
> had the blue screen.

Blue screen re-happen, in attachment qemu logs (before and after 
restore) with xen trace.
Also memory.dmp full this time but there is a problem, is 1,87 gb and my 
connection is max 256kbps of upload :(
If is really needed tell me and I'll try to load it in my webserver 
tomorrow.

>
>>
>>> Thanks for any reply and sorry for my bad english.
>



--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252;
 name="qemu-dm-W7-02.log"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="qemu-dm-W7-02.log"

xen_ram_alloc: do not alloc 78000000 bytes of ram at 0 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 4000000 bytes of ram at 78000000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 2000 bytes of ram at 7c000000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 4000000 bytes of ram at 7c002000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 10000 bytes of ram at 80002000 when runstate is INMIGRATE
xen_ram_alloc: do not alloc 40000 bytes of ram at 80012000 when runstate is INMIGRATE
red_dispatcher_loadvm_commands: 
qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

qemu-system-i386: usb-redir warning: usb-redir connection broken during migration

xen_platform_log xen platform: SUSPEND: SCHEDOP_shutdown:SHUTDOWN_suspend <==== (00000000)
xen_platform_log xen platform: XEN: HYPERCALL PAGE 0 @ 00000000.036a8000
xen_platform_log xen platform: SHARED_INFO: MAP XENMAPSPACE_shared_info @ 00000000.f8000000
xen_platform_log xen platform: XENCRSH|CRASH|XencrshEntryPoint:8.0.0.0 (12/11/2014)
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen be: qdisk-768: error: unknown operation (2)
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
xen_platform_log xen platform: 
main_channel_link: add main channel client
main_channel_handle_parsed: agent start
main_channel_handle_parsed: net test: latency 4.645000 ms, bitrate 2491484184 bps (2376.064476 Mbps)
inputs_connect: inputs channel client create
red_dispatcher_set_cursor_peer: 

--------------080400030902010507010701
Content-Type: text/plain; charset=windows-1252;
 name="qemu-dm-W7-02.log.1"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="qemu-dm-W7-02.log.1"

main_channel_link: add main channel client
main_channel_handle_parsed: net test: latency 6.002000 ms, bitrate 1035912999 bps (987.923621 Mbps)
red_dispatcher_set_cursor_peer: 
inputs_connect: inputs channel client create
xen_platform_log xen platform: XEN|DllInitialize: XEN 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XEN|SystemGetStartOptions:  TESTSIGNING  NOEXECUTE=OPTIN
xen_platform_log xen platform: XEN|SystemGetVersionInformation: KERNEL: 6.1 (BUILD 7601) PLATFORM WIN32_NT (x64)
xen_platform_log xen platform: XEN|SystemGetVersionInformation: SP: 1.0 ()
xen_platform_log xen platform: XEN|SystemGetVersionInformation: SUITES:
xen_platform_log xen platform: XEN|SystemGetVersionInformation: - TERMINAL
xen_platform_log xen platform: XEN|SystemGetVersionInformation: - SINGLEUSERTS
xen_platform_log xen platform: XEN|SystemGetVersionInformation: TYPE: WORKSTATION
xen_platform_log xen platform: XEN|SystemGetMemoryInformation: RANGE[0] 00000000.00001000 - 00000000.0009efff
xen_platform_log xen platform: XEN|SystemGetMemoryInformation: RANGE[1] 00000000.00100000 - 00000000.77ffefff
xen_platform_log xen platform: XEN|SystemCpuInformation: ====> (0)
xen_platform_log xen platform: XEN|SystemCpuInformation: Manufacturer: GenuineIntel
xen_platform_log xen platform: XEN|SystemCpuInformation: Local APIC ID: 00
xen_platform_log xen platform: XEN|SystemCpuInformation: <==== (0)
xen_platform_log xen platform: XEN|SystemCpuInformation: ====> (1)
xen_platform_log xen platform: XEN|SystemCpuInformation: Manufacturer: GenuineIntel
xen_platform_log xen platform: XEN|SystemCpuInformation: Local APIC ID: 02
xen_platform_log xen platform: XEN|SystemCpuInformation: <==== (1)
xen_platform_log xen platform: XEN: HYPERCALL PAGE 0 @ 00000000.036a8000
xen_platform_log xen platform: XEN: 4.5.0-rc
xen_platform_log xen platform: XENFILT|DriverEntry: XENFILT 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XENFILT|DriverSetActiveDeviceInstance: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01/10
xen_platform_log xen platform: XENFILT|UnplugCheckForPVDisks: PRESENT
xen_platform_log xen platform: XENFILT|UnplugCheckForPVNics: PRESENT
xen_platform_log xen platform: UNPLUG: PRE-AMBLE (DRIVERS NOT BLACKLISTED)
xen_platform_log xen platform: UNPLUG: DISKS
xen_platform_log xen platform: UNPLUG: NICS
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA80020F5040 (ACPI\PNP0A03\0)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80020F3040 (PCI\VEN_8086&DEV_1237&SUBSYS_11001AF4&REV_02\00)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214DAC0 (PCI\VEN_8086&DEV_7000&SUBSYS_11001AF4&REV_00\08)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214EAC0 (PCI\VEN_8086&DEV_7010&SUBSYS_11001AF4&REV_00\09)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA800214FAC0 (PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002150AC0 (PCI\VEN_8086&DEV_2668&SUBSYS_11001AF4&REV_01\18)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002151AC0 (PCI\VEN_1AF4&DEV_1003&SUBSYS_00031AF4&REV_00\20)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002152AC0 (PCI\VEN_1B36&DEV_0100&SUBSYS_11001AF4&REV_04\28)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80021535D0 (PCI\VEN_8086&DEV_2934&SUBSYS_11001AF4&REV_03\E8)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA80021545D0 (PCI\VEN_8086&DEV_2935&SUBSYS_11001AF4&REV_03\E9)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002156040 (PCI\VEN_8086&DEV_2936&SUBSYS_11001AF4&REV_03\EA)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002157040 (PCI\VEN_8086&DEV_293A&SUBSYS_11001AF4&REV_03\EF)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002158040 (ACPI\PNP0103\0)
xen_platform_log xen platform: XENBUS|DriverEntry: XENBUS 8.0.0 (0) (13.11.2014)
xen_platform_log xen platform: XENFILT|PdoQueryInterface: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10: UNPLUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|FdoCreate: FFFFFA80016F6D40 (XS0001 XENBUS) [ACTIVE]
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016EF9F8: Shared LevelSensitive CPU 0 VECTOR 51
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016F9A68: DeviceExclusive Latched CPU 0 VECTOR b0
xen_platform_log xen platform: XENBUS|FdoConnectInterrupt: FFFFFA80016F9878: DeviceExclusive Latched CPU 1 VECTOR b0
xen_platform_log xen platform: XENBUS|FdoScan: ====>
xen_platform_log xen platform: XENBUS|FdoCreateIoSpace: 00000000.f8000000 - 00000000.f8ffffff
xen_platform_log xen platform: XENBUS|FdoSuspend: ====>
xen_platform_log xen platform: SHARED_INFO: MAP XENMAPSPACE_shared_info @ 00000000.f8000000
xen_platform_log xen platform: XENBUS|FdoBalloon: ====>
xen_platform_log xen platform: EVTCHN_FIFO: CONTROLBLOCK[0] @ 00000000.25853000
xen_platform_log xen platform: EVTCHN_FIFO: CONTROLBLOCK[1] @ 00000000.25854000
xen_platform_log xen platform: XENBUS|EvtchnAbiAcquire: FIFO
xen_platform_log xen platform: STORE: PAGE @ 00000000.feffc000
xen_platform_log xen platform: STORE: EVTCHN 1
xen_platform_log xen platform: EVTCHN_FIFO: EVENTARRAY[0] @ 00000000.25855000
xen_platform_log xen platform: XENBUS|EvtchnFifoExpand: added ports [00000000 - 000003ff]
xen_platform_log xen platform: XENBUS|EvtchnInterruptEnable: CPU 0
xen_platform_log xen platform: XENBUS|EvtchnInterruptEnable: CPU 1
xen_platform_log xen platform: XENBUS|EvtchnBind: [1]: CPU 1
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB060 (VBD 00000004)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FB850 (VIF 00000004)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000001)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000002)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000003)
xen_platform_log xen platform: XENBUS|PdoCreate: FFFFFA80016FF060 (IFACE 00000004)
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA8002113AC0 (PCIIDE\IDEChannel\0)
xen_platform_log xen platform: XENFILT|FdoCreate: FFFFFA8002115AC0 (PCIIDE\IDEChannel\1)
xen_platform_log xen platform: XENFILT|PdoCreate: FFFFFA8002127630 (IDE\CdRomQEMU_QEMU_DVD-ROM_______________________2.1.____\0.1.0)
xen_platform_log xen platform: XENVBD|DriverEntry:8.0.0.0 (12/11/2014)
xen_platform_log xen platform: XENVBD|__DriverParseParameterKey:DriverParameters: 
xen_platform_log xen platform: XENDISK|DriverEntry:XENDISK 8.0.0 (0) (12.11.2014)
xen_platform_log xen platform: XENDISK|FdoCreate:FFFFFA800212CD40
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVBD|DispatchPnp:DeviceObject 0xFFFFFA8002131060 is not FDO (0x0000000000000000) or a PDO
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Version = 0
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Master = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: ScatterGather = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DemandMode = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: AutoInitialize = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma32BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: IgnoreCount = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma64BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: BusNumber = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaChannel = ffffffff
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: InterfaceType = Internal
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaWidth = 8Bits
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaSpeed = Compatible
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: MaximumLength = 000b0000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaPort = ffffffff
xen_platform_log xen platform: XENBUS|DmaGetAdapter: no interception
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: EVTCHN_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: GNTTAB_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: DEBUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VBD: EMULATED_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENFILT|PdoQueryInterface: PCI\VEN_5853&DEV_0001&SUBSYS_00015853&REV_01\10: EMULATED_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVBD|__FdoSetDevicePowerState:POWER D3 to D0
xen_platform_log xen platform: XENVBD|__FdoD3ToD0:D3->D0
xen_platform_log xen platform: XENVBD|__FdoIsPdoUnplugged:Target[0] : (vbd/768) Emulated NOT_PRESENT
xen_platform_log xen platform: XENVBD|PdoCreate:Target[0] : Creating (PV)
xen_platform_log xen platform: XENVBD|PdoSetDevicePowerState:Target[0] : POWER D3 to D0
xen_platform_log xen platform: XENVBD|PdoD3ToD0:Target[0] : D3->D0 (PV)
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : INITIALIZED ----> ENABLED
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state CLOSED
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|PdoReadInquiryData:Target[0] : Failed to get Page80 data
xen_platform_log xen platform: XENVBD|PdoReadInquiryData:Target[0] : Failed to get Page83 data
xen_platform_log xen platform: XENVBD|PdoUpdateInquiryData:Target[0] : VDI-UUID = {00000000-0000-0000-0000-000000000000}
xen_platform_log xen platform: XENVBD|FrontendPrepare:Target[0] : BackendId 0 (/local/domain/0/backend/qdisk/2/768)
xen_platform_log xen platform: XENVBD|FrontendReadFeatures:Target[0] : Features: PERSISTENT 
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state PREPARED
xen_platform_log xen platform: XENBUS|RangeSetPop: fail1 (c000009a)
xen_platform_log xen platform: GNTTAB: MAP XENMAPSPACE_grant_table[0] @ 00000000.f8001000
xen_platform_log xen platform: XENBUS|GnttabExpand: added references [00000009 - 000001ff]
xen_platform_log xen platform: XENVBD|__ReadDiskInfo:Target[0] : 102400000 sectors of 512 bytes (512)
xen_platform_log xen platform: XENVBD|__ReadDiskInfo:Target[0] : 48 GB (00000000) 
xen_platform_log xen platform: XENVBD|FrontendReadDiskInfo:Target[0] : Features: FLUSH DISCARD 
xen_platform_log xen platform: XENVBD|FrontendReadDiskInfo:Target[0] : DISCARD 0/0
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state CONNECTED
xen_platform_log xen platform: XENVBD|__FrontendSetState:Target[0] : in state ENABLED
xen_platform_log xen platform: XENVBD|PdoCreate:Target[0] : Created (PV)
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread ===>
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread : Target[0] = 0xFFFFFA8002122C70 (present)
xen_platform_log xen platform: XENVBD|FdoLogTargets:ScanThread <===
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENVBD|__HandlePage83:Target[0] : INQUIRY Using Fake Page83 Data
xen_platform_log xen platform: XENVBD|__HandlePage80:Target[0] : INQUIRY Using Fake Page80 Data
xen_platform_log xen platform: XENDISK|PdoCreate:FFFFFA8002295740
xen_platform_log xen platform: XENVBD|PdoSetDeviceObject:Target[0] : Setting DeviceObject = 0xFFFFFA8002295060
xen_platform_log xen platform: XENVBD|FdoMapDeviceObjectToPdo:0xFFFFFA8002295060 --> Target 0 (000000)
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 13:QUERY_ID -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 15:QUERY_BUS_INFORMATION -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 19:UNKNOWN -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 18:UNKNOWN -> c00000bb
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 0d:FILTER_RESOURCE_REQUIREMENTS -> c00000bb
xen_platform_log xen platform: XENVBD|PdoSetDevicePnpState:Target[0] : PNP Present to Started
xen_platform_log xen platform: XENVBD|PdoDispatchPnp:Target[0] : 07:QUERY_DEVICE_RELATIONS -> c00000bb
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENVIF|DriverEntry: XENVIF 8.0.0 (0) (24.09.2014)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: DEBUG_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: EVTCHN_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: RANGE_SET_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: CACHE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: VIF: GNTTAB_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENVIF|FdoCreate: FFFFFA800288DD40 (XS0001 XENVIF)
xen_platform_log xen platform: XENIFACE|DriverEntry: 8.0.0.0 (8/10/2014)
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423D5B0 FFFFFA80028A1D90
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423C630 FFFFFA80028A1DA0
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: SUSPEND_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: SHARED_INFO_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|PdoQueryInterface: IFACE: STORE_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENIFACE|FdoInitialiseXSRegistryEntries: no such xenstore key
xen_platform_log xen platform: XENIFACE|FdoInitialiseXSRegistryEntries: Failed to initialise registry (c0000022)
xen_platform_log xen platform: XENIFACE|ThreadCreate: Create thread FFFFF8800423D08C FFFFFA80028A1FB0
xen_platform_log xen platform: XENIFACE|FdoCreate: FFFFFA80028A1040 (IFACE)
xen_platform_log xen platform: XENBUS|RangeSetPop: fail1 (c000009a)
xen_platform_log xen platform: GNTTAB: MAP XENMAPSPACE_grant_table[1] @ 00000000.f8002000
xen_platform_log xen platform: XENBUS|GnttabExpand: added references [00000200 - 000003ff]
xen_platform_log xen platform: XENVIF|__PdoSetPermanentAddress: 0 00:16:3E:3E:00:77
xen_platform_log xen platform: XENVIF|__PdoSetContainerID: 0 {98381abd-649b-5822-b5c8-1de77941b503}
xen_platform_log xen platform: XENVIF|PdoCreate: FFFFFA8002FC71D0 (0 00000001)
xen_platform_log xen platform: XENNET|DriverEntry: XENNET 8.0.0 (0) (12.11.2014)
xen_platform_log xen platform: XENIFACE|WmiInit: DRV: XenIface WMI Initialisation
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:NotifyUnicastIpAddressChange (00F9) @ FFFFF880015DB850
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:GetUnicastIpAddressTable (0044) @ FFFFF880015DB900
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:FreeMibTable (0022) @ FFFFF880015C3FD0
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:CancelMibChangeNotify2 (0000) @ FFFFF880015D0D30
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:GetIfTable2 (0035) @ FFFFF880015D7270
xen_platform_log xen platform: XENVIF|LinkGetRoutineAddress: netio.sys:FreeMibTable (0022) @ FFFFF880015C3FD0
xen_platform_log xen platform: XENVIF|PdoQueryInterface: 0: VIF_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.IpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Receive.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Receive.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Receive.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.IpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv4Transmit.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Transmit.TcpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: Checksum.IPv6Transmit.UdpChecksum ON
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: LsoV2.IPv4.MaxOffLoadSize = 65201
xen_platform_log xen platform: XENNET|AdapterSetOffloadAttributes: LsoV2.IPv6.MaxOffLoadSize = 65201
xen_platform_log xen platform: XENVIF|PdoQueryInterface: 0: BUS_INTERFACE (VERSION 1)
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Version = 2
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Master = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: ScatterGather = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DemandMode = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: AutoInitialize = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma32BitAddresses = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: IgnoreCount = FALSE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: Dma64BitAddresses = TRUE
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: BusNumber = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaChannel = 00000000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: InterfaceType = Internal
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaWidth = 8Bits
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaSpeed = Compatible
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: MaximumLength = 00020000
xen_platform_log xen platform: XENBUS|DmaDumpDeviceDescription: DmaPort = 00000000
xen_platform_log xen platform: XENBUS|DmaGetAdapter: no interception
xen_platform_log xen platform: XENNET|AdapterMediaStateChange: LINK: UP: SPEED=1000000000 DUPLEX=FULL
xen_platform_log xen platform: XENNET|AdapterMediaStateChange: LINK: UP: SPEED=1000000000 DUPLEX=FULL
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER NOT_PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : NOT_DUMP NOT_HIBER PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENVBD|FrontendWriteUsage:Target[0] : DUMP NOT_HIBER PAGE
xen_platform_log xen platform: XENVBD|FdoDispatchPnp:14:QUERY_PNP_DEVICE_STATE -> c00000bb
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
xen_platform_log xen platform: XENBUS|FdoQueryPnpDeviceState: XS0001 XENBUS: not disableable
main_channel_handle_parsed: agent start
main_channel_handle_parsed: agent start
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Guest agent lite main loop starting
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Set time to XenTime
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: hosttimeIsUTC: Open Registry Key
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Time is now  2014.11.14 15:23:39.612
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Set time to 2014.11.14 15:23:39.475
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to add feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Establish watch control/shutdown
xen_platform_log xen platform: XENIFACE|StartWatch: Start Watch FFFFFA8003610C60
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to advertise features
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:MethodExec Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SessionStart Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SetVValue Failed
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: WmiSessionSetEntry:SetVPath Failed 
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Failed to advertise shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: About to kick xapi 
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent going to sleep
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent woke up for 3
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Fire 000000000024EC10
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: fire feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: Check if we need to shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: No need to shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: fired feature shutdown
xen_platform_log xen platform: XENIFACE|SessionExecuteLog: USER: win agent going to sleep
xen_platform_log xen platform: SUSPEND: ====>
xen_platform_log xen platform: SUSPEND: SCHEDOP_shutdown:SHUTDOWN_suspend ====>
qemu: terminating on signal 1 from pid 5818
red_channel_client_disconnect_dummy: rcc=0x7f756b1fe800 (channel=0x7f756b2c2330 type=5 id=0)
snd_channel_put: SndChannel=0x7f756b4286c0 freed
red_channel_client_disconnect_dummy: rcc=0x7f756b533020 (channel=0x7f756b2c2560 type=6 id=0)
snd_channel_put: SndChannel=0x7f756b5227e0 freed

--------------080400030902010507010701
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Fri Nov 14 16:15:13 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 16:15: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 1XpJWi-0000j4-U8; Fri, 14 Nov 2014 16:15:12 +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 1XpJWh-0000iz-7x
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 16:15:11 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	F2/B6-27785-E8A26645; Fri, 14 Nov 2014 16:15:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415981708!9306850!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31504 invoked from network); 14 Nov 2014 16:15:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 16:15:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,386,1413244800"; d="scan'208";a="26857987"
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: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ///y4ICAAanfAIAAE64g
Date: Fri, 14 Nov 2014 16:15:06 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz> <5466279C.207@m2r.biz>
In-Reply-To: <5466279C.207@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
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 14 November 2014 16:03
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore with
> new build of win pv drivers
> 
> Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> > Il 13/11/2014 15:26, Paul Durrant ha scritto:
> >>> -----Original Message-----
> >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> >>> Sent: 13 November 2014 14:20
> >>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
> >>> with new
> >>> build of win pv drivers
> >>>
> >>> I did a new build of winpv drivers and tested on one windows 7 64 bit
> >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with
> vcpu
> >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> >>> from spice git:
> >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> >>>
> >>> After restore windows showed blue screen with stop 1e, I open the
> dump
> >>> with "BlueScreenView" and showed that cause is xennet driver.
> >>> I attached the dump, if you need more informations/tests tell me and
> >>> I'll post them.
> >>>
> >> I've been testing with win7 32-bit and seen no problems. The minidump
> >> doesn't tell me much unfortunately do you have a full dump, plus the
> >> QEMU log?
> >>
> >>    Paul
> >
> > Thanks for reply.
> > qemu log was without errors or warning related, I changed windows
> > option for full memory dump and enable qemu trace of xen and retried
> > to reproduce the problem but this time after restore on same domU not
> > had the blue screen.
> 
> Blue screen re-happen, in attachment qemu logs (before and after
> restore) with xen trace.
> Also memory.dmp full this time but there is a problem, is 1,87 gb and my
> connection is max 256kbps of upload :(
> If is really needed tell me and I'll try to load it in my webserver
> tomorrow.
> 

I'll try to repro. You're crash happened very early in resume. Is your xenbus driver the built from tip?

  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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 14 16:15:13 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 16:15: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 1XpJWi-0000j4-U8; Fri, 14 Nov 2014 16:15:12 +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 1XpJWh-0000iz-7x
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 16:15:11 +0000
Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id
	F2/B6-27785-E8A26645; Fri, 14 Nov 2014 16:15:10 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1415981708!9306850!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31504 invoked from network); 14 Nov 2014 16:15:09 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 16:15:09 -0000
X-IronPort-AV: E=Sophos;i="5.07,386,1413244800"; d="scan'208";a="26857987"
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: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ///y4ICAAanfAIAAE64g
Date: Fri, 14 Nov 2014 16:15:06 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz> <5466279C.207@m2r.biz>
In-Reply-To: <5466279C.207@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
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 14 November 2014 16:03
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore with
> new build of win pv drivers
> 
> Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> > Il 13/11/2014 15:26, Paul Durrant ha scritto:
> >>> -----Original Message-----
> >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> >>> Sent: 13 November 2014 14:20
> >>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
> >>> with new
> >>> build of win pv drivers
> >>>
> >>> I did a new build of winpv drivers and tested on one windows 7 64 bit
> >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with
> vcpu
> >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> >>> from spice git:
> >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> >>>
> >>> After restore windows showed blue screen with stop 1e, I open the
> dump
> >>> with "BlueScreenView" and showed that cause is xennet driver.
> >>> I attached the dump, if you need more informations/tests tell me and
> >>> I'll post them.
> >>>
> >> I've been testing with win7 32-bit and seen no problems. The minidump
> >> doesn't tell me much unfortunately do you have a full dump, plus the
> >> QEMU log?
> >>
> >>    Paul
> >
> > Thanks for reply.
> > qemu log was without errors or warning related, I changed windows
> > option for full memory dump and enable qemu trace of xen and retried
> > to reproduce the problem but this time after restore on same domU not
> > had the blue screen.
> 
> Blue screen re-happen, in attachment qemu logs (before and after
> restore) with xen trace.
> Also memory.dmp full this time but there is a problem, is 1,87 gb and my
> connection is max 256kbps of upload :(
> If is really needed tell me and I'll try to load it in my webserver
> tomorrow.
> 

I'll try to repro. You're crash happened very early in resume. Is your xenbus driver the built from tip?

  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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 14 17:54:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 17:54: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 1XpL5F-0000LS-1r; Fri, 14 Nov 2014 17:54:57 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XpL5D-0000LN-BT
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 17:54:55 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	10/55-02576-EE146645; Fri, 14 Nov 2014 17:54:54 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-27.messagelabs.com!1415987692!8025673!1
X-Originating-IP: [209.85.216.173]
X-SpamReason: No, hits=2.1 required=7.0 tests=BIZ_TLD,HTML_30_40,
	HTML_MESSAGE,RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23687 invoked from network); 14 Nov 2014 17:54:52 -0000
Received: from mail-qc0-f173.google.com (HELO mail-qc0-f173.google.com)
	(209.85.216.173)
	by server-5.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 17:54:52 -0000
Received: by mail-qc0-f173.google.com with SMTP id x3so13198849qcv.18
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 14 Nov 2014 09:54:51 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
	d=1e100.net; s=20130820;
	h=x-gm-message-state:mime-version:in-reply-to:references:date
	:message-id:subject:from:to:cc:content-type;
	bh=MN3bvC7/QVYYMHRYIYp54axceMrawPF3mHHMksaT5Do=;
	b=My/2psI4Z8Dr5IynLnN0jypSIHf5jBn6sb6n3sHe79xuN8k9x22/yAoyA1lbxEHSL8
	HHf3aFvKGWJttO69QK4UqaMT0qM9OiJAW1giBaTg82SEQ6HAaBrBp41+BPbS6b074d1Z
	YzehBlvYgxwfzqhgLn2bWY+t4ZCEueF5iUcnurn1GmnFUd5jt11k8lp0sVm4CU/i/+xD
	gteoR0G6YQwPHH5q0MORullDewtLBf6FbdXryPzgd54+EeF6f4fM1rF2avE+ZcupYY52
	mtNZruqEwtQOWRUrNzukWzo1Gb6bDHPft4XbbOCMYHkuix1DdylFY5G3+rq8TkPeVLWi
	DcpA==
X-Gm-Message-State: ALoCoQl2SqXi3PltDCTwZGlIU0fIoXAmsHVdL7rdzXl7A8CsdVfYO/ktv6D0sgp+vJmjMC4H19bl
MIME-Version: 1.0
X-Received: by 10.229.105.196 with SMTP id u4mr12971358qco.27.1415987691732;
	Fri, 14 Nov 2014 09:54:51 -0800 (PST)
Received: by 10.96.151.227 with HTTP; Fri, 14 Nov 2014 09:54:51 -0800 (PST)
X-Originating-IP: [79.7.81.159]
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz> <5466279C.207@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
Date: Fri, 14 Nov 2014 18:54:51 +0100
Message-ID: <CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
From: Fabio Fantoni <fabio.fantoni@m2r.biz>
To: Paul Durrant <Paul.Durrant@citrix.com>
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: multipart/mixed; boundary="===============4068870183663961552=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============4068870183663961552==
Content-Type: multipart/alternative; boundary=001a113346045f5f7d0507d553e6

--001a113346045f5f7d0507d553e6
Content-Type: text/plain; charset=UTF-8

2014-11-14 17:15 GMT+01:00 Paul Durrant <Paul.Durrant@citrix.com>:

> > -----Original Message-----
> > From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> > Sent: 14 November 2014 16:03
> > To: Paul Durrant; win-pv-devel@lists.xenproject.org
> > Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore with
> > new build of win pv drivers
> >
> > Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> > > Il 13/11/2014 15:26, Paul Durrant ha scritto:
> > >>> -----Original Message-----
> > >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> > >>> Sent: 13 November 2014 14:20
> > >>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> > >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
> > >>> with new
> > >>> build of win pv drivers
> > >>>
> > >>> I did a new build of winpv drivers and tested on one windows 7 64 bit
> > >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with
> > vcpu
> > >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> > >>> from spice git:
> > >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> > >>>
> > >>> After restore windows showed blue screen with stop 1e, I open the
> > dump
> > >>> with "BlueScreenView" and showed that cause is xennet driver.
> > >>> I attached the dump, if you need more informations/tests tell me and
> > >>> I'll post them.
> > >>>
> > >> I've been testing with win7 32-bit and seen no problems. The minidump
> > >> doesn't tell me much unfortunately do you have a full dump, plus the
> > >> QEMU log?
> > >>
> > >>    Paul
> > >
> > > Thanks for reply.
> > > qemu log was without errors or warning related, I changed windows
> > > option for full memory dump and enable qemu trace of xen and retried
> > > to reproduce the problem but this time after restore on same domU not
> > > had the blue screen.
> >
> > Blue screen re-happen, in attachment qemu logs (before and after
> > restore) with xen trace.
> > Also memory.dmp full this time but there is a problem, is 1,87 gb and my
> > connection is max 256kbps of upload :(
> > If is really needed tell me and I'll try to load it in my webserver
> > tomorrow.
> >
>
> I'll try to repro. You're crash happened very early in resume. Is your
> xenbus driver the built from tip?
>

Yes I updated all to latest git in http://xenbits.xen.org/gitweb/?o=age,
all except xeniface was updated if I remember good.
Was happen 2 time on total of 5 save/restore I tried.
Latest test was with qemu upstream updated including also the new 2 xen
bugfix http://git.qemu.org/qemu.git (commit
4e70f9271dabc58fbf14680843bfac510c193152).


>
>   Paul
>
> > >
> > >>
> > >>> Thanks for any reply and sorry for my bad english.
> > >
> >
>
>

--001a113346045f5f7d0507d553e6
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">2014-11-14 17:15 GMT+01:00 Paul Durrant <span dir=3D"ltr">=
&lt;<a href=3D"mailto:Paul.Durrant@citrix.com" target=3D"_blank">Paul.Durra=
nt@citrix.com</a>&gt;</span>:<br><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=
=3D"">&gt; -----Original Message-----<br>
&gt; From: Fabio Fantoni [mailto:<a href=3D"mailto:fabio.fantoni@m2r.biz">f=
abio.fantoni@m2r.biz</a>]<br>
</span><div><div class=3D"h5">&gt; Sent: 14 November 2014 16:03<br>
&gt; To: Paul Durrant; <a href=3D"mailto:win-pv-devel@lists.xenproject.org"=
>win-pv-devel@lists.xenproject.org</a><br>
&gt; Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore w=
ith<br>
&gt; new build of win pv drivers<br>
&gt;<br>
&gt; Il 13/11/2014 15:38, Fabio Fantoni ha scritto:<br>
&gt; &gt; Il 13/11/2014 15:26, Paul Durrant ha scritto:<br>
&gt; &gt;&gt;&gt; -----Original Message-----<br>
&gt; &gt;&gt;&gt; From: Fabio Fantoni [mailto:<a href=3D"mailto:fabio.fanto=
ni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
&gt; &gt;&gt;&gt; Sent: 13 November 2014 14:20<br>
&gt; &gt;&gt;&gt; To: <a href=3D"mailto:win-pv-devel@lists.xenproject.org">=
win-pv-devel@lists.xenproject.org</a>; Paul Durrant<br>
&gt; &gt;&gt;&gt; Subject: Windows 7 64 bit blue screen with stop 1e after =
restore<br>
&gt; &gt;&gt;&gt; with new<br>
&gt; &gt;&gt;&gt; build of win pv drivers<br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt;&gt; I did a new build of winpv drivers and tested on one wind=
ows 7 64 bit<br>
&gt; &gt;&gt;&gt; domU, dom0 xen-unstable with &quot;x86/hvm: Extend HVM cp=
uid leaf with<br>
&gt; vcpu<br>
&gt; &gt;&gt;&gt; id&quot; and &quot;x86/hvm: Add per-vcpu evtchn upcalls&q=
uot; patches, and qemu 2.2<br>
&gt; &gt;&gt;&gt; from spice git:<br>
&gt; &gt;&gt;&gt; <a href=3D"https://github.com/Fantu/Xen/commits/rebase/m2=
r-staging" target=3D"_blank">https://github.com/Fantu/Xen/commits/rebase/m2=
r-staging</a><br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt;&gt; After restore windows showed blue screen with stop 1e, I =
open the<br>
&gt; dump<br>
&gt; &gt;&gt;&gt; with &quot;BlueScreenView&quot; and showed that cause is =
xennet driver.<br>
&gt; &gt;&gt;&gt; I attached the dump, if you need more informations/tests =
tell me and<br>
&gt; &gt;&gt;&gt; I&#39;ll post them.<br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt; I&#39;ve been testing with win7 32-bit and seen no problems. =
The minidump<br>
&gt; &gt;&gt; doesn&#39;t tell me much unfortunately do you have a full dum=
p, plus the<br>
&gt; &gt;&gt; QEMU log?<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt;=C2=A0 =C2=A0 Paul<br>
&gt; &gt;<br>
&gt; &gt; Thanks for reply.<br>
&gt; &gt; qemu log was without errors or warning related, I changed windows=
<br>
&gt; &gt; option for full memory dump and enable qemu trace of xen and retr=
ied<br>
&gt; &gt; to reproduce the problem but this time after restore on same domU=
 not<br>
&gt; &gt; had the blue screen.<br>
&gt;<br>
&gt; Blue screen re-happen, in attachment qemu logs (before and after<br>
&gt; restore) with xen trace.<br>
&gt; Also memory.dmp full this time but there is a problem, is 1,87 gb and =
my<br>
&gt; connection is max 256kbps of upload :(<br>
&gt; If is really needed tell me and I&#39;ll try to load it in my webserve=
r<br>
&gt; tomorrow.<br>
&gt;<br>
<br>
</div></div>I&#39;ll try to repro. You&#39;re crash happened very early in =
resume. Is your xenbus driver the built from tip?<br></blockquote><div><br>=
</div><div>Yes I updated all to latest git in <a href=3D"http://xenbits.xen=
.org/gitweb/?o=3Dage">http://xenbits.xen.org/gitweb/?o=3Dage</a>, all excep=
t xeniface was updated if I remember good.<br></div><div>Was happen 2 time =
on total of 5 save/restore I tried.<br></div><div>Latest test was with qemu=
 upstream updated including also the new 2 xen bugfix <a href=3D"http://git=
.qemu.org/qemu.git">http://git.qemu.org/qemu.git</a> (commit 4e70f9271dabc5=
8fbf14680843bfac510c193152).<br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex">
<span class=3D""><font color=3D"#888888"><br>
=C2=A0 Paul<br>
</font></span><div class=3D""><div class=3D"h5"><br>
&gt; &gt;<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt;&gt; Thanks for any reply and sorry for my bad english.<br>
&gt; &gt;<br>
&gt;<br>
<br>
</div></div></blockquote></div><br></div></div>

--001a113346045f5f7d0507d553e6--


--===============4068870183663961552==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Fri Nov 14 17:54:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 14 Nov 2014 17:54: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 1XpL5F-0000LS-1r; Fri, 14 Nov 2014 17:54:57 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XpL5D-0000LN-BT
	for win-pv-devel@lists.xenproject.org; Fri, 14 Nov 2014 17:54:55 +0000
Received: from [193.109.254.147] by server-16.bemta-14.messagelabs.com id
	10/55-02576-EE146645; Fri, 14 Nov 2014 17:54:54 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-27.messagelabs.com!1415987692!8025673!1
X-Originating-IP: [209.85.216.173]
X-SpamReason: No, hits=2.1 required=7.0 tests=BIZ_TLD,HTML_30_40,
	HTML_MESSAGE,RCVD_BY_IP
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23687 invoked from network); 14 Nov 2014 17:54:52 -0000
Received: from mail-qc0-f173.google.com (HELO mail-qc0-f173.google.com)
	(209.85.216.173)
	by server-5.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	14 Nov 2014 17:54:52 -0000
Received: by mail-qc0-f173.google.com with SMTP id x3so13198849qcv.18
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 14 Nov 2014 09:54:51 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
	d=1e100.net; s=20130820;
	h=x-gm-message-state:mime-version:in-reply-to:references:date
	:message-id:subject:from:to:cc:content-type;
	bh=MN3bvC7/QVYYMHRYIYp54axceMrawPF3mHHMksaT5Do=;
	b=My/2psI4Z8Dr5IynLnN0jypSIHf5jBn6sb6n3sHe79xuN8k9x22/yAoyA1lbxEHSL8
	HHf3aFvKGWJttO69QK4UqaMT0qM9OiJAW1giBaTg82SEQ6HAaBrBp41+BPbS6b074d1Z
	YzehBlvYgxwfzqhgLn2bWY+t4ZCEueF5iUcnurn1GmnFUd5jt11k8lp0sVm4CU/i/+xD
	gteoR0G6YQwPHH5q0MORullDewtLBf6FbdXryPzgd54+EeF6f4fM1rF2avE+ZcupYY52
	mtNZruqEwtQOWRUrNzukWzo1Gb6bDHPft4XbbOCMYHkuix1DdylFY5G3+rq8TkPeVLWi
	DcpA==
X-Gm-Message-State: ALoCoQl2SqXi3PltDCTwZGlIU0fIoXAmsHVdL7rdzXl7A8CsdVfYO/ktv6D0sgp+vJmjMC4H19bl
MIME-Version: 1.0
X-Received: by 10.229.105.196 with SMTP id u4mr12971358qco.27.1415987691732;
	Fri, 14 Nov 2014 09:54:51 -0800 (PST)
Received: by 10.96.151.227 with HTTP; Fri, 14 Nov 2014 09:54:51 -0800 (PST)
X-Originating-IP: [79.7.81.159]
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz> <5466279C.207@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
Date: Fri, 14 Nov 2014 18:54:51 +0100
Message-ID: <CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
From: Fabio Fantoni <fabio.fantoni@m2r.biz>
To: Paul Durrant <Paul.Durrant@citrix.com>
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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: multipart/mixed; boundary="===============4068870183663961552=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

--===============4068870183663961552==
Content-Type: multipart/alternative; boundary=001a113346045f5f7d0507d553e6

--001a113346045f5f7d0507d553e6
Content-Type: text/plain; charset=UTF-8

2014-11-14 17:15 GMT+01:00 Paul Durrant <Paul.Durrant@citrix.com>:

> > -----Original Message-----
> > From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> > Sent: 14 November 2014 16:03
> > To: Paul Durrant; win-pv-devel@lists.xenproject.org
> > Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore with
> > new build of win pv drivers
> >
> > Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
> > > Il 13/11/2014 15:26, Paul Durrant ha scritto:
> > >>> -----Original Message-----
> > >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> > >>> Sent: 13 November 2014 14:20
> > >>> To: win-pv-devel@lists.xenproject.org; Paul Durrant
> > >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
> > >>> with new
> > >>> build of win pv drivers
> > >>>
> > >>> I did a new build of winpv drivers and tested on one windows 7 64 bit
> > >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf with
> > vcpu
> > >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and qemu 2.2
> > >>> from spice git:
> > >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
> > >>>
> > >>> After restore windows showed blue screen with stop 1e, I open the
> > dump
> > >>> with "BlueScreenView" and showed that cause is xennet driver.
> > >>> I attached the dump, if you need more informations/tests tell me and
> > >>> I'll post them.
> > >>>
> > >> I've been testing with win7 32-bit and seen no problems. The minidump
> > >> doesn't tell me much unfortunately do you have a full dump, plus the
> > >> QEMU log?
> > >>
> > >>    Paul
> > >
> > > Thanks for reply.
> > > qemu log was without errors or warning related, I changed windows
> > > option for full memory dump and enable qemu trace of xen and retried
> > > to reproduce the problem but this time after restore on same domU not
> > > had the blue screen.
> >
> > Blue screen re-happen, in attachment qemu logs (before and after
> > restore) with xen trace.
> > Also memory.dmp full this time but there is a problem, is 1,87 gb and my
> > connection is max 256kbps of upload :(
> > If is really needed tell me and I'll try to load it in my webserver
> > tomorrow.
> >
>
> I'll try to repro. You're crash happened very early in resume. Is your
> xenbus driver the built from tip?
>

Yes I updated all to latest git in http://xenbits.xen.org/gitweb/?o=age,
all except xeniface was updated if I remember good.
Was happen 2 time on total of 5 save/restore I tried.
Latest test was with qemu upstream updated including also the new 2 xen
bugfix http://git.qemu.org/qemu.git (commit
4e70f9271dabc58fbf14680843bfac510c193152).


>
>   Paul
>
> > >
> > >>
> > >>> Thanks for any reply and sorry for my bad english.
> > >
> >
>
>

--001a113346045f5f7d0507d553e6
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">2014-11-14 17:15 GMT+01:00 Paul Durrant <span dir=3D"ltr">=
&lt;<a href=3D"mailto:Paul.Durrant@citrix.com" target=3D"_blank">Paul.Durra=
nt@citrix.com</a>&gt;</span>:<br><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=
=3D"">&gt; -----Original Message-----<br>
&gt; From: Fabio Fantoni [mailto:<a href=3D"mailto:fabio.fantoni@m2r.biz">f=
abio.fantoni@m2r.biz</a>]<br>
</span><div><div class=3D"h5">&gt; Sent: 14 November 2014 16:03<br>
&gt; To: Paul Durrant; <a href=3D"mailto:win-pv-devel@lists.xenproject.org"=
>win-pv-devel@lists.xenproject.org</a><br>
&gt; Subject: Re: Windows 7 64 bit blue screen with stop 1e after restore w=
ith<br>
&gt; new build of win pv drivers<br>
&gt;<br>
&gt; Il 13/11/2014 15:38, Fabio Fantoni ha scritto:<br>
&gt; &gt; Il 13/11/2014 15:26, Paul Durrant ha scritto:<br>
&gt; &gt;&gt;&gt; -----Original Message-----<br>
&gt; &gt;&gt;&gt; From: Fabio Fantoni [mailto:<a href=3D"mailto:fabio.fanto=
ni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
&gt; &gt;&gt;&gt; Sent: 13 November 2014 14:20<br>
&gt; &gt;&gt;&gt; To: <a href=3D"mailto:win-pv-devel@lists.xenproject.org">=
win-pv-devel@lists.xenproject.org</a>; Paul Durrant<br>
&gt; &gt;&gt;&gt; Subject: Windows 7 64 bit blue screen with stop 1e after =
restore<br>
&gt; &gt;&gt;&gt; with new<br>
&gt; &gt;&gt;&gt; build of win pv drivers<br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt;&gt; I did a new build of winpv drivers and tested on one wind=
ows 7 64 bit<br>
&gt; &gt;&gt;&gt; domU, dom0 xen-unstable with &quot;x86/hvm: Extend HVM cp=
uid leaf with<br>
&gt; vcpu<br>
&gt; &gt;&gt;&gt; id&quot; and &quot;x86/hvm: Add per-vcpu evtchn upcalls&q=
uot; patches, and qemu 2.2<br>
&gt; &gt;&gt;&gt; from spice git:<br>
&gt; &gt;&gt;&gt; <a href=3D"https://github.com/Fantu/Xen/commits/rebase/m2=
r-staging" target=3D"_blank">https://github.com/Fantu/Xen/commits/rebase/m2=
r-staging</a><br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt;&gt; After restore windows showed blue screen with stop 1e, I =
open the<br>
&gt; dump<br>
&gt; &gt;&gt;&gt; with &quot;BlueScreenView&quot; and showed that cause is =
xennet driver.<br>
&gt; &gt;&gt;&gt; I attached the dump, if you need more informations/tests =
tell me and<br>
&gt; &gt;&gt;&gt; I&#39;ll post them.<br>
&gt; &gt;&gt;&gt;<br>
&gt; &gt;&gt; I&#39;ve been testing with win7 32-bit and seen no problems. =
The minidump<br>
&gt; &gt;&gt; doesn&#39;t tell me much unfortunately do you have a full dum=
p, plus the<br>
&gt; &gt;&gt; QEMU log?<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt;=C2=A0 =C2=A0 Paul<br>
&gt; &gt;<br>
&gt; &gt; Thanks for reply.<br>
&gt; &gt; qemu log was without errors or warning related, I changed windows=
<br>
&gt; &gt; option for full memory dump and enable qemu trace of xen and retr=
ied<br>
&gt; &gt; to reproduce the problem but this time after restore on same domU=
 not<br>
&gt; &gt; had the blue screen.<br>
&gt;<br>
&gt; Blue screen re-happen, in attachment qemu logs (before and after<br>
&gt; restore) with xen trace.<br>
&gt; Also memory.dmp full this time but there is a problem, is 1,87 gb and =
my<br>
&gt; connection is max 256kbps of upload :(<br>
&gt; If is really needed tell me and I&#39;ll try to load it in my webserve=
r<br>
&gt; tomorrow.<br>
&gt;<br>
<br>
</div></div>I&#39;ll try to repro. You&#39;re crash happened very early in =
resume. Is your xenbus driver the built from tip?<br></blockquote><div><br>=
</div><div>Yes I updated all to latest git in <a href=3D"http://xenbits.xen=
.org/gitweb/?o=3Dage">http://xenbits.xen.org/gitweb/?o=3Dage</a>, all excep=
t xeniface was updated if I remember good.<br></div><div>Was happen 2 time =
on total of 5 save/restore I tried.<br></div><div>Latest test was with qemu=
 upstream updated including also the new 2 xen bugfix <a href=3D"http://git=
.qemu.org/qemu.git">http://git.qemu.org/qemu.git</a> (commit 4e70f9271dabc5=
8fbf14680843bfac510c193152).<br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex">
<span class=3D""><font color=3D"#888888"><br>
=C2=A0 Paul<br>
</font></span><div class=3D""><div class=3D"h5"><br>
&gt; &gt;<br>
&gt; &gt;&gt;<br>
&gt; &gt;&gt;&gt; Thanks for any reply and sorry for my bad english.<br>
&gt; &gt;<br>
&gt;<br>
<br>
</div></div></blockquote></div><br></div></div>

--001a113346045f5f7d0507d553e6--


--===============4068870183663961552==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Mon Nov 17 13:23:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:23: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 1XqMHI-0003Jw-EP; Mon, 17 Nov 2014 13:23:36 +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 1XqMHG-0003Jr-89
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:23:35 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	09/A7-25714-5D6F9645; Mon, 17 Nov 2014 13:23:33 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1416230606!6378852!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30465 invoked from network); 17 Nov 2014 13:23:26 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:23:26 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26900491"
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: [PATCH 1/4] Refactor for maintainability/coding style
Thread-Index: AQHP/pcqptJ0/lgdsE6oYfEVKXByPJxk1ZVg
Date: Mon, 17 Nov 2014 13:23:24 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115364D@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-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/4] Refactor for maintainability/coding
	style
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 1/4] Refactor for maintainability/coding style
> 
> Removes common headers and the disabling of warnings via #pragmas
> Fits code into driver.c (DriverEntry/Dispatch overrides), adapter.c
> (NDIS miniport). Resolves differences in receiver/transmitter
> implementations.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

This patch is not really reviewable, given its size, but I think it is worth taking the risk. I know that you need to re-factor a bit though due to WHQL failure (access of registry functions) so I'll wait until v2 is available (and passing WHQL) and the review the code after applying the patch.

  Paul

> ---
>  src/xennet/adapter.c         | 3833 +++++++++++++++++++-----------------------
>  src/xennet/adapter.h         |  154 +-
>  src/xennet/common.h          |   36 -
>  src/xennet/driver.c          |  550 ++++++
>  src/xennet/main.c            |  361 ----
>  src/xennet/miniport.c        |  297 ----
>  src/xennet/project.h         |   66 -
>  src/xennet/receiver.c        |  393 +++--
>  src/xennet/receiver.h        |   59 +-
>  src/xennet/std.h             |   45 -
>  src/xennet/transmitter.c     |  330 ++--
>  src/xennet/transmitter.h     |   61 +-
>  vs2012/xennet/xennet.vcxproj |    3 +-
>  vs2013/xennet/xennet.vcxproj |    3 +-
>  14 files changed, 2770 insertions(+), 3421 deletions(-)
>  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/miniport.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..6b32d1a 100644
> --- a/src/xennet/adapter.c
> +++ b/src/xennet/adapter.c
> @@ -28,51 +28,44 @@
>   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   * SUCH DAMAGE.
>   */
> +#define INITGUID
> 
> +#include <ndis.h>
> +#include <ntstrsafe.h>
>  #include <version.h>
> -#include "common.h"
> 
> -#pragma warning(disable:4711)
> +#include "adapter.h"
> +#include "registry.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> 
> -//
> -// List of supported OIDs.
> -//
> +struct _XENNET_ADAPTER {
> +    XENVIF_VIF_INTERFACE        VifInterface;
> 
> -static NDIS_STATUS
> -AdapterSetRegistrationAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    BOOLEAN                     Enabled;
> +    ULONG                       MaximumFrameSize;
> +    ULONG                       CurrentLookahead;
> 
> -static NDIS_STATUS
> -AdapterSetGeneralAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    NDIS_HANDLE                 NdisHandle;
> +    NDIS_HANDLE                 NdisDmaHandle;
> +    NDIS_PNP_CAPABILITIES       Capabilities;
> +    NDIS_OFFLOAD                Offload;
> +    XENNET_PROPERTIES           Properties;
> 
> -static NDIS_STATUS
> -AdapterSetOffloadAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    PXENNET_RECEIVER            Receiver;
> +    PXENNET_TRANSMITTER         Transmitter;
> +};
> 
> -static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
> -static VOID
> -AdapterProcessSGList (
> -    IN PDEVICE_OBJECT       DeviceObject,
> -    IN PVOID                Reserved,
> -    IN PSCATTER_GATHER_LIST SGL,
> -    IN PVOID                Context
> -    );
> +#define XENNET_POOL_TAG         'tenX'
> 
> -static NDIS_STATUS
> -AdapterSetInformation (
> -    IN  PADAPTER            Adapter,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    );
> +#define XENNET_MEDIA_MAX_SPEED  1000000000ull
> 
> -static NDIS_STATUS
> -AdapterQueryInformation (
> -    IN  PADAPTER            Adapter,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    );
> +#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)
> 
>  static NDIS_OID XennetSupportedOids[] =
>  {
> @@ -129,31 +122,9 @@ 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)
> -
> -NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
> -{
> -    if (Adapter == NULL)
> -        return STATUS_INVALID_PARAMETER;
> -
> -    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof
> (ADAPTER), ' TEN');
> -    if (*Adapter == NULL)
> -        return STATUS_INSUFFICIENT_RESOURCES;
> -
> -    return STATUS_SUCCESS;
> -}
> -
> -//
> -// Scatter gather allocate handler callback.
> -// Should never get called.
> -//
>  __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
>  static VOID
> -AdapterAllocateComplete (
> +AdapterAllocateComplete(
>      IN NDIS_HANDLE              MiniportAdapterContext,
>      IN PVOID                    VirtualAddress,
>      IN PNDIS_PHYSICAL_ADDRESS   PhysicalAddress,
> @@ -168,139 +139,33 @@ 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;
>  }
> 
> +__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
>  static VOID
> -AdapterMediaStateChange(
> -    IN  PADAPTER                Adapter
> +AdapterProcessSGList(
> +    IN PDEVICE_OBJECT           DeviceObject,
> +    IN PVOID                    Reserved,
> +    IN PSCATTER_GATHER_LIST     SGL,
> +    IN PVOID                    Context
>      )
>  {
> -    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);
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +    UNREFERENCED_PARAMETER(Reserved);
> +    UNREFERENCED_PARAMETER(SGL);
> +    UNREFERENCED_PARAMETER(Context);
> 
> -    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
> +    ASSERT(FALSE);
>  }
> 
> -
> -//
> -// 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;
> +    PXENNET_ADAPTER                 Adapter = Context;
>      va_list                         Arguments;
> 
>      va_start(Arguments, Type);
> @@ -319,7 +184,7 @@ AdapterVifCallback(
> 
>          List = va_arg(Arguments, PLIST_ENTRY);
> 
> -        ReceiverReceivePackets(&Adapter->Receiver, List);
> +        ReceiverReceivePackets(Adapter->Receiver, List);
>          break;
>      }
>      case XENVIF_MAC_STATE_CHANGE: {
> @@ -331,39 +196,220 @@ AdapterVifCallback(
>      va_end(Arguments);
>  }
> 
> -NDIS_STATUS
> -AdapterGetAdvancedSettings(
> -    IN PADAPTER pAdapter
> +#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,
> +    IN  ULONG           Size,
> +    IN  BOOLEAN         Optional
>      )
>  {
> -    NDIS_CONFIGURATION_OBJECT configObject;
> -    NDIS_HANDLE hConfigurationHandle;
> -    NDIS_STRING ndisValue;
> -    PNDIS_CONFIGURATION_PARAMETER pNdisData;
> -    NDIS_STATUS ndisStatus;
> -    NTSTATUS status;
> +    UNICODE_STRING      Unicode;
> +    HANDLE              InterfacesKey;
> +    HANDLE              SubscriberKey;
> +    KEVENT              Event;
> +    IO_STATUS_BLOCK     StatusBlock;
> +    PIRP                Irp;
> +    PIO_STACK_LOCATION  StackLocation;
> +    NTSTATUS            status;
> +
> +    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));
> 
> -    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;
> +    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
> 
> -    ndisStatus = NdisOpenConfigurationEx(&configObject,
> &hConfigurationHandle);
> +    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));
> +
> +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
> +                                       DeviceObject,
> +                                       NULL,
> +                                       0,
> +                                       NULL,
> +                                       &Event,
> +                                       &StatusBlock);
> 
>      status = STATUS_UNSUCCESSFUL;
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +    if (Irp == NULL)
> +        goto fail4;
> +
> +    StackLocation = IoGetNextIrpStackLocation(Irp);
> +    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
> +
> +    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;
> +    }
> +
> +    if (!NT_SUCCESS(status)) {
> +        if (status == STATUS_NOT_SUPPORTED && Optional)
> +            goto done;
> +
> +        goto fail5;
> +    }
> +
> +    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);
> +
> +    return status;
> +}
> +
> +#define QUERY_INTERFACE(                                                                \
> +    _DeviceObject,                                                                      \
> +    _ProviderName,                                                                      \
> +    _InterfaceName,                                                                     \
> +    _Version,                                                                           \
> +    _Interface,                                                                         \
> +    _Size,                                                                              \
> +    _Optional)                                                                          \
> +    __QueryInterface((_DeviceObject),                                                   \
> +                     L ## #_ProviderName,                                               \
> +                     #_InterfaceName,                                                   \
> +                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ##
> _INTERFACE,      \
> +                     (_Version),                                                        \
> +                     (_Interface),                                                      \
> +                     (_Size),                                                           \
> +                     (_Optional))
> +
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetRegistrationAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs;
> +    NDIS_STATUS                                   status;
> +
> +    RtlZeroMemory(&Attribs,
> sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
> +    Attribs.Header.Type                 =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
> +    Attribs.Header.Size                 =
> sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
> +    Attribs.Header.Revision             =
> NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
> +    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;
> +
> +    status = NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
> +    return status;
> +}
> +
> +static FORCEINLINE NDIS_STATUS
> +AdapterGetAdvancedSettings(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_CONFIGURATION_OBJECT   Config;
> +    NDIS_HANDLE                 Handle;
> +    NDIS_STRING                 Value;
> +    PNDIS_CONFIGURATION_PARAMETER Data;
> +    NDIS_STATUS                 NdisStatus;
> +
> +    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
> +    Config.Header.Type      = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
> +    Config.Header.Size      =
> NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
> +    Config.Header.Revision  = NDIS_CONFIGURATION_OBJECT_REVISION_1;
> +    Config.NdisHandle       = Adapter->NdisHandle;
> +    Config.Flags            = 0;
> +
> +    NdisStatus = NdisOpenConfigurationEx(&Config, &Handle);
> +    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; \
> -        } \
> +#define read_property(_field, _name, _default_val)                                          \
> +    do {                                                                                    \
> +        RtlInitUnicodeString(&Value, _name);                                                \
> +        NdisReadConfiguration(&NdisStatus, &Data, Handle, &Value,
> NdisParameterInteger);    \
> +        if (NdisStatus == NDIS_STATUS_SUCCESS) {                                            \
> +            Adapter->Properties._field = Data->ParameterData.IntegerData;
> \
> +        } else {                                                                            \
> +            Adapter->Properties._field = _default_val;                                      \
> +        }                                                                                   \
>      } while (FALSE);
> 
>      read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
> @@ -377,465 +423,827 @@ AdapterGetAdvancedSettings(
>      read_property(lrov6, L"LROIPv6", 1);
>      read_property(need_csum_value, L"NeedChecksumValue", 1);
> 
> -    NdisCloseConfiguration(hConfigurationHandle);
> -
> +    NdisCloseConfiguration(Handle);
>      return NDIS_STATUS_SUCCESS;
> 
>  fail1:
> -    Error("fail1\n");
> -    return NDIS_STATUS_FAILURE;
> +    Error("fail1 (%08x)\n", NdisStatus);
> +    return NdisStatus;
>  }
> 
> -NDIS_STATUS
> -AdapterInitialize (
> -    IN  PADAPTER    Adapter,
> -    IN  NDIS_HANDLE AdapterHandle
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetGeneralAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
>      )
>  {
> -    NDIS_STATUS ndisStatus;
> -    NDIS_SG_DMA_DESCRIPTION DmaDescription;
> -    NTSTATUS status;
> -
> -    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
> -    if (!NT_SUCCESS(status))
> -        return NDIS_STATUS_FAILURE;
> +    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
> 
> -    Adapter->AcquiredInterfaces = TRUE;
> +    XENVIF_VIF(MacQueryMaximumFrameSize,
> +               &Adapter->VifInterface,
> +               (PULONG)&Adapter->MaximumFrameSize);
> 
> -    Trace("====>\n");
> +    RtlZeroMemory(&Attribs,
> sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
> +
> +    Attribs.Header.Type         =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
> +    Attribs.Header.Size         =
> sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
> +    Attribs.Header.Revision     =
> NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
> +    Attribs.MediaType               = XENNET_MEDIA_TYPE;
> +    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;
> +    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;
> +    Attribs.SupportedOidList        = XennetSupportedOids;
> +    Attribs.SupportedOidListLength  = sizeof(XennetSupportedOids);
> 
> -    Adapter->NdisAdapterHandle = AdapterHandle;
> +    XENVIF_VIF(MacQueryPermanentAddress,
> +               &Adapter->VifInterface,
> +               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
> +    XENVIF_VIF(MacQueryCurrentAddress,
> +               &Adapter->VifInterface,
> +               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
> 
> -    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
> +    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
> +}
> 
> -    Adapter->Transmitter =
> (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool,
> sizeof(TRANSMITTER), ' TEN');
> -    if (!Adapter->Transmitter) {
> -        ndisStatus = NDIS_STATUS_RESOURCES;
> -        goto exit;
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetOffloadAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
> +    NDIS_OFFLOAD                                Default;
> +    NDIS_OFFLOAD                                Supported;
> +
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> +    RxOptions->Value = 0;
> +    RxOptions->OffloadTagManipulation = 1;
> +
> +    if (Adapter->Properties.need_csum_value) {
> +        RxOptions->NeedChecksumValue = 1;
>      }
> -
> -    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
> -
> -    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (Adapter->Properties.lrov4) {
> +        RxOptions->OffloadIpVersion4LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
>      }
> -
> -    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (Adapter->Properties.lrov6) {
> +        RxOptions->OffloadIpVersion6LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
>      }
> +    XENVIF_VIF(ReceiverSetOffloadOptions,
> +               &Adapter->VifInterface,
> +               *RxOptions);
> 
> -    ndisStatus = AdapterGetAdvancedSettings(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> +    XENVIF_VIF(TransmitterQueryOffloadOptions,
> +               &Adapter->VifInterface,
> +               TxOptions);
> +
> +    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
> +    Supported.Header.Type       = NDIS_OBJECT_TYPE_OFFLOAD;
> +    Supported.Header.Size       = sizeof(NDIS_OFFLOAD);
> +    Supported.Header.Revision   = NDIS_OFFLOAD_REVISION_1;
> +
> +    Supported.Checksum.IPv4Receive.Encapsulation        =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv4Receive.IpChecksum           = 1;
> +    Supported.Checksum.IPv4Receive.IpOptionsSupported   = 1;
> +    Supported.Checksum.IPv4Receive.TcpChecksum          = 1;
> +    Supported.Checksum.IPv4Receive.TcpOptionsSupported  = 1;
> +    Supported.Checksum.IPv4Receive.UdpChecksum          = 1;
> +
> +    Supported.Checksum.IPv6Receive.Encapsulation        =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> +    Supported.Checksum.IPv6Receive.TcpChecksum          = 1;
> +    Supported.Checksum.IPv6Receive.TcpOptionsSupported  = 1;
> +    Supported.Checksum.IPv6Receive.UdpChecksum          = 1;
> +
> +    Supported.Checksum.IPv4Transmit.Encapsulation       =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
> +        Supported.Checksum.IPv4Transmit.IpChecksum          = 1;
> +        Supported.Checksum.IPv4Transmit.IpOptionsSupported  = 1;
>      }
> -
> -    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (TxOptions->OffloadIpVersion4TcpChecksum) {
> +        Supported.Checksum.IPv4Transmit.TcpChecksum         = 1;
> +        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4UdpChecksum) {
> +        Supported.Checksum.IPv4Transmit.UdpChecksum         = 1;
>      }
> 
> -    ndisStatus = AdapterSetGeneralAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    Supported.Checksum.IPv6Transmit.Encapsulation       =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> +    if (TxOptions->OffloadIpVersion6TcpChecksum) {
> +        Supported.Checksum.IPv6Transmit.TcpChecksum         = 1;
> +        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion6UdpChecksum) {
> +        Supported.Checksum.IPv6Transmit.UdpChecksum         = 1;
>      }
> 
> -    ndisStatus = AdapterSetOffloadAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (TxOptions->OffloadIpVersion4LargePacket) {
> +        XENVIF_VIF(TransmitterQueryLargePacketSize,
> +                   &Adapter->VifInterface,
> +                   4,
> +                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
> +        Supported.LsoV2.IPv4.Encapsulation              =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +        Supported.LsoV2.IPv4.MinSegmentCount            = 2;
>      }
> 
> -    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
> +    if (TxOptions->OffloadIpVersion6LargePacket) {
> +        XENVIF_VIF(TransmitterQueryLargePacketSize,
> +                   &Adapter->VifInterface,
> +                   6,
> +                   &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;
> +    }
> 
> -    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;
> +    Default = Supported;
> 
> -    ndisStatus = NdisMRegisterScatterGatherDma(Adapter-
> >NdisAdapterHandle,
> -                                               &DmaDescription,
> -                                               &Adapter->NdisDmaHandle);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        Adapter->NdisDmaHandle = NULL;
> +    if (!(Adapter->Properties.ipv4_csum & 2))
> +        Default.Checksum.IPv4Receive.IpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv4_csum & 2))
> +        Default.Checksum.IPv4Receive.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv4_csum & 2))
> +        Default.Checksum.IPv4Receive.UdpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv6_csum & 2))
> +        Default.Checksum.IPv6Receive.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv6_csum & 2))
> +        Default.Checksum.IPv6Receive.UdpChecksum = 0;
> +    if (!(Adapter->Properties.ipv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.IpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv6_csum & 1))
> +        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv6_csum & 1))
> +        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
> +    if (!(Adapter->Properties.lsov4)) {
> +        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
> +        Default.LsoV2.IPv4.MinSegmentCount = 0;
> +    }
> +    if (!(Adapter->Properties.lsov6)) {
> +        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
> +        Default.LsoV2.IPv6.MinSegmentCount = 0;
> +    }
> 
> -    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, &Default,
> sizeof(NDIS_OFFLOAD))) {
> +        Adapter->Offload = Default;
> +        //DISPLAY_OFFLOAD(Default);
>      }
> 
> -exit:
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        XENVIF_VIF(Release, &Adapter->VifInterface);
> +    RtlZeroMemory(&Attribs, sizeof(Attribs));
> +    Attribs.Header.Type         =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
> +    Attribs.Header.Size         = sizeof(Attribs);
> +    Attribs.Header.Revision     =
> NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
> +    Attribs.DefaultOffloadConfiguration = &Default;
> +    Attribs.HardwareOffloadCapabilities = &Supported;
> 
> -    Trace("<==== (%08x)\n", ndisStatus);
> -    return ndisStatus;
> +    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
>  }
> 
> -//
> -// 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
> +AdapterIndicateOffloadChanged(
> +    IN  PXENNET_ADAPTER         Adapter
>      )
>  {
> -    UNREFERENCED_PARAMETER(DeviceObject);
> -    UNREFERENCED_PARAMETER(Reserved);
> -    UNREFERENCED_PARAMETER(SGL);
> -    UNREFERENCED_PARAMETER(Context);
> -
> -    ASSERT(FALSE);
> -
> -    return;
> -}
> +    NDIS_STATUS_INDICATION      Indication;
> +    NDIS_OFFLOAD                Offload;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> 
> -//
> -// Get\Set OID handler.
> -//
> -NDIS_STATUS
> -AdapterOidRequest (
> -    IN  NDIS_HANDLE         NdisHandle,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    )
> -{
> -    NDIS_STATUS ndisStatus;
> -    PADAPTER Adapter = (PADAPTER)NdisHandle;
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> 
> -    switch (NdisRequest->RequestType) {
> -        case NdisRequestSetInformation:
> -            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
> -            break;
> -
> -        case NdisRequestQueryInformation:
> -        case NdisRequestQueryStatistics:
> -            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
> -            break;
> +    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
> +    Offload.Header.Type         = NDIS_OBJECT_TYPE_OFFLOAD;
> +    Offload.Header.Size         = sizeof(NDIS_OFFLOAD);
> +    Offload.Header.Revision     = NDIS_OFFLOAD_REVISION_1;
> +
> +    Offload.Checksum.IPv4Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    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;
> +    }
> 
> -        default:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> -            break;
> -    };
> +    Offload.Checksum.IPv6Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> +    if (RxOptions->OffloadIpVersion6TcpChecksum) {
> +        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
> +        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
> +    }
> +    if (RxOptions->OffloadIpVersion6UdpChecksum) {
> +        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
> +    }
> 
> -    return ndisStatus;
> -}
> +    XENVIF_VIF(ReceiverSetOffloadOptions,
> +               &Adapter->VifInterface,
> +               *RxOptions);
> 
> -//
> -// Temporarily pauses adapter.
> -//
> -NDIS_STATUS
> -AdapterPause (
> -    IN  NDIS_HANDLE                     NdisHandle,
> -    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)NdisHandle;
> -    UNREFERENCED_PARAMETER(MiniportPauseParameters);
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> 
> -    Trace("====>\n");
> +    Offload.Checksum.IPv4Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
> +        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
> +        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4TcpChecksum) {
> +        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
> +        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4UdpChecksum) {
> +        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
> +    }
> 
> -    if (!Adapter->Enabled)
> -        goto done;
> +    Offload.Checksum.IPv6Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> +    if (TxOptions->OffloadIpVersion6TcpChecksum) {
> +        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
> +        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion6UdpChecksum) {
> +        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
> +    }
> 
> -    XENVIF_VIF(Disable,
> -               &Adapter->VifInterface);
> +    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;
> +    }
> +    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;
> +    }
> 
> -    AdapterMediaStateChange(Adapter);
> +    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof
> (NDIS_OFFLOAD))) {
> +        Adapter->Offload = Offload;
> +        //DISPLAY_OFFLOAD(Offload);
> +    }
> 
> -    Adapter->Enabled = FALSE;
> +    RtlZeroMemory(&Indication, sizeof(Indication));
> +    Indication.Header.Type      = NDIS_OBJECT_TYPE_STATUS_INDICATION;
> +    Indication.Header.Size      = sizeof(Indication);
> +    Indication.Header.Revision  = NDIS_STATUS_INDICATION_REVISION_1;
> +    Indication.SourceHandle     = Adapter->NdisHandle;
> +    Indication.StatusCode       =
> NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
> +    Indication.StatusBuffer     = &Offload;
> +    Indication.StatusBufferSize = sizeof(Offload);
> 
> -done:
> -    Trace("<====\n");
> -    return NDIS_STATUS_SUCCESS;
> +    NdisMIndicateStatusEx(Adapter->NdisHandle, &Indication);
>  }
> 
> -//
> -// Handles PNP and Power events. NOP.
> -//
> -VOID
> -AdapterPnPEventHandler (
> -    IN  NDIS_HANDLE             NdisHandle,
> -    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +static NDIS_STATUS
> +AdapterSetPacketFilter(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PULONG                  PacketFilter
>      )
>  {
> -    UNREFERENCED_PARAMETER(NdisHandle);
> +    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;
> 
> -    switch (NetDevicePnPEvent->DevicePnPEvent) {
> -        case NdisDevicePnPEventQueryRemoved:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        goto done;
> +    }
> 
> -        case NdisDevicePnPEventRemoved:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
> +    else
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
> 
> -        case NdisDevicePnPEventSurpriseRemoved:
> -            break;
> +    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;
> 
> -        case NdisDevicePnPEventQueryStopped:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +    else
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
> 
> -        case NdisDevicePnPEventStopped:
> -            break;
> -
> -        case NdisDevicePnPEventPowerProfileChanged:
> -            break;
> -
> -        default:
> -            break;
> -    };
> +done:
> +    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;
> +    return NDIS_STATUS_SUCCESS;
>  }
> 
> -//
> -// Reports general statistics to NDIS.
> -//
> -static NDIS_STATUS
> -AdapterQueryGeneralStatistics (
> -    IN  PADAPTER                Adapter,
> -    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
> +static NDIS_STATUS
> +AdapterSetMulticastAddresses(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PETHERNET_ADDRESS       Address,
> +    IN  ULONG                   Count
>      )
>  {
> -    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
> -    ULONGLONG   Value;
> -
> -    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);
> +    NTSTATUS status;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
> +    status = XENVIF_VIF(MacSetMulticastAddresses,
> +                        &Adapter->VifInterface,
> +                        Address,
> +                        Count);
> +    if (!NT_SUCCESS(status))
> +        return NDIS_STATUS_INVALID_DATA;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BACKEND_ERRORS,
> -                      &Value);
> +    return NDIS_STATUS_SUCCESS;
> +}
> 
> -    NdisStatisticsInfo->ifInErrors = Value;
> +static NDIS_STATUS
> +AdapterSetOffloadEncapsulation(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OFFLOAD_ENCAPSULATION Encapsulation
> +    )
> +{
> +    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_FRONTEND_ERRORS,
> -                      &Value);
> +    if (Encapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
> +        Encapsulation->IPv4.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> +        goto fail1;
> +    if (Encapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
> +        Encapsulation->IPv6.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> +        goto fail2;
> 
> -    NdisStatisticsInfo->ifInErrors += Value;
> +    XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                &Adapter->VifInterface,
> +                &Options);
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
> +    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;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_PACKETS_DROPPED,
> -                      &Value);
> +    if (Adapter->Properties.need_csum_value)
> +        RxOptions->NeedChecksumValue = 1;
> +    if (Adapter->Properties.lrov4) {
> +        RxOptions->OffloadIpVersion4LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
> +    }
> +    if (Adapter->Properties.lrov6) {
> +        RxOptions->OffloadIpVersion6LargePacket = 1;
> +        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;
> 
> -    NdisStatisticsInfo->ifInDiscards = Value;
> +fail2:
> +    Error("fail2\n");
> +fail1:
> +    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
> +    return NDIS_STATUS_INVALID_PARAMETER;
> +}
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
> +static NDIS_STATUS
> +AdapterSetTcpOffloadParameters(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OFFLOAD_PARAMETERS    Parameters
> +    )
> +{
> +    BOOLEAN     Changed = FALSE;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> +
> +    if (Parameters->IPsecV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE
> ||
> +        Parameters->LsoV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
> +        Parameters->TcpConnectionIPv4 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
> +        Parameters->TcpConnectionIPv6 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        goto fail1;
> +    }
> +    if (Parameters->LsoV2IPv4 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_OCTETS,
> -                      &Value);
> +        XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                    &Adapter->VifInterface,
> +                    &Options);
> 
> -    NdisStatisticsInfo->ifHCInOctets = Value;
> +        if (!(Options.OffloadIpVersion4LargePacket))
> +            goto fail2;
> +    }
> +    if (Parameters->LsoV2IPv6 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                      &Value);
> +        XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                    &Adapter->VifInterface,
> +                    &Options);
> 
> -    NdisStatisticsInfo->ifHCInOctets += Value;
> +        if (!(Options.OffloadIpVersion6LargePacket))
> +            goto fail3;
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                      &Value);
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> 
> -    NdisStatisticsInfo->ifHCInOctets += Value;
> +#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 set_value(x, y)     ((x) == (y)) ? FALSE : ( ((x) = (y)) == (y) )
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
> +    if (Parameters->LsoV2IPv4 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 1);
> +    } else if (Parameters->LsoV2IPv4 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_OCTETS,
> -                      &Value);
> +    if (Parameters->LsoV2IPv6 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 1);
> +    } else if (Parameters->LsoV2IPv6 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInUcastOctets = Value;
> +    if (tx_enabled(Parameters->IPv4Checksum)) {
> +        Changed |= set_value(TxOptions-
> >OffloadIpVersion4HeaderChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions-
> >OffloadIpVersion4HeaderChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
> +    if (tx_enabled(Parameters->TCPIPv4Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_PACKETS,
> -                      &Value);
> +    if (tx_enabled(Parameters->UDPIPv4Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum,
> 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInUcastPkts = Value;
> +    if (tx_enabled(Parameters->TCPIPv6Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
> +    if (tx_enabled(Parameters->UDPIPv6Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum,
> 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                      &Value);
> +    if (rx_enabled(Parameters->IPv4Checksum)) {
> +        Changed |= set_value(RxOptions-
> >OffloadIpVersion4HeaderChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions-
> >OffloadIpVersion4HeaderChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
> +    if (rx_enabled(Parameters->TCPIPv4Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
> +    if (rx_enabled(Parameters->UDPIPv4Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum,
> 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                      &Value);
> +    if (rx_enabled(Parameters->TCPIPv6Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
> +    if (rx_enabled(Parameters->UDPIPv6Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum,
> 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
> +#undef tx_enabled
> +#undef rx_enabled
> +#undef set_value
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                      &Value);
> +    if (Changed)
> +        AdapterIndicateOffloadChanged(Adapter);
> 
> -    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
> +    return NDIS_STATUS_SUCCESS;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
> +fail3:
> +    Error("fail3\n");
> +fail2:
> +    Error("fail2\n");
> +fail1:
> +    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
> +    return NDIS_STATUS_INVALID_PARAMETER;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                      &Value);
> +static NDIS_STATUS
> +AdapterSetInformation(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PNDIS_OID_REQUEST       Request
> +    )
> +{
> +    PVOID           Buffer;
> +    ULONG           BufferLength;
> +    ULONG           BytesNeeded = 0;
> +    ULONG           BytesRead   = 0;
> +    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
> 
> -    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
> +    Buffer          = Request->DATA.SET_INFORMATION.InformationBuffer;
> +    BufferLength    = Request-
> >DATA.SET_INFORMATION.InformationBufferLength;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
> +    switch (Request->DATA.QUERY_INFORMATION.Oid) {
> +        case OID_PNP_SET_POWER:
> +            BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> -                      &Value);
> +        case OID_GEN_CURRENT_LOOKAHEAD:
> +            BytesNeeded = sizeof(ULONG);
> +            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
> +            if (BufferLength == sizeof(ULONG)) {
> +                Adapter->CurrentLookahead = *(PULONG)Buffer;
> +                BytesRead = sizeof(ULONG);
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->ifOutErrors = Value;
> +        case OID_GEN_CURRENT_PACKET_FILTER:
> +            BytesNeeded = sizeof(ULONG);
> +            if (BufferLength == sizeof(ULONG)) {
> +                NdisStatus = AdapterSetPacketFilter(Adapter, (PULONG)Buffer);
> +                BytesRead = sizeof(ULONG);
> +            }
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> -                      &Value);
> +        case OID_802_3_MULTICAST_LIST:
> +            BytesNeeded = ETHERNET_ADDRESS_LENGTH;
> +            if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
> +                ULONG   Count = BufferLength / ETHERNET_ADDRESS_LENGTH;
> +                NdisStatus = AdapterSetMulticastAddresses(Adapter, Buffer,
> Count);
> +                BytesRead = BufferLength;
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->ifOutErrors += Value;
> +        case OID_OFFLOAD_ENCAPSULATION:
> +            BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
> +            if (BufferLength == sizeof(NDIS_OFFLOAD_ENCAPSULATION)) {
> +                NdisStatus = AdapterSetOffloadEncapsulation(Adapter, Buffer);
> +                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
> +        case OID_TCP_OFFLOAD_PARAMETERS:
> +            BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
> +            if (BufferLength == sizeof(NDIS_OFFLOAD_PARAMETERS)) {
> +                NdisStatus = AdapterSetTcpOffloadParameters(Adapter, Buffer);
> +                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> -                      &Value);
> +        case OID_GEN_INTERRUPT_MODERATION:
> +            NdisStatus = NDIS_STATUS_INVALID_DATA;
> +            break;
> 
> -    NdisStatisticsInfo->ifHCOutOctets = Value;
> +        case OID_GEN_MACHINE_NAME:
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> +    };
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                      &Value);
> +    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
> +    if (NdisStatus == NDIS_STATUS_SUCCESS) {
> +        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
> +    }
> 
> -    NdisStatisticsInfo->ifHCOutOctets += Value;
> +    return NdisStatus;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                      &Value);
> +static FORCEINLINE ULONG64
> +AdapterGetXmitOk(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                &Value);
> +    Result = Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->ifHCOutOctets += Value;
> +static FORCEINLINE ULONG64
> +AdapterGetRcvOk(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_UNICAST_PACKETS,
> +                &Value);
> +    Result = Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
> +static FORCEINLINE ULONG64
> +AdapterGetXmitError(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> -                      &Value);
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +                &Value);
> +    Result = Value;
> 
> -    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +                &Value);
> +    Result += Value;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
> +    return Result;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> -                      &Value);
> +static FORCEINLINE ULONG64
> +AdapterGetRcvError(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> 
> -    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_BACKEND_ERRORS,
> +                &Value);
> +    Result = Value;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_FRONTEND_ERRORS,
> +                &Value);
> +    Result += Value;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                      &Value);
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
> +static VOID
> +AdapterGetPacketFilter(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PULONG                  PacketFilter
> +    )
> +{
> +    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
> +    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
> +    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
> +    XENVIF_VIF(MacQueryFilterLevel,
> +               &Adapter->VifInterface,
> +               ETHERNET_ADDRESS_UNICAST,
> +               &UnicastFilterLevel);
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
> -
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
> -
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
> -    NdisStatisticsInfo->ifOutDiscards = 0;
> -
> -    return ndisStatus;
> -}
> -
> -static VOID
> -GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
> -{
> -    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
> -    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
> -    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
> -
> -    XENVIF_VIF(MacQueryFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_UNICAST,
> -               &UnicastFilterLevel);
> -
> -    XENVIF_VIF(MacQueryFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_MULTICAST,
> -               &MulticastFilterLevel);
> +    XENVIF_VIF(MacQueryFilterLevel,
> +               &Adapter->VifInterface,
> +               ETHERNET_ADDRESS_MULTICAST,
> +               &MulticastFilterLevel);
> 
>      XENVIF_VIF(MacQueryFilterLevel,
>                 &Adapter->VifInterface,
> @@ -863,1715 +1271,934 @@ GetPacketFilter(PADAPTER Adapter, PULONG
> PacketFilter)
>          *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
>  }
> 
> -#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
> +AdapterQueryGeneralStatistics (
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PNDIS_STATISTICS_INFO   Stats
>      )
>  {
> -    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");
> +    ULONGLONG                   Value;
> 
> -            info = &Adapter->Capabilities;
> -            bytesAvailable = sizeof(Adapter->Capabilities);
> -            break;
> +    RtlZeroMemory(Stats, sizeof(NDIS_STATISTICS_INFO));
> +    Stats->Header.Type         = NDIS_OBJECT_TYPE_DEFAULT;
> +    Stats->Header.Size         = sizeof(NDIS_STATISTICS_INFO);
> +    Stats->Header.Revision     = NDIS_OBJECT_REVISION_1;
> 
> -        case OID_PNP_QUERY_POWER:
> -            Trace("QUERY_POWER\n");
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BACKEND_ERRORS,
> +                      &Value);
> +    Stats->ifInErrors = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_FRONTEND_ERRORS,
> +                      &Value);
> +    Stats->ifInErrors += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_PACKETS_DROPPED,
> +                      &Value);
> +    Stats->ifInDiscards = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets += Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInUcastOctets = Value;
> 
> -            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
> -            if (informationBufferLength >= bytesNeeded) {
> -                PNDIS_DEVICE_POWER_STATE state;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInUcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInMulticastOctets = Value;
> 
> -                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
> -                switch (*state) {
> -                case NdisDeviceStateD0:
> -                    Trace("D0\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInMulticastPkts = Value;
> 
> -                case NdisDeviceStateD1:
> -                    Trace("D1\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInBroadcastOctets = Value;
> 
> -                case NdisDeviceStateD2:
> -                    Trace("D2\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInBroadcastPkts = Value;
> 
> -                case NdisDeviceStateD3:
> -                    Trace("D3\n");
> -                    break;
> -                }
> -            }
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +                      &Value);
> +    Stats->ifOutErrors = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +                      &Value);
> +    Stats->ifOutErrors += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets += Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutUcastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutUcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutMulticastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutMulticastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutBroadcastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutBroadcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
> +    Stats->ifOutDiscards = 0;
> +
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +static FORCEINLINE VOID
> +AdapterGetInterruptModeration(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PNDIS_INTERRUPT_MODERATION_PARAMETERS   Parameters
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Adapter);
> +
> +    RtlZeroMemory(Parameters,
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS));
> +    Parameters->Header.Type      = NDIS_OBJECT_TYPE_DEFAULT;
> +    Parameters->Header.Size      =
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
> +    Parameters->Header.Revision  =
> NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
> +    Parameters->Flags            = 0;
> +    Parameters->InterruptModeration =
> NdisInterruptModerationNotSupported;
> +}
> +
> +static NDIS_STATUS
> +AdapterQueryInformation(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
> +    )
> +{
> +    ULONG           Value32;
> +    ULONG64         Value64;
> +    PVOID           Buffer;
> +    ULONG           BufferLength;
> +    BOOLEAN         DoCopy = TRUE;
> +    ULONG           BytesAvailable = 0;
> +    PVOID           BytesToCopy = NULL;
> +    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
> +
> +    Buffer          = Request->DATA.QUERY_INFORMATION.InformationBuffer;
> +    BufferLength    = Request-
> >DATA.QUERY_INFORMATION.InformationBufferLength;
> +
> +    switch (Request->DATA.QUERY_INFORMATION.Oid) {
> +        case OID_PNP_CAPABILITIES:
> +            BytesToCopy = &Adapter->Capabilities;
> +            BytesAvailable = sizeof(Adapter->Capabilities);
>              break;
> 
>          case OID_GEN_SUPPORTED_LIST:
> -            info = &XennetSupportedOids[0];
> -            bytesAvailable = sizeof(XennetSupportedOids);
> +            BytesToCopy = &XennetSupportedOids[0];
> +            BytesAvailable = sizeof(XennetSupportedOids);
>              break;
> 
>          case OID_GEN_HARDWARE_STATUS:
> -            infoData = NdisHardwareStatusReady;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = NdisHardwareStatusReady;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MEDIA_SUPPORTED:
>          case OID_GEN_MEDIA_IN_USE:
> -            infoData = XENNET_MEDIA_TYPE;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = XENNET_MEDIA_TYPE;
> +            BytesToCopy = &Value32;
> +            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);
> +            Value32 = Adapter->MaximumFrameSize;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_VENDOR_DESCRIPTION:
> -            info = COMPANY_NAME_STR;
> -            bytesAvailable = (ULONG)strlen(info) + 1;
> +            BytesToCopy = COMPANY_NAME_STR;
> +            BytesAvailable = (ULONG)strlen(BytesToCopy) + 1;
>              break;
> 
>          case OID_GEN_VENDOR_DRIVER_VERSION:
> -            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_DRIVER_VERSION:
> -            infoData = (6 << 8) | 0;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = (6 << 8) | 0;
> +            BytesToCopy = &Value32;
> +            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);
> -
> -            }
> -
> +            Value32 = XENNET_MAC_OPTIONS;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_802_3_MULTICAST_LIST: {
> -            ULONG Count;
> -
> -            doCopy = FALSE;
> -
> -            XENVIF_VIF(MacQueryMulticastAddresses,
> +        case OID_GEN_TRANSMIT_BUFFER_SPACE:
> +        case OID_GEN_RECEIVE_BUFFER_SPACE:
> +            XENVIF_VIF(TransmitterQueryRingSize,
>                         &Adapter->VifInterface,
> -                       NULL,
> -                       &Count);
> -            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
> -
> -            if (informationBufferLength >= bytesAvailable) {
> -                NTSTATUS status;
> -
> -                status = XENVIF_VIF(MacQueryMulticastAddresses,
> -                                    &Adapter->VifInterface,
> -                                    informationBuffer,
> -                                    &Count);
> -                if (!NT_SUCCESS(status))
> -                    ndisStatus = NDIS_STATUS_FAILURE;
> -            }
> -
> +                       (PULONG)&Value32);
> +            Value32 *= Adapter->MaximumFrameSize;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> -        }
> +
>          case OID_802_3_PERMANENT_ADDRESS:
>              XENVIF_VIF(MacQueryPermanentAddress,
>                         &Adapter->VifInterface,
> -                       (PETHERNET_ADDRESS)&infoData);
> -            info = &infoData;
> -            bytesAvailable = sizeof (ETHERNET_ADDRESS);
> +                       (PETHERNET_ADDRESS)&Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_802_3_CURRENT_ADDRESS:
>              XENVIF_VIF(MacQueryCurrentAddress,
>                         &Adapter->VifInterface,
> -                       (PETHERNET_ADDRESS)&infoData);
> -            info = &infoData;
> -            bytesAvailable = sizeof (ETHERNET_ADDRESS);
> +                       (PETHERNET_ADDRESS)&Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MAXIMUM_FRAME_SIZE:
> -            infoData = Adapter->MaximumFrameSize -
> +            Value32 = Adapter->MaximumFrameSize -
>                         sizeof (ETHERNET_TAGGED_HEADER);
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MAXIMUM_TOTAL_SIZE:
> -            infoData = Adapter->MaximumFrameSize -
> +            Value32 = Adapter->MaximumFrameSize -
>                         sizeof (ETHERNET_TAGGED_HEADER) +
>                         sizeof (ETHERNET_UNTAGGED_HEADER);
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_CURRENT_LOOKAHEAD:
> -            infoData = Adapter->CurrentLookahead;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = Adapter->CurrentLookahead;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_VENDOR_ID:
> -            infoData = 0x5853;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = 0x5853;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_LINK_SPEED: {
> -            ULONG64 LinkSpeed;
> -
> -            XENVIF_VIF(MacQueryState,
> -                       &Adapter->VifInterface,
> -                       NULL,
> -                       &LinkSpeed,
> -                       NULL);
> -
> -            infoData = (ULONG)(LinkSpeed / 100);
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MEDIA_CONNECT_STATUS:
> +        case OID_GEN_LINK_SPEED:
>              XENVIF_VIF(MacQueryState,
>                         &Adapter->VifInterface,
> -                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
>                         NULL,
> +                       &Value64,
>                         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);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONGLONG);
> -            break;
> -        }
> -        case OID_GEN_RCV_OK: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONGLONG);
> +            Value32 = (ULONG)(Value64 / 100);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> -        }
> -        case OID_GEN_XMIT_ERROR: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_RCV_ERROR: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BACKEND_ERRORS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_FRONTEND_ERRORS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            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);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_BYTES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_BYTES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        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;
> -
> -        // 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;
> -        }
> -
> -        if (bytesWritten && doCopy) {
> -            NdisMoveMemory(informationBuffer, info, bytesWritten);
> -
> -            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> -        }
> -    }
> -
> -    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten =
> bytesWritten;
> -    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded =
> bytesNeeded;
> -    return ndisStatus;
> -}
> -#pragma warning(pop)
> -
> -NDIS_STATUS
> -AdapterReset (
> -    IN  NDIS_HANDLE     MiniportAdapterContext,
> -    OUT PBOOLEAN        AddressingReset
> -    )
> -{
> -    UNREFERENCED_PARAMETER(MiniportAdapterContext);
> -
> -
> -    *AddressingReset = FALSE;
> -
> -    return NDIS_STATUS_SUCCESS;
> -}
> -
> -//
> -// 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;
> -
> -    UNREFERENCED_PARAMETER(MiniportRestartParameters);
> -
> -    Trace("====>\n");
> -
> -    if (Adapter->Enabled) {
> -        ndisStatus = NDIS_STATUS_SUCCESS;
> -        goto done;
> -    }
> -
> -    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;
> -    }
> -
> -done:
> -    Trace("<====\n");
> -    return ndisStatus;
> -}
> -
> -//
> -// Recycle of received net buffer lists.
> -//
> -VOID
> -AdapterReturnNetBufferLists (
> -    IN  NDIS_HANDLE         MiniportAdapterContext,
> -    IN  PNET_BUFFER_LIST    NetBufferLists,
> -    IN  ULONG               ReturnFlags
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> -
> -    ReceiverReturnNetBufferLists(&Adapter->Receiver,
> -                                 NetBufferLists,
> -                                 ReturnFlags);
> -
> -    return;
> -}
> -
> -//
> -// 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
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> -
> -    TransmitterSendNetBufferLists(Adapter->Transmitter,
> -                                  NetBufferList,
> -                                  PortNumber,
> -                                  SendFlags);
> -}
> -
> -#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)
> -
> -//
> -// Sets general adapter attributes.
> -//
> -static NDIS_STATUS
> -AdapterSetGeneralAttributes (
> -    IN  PADAPTER Adapter
> -    )
> -{
> -    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
> -    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
> -    NDIS_STATUS ndisStatus;
> -
> -    NdisZeroMemory(&generalAttributes,
> -                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
> -
> -    generalAttributes.Header.Type =
> -
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
> -
> -    generalAttributes.Header.Revision =
> -                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
> -
> -    generalAttributes.Header.Size =
> -                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
> -
> -    generalAttributes.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;
> -
> -    XENVIF_VIF(MacQueryPermanentAddress,
> -               &Adapter->VifInterface,
> -               (PETHERNET_ADDRESS)&generalAttributes.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;
> -
> -    generalAttributes.SupportedOidList = XennetSupportedOids;
> -    generalAttributes.SupportedOidListLength =
> sizeof(XennetSupportedOids);
> -    adapterAttributes =
> -                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
> -
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> -
> -    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
> -    )
> -{
> -    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;
> -
> -    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;
> -    }
> -
> -    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);
> -
> -    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
> -    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
> -    supported.Header.Size = sizeof(supported);
> -
> -    supported.Checksum.IPv4Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv4Receive.IpChecksum = 1;
> -    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv4Receive.TcpChecksum = 1;
> -    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv4Receive.UdpChecksum = 1;
> -
> -    supported.Checksum.IPv6Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> -
> -    supported.Checksum.IPv6Receive.TcpChecksum = 1;
> -    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv6Receive.UdpChecksum = 1;
> -
> -    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -               &Adapter->VifInterface,
> -               &Options);
> -
> -    supported.Checksum.IPv4Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    if (Options.OffloadIpVersion4HeaderChecksum) {
> -        supported.Checksum.IPv4Transmit.IpChecksum = 1;
> -        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion4TcpChecksum) {
> -        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
> -        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion4UdpChecksum)
> -        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
> -
> -    supported.Checksum.IPv6Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> -
> -    if (Options.OffloadIpVersion6TcpChecksum) {
> -        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
> -        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion6UdpChecksum)
> -        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;
> -    }
> -
> -    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;
> -    }
> -
> -    current = supported;
> -
> -    if (!(Adapter->Properties.ipv4_csum & 2))
> -        current.Checksum.IPv4Receive.IpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv4_csum & 2))
> -        current.Checksum.IPv4Receive.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv4_csum & 2))
> -        current.Checksum.IPv4Receive.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv6_csum & 2))
> -        current.Checksum.IPv6Receive.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv6_csum & 2))
> -        current.Checksum.IPv6Receive.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.ipv4_csum & 1))
> -        current.Checksum.IPv4Transmit.IpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv4_csum & 1))
> -        current.Checksum.IPv4Transmit.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv4_csum & 1))
> -        current.Checksum.IPv4Transmit.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv6_csum & 1))
> -        current.Checksum.IPv6Transmit.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv6_csum & 1))
> -        current.Checksum.IPv6Transmit.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.lsov4)) {
> -        current.LsoV2.IPv4.MaxOffLoadSize = 0;
> -        current.LsoV2.IPv4.MinSegmentCount = 0;
> -    }
> -
> -    if (!(Adapter->Properties.lsov6)) {
> -        current.LsoV2.IPv6.MaxOffLoadSize = 0;
> -        current.LsoV2.IPv6.MinSegmentCount = 0;
> -    }
> -
> -    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof
> (NDIS_OFFLOAD))) {
> -        Adapter->Offload = current;
> -
> -        DISPLAY_OFFLOAD(current);
> -    }
> -
> -    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;
> -
> -    adapterAttributes =
> -        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> -
> -    return ndisStatus;
> -}
> -
> -static void
> -AdapterIndicateOffloadChanged (
> -    IN  PADAPTER 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;
> -    }
> -
> -    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);
> -    }
> -
> -    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);
> -
> -    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
> -
> -}
> -
> -static NDIS_STATUS
> -SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address,
> ULONG Count)
> -{
> -    NTSTATUS status;
> -
> -    status = XENVIF_VIF(MacSetMulticastAddresses,
> -                        &Adapter->VifInterface,
> -                        Address,
> -                        Count);
> -    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;
> -
> -    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        goto done;
> -    }
> -
> -    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
> -    else
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
> -
> -    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;
> 
> -    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -    else
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
> +        case OID_GEN_MEDIA_CONNECT_STATUS:
> +            XENVIF_VIF(MacQueryState,
> +                       &Adapter->VifInterface,
> +                       (PNET_IF_MEDIA_CONNECT_STATE)&Value32,
> +                       NULL,
> +                       NULL);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -done:
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_UNICAST,
> -               UnicastFilterLevel);
> +        case OID_GEN_MAXIMUM_SEND_PACKETS:
> +            Value32 = 16;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_MULTICAST,
> -               MulticastFilterLevel);
> +        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:
> +            Value32 = 0;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_BROADCAST,
> -               BroadcastFilterLevel);
> +        case OID_802_3_MAXIMUM_LIST_SIZE:
> +            Value32 = 32;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    return NDIS_STATUS_SUCCESS;
> -}
> +        case OID_GEN_STATISTICS:
> +            DoCopy = FALSE;
> +            BytesAvailable = sizeof(NDIS_STATISTICS_INFO);
> +            if (BufferLength >= sizeof(NDIS_STATISTICS_INFO))
> +                NdisStatus = AdapterQueryGeneralStatistics(Adapter, Buffer);
> +            break;
> 
> -//
> -// 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;
> +        case OID_802_3_MULTICAST_LIST:
> +            DoCopy = FALSE;
> +            XENVIF_VIF(MacQueryMulticastAddresses,
> +                       &Adapter->VifInterface,
> +                       NULL,
> +                       &Value32);
> +            BytesAvailable = Value32 * ETHERNET_ADDRESS_LENGTH;
> +            if (BufferLength >= BytesAvailable) {
> +                if (!NT_SUCCESS(XENVIF_VIF(MacQueryMulticastAddresses,
> +                                           &Adapter->VifInterface,
> +                                           Buffer,
> +                                           &Value32))) {
> +                    NdisStatus = NDIS_STATUS_FAILURE;
>                  }
>              }
>              break;
> 
> -        case OID_GEN_MACHINE_NAME:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +        case OID_GEN_CURRENT_PACKET_FILTER:
> +            AdapterGetPacketFilter(Adapter, &Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_CURRENT_LOOKAHEAD:
> -            bytesNeeded = sizeof(ULONG);
> -            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
> -            if (informationBufferLength == sizeof(ULONG)) {
> -                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
> -                bytesRead = sizeof(ULONG);
> -            }
> -
> +        case OID_GEN_XMIT_OK:
> +            Value64 = AdapterGetXmitOk(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
>              break;
> 
> -        case OID_GEN_CURRENT_PACKET_FILTER:
> -            bytesNeeded = sizeof(ULONG);
> -            if (informationBufferLength == sizeof(ULONG)) {
> -                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
> -                bytesRead = sizeof(ULONG);
> -            }
> -
> +        case OID_GEN_RCV_OK:
> +            Value64 = AdapterGetRcvOk(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
>              break;
> 
> -        case OID_802_3_MULTICAST_LIST:
> -            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
> -            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
> -                addressCount = informationBufferLength /
> ETHERNET_ADDRESS_LENGTH;
> +        case OID_GEN_XMIT_ERROR:
> +            Value64 = AdapterGetXmitError(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
> +            break;
> 
> -                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer,
> addressCount);
> -                if (ndisStatus == NDIS_STATUS_SUCCESS)
> -                    bytesRead = informationBufferLength;
> -            } else {
> -                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
> -            }
> +        case OID_GEN_RCV_ERROR:
> +            Value64 = AdapterGetRcvError(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
> +            break;
> 
> +        case OID_GEN_DIRECTED_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_INTERRUPT_MODERATION:
> -            ndisStatus = NDIS_STATUS_INVALID_DATA;
> +        case OID_GEN_DIRECTED_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_OFFLOAD_ENCAPSULATION: {
> -            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
> +        case OID_GEN_MULTICAST_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -            bytesNeeded = sizeof(*offloadEncapsulation);
> -            if (informationBufferLength >= bytesNeeded) {
> -                XENVIF_VIF_OFFLOAD_OPTIONS Options;
> +        case OID_GEN_MULTICAST_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                bytesRead = bytesNeeded;
> -                offloadEncapsulation = informationBuffer;
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> +        case OID_GEN_BROADCAST_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON)
> {
> -                    if (offloadEncapsulation->IPv4.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +        case OID_GEN_BROADCAST_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON)
> {
> -                    if (offloadEncapsulation->IPv6.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +        case OID_GEN_DIRECTED_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_UNICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                           &Adapter->VifInterface,
> -                           &Options);
> -
> -                Adapter->Transmitter->OffloadOptions.Value = 0;
> -                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation =
> 1;
> +        case OID_GEN_DIRECTED_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_UNICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.lsov4) &&
> (Options.OffloadIpVersion4LargePacket))
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4LargePacket = 1;
> +        case OID_GEN_MULTICAST_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.lsov6) &&
> (Options.OffloadIpVersion6LargePacket))
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6LargePacket = 1;
> +        case OID_GEN_MULTICAST_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.ipv4_csum & 1) &&
> Options.OffloadIpVersion4HeaderChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
> +        case OID_GEN_BROADCAST_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.tcpv4_csum & 1) &&
> Options.OffloadIpVersion4TcpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
> +        case OID_GEN_BROADCAST_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.udpv4_csum & 1) &&
> Options.OffloadIpVersion4UdpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
> +        case OID_GEN_INTERRUPT_MODERATION:
> +            DoCopy = FALSE;
> +            BytesAvailable =
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
> +            if (BufferLength >= BytesAvailable)
> +                AdapterGetInterruptModeration(Adapter, Buffer);
> +            else
> +                NdisStatus = NDIS_STATUS_FAILURE;
> +            break;
> 
> -                if ((Adapter->Properties.tcpv6_csum & 1) &&
> Options.OffloadIpVersion6TcpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
> +        case OID_PNP_QUERY_POWER:
> +            // do nothing!
> +            break;
> 
> -                if ((Adapter->Properties.udpv6_csum & 1) &&
> Options.OffloadIpVersion6UdpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
> +        case OID_GEN_MAC_ADDRESS:
> +        case OID_GEN_MAX_LINK_SPEED:
> +        case OID_IP4_OFFLOAD_STATS:
> +        case OID_IP6_OFFLOAD_STATS:
> +        case OID_GEN_SUPPORTED_GUIDS:
> +		case OID_GEN_INIT_TIME_MS:
> +		case OID_GEN_RESET_COUNTS:
> +		case OID_GEN_MEDIA_SENSE_COUNTS:
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> 
> -                Adapter->Receiver.OffloadOptions.Value = 0;
> -                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
> +    }
> 
> -                if (Adapter->Properties.need_csum_value)
> -                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
> +    if (NdisStatus == NDIS_STATUS_SUCCESS) {
> +        Request->DATA.QUERY_INFORMATION.BytesNeeded =
> BytesAvailable;
> +        if (BytesAvailable <= BufferLength) {
> +            Request->DATA.QUERY_INFORMATION.BytesWritten =
> BytesAvailable;
> +        } else {
> +            Request->DATA.QUERY_INFORMATION.BytesWritten =
> BufferLength;
> +            NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
> +        }
> +        if (Request->DATA.QUERY_INFORMATION.BytesWritten && DoCopy) {
> +            RtlMoveMemory(Buffer, BytesToCopy, Request-
> >DATA.QUERY_INFORMATION.BytesWritten);
> 
> -                if (Adapter->Properties.lrov4) {
> -                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket
> = 1;
> -                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
> -                }
> +            // Its Ok to short transfers on these Oids
> +            if (Request->DATA.QUERY_INFORMATION.Oid ==
> OID_GEN_XMIT_OK ||
> +                Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_RCV_OK)
> +                NdisStatus = NDIS_STATUS_SUCCESS;
> +        }
> +    }
> 
> -                if (Adapter->Properties.lrov6) {
> -                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket
> = 1;
> -                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
> -                }
> +    return NdisStatus;
> +}
> 
> -                if (Adapter->Properties.ipv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
> +NDIS_STATUS
> +AdapterOidRequest(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
> +    )
> +{
> +    NDIS_STATUS     NdisStatus;
> +
> +    switch (Request->RequestType) {
> +        case NdisRequestSetInformation:
> +            NdisStatus = AdapterSetInformation(Adapter, Request);
> +            break;
> +
> +        case NdisRequestQueryInformation:
> +        case NdisRequestQueryStatistics:
> +            NdisStatus = AdapterQueryInformation(Adapter, Request);
> +            break;
> 
> -                if (Adapter->Properties.tcpv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> +    };
> 
> -                if (Adapter->Properties.udpv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
> +    return NdisStatus;
> +}
> 
> -                if (Adapter->Properties.tcpv6_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
> +NTSTATUS
> +AdapterEnable(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    NTSTATUS        status;
> 
> -                if (Adapter->Properties.udpv6_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
> +    if (Adapter->Enabled)
> +        goto done;
> 
> -                AdapterIndicateOffloadChanged(Adapter);
> -            }
> -            break;
> -        }
> -        case OID_TCP_OFFLOAD_PARAMETERS: {
> -            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
> +    status = XENVIF_VIF(Enable,
> +                        &Adapter->VifInterface,
> +                        AdapterVifCallback,
> +                        Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    TransmitterEnable(Adapter->Transmitter);
> +    Adapter->Enabled = TRUE;
> 
> -            bytesNeeded = sizeof(*offloadParameters);
> -            if (informationBufferLength >= bytesNeeded) {
> -                bytesRead = bytesNeeded;
> -                offloadParameters = informationBuffer;
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> +done:
> +    return STATUS_SUCCESS;
> 
> -#define no_change(x)  ((x) ==
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> 
> -                if (!no_change(offloadParameters->IPsecV1))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -
> -                if (!no_change(offloadParameters->LsoV1))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +BOOLEAN
> +AdapterDisable(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    if (!Adapter->Enabled)
> +        return FALSE;
> 
> -                if (!no_change(offloadParameters->TcpConnectionIPv4))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +    XENVIF_VIF(Disable, &Adapter->VifInterface);
> +    Adapter->Enabled = FALSE;
> +    return TRUE;
> +}
> 
> -                if (!no_change(offloadParameters->TcpConnectionIPv6))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +VOID
> +AdapterMediaStateChange(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    NDIS_LINK_STATE                 LinkState;
> +    NDIS_STATUS_INDICATION          StatusIndication;
> 
> -                if (!no_change(offloadParameters->LsoV2IPv4)) {
> -                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
> +    LinkState.Header.Type       = NDIS_OBJECT_TYPE_DEFAULT;
> +    LinkState.Header.Size       = sizeof(NDIS_LINK_STATE);
> +    LinkState.Header.Revision   = NDIS_LINK_STATE_REVISION_1;
> 
> -                    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                               &Adapter->VifInterface,
> -                               &Options);
> +    XENVIF_VIF(MacQueryState,
> +               &Adapter->VifInterface,
> +               &LinkState.MediaConnectState,
> +               &LinkState.RcvLinkSpeed,
> +               &LinkState.MediaDuplexState);
> 
> -                    if (!(Options.OffloadIpVersion4LargePacket))
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
> +        Info("LINK: STATE UNKNOWN\n");
> +    } else if (LinkState.MediaConnectState ==
> MediaConnectStateDisconnected) {
> +        Info("LINK: DOWN\n");
> +    } else {
> +        ASSERT3U(LinkState.MediaConnectState, ==,
> MediaConnectStateConnected);
> 
> -                if (!no_change(offloadParameters->LsoV2IPv6)) {
> -                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +        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);
> +    }
> 
> -                    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                               &Adapter->VifInterface,
> -                               &Options);
> +    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
> 
> -                    if (!(Options.OffloadIpVersion6LargePacket))
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
> +    StatusIndication.Header.Type        =
> NDIS_OBJECT_TYPE_STATUS_INDICATION;
> +    StatusIndication.Header.Size        = sizeof (NDIS_STATUS_INDICATION);
> +    StatusIndication.Header.Revision    =
> NDIS_STATUS_INDICATION_REVISION_1;
> +    StatusIndication.SourceHandle       = Adapter->NdisHandle;
> +    StatusIndication.StatusCode         = NDIS_STATUS_LINK_STATE;
> +    StatusIndication.StatusBuffer       = &LinkState;
> +    StatusIndication.StatusBufferSize   = sizeof (NDIS_LINK_STATE);
> 
> -#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;
> -                        }
> -                    }
> +    NdisMIndicateStatusEx(Adapter->NdisHandle, &StatusIndication);
> +}
> 
> -#undef tx_enabled
> -#undef rx_enabled
> -#undef no_change
> +PXENNET_RECEIVER
> +AdapterGetReceiver(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->Receiver;
> +}
> 
> -                    if (offloadChanged)
> -                        AdapterIndicateOffloadChanged(Adapter);
> -                }
> -            } else {
> -                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
> -            }
> -            break;
> -        }
> -        default:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> -            break;
> -    };
> +PXENNET_TRANSMITTER
> +AdapterGetTransmitter(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->Transmitter;
> +}
> 
> -    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
> -    if (ndisStatus == NDIS_STATUS_SUCCESS) {
> -        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
> -    }
> +PXENVIF_VIF_INTERFACE
> +AdapterGetVifInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return &Adapter->VifInterface;
> +}
> 
> -    return ndisStatus;
> +NDIS_HANDLE
> +AdapterGetHandle(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->NdisHandle;
>  }
> 
> -//
> -// Sets miniport registration attributes.
> -//
> -static NDIS_STATUS
> -AdapterSetRegistrationAttributes (
> -    IN  PADAPTER Adapter
> +NTSTATUS
> +AdapterInitialize(
> +    IN  NDIS_HANDLE                 NdisHandle,
> +    OUT PXENNET_ADAPTER             *Adapter
>      )
>  {
> -    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
> -    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES
> registrationAttributes;
> -    NDIS_STATUS ndisStatus;
> +    PDEVICE_OBJECT          DeviceObject;
> +    NTSTATUS                status;
> +    NDIS_SG_DMA_DESCRIPTION DmaDescription;
> +    NDIS_STATUS             NdisStatus;
> +
> +    status = STATUS_NO_MEMORY;
> +    *Adapter = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_ADAPTER), XENNET_POOL_TAG);
> +    if (*Adapter == NULL)
> +        goto fail1;
> 
> +    RtlZeroMemory(*Adapter, sizeof(XENNET_ADAPTER));
> +    (*Adapter)->NdisHandle = NdisHandle;
> +
> +    DeviceObject = NULL;
> +    NdisMGetDeviceProperty(NdisHandle,
> +                           &DeviceObject,
> +                           NULL,
> +                           NULL,
> +                           NULL,
> +                           NULL);
> +
> +    status = QUERY_INTERFACE(DeviceObject,
> +                             XENVIF,
> +                             VIF,
> +                             XENVIF_VIF_INTERFACE_VERSION_MAX,
> +                             (PINTERFACE)&(*Adapter)->VifInterface,
> +                             sizeof ((*Adapter)->VifInterface),
> +                             FALSE);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> 
> -    NdisZeroMemory(&registrationAttributes,
> -                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
> +    status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
> -    registrationAttributes.Header.Type =
> -
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
> +    status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> 
> -    registrationAttributes.Header.Revision =
> -
> NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
> +    status = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> 
> -    registrationAttributes.Header.Size =
> -                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
> +    NdisStatus = AdapterGetAdvancedSettings(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail6;
> 
> -    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;
> +    NdisStatus = AdapterSetRegistrationAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail7;
> 
> -    adapterAttributes =
> -                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
> +    NdisStatus = AdapterSetGeneralAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail8;
> 
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> +    NdisStatus = AdapterSetOffloadAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail9;
> 
> -    return ndisStatus;
> -}
> +    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
> +    DmaDescription.Header.Type      =
> NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
> +    DmaDescription.Header.Size      = sizeof(NDIS_SG_DMA_DESCRIPTION);
> +    DmaDescription.Header.Revision  =
> NDIS_SG_DMA_DESCRIPTION_REVISION_1;
> +    DmaDescription.Flags            = NDIS_SG_DMA_64_BIT_ADDRESS;
> +    DmaDescription.MaximumPhysicalMapping           = 65536;
> +    DmaDescription.ProcessSGListHandler             = AdapterProcessSGList;
> +    DmaDescription.SharedMemAllocateCompleteHandler =
> AdapterAllocateComplete;
> 
> -//
> -// Shuts down adapter.
> -//
> -VOID
> -AdapterShutdown (
> -    IN  NDIS_HANDLE             MiniportAdapterContext,
> -    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> +    NdisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisHandle,
> +                                               &DmaDescription,
> +                                               &(*Adapter)->NdisDmaHandle);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        (*Adapter)->NdisDmaHandle = NULL;
> 
> -    UNREFERENCED_PARAMETER(ShutdownAction);
> +    status = AdapterEnable(*Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail10;
> 
> -    if (ShutdownAction != NdisShutdownBugCheck)
> -        AdapterStop(Adapter);
> +    return STATUS_SUCCESS;
> 
> -    return;
> +fail10:
> +    Error("fail10 (%08x)\n", status);
> +    if ((*Adapter)->NdisDmaHandle)
> +        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
> +    (*Adapter)->NdisDmaHandle = NULL;
> +fail9:
> +    Error("fail9\n");
> +fail8:
> +    Error("fail8\n");
> +fail7:
> +    Error("fail7\n");
> +fail6:
> +    Error("fail6 (%08x)\n", NdisStatus);
> +    if (NT_SUCCESS(status))
> +        status = STATUS_UNSUCCESSFUL;
> +    ReceiverTeardown((*Adapter)->Receiver);
> +    (*Adapter)->Receiver = NULL;
> +fail5:
> +    Error("fail5\n");
> +    TransmitterTeardown((*Adapter)->Transmitter);
> +    (*Adapter)->Transmitter = NULL;
> +fail4:
> +    Error("fail4\n");
> +    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
> +fail3:
> +    Error("fail3\n");
> +    RtlZeroMemory(&(*Adapter)->VifInterface,
> sizeof(XENVIF_VIF_INTERFACE));
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Adapter, XENNET_POOL_TAG);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
>  }
> 
> -//
> -// 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
> -)
> +VOID
> +AdapterTeardown(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
>  {
> -    Trace("====>\n");
> +    if (Adapter->NdisDmaHandle)
> +        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
> +    Adapter->NdisDmaHandle = NULL;
> 
> -    if (!Adapter->Enabled)
> -        goto done;
> +    ReceiverTeardown(Adapter->Receiver);
> +    Adapter->Receiver = NULL;
> 
> -    XENVIF_VIF(Disable,
> -               &Adapter->VifInterface);
> +    TransmitterTeardown(Adapter->Transmitter);
> +    Adapter->Transmitter = 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, XENNET_POOL_TAG);
>  }
> +
> +//
> +//#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)
> +//
> diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
> index e64e40d..a1f4b85 100644
> --- a/src/xennet/adapter.h
> +++ b/src/xennet/adapter.h
> @@ -29,19 +29,20 @@
>   * SUCH DAMAGE.
>   */
> 
> -#pragma once
> +#ifndef _XENNET_ADAPTER_H_
> +#define _XENNET_ADAPTER_H_
> 
> -#define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
> +#define XENNET_INTERFACE_TYPE   NdisInterfaceInternal
> 
> -#define XENNET_MEDIA_TYPE               NdisMedium802_3
> +#define XENNET_MEDIA_TYPE       NdisMedium802_3
> 
> -#define XENNET_MAC_OPTIONS
> (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
> -                                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
> -                                         NDIS_MAC_OPTION_NO_LOOPBACK |          \
> -                                         NDIS_MAC_OPTION_8021P_PRIORITY |       \
> -
> NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
> +#define XENNET_MAC_OPTIONS
> (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
> +                                 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
> +                                 NDIS_MAC_OPTION_NO_LOOPBACK |          \
> +                                 NDIS_MAC_OPTION_8021P_PRIORITY |       \
> +
> NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
> 
> -typedef struct _PROPERTIES {
> +typedef struct _XENNET_PROPERTIES {
>      int ipv4_csum;
>      int tcpv4_csum;
>      int udpv4_csum;
> @@ -52,122 +53,63 @@ typedef struct _PROPERTIES {
>      int lsov6;
>      int lrov4;
>      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
> -    );
> -
> -MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
> -VOID
> -AdapterCancelSendNetBufferLists (
> -    IN  NDIS_HANDLE NdisHandle,
> -    IN  PVOID       CancelId
> -    );
> +} XENNET_PROPERTIES, *PXENNET_PROPERTIES;
> 
> -MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
> -BOOLEAN
> -AdapterCheckForHang (
> -    IN  NDIS_HANDLE NdisHandle
> -    );
> -
> -VOID
> -AdapterCleanup (
> -    IN PADAPTER Adapter
> -    );
> +typedef struct _XENNET_ADAPTER  XENNET_ADAPTER,
> *PXENNET_ADAPTER;
> 
> -NDIS_STATUS
> -AdapterInitialize (
> -    IN  PADAPTER    Adapter,
> -    IN  NDIS_HANDLE AdapterHandle
> +extern NDIS_STATUS
> +AdapterOidRequest(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
>      );
> 
> -MINIPORT_OID_REQUEST AdapterOidRequest;
> -NDIS_STATUS
> -AdapterOidRequest (
> -    IN  NDIS_HANDLE         NdisHandle,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> +extern NTSTATUS
> +AdapterEnable(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_PAUSE AdapterPause;
> -NDIS_STATUS
> -AdapterPause (
> -    IN  NDIS_HANDLE                     NdisHandle,
> -    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> +extern BOOLEAN
> +AdapterDisable(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
> -VOID
> -AdapterPnPEventHandler (
> -    IN  NDIS_HANDLE             NdisHandle,
> -    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +extern VOID
> +AdapterMediaStateChange(
> +    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
> +#include "transmitter.h"
> +extern PXENNET_TRANSMITTER
> +AdapterGetTransmitter(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
> -VOID
> -AdapterReturnNetBufferLists (
> -    IN  NDIS_HANDLE         MiniportAdapterContext,
> -    IN  PNET_BUFFER_LIST    NetBufferLists,
> -    IN  ULONG               ReturnFlags
> +#include <vif_interface.h>
> +extern PXENVIF_VIF_INTERFACE
> +AdapterGetVifInterface(
> +    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 NDIS_HANDLE
> +AdapterGetHandle(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -NDIS_STATUS
> -AdapterStop (
> -    IN  PADAPTER    Adapter
> -    );
> -
> -MINIPORT_SHUTDOWN AdapterShutdown;
> -
> -VOID
> -AdapterShutdown (
> -    IN  NDIS_HANDLE             MiniportAdapterContext,
> -    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> +extern NTSTATUS
> +AdapterInitialize(
> +    IN  NDIS_HANDLE                 NdisHandle,
> +    OUT PXENNET_ADAPTER             *Adapter
>      );
> 
>  extern VOID
> -ReceiverReceivePackets(
> -    IN  PRECEIVER   Receiver,
> -    IN  PLIST_ENTRY List
> +AdapterTeardown(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> +
> +#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/driver.c b/src/xennet/driver.c
> new file mode 100644
> index 0000000..66aff1d
> --- /dev/null
> +++ b/src/xennet/driver.c
> @@ -0,0 +1,550 @@
> +/* 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 <ndis.h>
> +#include <ntstrsafe.h>
> +#include <version.h>
> +
> +#include "adapter.h"
> +#include "transmitter.h"
> +#include "receiver.h"
> +#include "registry.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> +
> +extern PULONG InitSafeBootMode;
> +
> +typedef struct _XENNET_DRIVER {
> +    PDRIVER_OBJECT              DriverObject;
> +    NDIS_HANDLE                 MiniportHandle;
> +    NTSTATUS                    (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
> +} XENNET_DRIVER;
> +
> +static XENNET_DRIVER            Driver;
> +
> +MINIPORT_CANCEL_OID_REQUEST     DriverCancelOidRequest;
> +VOID
> +DriverCancelOidRequest(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PVOID                   RequestId
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(RequestId);
> +}
> +
> +MINIPORT_CANCEL_SEND            DriverCancelSendNetBufferLists;
> +VOID
> +DriverCancelSendNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PVOID                   CancelId
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(CancelId);
> +}
> +
> +MINIPORT_CHECK_FOR_HANG DriverCheckForHang;
> +BOOLEAN
> +DriverCheckForHang(
> +    IN  NDIS_HANDLE             NdisHandle
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    return FALSE;
> +}
> +
> +MINIPORT_DEVICE_PNP_EVENT_NOTIFY DriverPnPEventHandler;
> +VOID
> +DriverPnPEventHandler(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(NetDevicePnPEvent);
> +}
> +
> +MINIPORT_RESET                  DriverReset;
> +NDIS_STATUS
> +DriverReset(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    OUT PBOOLEAN                AddressingReset
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    *AddressingReset = FALSE;
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +MINIPORT_OID_REQUEST            DriverOidRequest;
> +NDIS_STATUS
> +DriverOidRequest(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNDIS_OID_REQUEST       NdisRequest
> +    )
> +{
> +    return AdapterOidRequest((PXENNET_ADAPTER)NdisHandle,
> NdisRequest);
> +}
> +
> +MINIPORT_PAUSE DriverPause;
> +NDIS_STATUS
> +DriverPause(
> +    IN  NDIS_HANDLE                     NdisHandle,
> +    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> +    )
> +{
> +    UNREFERENCED_PARAMETER(MiniportPauseParameters);
> +
> +    if (AdapterDisable((PXENNET_ADAPTER)NdisHandle))
> +        AdapterMediaStateChange((PXENNET_ADAPTER)NdisHandle);
> +
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +MINIPORT_RESTART DriverRestart;
> +NDIS_STATUS
> +DriverRestart(
> +    IN  NDIS_HANDLE                         NdisHandle,
> +    IN  PNDIS_MINIPORT_RESTART_PARAMETERS
> MiniportRestartParameters
> +    )
> +{
> +    NTSTATUS    status;
> +
> +    UNREFERENCED_PARAMETER(MiniportRestartParameters);
> +
> +    status = AdapterEnable((PXENNET_ADAPTER)NdisHandle);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return NDIS_STATUS_FAILURE;
> +}
> +
> +MINIPORT_RETURN_NET_BUFFER_LISTS DriverReturnNetBufferLists;
> +VOID
> +DriverReturnNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
> +    )
> +{
> +    PXENNET_RECEIVER            Receiver;
> +    Receiver = AdapterGetReceiver((PXENNET_ADAPTER)NdisHandle);
> +    ReceiverReturnNetBufferLists(Receiver,
> +                                 NetBufferLists,
> +                                 ReturnFlags);
> +}
> +
> +MINIPORT_SEND_NET_BUFFER_LISTS  DriverSendNetBufferLists;
> +VOID
> +DriverSendNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
> +    )
> +{
> +    PXENNET_TRANSMITTER         Transmitter;
> +    Transmitter = AdapterGetTransmitter((PXENNET_ADAPTER)NdisHandle);
> +    TransmitterSendNetBufferLists(Transmitter,
> +                                  NetBufferList,
> +                                  PortNumber,
> +                                  SendFlags);
> +}
> +
> +MINIPORT_SHUTDOWN DriverShutdown;
> +VOID
> +DriverShutdown(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> +    )
> +{
> +    UNREFERENCED_PARAMETER(ShutdownAction);
> +
> +    if (ShutdownAction != NdisShutdownBugCheck)
> +        (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
> +}
> +
> +MINIPORT_INITIALIZE             DriverInitialize;
> +NDIS_STATUS
> +DriverInitialize(
> +    IN  NDIS_HANDLE                        NdisHandle,
> +    IN  NDIS_HANDLE                        DriverContext,
> +    IN  PNDIS_MINIPORT_INIT_PARAMETERS     Parameters
> +    )
> +{
> +    NTSTATUS            status;
> +    PXENNET_ADAPTER     Adapter;
> +
> +    UNREFERENCED_PARAMETER(DriverContext);
> +    UNREFERENCED_PARAMETER(Parameters);
> +
> +    status = AdapterInitialize(NdisHandle, &Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return NDIS_STATUS_ADAPTER_NOT_FOUND;
> +}
> +
> +MINIPORT_HALT                   DriverHalt;
> +VOID
> +DriverHalt(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  NDIS_HALT_ACTION        HaltAction
> +    )
> +{
> +    if (NdisHandle == NULL)
> +        return;
> +
> +    UNREFERENCED_PARAMETER(HaltAction);
> +
> +    (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
> +    AdapterTeardown((PXENNET_ADAPTER)NdisHandle);
> +}
> +
> +typedef struct _XENNET_CONTEXT {
> +    PDEVICE_CAPABILITIES    Capabilities;
> +    PIO_COMPLETION_ROUTINE  CompletionRoutine;
> +    PVOID                   CompletionContext;
> +    UCHAR                   CompletionControl;
> +} XENNET_CONTEXT, *PXENNET_CONTEXT;
> +
> +__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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
> +
> +    Trace("<====\n");
> +
> +    return status;
> +}
> +
> +_Dispatch_type_(IRP_MJ_PNP)
> +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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
> +        break;
> +    }
> +
> +    return status;
> +}
> +
> +_Dispatch_type_(IRP_MJ_CREATE)
> +_Dispatch_type_(IRP_MJ_CLOSE)
> +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
> +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
> +    )
> +{
> +    Trace("====>\n");
> +
> +    if (*InitSafeBootMode > 0)
> +        goto done;
> +
> +    ASSERT3P(Driver.DriverObject, ==, DriverObject);
> +    Driver.DriverObject = NULL;
> +
> +    if (Driver.MiniportHandle)
> +        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
> +    Driver.MiniportHandle = NULL;
> +
> +    Driver.NdisDispatchPnp = NULL;
> +
> +    RegistryTeardown();
> +
> +    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;
> +    NTSTATUS                                status;
> +
> +    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
> +
> +    Trace("====>\n");
> +
> +    if (*InitSafeBootMode > 0)
> +        return NDIS_STATUS_SUCCESS;
> +
> +    ASSERT3P(Driver.DriverObject, ==, NULL);
> +    Driver.DriverObject = DriverObject;
> +
> +    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
> +         MAJOR_VERSION,
> +         MINOR_VERSION,
> +         MICRO_VERSION,
> +         BUILD_NUMBER,
> +         DAY,
> +         MONTH,
> +         YEAR);
> +
> +    status = RegistryInitialize(RegistryPath);
> +
> +    ndisStatus = (NT_SUCCESS(status)) ?
> +                 NDIS_STATUS_SUCCESS :
> +                 NDIS_STATUS_FAILURE;
> +
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail1;
> +
> +    //
> +    // Register miniport with NDIS.
> +    //
> +
> +    RtlZeroMemory(&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     = DriverCancelOidRequest;
> +    mpChars.CancelSendHandler           = DriverCancelSendNetBufferLists;
> +    mpChars.CheckForHangHandlerEx       = DriverCheckForHang;
> +    mpChars.InitializeHandlerEx         = DriverInitialize;
> +    mpChars.HaltHandlerEx               = DriverHalt;
> +    mpChars.OidRequestHandler           = DriverOidRequest;
> +    mpChars.PauseHandler                = DriverPause;
> +    mpChars.DevicePnPEventNotifyHandler = DriverPnPEventHandler;
> +    mpChars.ResetHandlerEx              = DriverReset;
> +    mpChars.RestartHandler              = DriverRestart;
> +    mpChars.ReturnNetBufferListsHandler = DriverReturnNetBufferLists;
> +    mpChars.SendNetBufferListsHandler   = DriverSendNetBufferLists;
> +    mpChars.ShutdownHandlerEx           = DriverShutdown;
> +    mpChars.UnloadHandler               = DriverUnload;
> +
> +    Driver.MiniportHandle = NULL;
> +    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
> +                                             RegistryPath,
> +                                             NULL,
> +                                             &mpChars,
> +                                             &Driver.MiniportHandle);
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail2;
> +
> +    RtlZeroMemory(&ConfigurationObject, sizeof(ConfigurationObject));
> +    ConfigurationObject.Header.Type     =
> NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
> +    ConfigurationObject.Header.Size     =
> NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
> +    ConfigurationObject.Header.Revision =
> NDIS_CONFIGURATION_OBJECT_REVISION_1;
> +    ConfigurationObject.NdisHandle      = Driver.MiniportHandle;
> +    ConfigurationObject.Flags           = 0;
> +
> +    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject,
> &ConfigurationHandle);
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail3;
> +
> +    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);
> +
> +    Driver.NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
> +    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
> +
> +    if (FailCreateClose != 0) {
> +        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
> +        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
> +    }
> +
> +    if (FailDeviceControl != 0) {
> +        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
> DispatchFail;
> +    }
> +
> +    Trace("<====\n");
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
> +    Driver.MiniportHandle = NULL;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    RegistryTeardown();
> +
> +fail1:
> +    Error("fail1\n");
> +
> +    Driver.DriverObject = NULL;
> +    return ndisStatus;
> +}
> +
> diff --git a/src/xennet/main.c b/src/xennet/main.c
> deleted file mode 100644
> index 6622e82..0000000
> --- a/src/xennet/main.c
> +++ /dev/null
> @@ -1,361 +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"
> -#include "registry.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;
> -    NTSTATUS status;
> -
> -    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);
> -
> -    status = RegistryInitialize(RegistryPath);
> -
> -    ndisStatus = (NT_SUCCESS(status)) ?
> -                 NDIS_STATUS_SUCCESS :
> -                 NDIS_STATUS_FAILURE;
> -
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        goto fail;
> -
> -    //
> -    // 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);
> -
> -    RegistryTeardown();
> -
> -    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/miniport.c b/src/xennet/miniport.c
> deleted file mode 100644
> index a1d605f..0000000
> --- a/src/xennet/miniport.c
> +++ /dev/null
> @@ -1,297 +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.
> - */
> -
> -#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,
> -    IN  ULONG           Size,
> -    IN  BOOLEAN         Optional
> -    )
> -{
> -    UNICODE_STRING      Unicode;
> -    HANDLE              InterfacesKey;
> -    HANDLE              SubscriberKey;
> -    KEVENT              Event;
> -    IO_STATUS_BLOCK     StatusBlock;
> -    PIRP                Irp;
> -    PIO_STACK_LOCATION  StackLocation;
> -    NTSTATUS            status;
> -
> -    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));
> -
> -    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
> -                                       DeviceObject,
> -                                       NULL,
> -                                       0,
> -                                       NULL,
> -                                       &Event,
> -                                       &StatusBlock);
> -
> -    status = STATUS_UNSUCCESSFUL;
> -    if (Irp == NULL)
> -        goto fail4;
> -
> -    StackLocation = IoGetNextIrpStackLocation(Irp);
> -    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
> -
> -    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;
> -    }
> -
> -    if (!NT_SUCCESS(status)) {
> -        if (status == STATUS_NOT_SUPPORTED && Optional)
> -            goto done;
> -
> -        goto fail5;
> -    }
> -
> -    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);
> -
> -    return status;
> -}
> -
> -#define QUERY_INTERFACE(                                                                \
> -    _DeviceObject,                                                                      \
> -    _ProviderName,                                                                      \
> -    _InterfaceName,                                                                     \
> -    _Version,                                                                           \
> -    _Interface,                                                                         \
> -    _Size,                                                                              \
> -    _Optional)                                                                          \
> -    __QueryInterface((_DeviceObject),                                                   \
> -                     L ## #_ProviderName,                                               \
> -                     #_InterfaceName,                                                   \
> -                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ##
> _INTERFACE,      \
> -                     (_Version),                                                        \
> -                     (_Interface),                                                      \
> -                     (_Size),                                                           \
> -                     (_Optional))
> -
> -NDIS_STATUS
> -MiniportInitialize (
> -    IN  NDIS_HANDLE                        MiniportAdapterHandle,
> -    IN  NDIS_HANDLE                        MiniportDriverContext,
> -    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
> -    )
> -{
> -    PADAPTER Adapter = NULL;
> -    NDIS_STATUS ndisStatus;
> -    PDEVICE_OBJECT DeviceObject;
> -    NTSTATUS status;
> -
> -    UNREFERENCED_PARAMETER(MiniportDriverContext);
> -    UNREFERENCED_PARAMETER(MiniportInitParameters);
> -
> -    Trace("====>\n");
> -
> -    status = AllocAdapter(&Adapter);
> -
> -    if (!NT_SUCCESS(status) || Adapter == NULL) {
> -        ndisStatus = NDIS_STATUS_RESOURCES;
> -        goto fail1;
> -    }
> -
> -    RtlZeroMemory(Adapter, sizeof (ADAPTER));
> -
> -    DeviceObject = NULL;
> -    NdisMGetDeviceProperty(MiniportAdapterHandle,
> -                           &DeviceObject,
> -                           NULL,
> -                           NULL,
> -                           NULL,
> -                           NULL);
> -
> -    status = QUERY_INTERFACE(DeviceObject,
> -                             XENVIF,
> -                             VIF,
> -                             XENVIF_VIF_INTERFACE_VERSION_MAX,
> -                             (PINTERFACE)&Adapter->VifInterface,
> -                             sizeof (Adapter->VifInterface),
> -                             FALSE);
> -
> -    if (!NT_SUCCESS(status)) {
> -        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
> -        goto fail2;
> -    }
> -
> -    ndisStatus = AdapterInitialize(Adapter, MiniportAdapterHandle);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto fail3;
> -    }
> -
> -    Trace("<====\n");
> -    return ndisStatus;
> -
> -fail3:
> -    Error("fail3\n");
> -
> -    RtlZeroMemory(&Adapter->VifInterface,
> -                  sizeof (XENVIF_VIF_INTERFACE));
> -
> -fail2:
> -    Error("fail2\n");
> -
> -    ExFreePool(Adapter);
> -
> -fail1:
> -    Error("fail1\n");
> -
> -    return ndisStatus;
> -}
> -
> -//
> -// Stops adapter and frees all resources.
> -//
> -VOID
> -MiniportHalt (
> -    IN  NDIS_HANDLE             MiniportAdapterHandle,
> -    IN  NDIS_HALT_ACTION        HaltAction
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterHandle;
> -
> -    UNREFERENCED_PARAMETER(HaltAction);
> -
> -    if (Adapter == NULL)
> -        return;
> -
> -    (VOID) AdapterStop(Adapter);
> -
> -    AdapterCleanup(Adapter);
> -
> -    RtlZeroMemory(&Adapter->VifInterface,
> -                  sizeof (XENVIF_VIF_INTERFACE));
> -
> -    ExFreePool(Adapter);
> -}
> 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..ee01a18 100644
> --- a/src/xennet/receiver.c
> +++ b/src/xennet/receiver.c
> @@ -29,103 +29,38 @@
>   * SUCH DAMAGE.
>   */
> 
> -#include "common.h"
> -
> -#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;
> -}
> +#include <ndis.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       'teNX'
> +#define IN_NDIS_MAX 1024
> 
> -PNET_BUFFER_LIST
> +static PNET_BUFFER_LIST
>  ReceiverAllocateNetBufferList(
> -    IN  PRECEIVER       Receiver,
> -    IN  PMDL            Mdl,
> -    IN  ULONG           Offset,
> -    IN  ULONG           Length
> +    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();
> -
>      NetBufferList = Receiver->GetList[Cpu];
> 
>      if (NetBufferList == NULL)
> @@ -158,16 +93,16 @@ ReceiverAllocateNetBufferList(
>      return NetBufferList;
>  }
> 
> -VOID
> +static VOID
>  ReceiverReleaseNetBufferList(
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  BOOLEAN             Cache
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  BOOLEAN                 Cache
>      )
>  {
>      if (Cache) {
> -        PNET_BUFFER_LIST    Old;
> -        PNET_BUFFER_LIST    New;
> +        PNET_BUFFER_LIST        Old;
> +        PNET_BUFFER_LIST        New;
> 
>          ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> 
> @@ -182,72 +117,9 @@ ReceiverReleaseNetBufferList(
>      }
>  }
> 
> -static FORCEINLINE ULONG
> -__ReceiverReturnNetBufferLists(
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  BOOLEAN             Cache
> -    )
> -{
> -    PADAPTER                Adapter;
> -    LIST_ENTRY              List;
> -    ULONG                   Count;
> -
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> -
> -    InitializeListHead(&List);
> -
> -    Count = 0;
> -    while (NetBufferList != NULL) {
> -        PNET_BUFFER_LIST        Next;
> -        PNET_BUFFER             NetBuffer;
> -        PMDL                    Mdl;
> -        PXENVIF_RECEIVER_PACKET Packet;
> -
> -        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> -        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> -
> -        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> -        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
> -
> -        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
> -
> -        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
> -
> -        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
> -
> -        InsertTailList(&List, &Packet->ListEntry);
> -
> -        Count++;
> -        NetBufferList = Next;
> -    }
> -
> -    if (Count != 0)
> -        XENVIF_VIF(ReceiverReturnPackets,
> -                   &Adapter->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  PXENNET_RECEIVER                        Receiver,
>      IN  PMDL                                    Mdl,
>      IN  ULONG                                   Offset,
>      IN  ULONG                                   Length,
> @@ -255,11 +127,11 @@ ReceiverReceivePacket(
>      IN  USHORT                                  TagControlInformation
>      )
>  {
> -    PADAPTER                                    Adapter;
> +    PXENNET_ADAPTER                             Adapter;
>      PNET_BUFFER_LIST                            NetBufferList;
>      NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> +    Adapter = Receiver->Adapter;
> 
>      NetBufferList = ReceiverAllocateNetBufferList(Receiver,
>                                                    Mdl,
> @@ -268,7 +140,7 @@ ReceiverReceivePacket(
>      if (NetBufferList == NULL)
>          goto fail1;
> 
> -    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
> +    NetBufferList->SourceHandle = AdapterGetHandle(Adapter);
> 
>      csumInfo.Value = 0;
> 
> @@ -281,8 +153,8 @@ ReceiverReceivePacket(
>      csumInfo.Receive.UdpChecksumSucceeded =
> Flags.UdpChecksumSucceeded;
>      csumInfo.Receive.UdpChecksumFailed = Flags.UdpChecksumFailed;
> 
> -    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo)
> = (PVOID)(ULONG_PTR)csumInfo.Value;
> -
> +    NET_BUFFER_LIST_INFO(NetBufferList,
> TcpIpChecksumNetBufferListInfo) =
> +                                            (PVOID)(ULONG_PTR)csumInfo.Value;
>      if (TagControlInformation != 0) {
>          NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
> 
> @@ -306,20 +178,67 @@ fail1:
>      return NULL;
>  }
> 
> +static FORCEINLINE ULONG
> +__ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  BOOLEAN                 Cache
> +    )
> +{
> +    PXENNET_ADAPTER             Adapter;
> +    LIST_ENTRY                  List;
> +    ULONG                       Count;
> +
> +    Adapter = Receiver->Adapter;
> +
> +    InitializeListHead(&List);
> +
> +    Count = 0;
> +    while (NetBufferList != NULL) {
> +        PNET_BUFFER_LIST        Next;
> +        PNET_BUFFER             NetBuffer;
> +        PMDL                    Mdl;
> +        PXENVIF_RECEIVER_PACKET Packet;
> +
> +        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> +        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> +
> +        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> +        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
> +
> +        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
> +
> +        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
> +
> +        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
> +
> +        InsertTailList(&List, &Packet->ListEntry);
> +
> +        Count++;
> +        NetBufferList = Next;
> +    }
> +
> +    if (Count != 0) {
> +        XENVIF_VIF(ReceiverReturnPackets,
> +                   AdapterGetVifInterface(Adapter),
> +                   &List);
> +    }
> +    return Count;
> +}
> +
>  static VOID
>  ReceiverPushPackets(
> -    IN  PRECEIVER           Receiver,
> +    IN  PXENNET_RECEIVER    Receiver,
>      IN  PNET_BUFFER_LIST    NetBufferList,
>      IN  ULONG               Count,
>      IN  BOOLEAN             LowResources
>      )
>  {
> -    PADAPTER                Adapter;
> +    PXENNET_ADAPTER         Adapter;
>      ULONG                   Flags;
>      LONG                    InNDIS;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> -
> +    Adapter = Receiver->Adapter;
>      InNDIS = Receiver->InNDIS;
> 
>      Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
> @@ -342,7 +261,7 @@ ReceiverPushPackets(
>              break;
>      }
> 
> -    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
> +    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Adapter),
>                                         NetBufferList,
>                                         NDIS_DEFAULT_PORT_NUMBER,
>                                         Count,
> @@ -352,21 +271,34 @@ ReceiverPushPackets(
>          (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
>  }
> 
> -#define IN_NDIS_MAX 1024
> +VOID
> +ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
> +    )
> +{
> +    ULONG                   Count;
> +
> +    UNREFERENCED_PARAMETER(ReturnFlags);
> +
> +    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferLists,
> 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;
> +    PXENNET_ADAPTER     Adapter;
>      PNET_BUFFER_LIST    HeadNetBufferList;
>      PNET_BUFFER_LIST    *TailNetBufferList;
>      ULONG               Count;
>      BOOLEAN             LowResources;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> +    Adapter = Receiver->Adapter;
>      LowResources = FALSE;
> 
>  again:
> @@ -404,21 +336,26 @@ 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);
> +                       AdapterGetVifInterface(Adapter),
> +                       &PacketList);
>          }
>      }
> 
> @@ -434,3 +371,95 @@ again:
>          goto again;
>      }
>  }
> +
> +PXENVIF_VIF_OFFLOAD_OPTIONS
> +ReceiverOffloadOptions(
> +    IN  PXENNET_RECEIVER        Receiver
> +    )
> +{
> +    return &Receiver->OffloadOptions;
> +}
> +
> +NTSTATUS
> +ReceiverInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_RECEIVER        *Receiver
> +    )
> +{
> +    NTSTATUS                        status;
> +    NET_BUFFER_LIST_POOL_PARAMETERS Pool;
> +
> +    status = STATUS_NO_MEMORY;
> +    *Receiver = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_RECEIVER), RECEIVER_POOL_TAG);
> +    if (*Receiver == NULL)
> +        goto fail1;
> +
> +    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
> +    (*Receiver)->Adapter = Adapter;
> +
> +    RtlZeroMemory(&Pool, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
> +    Pool.Header.Type        = NDIS_OBJECT_TYPE_DEFAULT;
> +    Pool.Header.Size        = sizeof(NET_BUFFER_LIST_POOL_PARAMETERS);
> +    Pool.Header.Revision    =
> NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
> +    Pool.ProtocolId         = 0;
> +    Pool.ContextSize        = 0;
> +    Pool.fAllocateNetBuffer = TRUE;
> +    Pool.PoolTag            = RECEIVER_POOL_TAG;
> +
> +    (*Receiver)->NetBufferListPool =
> NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
> +                                                                   &Pool);
> +    if ((*Receiver)->NetBufferListPool == NULL)
> +        goto fail2;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    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;
> +
> +    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
> +}
> +
> diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
> index 1a58053..715f02e 100644
> --- a/src/xennet/receiver.h
> +++ b/src/xennet/receiver.h
> @@ -29,49 +29,42 @@
>   * 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;
> +typedef struct _XENNET_RECEIVER     XENNET_RECEIVER,
> *PXENNET_RECEIVER;
> 
> -VOID
> -ReceiverDebugDump (
> -    IN PRECEIVER Receiver
> -    );
> +#include <vif_interface.h>
> 
> -VOID
> -ReceiverCleanup (
> -    IN  PRECEIVER Receiver
> +extern VOID
> +ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
>      );
> 
> -VOID
> -ReceiverHandleNotification (
> -    IN  PRECEIVER Receiver
> +extern VOID
> +ReceiverReceivePackets(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PLIST_ENTRY             List
>      );
> 
> -NDIS_STATUS
> -ReceiverInitialize (
> -    IN  PRECEIVER   Receiver
> +extern PXENVIF_VIF_OFFLOAD_OPTIONS
> +ReceiverOffloadOptions(
> +    IN  PXENNET_RECEIVER        Receiver
>      );
> 
> -VOID
> -ReceiverReturnNetBufferLists (
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  ULONG               ReturnFlags
> +#include "adapter.h"
> +extern NTSTATUS
> +ReceiverInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_RECEIVER        *Receiver
>      );
> 
> -VOID
> -ReceiverWaitForPacketReturn(
> -    IN  PRECEIVER   Receiver,
> -    IN  BOOLEAN     Locked
> +extern VOID
> +ReceiverTeardown(
> +    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..be07458 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -29,59 +29,18 @@
>   * SUCH DAMAGE.
>   */
> 
> -#include "common.h"
> +#include <ndis.h>
> +#include "transmitter.h"
> +#include "adapter.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> 
> -#pragma warning(disable:4711)
> +struct _XENNET_TRANSMITTER {
> +    PXENNET_ADAPTER             Adapter;
> +    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> +};
> 
> -NDIS_STATUS
> -TransmitterInitialize(
> -    IN  PTRANSMITTER    Transmitter,
> -    IN  PADAPTER        Adapter
> -    )
> -{
> -    Transmitter->Adapter = Adapter;
> -
> -    return NDIS_STATUS_SUCCESS;
> -}
> -
> -VOID
> -TransmitterEnable(
> -    IN  PTRANSMITTER    Transmitter
> -    )
> -{
> -    PADAPTER            Adapter = Transmitter->Adapter;
> -
> -    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> -                      &Adapter->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,
> -                      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,
> -                      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;
> -    }
> -}
> +#define TRANSMITTER_POOL_TAG    'teNX'
> 
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
> @@ -97,24 +56,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             NdisStatus
>      )
>  {
> +    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
> +
>      ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> 
> -    NET_BUFFER_LIST_STATUS(NetBufferList) =
> NDIS_STATUS_NOT_ACCEPTED;
> +    if (NdisStatus == 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;
> +    }
> +    NET_BUFFER_LIST_STATUS(NetBufferList) = NdisStatus;
> 
> -    NdisMSendNetBufferListsComplete(Transmitter->Adapter-
> >NdisAdapterHandle,
> +    NdisMSendNetBufferListsComplete(AdapterGetHandle(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                 NdisStatus
>      )
>  {
>      while (Packet != NULL) {
> @@ -135,21 +107,85 @@ TransmitterAbortPackets(
> 
>          ASSERT(ListReserved->Reference != 0);
>          if (InterlockedDecrement(&ListReserved->Reference) == 0)
> -            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
> +            TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NdisStatus);
> 
>          Packet = Next;
>      }
>  }
> +
> +static FORCEINLINE VOID
> +__OffloadOptions(
> +    IN  PNET_BUFFER_LIST            NetBufferList,
> +    OUT PXENVIF_VIF_OFFLOAD_OPTIONS Offload,
> +    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);
> +
> +    Offload->Value = 0;
> +    *TagControlInformation = 0;
> +    *MaximumSegmentSize = 0;
> +
> +    if (ChecksumInfo->Transmit.IsIPv4) {
> +        if (ChecksumInfo->Transmit.IpHeaderChecksum)
> +            Offload->OffloadIpVersion4HeaderChecksum = 1;
> +        if (ChecksumInfo->Transmit.TcpChecksum)
> +            Offload->OffloadIpVersion4TcpChecksum = 1;
> +        if (ChecksumInfo->Transmit.UdpChecksum)
> +            Offload->OffloadIpVersion4UdpChecksum = 1;
> +    }
> +
> +    if (ChecksumInfo->Transmit.IsIPv6) {
> +        if (ChecksumInfo->Transmit.TcpChecksum)
> +            Offload->OffloadIpVersion6TcpChecksum = 1;
> +        if (ChecksumInfo->Transmit.UdpChecksum)
> +            Offload->OffloadIpVersion6UdpChecksum = 1;
> +    }
> +
> +    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
> +        Offload->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)
> +            Offload->OffloadIpVersion4LargePacket = 1;
> +        if (LargeSendInfo->LsoV2Transmit.IPVersion ==
> NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
> +            Offload->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;
> +    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
>      PXENVIF_TRANSMITTER_PACKET  HeadPacket;
>      PXENVIF_TRANSMITTER_PACKET  *TailPacket;
>      KIRQL                       Irql;
> @@ -158,21 +194,21 @@ TransmitterSendNetBufferLists(
> 
>      HeadPacket = NULL;
>      TailPacket = &HeadPacket;
> -
> +
>      if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
>          ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
>          NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
>      } else {
>          Irql = DISPATCH_LEVEL;
>      }
> -
> +
>      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;
> +        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
> +        USHORT                          TagControlInformation;
> +        USHORT                          MaximumSegmentSize;
> +        PNET_BUFFER                     NetBuffer;
> 
>          ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
>          NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> @@ -180,12 +216,7 @@ TransmitterSendNetBufferLists(
>          ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
>          RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
> 
> -        LargeSendInfo =
> (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFF
> ER_LIST_INFO(NetBufferList,
> -
> TcpLargeSendNetBufferListInfo);
> -        ChecksumInfo =
> (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_I
> NFO(NetBufferList,
> -
> TcpIpChecksumNetBufferListInfo);
> -        Ieee8021QInfo =
> (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBuff
> erList,
> -                                                                                Ieee8021QNetBufferListInfo);
> +        __OffloadOptions(NetBufferList, &Options, &TagControlInformation,
> &MaximumSegmentSize);
> 
>          NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
>          while (NetBuffer != NULL) {
> @@ -199,50 +230,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   = Options.Value & Transmitter-
> >OffloadOptions.Value;
> +            Packet->Send.TagControlInformation  = TagControlInformation;
> +            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
> 
>              ASSERT3P(Packet->Next, ==, NULL);
>              *TailPacket = Packet;
> @@ -258,65 +248,89 @@ TransmitterSendNetBufferLists(
>          NTSTATUS    status;
> 
>          status = XENVIF_VIF(TransmitterQueuePackets,
> -                            &Adapter->VifInterface,
> +                            AdapterGetVifInterface(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
> +VOID
> +TransmitterCompletePackets(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET  Packet
>      )
>  {
> -    PADAPTER                                            Adapter = Transmitter->Adapter;
> -    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO
> LargeSendInfo;
> +    __TransmitterCompletePackets(Transmitter,
> +                                 Packet,
> +                                 NDIS_STATUS_SUCCESS);
> +}
> 
> -    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> +VOID
> +TransmitterEnable(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter-
> >Adapter);
> 
> -    LargeSendInfo =
> (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFF
> ER_LIST_INFO(NetBufferList,
> -
> TcpLargeSendNetBufferListInfo);
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> 
> -    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
> -        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> 
> -    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> +}
> 
> -    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
> -                                    NetBufferList,
> -                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
> +PXENVIF_VIF_OFFLOAD_OPTIONS
> +TransmitterOffloadOptions(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    return &Transmitter->OffloadOptions;
>  }
> 
> -VOID
> -TransmitterCompletePackets(
> -    IN  PTRANSMITTER                Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +NTSTATUS
> +TransmitterInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_TRANSMITTER     *Transmitter
>      )
>  {
> -    while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> -        PNET_BUFFER_RESERVED        Reserved;
> -        PNET_BUFFER_LIST            NetBufferList;
> -        PNET_BUFFER_LIST_RESERVED   ListReserved;
> +    NTSTATUS            status;
> 
> -        Next = Packet->Next;
> -        Packet->Next = NULL;
> +    status = STATUS_NO_MEMORY;
> +    *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_TRANSMITTER), TRANSMITTER_POOL_TAG);
> +    if (*Transmitter == NULL)
> +        goto fail1;
> 
> -        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED,
> Packet);
> +    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
> +    (*Transmitter)->Adapter = Adapter;
> 
> -        NetBufferList = Reserved->NetBufferList;
> -        ASSERT(NetBufferList != NULL);
> +    return STATUS_SUCCESS;
> 
> -        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> 
> -        ASSERT(ListReserved->Reference != 0);
> -        if (InterlockedDecrement(&ListReserved->Reference) == 0)
> -            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
> +}
> 
> -        Packet = Next;
> -    }
> +VOID
> +TransmitterTeardown(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
>  }
> +
> diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
> index 8dc7e8d..f99ffd3 100644
> --- a/src/xennet/transmitter.h
> +++ b/src/xennet/transmitter.h
> @@ -29,47 +29,48 @@
>   * SUCH DAMAGE.
>   */
> 
> -#pragma once
> +#ifndef _XENNET_TRANSMITTER_H_
> +#define _XENNET_TRANSMITTER_H_
> 
> -typedef struct _TRANSMITTER {
> -    PADAPTER                    Adapter;
> -    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> -} TRANSMITTER, *PTRANSMITTER;
> +typedef struct _XENNET_TRANSMITTER  XENNET_TRANSMITTER,
> *PXENNET_TRANSMITTER;
> 
> -VOID
> -TransmitterCleanup (
> -    IN OUT PTRANSMITTER* Transmitter
> +#include <vif_interface.h>
> +
> +extern VOID
> +TransmitterSendNetBufferLists(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
>      );
> 
> -NDIS_STATUS
> -TransmitterInitialize (
> -    IN  PTRANSMITTER    Transmitter,
> -    IN  PADAPTER        Adapter
> +extern VOID
> +TransmitterCompletePackets(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET  Packet
>      );
> 
> -VOID
> -TransmitterEnable (
> -    IN  PTRANSMITTER    Transmitter
> +extern VOID
> +TransmitterEnable(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -VOID
> -TransmitterDelete (
> -    IN OUT PTRANSMITTER* Transmitter
> +extern PXENVIF_VIF_OFFLOAD_OPTIONS
> +TransmitterOffloadOptions(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -VOID
> -TransmitterSendNetBufferLists (
> -    IN  PTRANSMITTER        Transmitter,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  NDIS_PORT_NUMBER    PortNumber,
> -    IN  ULONG               SendFlags
> +#include "adapter.h"
> +extern NTSTATUS
> +TransmitterInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_TRANSMITTER     *Transmitter
>      );
> 
> -VOID
> -TransmitterCompletePackets(
> -    IN  PTRANSMITTER                Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +extern VOID
> +TransmitterTeardown(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -void TransmitterPause(PTRANSMITTER Transmitter);
> -void TransmitterUnpause(PTRANSMITTER Transmitter);
> +#endif // _XENNET_TRANSMITTER_H_
> +
> diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
> index db07e9b..4b6e780 100644
> --- a/vs2012/xennet/xennet.vcxproj
> +++ b/vs2012/xennet/xennet.vcxproj
> @@ -84,9 +84,8 @@
>  	</ItemGroup>
>  	<ItemGroup>
>  		<ClCompile Include="../../src/xennet/registry.c" />
> +		<ClCompile Include="../../src/xennet/driver.c" />
>  		<ClCompile Include="../../src/xennet/adapter.c" />
> -		<ClCompile Include="../../src/xennet/main.c" />
> -		<ClCompile Include="../../src/xennet/miniport.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 908bc2d..d890878 100644
> --- a/vs2013/xennet/xennet.vcxproj
> +++ b/vs2013/xennet/xennet.vcxproj
> @@ -115,9 +115,8 @@
>    </ItemGroup>
>    <ItemGroup>
>      <ClCompile Include="../../src/xennet/registry.c" />
> +    <ClCompile Include="../../src/xennet/driver.c" />
>      <ClCompile Include="../../src/xennet/adapter.c" />
> -    <ClCompile Include="../../src/xennet/main.c" />
> -    <ClCompile Include="../../src/xennet/miniport.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 Mon Nov 17 13:23:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:23: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 1XqMHI-0003Jw-EP; Mon, 17 Nov 2014 13:23:36 +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 1XqMHG-0003Jr-89
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:23:35 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	09/A7-25714-5D6F9645; Mon, 17 Nov 2014 13:23:33 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1416230606!6378852!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30465 invoked from network); 17 Nov 2014 13:23:26 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:23:26 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26900491"
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: [PATCH 1/4] Refactor for maintainability/coding style
Thread-Index: AQHP/pcqptJ0/lgdsE6oYfEVKXByPJxk1ZVg
Date: Mon, 17 Nov 2014 13:23:24 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115364D@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-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/4] Refactor for maintainability/coding
	style
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 1/4] Refactor for maintainability/coding style
> 
> Removes common headers and the disabling of warnings via #pragmas
> Fits code into driver.c (DriverEntry/Dispatch overrides), adapter.c
> (NDIS miniport). Resolves differences in receiver/transmitter
> implementations.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

This patch is not really reviewable, given its size, but I think it is worth taking the risk. I know that you need to re-factor a bit though due to WHQL failure (access of registry functions) so I'll wait until v2 is available (and passing WHQL) and the review the code after applying the patch.

  Paul

> ---
>  src/xennet/adapter.c         | 3833 +++++++++++++++++++-----------------------
>  src/xennet/adapter.h         |  154 +-
>  src/xennet/common.h          |   36 -
>  src/xennet/driver.c          |  550 ++++++
>  src/xennet/main.c            |  361 ----
>  src/xennet/miniport.c        |  297 ----
>  src/xennet/project.h         |   66 -
>  src/xennet/receiver.c        |  393 +++--
>  src/xennet/receiver.h        |   59 +-
>  src/xennet/std.h             |   45 -
>  src/xennet/transmitter.c     |  330 ++--
>  src/xennet/transmitter.h     |   61 +-
>  vs2012/xennet/xennet.vcxproj |    3 +-
>  vs2013/xennet/xennet.vcxproj |    3 +-
>  14 files changed, 2770 insertions(+), 3421 deletions(-)
>  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/miniport.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..6b32d1a 100644
> --- a/src/xennet/adapter.c
> +++ b/src/xennet/adapter.c
> @@ -28,51 +28,44 @@
>   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>   * SUCH DAMAGE.
>   */
> +#define INITGUID
> 
> +#include <ndis.h>
> +#include <ntstrsafe.h>
>  #include <version.h>
> -#include "common.h"
> 
> -#pragma warning(disable:4711)
> +#include "adapter.h"
> +#include "registry.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> 
> -//
> -// List of supported OIDs.
> -//
> +struct _XENNET_ADAPTER {
> +    XENVIF_VIF_INTERFACE        VifInterface;
> 
> -static NDIS_STATUS
> -AdapterSetRegistrationAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    BOOLEAN                     Enabled;
> +    ULONG                       MaximumFrameSize;
> +    ULONG                       CurrentLookahead;
> 
> -static NDIS_STATUS
> -AdapterSetGeneralAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    NDIS_HANDLE                 NdisHandle;
> +    NDIS_HANDLE                 NdisDmaHandle;
> +    NDIS_PNP_CAPABILITIES       Capabilities;
> +    NDIS_OFFLOAD                Offload;
> +    XENNET_PROPERTIES           Properties;
> 
> -static NDIS_STATUS
> -AdapterSetOffloadAttributes (
> -    IN  PADAPTER Adapter
> -    );
> +    PXENNET_RECEIVER            Receiver;
> +    PXENNET_TRANSMITTER         Transmitter;
> +};
> 
> -static MINIPORT_PROCESS_SG_LIST AdapterProcessSGList;
> -static VOID
> -AdapterProcessSGList (
> -    IN PDEVICE_OBJECT       DeviceObject,
> -    IN PVOID                Reserved,
> -    IN PSCATTER_GATHER_LIST SGL,
> -    IN PVOID                Context
> -    );
> +#define XENNET_POOL_TAG         'tenX'
> 
> -static NDIS_STATUS
> -AdapterSetInformation (
> -    IN  PADAPTER            Adapter,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    );
> +#define XENNET_MEDIA_MAX_SPEED  1000000000ull
> 
> -static NDIS_STATUS
> -AdapterQueryInformation (
> -    IN  PADAPTER            Adapter,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    );
> +#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)
> 
>  static NDIS_OID XennetSupportedOids[] =
>  {
> @@ -129,31 +122,9 @@ 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)
> -
> -NTSTATUS AllocAdapter(OUT PADAPTER *Adapter)
> -{
> -    if (Adapter == NULL)
> -        return STATUS_INVALID_PARAMETER;
> -
> -    *Adapter = (PADAPTER)ExAllocatePoolWithTag(NonPagedPool, sizeof
> (ADAPTER), ' TEN');
> -    if (*Adapter == NULL)
> -        return STATUS_INSUFFICIENT_RESOURCES;
> -
> -    return STATUS_SUCCESS;
> -}
> -
> -//
> -// Scatter gather allocate handler callback.
> -// Should never get called.
> -//
>  __drv_functionClass(MINIPORT_ALLOCATE_SHARED_MEM_COMPLETE)
>  static VOID
> -AdapterAllocateComplete (
> +AdapterAllocateComplete(
>      IN NDIS_HANDLE              MiniportAdapterContext,
>      IN PVOID                    VirtualAddress,
>      IN PNDIS_PHYSICAL_ADDRESS   PhysicalAddress,
> @@ -168,139 +139,33 @@ 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;
>  }
> 
> +__drv_functionClass(MINIPORT_PROCESS_SG_LIST)
>  static VOID
> -AdapterMediaStateChange(
> -    IN  PADAPTER                Adapter
> +AdapterProcessSGList(
> +    IN PDEVICE_OBJECT           DeviceObject,
> +    IN PVOID                    Reserved,
> +    IN PSCATTER_GATHER_LIST     SGL,
> +    IN PVOID                    Context
>      )
>  {
> -    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);
> +    UNREFERENCED_PARAMETER(DeviceObject);
> +    UNREFERENCED_PARAMETER(Reserved);
> +    UNREFERENCED_PARAMETER(SGL);
> +    UNREFERENCED_PARAMETER(Context);
> 
> -    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
> +    ASSERT(FALSE);
>  }
> 
> -
> -//
> -// 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;
> +    PXENNET_ADAPTER                 Adapter = Context;
>      va_list                         Arguments;
> 
>      va_start(Arguments, Type);
> @@ -319,7 +184,7 @@ AdapterVifCallback(
> 
>          List = va_arg(Arguments, PLIST_ENTRY);
> 
> -        ReceiverReceivePackets(&Adapter->Receiver, List);
> +        ReceiverReceivePackets(Adapter->Receiver, List);
>          break;
>      }
>      case XENVIF_MAC_STATE_CHANGE: {
> @@ -331,39 +196,220 @@ AdapterVifCallback(
>      va_end(Arguments);
>  }
> 
> -NDIS_STATUS
> -AdapterGetAdvancedSettings(
> -    IN PADAPTER pAdapter
> +#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,
> +    IN  ULONG           Size,
> +    IN  BOOLEAN         Optional
>      )
>  {
> -    NDIS_CONFIGURATION_OBJECT configObject;
> -    NDIS_HANDLE hConfigurationHandle;
> -    NDIS_STRING ndisValue;
> -    PNDIS_CONFIGURATION_PARAMETER pNdisData;
> -    NDIS_STATUS ndisStatus;
> -    NTSTATUS status;
> +    UNICODE_STRING      Unicode;
> +    HANDLE              InterfacesKey;
> +    HANDLE              SubscriberKey;
> +    KEVENT              Event;
> +    IO_STATUS_BLOCK     StatusBlock;
> +    PIRP                Irp;
> +    PIO_STACK_LOCATION  StackLocation;
> +    NTSTATUS            status;
> +
> +    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));
> 
> -    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;
> +    Unicode.Length = (USHORT)(wcslen(Unicode.Buffer) * sizeof (WCHAR));
> 
> -    ndisStatus = NdisOpenConfigurationEx(&configObject,
> &hConfigurationHandle);
> +    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));
> +
> +    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
> +                                       DeviceObject,
> +                                       NULL,
> +                                       0,
> +                                       NULL,
> +                                       &Event,
> +                                       &StatusBlock);
> 
>      status = STATUS_UNSUCCESSFUL;
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +    if (Irp == NULL)
> +        goto fail4;
> +
> +    StackLocation = IoGetNextIrpStackLocation(Irp);
> +    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
> +
> +    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;
> +    }
> +
> +    if (!NT_SUCCESS(status)) {
> +        if (status == STATUS_NOT_SUPPORTED && Optional)
> +            goto done;
> +
> +        goto fail5;
> +    }
> +
> +    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);
> +
> +    return status;
> +}
> +
> +#define QUERY_INTERFACE(                                                                \
> +    _DeviceObject,                                                                      \
> +    _ProviderName,                                                                      \
> +    _InterfaceName,                                                                     \
> +    _Version,                                                                           \
> +    _Interface,                                                                         \
> +    _Size,                                                                              \
> +    _Optional)                                                                          \
> +    __QueryInterface((_DeviceObject),                                                   \
> +                     L ## #_ProviderName,                                               \
> +                     #_InterfaceName,                                                   \
> +                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ##
> _INTERFACE,      \
> +                     (_Version),                                                        \
> +                     (_Interface),                                                      \
> +                     (_Size),                                                           \
> +                     (_Optional))
> +
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetRegistrationAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES Attribs;
> +    NDIS_STATUS                                   status;
> +
> +    RtlZeroMemory(&Attribs,
> sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
> +    Attribs.Header.Type                 =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
> +    Attribs.Header.Size                 =
> sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
> +    Attribs.Header.Revision             =
> NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
> +    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;
> +
> +    status = NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
> +    return status;
> +}
> +
> +static FORCEINLINE NDIS_STATUS
> +AdapterGetAdvancedSettings(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_CONFIGURATION_OBJECT   Config;
> +    NDIS_HANDLE                 Handle;
> +    NDIS_STRING                 Value;
> +    PNDIS_CONFIGURATION_PARAMETER Data;
> +    NDIS_STATUS                 NdisStatus;
> +
> +    RtlZeroMemory(&Config, sizeof(NDIS_CONFIGURATION_OBJECT));
> +    Config.Header.Type      = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
> +    Config.Header.Size      =
> NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
> +    Config.Header.Revision  = NDIS_CONFIGURATION_OBJECT_REVISION_1;
> +    Config.NdisHandle       = Adapter->NdisHandle;
> +    Config.Flags            = 0;
> +
> +    NdisStatus = NdisOpenConfigurationEx(&Config, &Handle);
> +    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; \
> -        } \
> +#define read_property(_field, _name, _default_val)                                          \
> +    do {                                                                                    \
> +        RtlInitUnicodeString(&Value, _name);                                                \
> +        NdisReadConfiguration(&NdisStatus, &Data, Handle, &Value,
> NdisParameterInteger);    \
> +        if (NdisStatus == NDIS_STATUS_SUCCESS) {                                            \
> +            Adapter->Properties._field = Data->ParameterData.IntegerData;
> \
> +        } else {                                                                            \
> +            Adapter->Properties._field = _default_val;                                      \
> +        }                                                                                   \
>      } while (FALSE);
> 
>      read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
> @@ -377,465 +423,827 @@ AdapterGetAdvancedSettings(
>      read_property(lrov6, L"LROIPv6", 1);
>      read_property(need_csum_value, L"NeedChecksumValue", 1);
> 
> -    NdisCloseConfiguration(hConfigurationHandle);
> -
> +    NdisCloseConfiguration(Handle);
>      return NDIS_STATUS_SUCCESS;
> 
>  fail1:
> -    Error("fail1\n");
> -    return NDIS_STATUS_FAILURE;
> +    Error("fail1 (%08x)\n", NdisStatus);
> +    return NdisStatus;
>  }
> 
> -NDIS_STATUS
> -AdapterInitialize (
> -    IN  PADAPTER    Adapter,
> -    IN  NDIS_HANDLE AdapterHandle
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetGeneralAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
>      )
>  {
> -    NDIS_STATUS ndisStatus;
> -    NDIS_SG_DMA_DESCRIPTION DmaDescription;
> -    NTSTATUS status;
> -
> -    status = XENVIF_VIF(Acquire, &Adapter->VifInterface);
> -    if (!NT_SUCCESS(status))
> -        return NDIS_STATUS_FAILURE;
> +    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES    Attribs;
> 
> -    Adapter->AcquiredInterfaces = TRUE;
> +    XENVIF_VIF(MacQueryMaximumFrameSize,
> +               &Adapter->VifInterface,
> +               (PULONG)&Adapter->MaximumFrameSize);
> 
> -    Trace("====>\n");
> +    RtlZeroMemory(&Attribs,
> sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
> +
> +    Attribs.Header.Type         =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
> +    Attribs.Header.Size         =
> sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
> +    Attribs.Header.Revision     =
> NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
> +    Attribs.MediaType               = XENNET_MEDIA_TYPE;
> +    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;
> +    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;
> +    Attribs.SupportedOidList        = XennetSupportedOids;
> +    Attribs.SupportedOidListLength  = sizeof(XennetSupportedOids);
> 
> -    Adapter->NdisAdapterHandle = AdapterHandle;
> +    XENVIF_VIF(MacQueryPermanentAddress,
> +               &Adapter->VifInterface,
> +               (PETHERNET_ADDRESS)&Attribs.PermanentMacAddress);
> +    XENVIF_VIF(MacQueryCurrentAddress,
> +               &Adapter->VifInterface,
> +               (PETHERNET_ADDRESS)&Attribs.CurrentMacAddress);
> 
> -    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
> +    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
> +}
> 
> -    Adapter->Transmitter =
> (PTRANSMITTER)ExAllocatePoolWithTag(NonPagedPool,
> sizeof(TRANSMITTER), ' TEN');
> -    if (!Adapter->Transmitter) {
> -        ndisStatus = NDIS_STATUS_RESOURCES;
> -        goto exit;
> +static FORCEINLINE NDIS_STATUS
> +AdapterSetOffloadAttributes(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES    Attribs;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS                 RxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS                 TxOptions;
> +    NDIS_OFFLOAD                                Default;
> +    NDIS_OFFLOAD                                Supported;
> +
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> +    RxOptions->Value = 0;
> +    RxOptions->OffloadTagManipulation = 1;
> +
> +    if (Adapter->Properties.need_csum_value) {
> +        RxOptions->NeedChecksumValue = 1;
>      }
> -
> -    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
> -
> -    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (Adapter->Properties.lrov4) {
> +        RxOptions->OffloadIpVersion4LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
>      }
> -
> -    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (Adapter->Properties.lrov6) {
> +        RxOptions->OffloadIpVersion6LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
>      }
> +    XENVIF_VIF(ReceiverSetOffloadOptions,
> +               &Adapter->VifInterface,
> +               *RxOptions);
> 
> -    ndisStatus = AdapterGetAdvancedSettings(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> +    XENVIF_VIF(TransmitterQueryOffloadOptions,
> +               &Adapter->VifInterface,
> +               TxOptions);
> +
> +    RtlZeroMemory(&Supported, sizeof(NDIS_OFFLOAD));
> +    Supported.Header.Type       = NDIS_OBJECT_TYPE_OFFLOAD;
> +    Supported.Header.Size       = sizeof(NDIS_OFFLOAD);
> +    Supported.Header.Revision   = NDIS_OFFLOAD_REVISION_1;
> +
> +    Supported.Checksum.IPv4Receive.Encapsulation        =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv4Receive.IpChecksum           = 1;
> +    Supported.Checksum.IPv4Receive.IpOptionsSupported   = 1;
> +    Supported.Checksum.IPv4Receive.TcpChecksum          = 1;
> +    Supported.Checksum.IPv4Receive.TcpOptionsSupported  = 1;
> +    Supported.Checksum.IPv4Receive.UdpChecksum          = 1;
> +
> +    Supported.Checksum.IPv6Receive.Encapsulation        =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> +    Supported.Checksum.IPv6Receive.TcpChecksum          = 1;
> +    Supported.Checksum.IPv6Receive.TcpOptionsSupported  = 1;
> +    Supported.Checksum.IPv6Receive.UdpChecksum          = 1;
> +
> +    Supported.Checksum.IPv4Transmit.Encapsulation       =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
> +        Supported.Checksum.IPv4Transmit.IpChecksum          = 1;
> +        Supported.Checksum.IPv4Transmit.IpOptionsSupported  = 1;
>      }
> -
> -    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (TxOptions->OffloadIpVersion4TcpChecksum) {
> +        Supported.Checksum.IPv4Transmit.TcpChecksum         = 1;
> +        Supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4UdpChecksum) {
> +        Supported.Checksum.IPv4Transmit.UdpChecksum         = 1;
>      }
> 
> -    ndisStatus = AdapterSetGeneralAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    Supported.Checksum.IPv6Transmit.Encapsulation       =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> +    if (TxOptions->OffloadIpVersion6TcpChecksum) {
> +        Supported.Checksum.IPv6Transmit.TcpChecksum         = 1;
> +        Supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion6UdpChecksum) {
> +        Supported.Checksum.IPv6Transmit.UdpChecksum         = 1;
>      }
> 
> -    ndisStatus = AdapterSetOffloadAttributes(Adapter);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto exit;
> +    if (TxOptions->OffloadIpVersion4LargePacket) {
> +        XENVIF_VIF(TransmitterQueryLargePacketSize,
> +                   &Adapter->VifInterface,
> +                   4,
> +                   &Supported.LsoV2.IPv4.MaxOffLoadSize);
> +        Supported.LsoV2.IPv4.Encapsulation              =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +        Supported.LsoV2.IPv4.MinSegmentCount            = 2;
>      }
> 
> -    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
> +    if (TxOptions->OffloadIpVersion6LargePacket) {
> +        XENVIF_VIF(TransmitterQueryLargePacketSize,
> +                   &Adapter->VifInterface,
> +                   6,
> +                   &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;
> +    }
> 
> -    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;
> +    Default = Supported;
> 
> -    ndisStatus = NdisMRegisterScatterGatherDma(Adapter-
> >NdisAdapterHandle,
> -                                               &DmaDescription,
> -                                               &Adapter->NdisDmaHandle);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        Adapter->NdisDmaHandle = NULL;
> +    if (!(Adapter->Properties.ipv4_csum & 2))
> +        Default.Checksum.IPv4Receive.IpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv4_csum & 2))
> +        Default.Checksum.IPv4Receive.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv4_csum & 2))
> +        Default.Checksum.IPv4Receive.UdpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv6_csum & 2))
> +        Default.Checksum.IPv6Receive.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv6_csum & 2))
> +        Default.Checksum.IPv6Receive.UdpChecksum = 0;
> +    if (!(Adapter->Properties.ipv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.IpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv4_csum & 1))
> +        Default.Checksum.IPv4Transmit.UdpChecksum = 0;
> +    if (!(Adapter->Properties.tcpv6_csum & 1))
> +        Default.Checksum.IPv6Transmit.TcpChecksum = 0;
> +    if (!(Adapter->Properties.udpv6_csum & 1))
> +        Default.Checksum.IPv6Transmit.UdpChecksum = 0;
> +    if (!(Adapter->Properties.lsov4)) {
> +        Default.LsoV2.IPv4.MaxOffLoadSize = 0;
> +        Default.LsoV2.IPv4.MinSegmentCount = 0;
> +    }
> +    if (!(Adapter->Properties.lsov6)) {
> +        Default.LsoV2.IPv6.MaxOffLoadSize = 0;
> +        Default.LsoV2.IPv6.MinSegmentCount = 0;
> +    }
> 
> -    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, &Default,
> sizeof(NDIS_OFFLOAD))) {
> +        Adapter->Offload = Default;
> +        //DISPLAY_OFFLOAD(Default);
>      }
> 
> -exit:
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        XENVIF_VIF(Release, &Adapter->VifInterface);
> +    RtlZeroMemory(&Attribs, sizeof(Attribs));
> +    Attribs.Header.Type         =
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
> +    Attribs.Header.Size         = sizeof(Attribs);
> +    Attribs.Header.Revision     =
> NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
> +    Attribs.DefaultOffloadConfiguration = &Default;
> +    Attribs.HardwareOffloadCapabilities = &Supported;
> 
> -    Trace("<==== (%08x)\n", ndisStatus);
> -    return ndisStatus;
> +    return NdisMSetMiniportAttributes(Adapter->NdisHandle,
> +                                      (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&Attribs);
>  }
> 
> -//
> -// 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
> +AdapterIndicateOffloadChanged(
> +    IN  PXENNET_ADAPTER         Adapter
>      )
>  {
> -    UNREFERENCED_PARAMETER(DeviceObject);
> -    UNREFERENCED_PARAMETER(Reserved);
> -    UNREFERENCED_PARAMETER(SGL);
> -    UNREFERENCED_PARAMETER(Context);
> -
> -    ASSERT(FALSE);
> -
> -    return;
> -}
> +    NDIS_STATUS_INDICATION      Indication;
> +    NDIS_OFFLOAD                Offload;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> 
> -//
> -// Get\Set OID handler.
> -//
> -NDIS_STATUS
> -AdapterOidRequest (
> -    IN  NDIS_HANDLE         NdisHandle,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> -    )
> -{
> -    NDIS_STATUS ndisStatus;
> -    PADAPTER Adapter = (PADAPTER)NdisHandle;
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> 
> -    switch (NdisRequest->RequestType) {
> -        case NdisRequestSetInformation:
> -            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
> -            break;
> -
> -        case NdisRequestQueryInformation:
> -        case NdisRequestQueryStatistics:
> -            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
> -            break;
> +    RtlZeroMemory(&Offload, sizeof(NDIS_OFFLOAD));
> +    Offload.Header.Type         = NDIS_OBJECT_TYPE_OFFLOAD;
> +    Offload.Header.Size         = sizeof(NDIS_OFFLOAD);
> +    Offload.Header.Revision     = NDIS_OFFLOAD_REVISION_1;
> +
> +    Offload.Checksum.IPv4Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    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;
> +    }
> 
> -        default:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> -            break;
> -    };
> +    Offload.Checksum.IPv6Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> +    if (RxOptions->OffloadIpVersion6TcpChecksum) {
> +        Offload.Checksum.IPv6Receive.TcpChecksum = 1;
> +        Offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
> +    }
> +    if (RxOptions->OffloadIpVersion6UdpChecksum) {
> +        Offload.Checksum.IPv6Receive.UdpChecksum = 1;
> +    }
> 
> -    return ndisStatus;
> -}
> +    XENVIF_VIF(ReceiverSetOffloadOptions,
> +               &Adapter->VifInterface,
> +               *RxOptions);
> 
> -//
> -// Temporarily pauses adapter.
> -//
> -NDIS_STATUS
> -AdapterPause (
> -    IN  NDIS_HANDLE                     NdisHandle,
> -    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)NdisHandle;
> -    UNREFERENCED_PARAMETER(MiniportPauseParameters);
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> 
> -    Trace("====>\n");
> +    Offload.Checksum.IPv4Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    if (TxOptions->OffloadIpVersion4HeaderChecksum) {
> +        Offload.Checksum.IPv4Transmit.IpChecksum = 1;
> +        Offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4TcpChecksum) {
> +        Offload.Checksum.IPv4Transmit.TcpChecksum = 1;
> +        Offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion4UdpChecksum) {
> +        Offload.Checksum.IPv4Transmit.UdpChecksum = 1;
> +    }
> 
> -    if (!Adapter->Enabled)
> -        goto done;
> +    Offload.Checksum.IPv6Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> +    Offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> +    if (TxOptions->OffloadIpVersion6TcpChecksum) {
> +        Offload.Checksum.IPv6Transmit.TcpChecksum = 1;
> +        Offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> +    }
> +    if (TxOptions->OffloadIpVersion6UdpChecksum) {
> +        Offload.Checksum.IPv6Transmit.UdpChecksum = 1;
> +    }
> 
> -    XENVIF_VIF(Disable,
> -               &Adapter->VifInterface);
> +    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;
> +    }
> +    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;
> +    }
> 
> -    AdapterMediaStateChange(Adapter);
> +    if (!RtlEqualMemory(&Adapter->Offload, &Offload, sizeof
> (NDIS_OFFLOAD))) {
> +        Adapter->Offload = Offload;
> +        //DISPLAY_OFFLOAD(Offload);
> +    }
> 
> -    Adapter->Enabled = FALSE;
> +    RtlZeroMemory(&Indication, sizeof(Indication));
> +    Indication.Header.Type      = NDIS_OBJECT_TYPE_STATUS_INDICATION;
> +    Indication.Header.Size      = sizeof(Indication);
> +    Indication.Header.Revision  = NDIS_STATUS_INDICATION_REVISION_1;
> +    Indication.SourceHandle     = Adapter->NdisHandle;
> +    Indication.StatusCode       =
> NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
> +    Indication.StatusBuffer     = &Offload;
> +    Indication.StatusBufferSize = sizeof(Offload);
> 
> -done:
> -    Trace("<====\n");
> -    return NDIS_STATUS_SUCCESS;
> +    NdisMIndicateStatusEx(Adapter->NdisHandle, &Indication);
>  }
> 
> -//
> -// Handles PNP and Power events. NOP.
> -//
> -VOID
> -AdapterPnPEventHandler (
> -    IN  NDIS_HANDLE             NdisHandle,
> -    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +static NDIS_STATUS
> +AdapterSetPacketFilter(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PULONG                  PacketFilter
>      )
>  {
> -    UNREFERENCED_PARAMETER(NdisHandle);
> +    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;
> 
> -    switch (NetDevicePnPEvent->DevicePnPEvent) {
> -        case NdisDevicePnPEventQueryRemoved:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +        goto done;
> +    }
> 
> -        case NdisDevicePnPEventRemoved:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
> +    else
> +        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
> 
> -        case NdisDevicePnPEventSurpriseRemoved:
> -            break;
> +    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;
> 
> -        case NdisDevicePnPEventQueryStopped:
> -            break;
> +    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> +    else
> +        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
> 
> -        case NdisDevicePnPEventStopped:
> -            break;
> -
> -        case NdisDevicePnPEventPowerProfileChanged:
> -            break;
> -
> -        default:
> -            break;
> -    };
> +done:
> +    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;
> +    return NDIS_STATUS_SUCCESS;
>  }
> 
> -//
> -// Reports general statistics to NDIS.
> -//
> -static NDIS_STATUS
> -AdapterQueryGeneralStatistics (
> -    IN  PADAPTER                Adapter,
> -    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
> +static NDIS_STATUS
> +AdapterSetMulticastAddresses(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PETHERNET_ADDRESS       Address,
> +    IN  ULONG                   Count
>      )
>  {
> -    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
> -    ULONGLONG   Value;
> -
> -    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);
> +    NTSTATUS status;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
> +    status = XENVIF_VIF(MacSetMulticastAddresses,
> +                        &Adapter->VifInterface,
> +                        Address,
> +                        Count);
> +    if (!NT_SUCCESS(status))
> +        return NDIS_STATUS_INVALID_DATA;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BACKEND_ERRORS,
> -                      &Value);
> +    return NDIS_STATUS_SUCCESS;
> +}
> 
> -    NdisStatisticsInfo->ifInErrors = Value;
> +static NDIS_STATUS
> +AdapterSetOffloadEncapsulation(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OFFLOAD_ENCAPSULATION Encapsulation
> +    )
> +{
> +    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_FRONTEND_ERRORS,
> -                      &Value);
> +    if (Encapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON &&
> +        Encapsulation->IPv4.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> +        goto fail1;
> +    if (Encapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON &&
> +        Encapsulation->IPv6.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> +        goto fail2;
> 
> -    NdisStatisticsInfo->ifInErrors += Value;
> +    XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                &Adapter->VifInterface,
> +                &Options);
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
> +    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;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_PACKETS_DROPPED,
> -                      &Value);
> +    if (Adapter->Properties.need_csum_value)
> +        RxOptions->NeedChecksumValue = 1;
> +    if (Adapter->Properties.lrov4) {
> +        RxOptions->OffloadIpVersion4LargePacket = 1;
> +        RxOptions->NeedLargePacketSplit = 1;
> +    }
> +    if (Adapter->Properties.lrov6) {
> +        RxOptions->OffloadIpVersion6LargePacket = 1;
> +        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;
> 
> -    NdisStatisticsInfo->ifInDiscards = Value;
> +fail2:
> +    Error("fail2\n");
> +fail1:
> +    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
> +    return NDIS_STATUS_INVALID_PARAMETER;
> +}
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
> +static NDIS_STATUS
> +AdapterSetTcpOffloadParameters(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OFFLOAD_PARAMETERS    Parameters
> +    )
> +{
> +    BOOLEAN     Changed = FALSE;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS TxOptions;
> +    PXENVIF_VIF_OFFLOAD_OPTIONS RxOptions;
> +
> +    if (Parameters->IPsecV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE
> ||
> +        Parameters->LsoV1 != NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
> +        Parameters->TcpConnectionIPv4 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE ||
> +        Parameters->TcpConnectionIPv6 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        goto fail1;
> +    }
> +    if (Parameters->LsoV2IPv4 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_OCTETS,
> -                      &Value);
> +        XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                    &Adapter->VifInterface,
> +                    &Options);
> 
> -    NdisStatisticsInfo->ifHCInOctets = Value;
> +        if (!(Options.OffloadIpVersion4LargePacket))
> +            goto fail2;
> +    }
> +    if (Parameters->LsoV2IPv6 !=
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE) {
> +        XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                      &Value);
> +        XENVIF_VIF(TransmitterQueryOffloadOptions,
> +                    &Adapter->VifInterface,
> +                    &Options);
> 
> -    NdisStatisticsInfo->ifHCInOctets += Value;
> +        if (!(Options.OffloadIpVersion6LargePacket))
> +            goto fail3;
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                      &Value);
> +    TxOptions = TransmitterOffloadOptions(Adapter->Transmitter);
> +    RxOptions = ReceiverOffloadOptions(Adapter->Receiver);
> 
> -    NdisStatisticsInfo->ifHCInOctets += Value;
> +#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 set_value(x, y)     ((x) == (y)) ? FALSE : ( ((x) = (y)) == (y) )
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
> +    if (Parameters->LsoV2IPv4 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 1);
> +    } else if (Parameters->LsoV2IPv4 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4LargePacket, 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_OCTETS,
> -                      &Value);
> +    if (Parameters->LsoV2IPv6 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 1);
> +    } else if (Parameters->LsoV2IPv6 ==
> NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6LargePacket, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInUcastOctets = Value;
> +    if (tx_enabled(Parameters->IPv4Checksum)) {
> +        Changed |= set_value(TxOptions-
> >OffloadIpVersion4HeaderChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions-
> >OffloadIpVersion4HeaderChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
> +    if (tx_enabled(Parameters->TCPIPv4Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4TcpChecksum, 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_UNICAST_PACKETS,
> -                      &Value);
> +    if (tx_enabled(Parameters->UDPIPv4Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion4UdpChecksum,
> 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInUcastPkts = Value;
> +    if (tx_enabled(Parameters->TCPIPv6Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
> +    if (tx_enabled(Parameters->UDPIPv6Checksum)) {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(TxOptions->OffloadIpVersion6UdpChecksum,
> 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                      &Value);
> +    if (rx_enabled(Parameters->IPv4Checksum)) {
> +        Changed |= set_value(RxOptions-
> >OffloadIpVersion4HeaderChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions-
> >OffloadIpVersion4HeaderChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInMulticastOctets = Value;
> +    if (rx_enabled(Parameters->TCPIPv4Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
> +    if (rx_enabled(Parameters->UDPIPv4Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion4UdpChecksum,
> 0);
> +    }
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                      &Value);
> +    if (rx_enabled(Parameters->TCPIPv6Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6TcpChecksum, 0);
> +    }
> 
> -    NdisStatisticsInfo->ifHCInMulticastPkts = Value;
> +    if (rx_enabled(Parameters->UDPIPv6Checksum)) {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum,
> 1);
> +    } else {
> +        Changed |= set_value(RxOptions->OffloadIpVersion6UdpChecksum,
> 0);
> +    }
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
> +#undef tx_enabled
> +#undef rx_enabled
> +#undef set_value
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                      &Value);
> +    if (Changed)
> +        AdapterIndicateOffloadChanged(Adapter);
> 
> -    NdisStatisticsInfo->ifHCInBroadcastOctets = Value;
> +    return NDIS_STATUS_SUCCESS;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
> +fail3:
> +    Error("fail3\n");
> +fail2:
> +    Error("fail2\n");
> +fail1:
> +    Error("fail1 (%08x)\n", NDIS_STATUS_INVALID_PARAMETER);
> +    return NDIS_STATUS_INVALID_PARAMETER;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                      &Value);
> +static NDIS_STATUS
> +AdapterSetInformation(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PNDIS_OID_REQUEST       Request
> +    )
> +{
> +    PVOID           Buffer;
> +    ULONG           BufferLength;
> +    ULONG           BytesNeeded = 0;
> +    ULONG           BytesRead   = 0;
> +    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
> 
> -    NdisStatisticsInfo->ifHCInBroadcastPkts = Value;
> +    Buffer          = Request->DATA.SET_INFORMATION.InformationBuffer;
> +    BufferLength    = Request-
> >DATA.SET_INFORMATION.InformationBufferLength;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
> +    switch (Request->DATA.QUERY_INFORMATION.Oid) {
> +        case OID_PNP_SET_POWER:
> +            BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> -                      &Value);
> +        case OID_GEN_CURRENT_LOOKAHEAD:
> +            BytesNeeded = sizeof(ULONG);
> +            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
> +            if (BufferLength == sizeof(ULONG)) {
> +                Adapter->CurrentLookahead = *(PULONG)Buffer;
> +                BytesRead = sizeof(ULONG);
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->ifOutErrors = Value;
> +        case OID_GEN_CURRENT_PACKET_FILTER:
> +            BytesNeeded = sizeof(ULONG);
> +            if (BufferLength == sizeof(ULONG)) {
> +                NdisStatus = AdapterSetPacketFilter(Adapter, (PULONG)Buffer);
> +                BytesRead = sizeof(ULONG);
> +            }
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> -                      &Value);
> +        case OID_802_3_MULTICAST_LIST:
> +            BytesNeeded = ETHERNET_ADDRESS_LENGTH;
> +            if (BufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
> +                ULONG   Count = BufferLength / ETHERNET_ADDRESS_LENGTH;
> +                NdisStatus = AdapterSetMulticastAddresses(Adapter, Buffer,
> Count);
> +                BytesRead = BufferLength;
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->ifOutErrors += Value;
> +        case OID_OFFLOAD_ENCAPSULATION:
> +            BytesNeeded = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
> +            if (BufferLength == sizeof(NDIS_OFFLOAD_ENCAPSULATION)) {
> +                NdisStatus = AdapterSetOffloadEncapsulation(Adapter, Buffer);
> +                BytesRead = sizeof(NDIS_OFFLOAD_ENCAPSULATION);
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
> +        case OID_TCP_OFFLOAD_PARAMETERS:
> +            BytesNeeded = sizeof(NDIS_OFFLOAD_PARAMETERS);
> +            if (BufferLength == sizeof(NDIS_OFFLOAD_PARAMETERS)) {
> +                NdisStatus = AdapterSetTcpOffloadParameters(Adapter, Buffer);
> +                BytesRead = sizeof(NDIS_OFFLOAD_PARAMETERS);
> +            } else {
> +                NdisStatus = NDIS_STATUS_INVALID_LENGTH;
> +            }
> +            break;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> -                      &Value);
> +        case OID_GEN_INTERRUPT_MODERATION:
> +            NdisStatus = NDIS_STATUS_INVALID_DATA;
> +            break;
> 
> -    NdisStatisticsInfo->ifHCOutOctets = Value;
> +        case OID_GEN_MACHINE_NAME:
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> +    };
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                      &Value);
> +    Request->DATA.SET_INFORMATION.BytesNeeded = BytesNeeded;
> +    if (NdisStatus == NDIS_STATUS_SUCCESS) {
> +        Request->DATA.SET_INFORMATION.BytesRead = BytesRead;
> +    }
> 
> -    NdisStatisticsInfo->ifHCOutOctets += Value;
> +    return NdisStatus;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                      &Value);
> +static FORCEINLINE ULONG64
> +AdapterGetXmitOk(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                &Value);
> +    Result = Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->ifHCOutOctets += Value;
> +static FORCEINLINE ULONG64
> +AdapterGetRcvOk(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_UNICAST_PACKETS,
> +                &Value);
> +    Result = Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                &Value);
> +    Result += Value;
> +
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
> +static FORCEINLINE ULONG64
> +AdapterGetXmitError(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> -                      &Value);
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +                &Value);
> +    Result = Value;
> 
> -    NdisStatisticsInfo->ifHCOutUcastOctets = Value;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +                &Value);
> +    Result += Value;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
> +    return Result;
> +}
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> -                      &Value);
> +static FORCEINLINE ULONG64
> +AdapterGetRcvError(
> +    IN  PXENNET_ADAPTER         Adapter
> +    )
> +{
> +    ULONGLONG   Value;
> +    ULONG64     Result = 0;
> 
> -    NdisStatisticsInfo->ifHCOutUcastPkts = Value;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_BACKEND_ERRORS,
> +                &Value);
> +    Result = Value;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
> +    XENVIF_VIF(QueryStatistic,
> +                &Adapter->VifInterface,
> +                XENVIF_RECEIVER_FRONTEND_ERRORS,
> +                &Value);
> +    Result += Value;
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                      &Value);
> +    return Result;
> +}
> 
> -    NdisStatisticsInfo->ifHCOutMulticastOctets = Value;
> +static VOID
> +AdapterGetPacketFilter(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PULONG                  PacketFilter
> +    )
> +{
> +    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
> +    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
> +    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
> 
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
> +    XENVIF_VIF(MacQueryFilterLevel,
> +               &Adapter->VifInterface,
> +               ETHERNET_ADDRESS_UNICAST,
> +               &UnicastFilterLevel);
> 
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutMulticastPkts = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
> -
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutBroadcastOctets = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
> -
> -    (VOID) XENVIF_VIF(QueryStatistic,
> -                      &Adapter->VifInterface,
> -                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                      &Value);
> -
> -    NdisStatisticsInfo->ifHCOutBroadcastPkts = Value;
> -
> -    NdisStatisticsInfo->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
> -    NdisStatisticsInfo->ifOutDiscards = 0;
> -
> -    return ndisStatus;
> -}
> -
> -static VOID
> -GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
> -{
> -    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
> -    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
> -    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
> -
> -    XENVIF_VIF(MacQueryFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_UNICAST,
> -               &UnicastFilterLevel);
> -
> -    XENVIF_VIF(MacQueryFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_MULTICAST,
> -               &MulticastFilterLevel);
> +    XENVIF_VIF(MacQueryFilterLevel,
> +               &Adapter->VifInterface,
> +               ETHERNET_ADDRESS_MULTICAST,
> +               &MulticastFilterLevel);
> 
>      XENVIF_VIF(MacQueryFilterLevel,
>                 &Adapter->VifInterface,
> @@ -863,1715 +1271,934 @@ GetPacketFilter(PADAPTER Adapter, PULONG
> PacketFilter)
>          *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
>  }
> 
> -#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
> +AdapterQueryGeneralStatistics (
> +    IN  PXENNET_ADAPTER         Adapter,
> +    IN  PNDIS_STATISTICS_INFO   Stats
>      )
>  {
> -    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");
> +    ULONGLONG                   Value;
> 
> -            info = &Adapter->Capabilities;
> -            bytesAvailable = sizeof(Adapter->Capabilities);
> -            break;
> +    RtlZeroMemory(Stats, sizeof(NDIS_STATISTICS_INFO));
> +    Stats->Header.Type         = NDIS_OBJECT_TYPE_DEFAULT;
> +    Stats->Header.Size         = sizeof(NDIS_STATISTICS_INFO);
> +    Stats->Header.Revision     = NDIS_OBJECT_REVISION_1;
> 
> -        case OID_PNP_QUERY_POWER:
> -            Trace("QUERY_POWER\n");
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BACKEND_ERRORS,
> +                      &Value);
> +    Stats->ifInErrors = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_FRONTEND_ERRORS,
> +                      &Value);
> +    Stats->ifInErrors += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_PACKETS_DROPPED,
> +                      &Value);
> +    Stats->ifInDiscards = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets += Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInOctets += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInUcastOctets = Value;
> 
> -            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
> -            if (informationBufferLength >= bytesNeeded) {
> -                PNDIS_DEVICE_POWER_STATE state;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_UNICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInUcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInMulticastOctets = Value;
> 
> -                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
> -                switch (*state) {
> -                case NdisDeviceStateD0:
> -                    Trace("D0\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInMulticastPkts = Value;
> 
> -                case NdisDeviceStateD1:
> -                    Trace("D1\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCInBroadcastOctets = Value;
> 
> -                case NdisDeviceStateD2:
> -                    Trace("D2\n");
> -                    break;
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCInBroadcastPkts = Value;
> 
> -                case NdisDeviceStateD3:
> -                    Trace("D3\n");
> -                    break;
> -                }
> -            }
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +                      &Value);
> +    Stats->ifOutErrors = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +                      &Value);
> +    Stats->ifOutErrors += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets = Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets += Value;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutOctets += Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutUcastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutUcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutMulticastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutMulticastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                      &Value);
> +    Stats->ifHCOutBroadcastOctets = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
> +    (VOID) XENVIF_VIF(QueryStatistic,
> +                      &Adapter->VifInterface,
> +                      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                      &Value);
> +    Stats->ifHCOutBroadcastPkts = Value;
> +
> +    Stats->SupportedStatistics |=
> NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
> +    Stats->ifOutDiscards = 0;
> +
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +static FORCEINLINE VOID
> +AdapterGetInterruptModeration(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PNDIS_INTERRUPT_MODERATION_PARAMETERS   Parameters
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Adapter);
> +
> +    RtlZeroMemory(Parameters,
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS));
> +    Parameters->Header.Type      = NDIS_OBJECT_TYPE_DEFAULT;
> +    Parameters->Header.Size      =
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
> +    Parameters->Header.Revision  =
> NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
> +    Parameters->Flags            = 0;
> +    Parameters->InterruptModeration =
> NdisInterruptModerationNotSupported;
> +}
> +
> +static NDIS_STATUS
> +AdapterQueryInformation(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
> +    )
> +{
> +    ULONG           Value32;
> +    ULONG64         Value64;
> +    PVOID           Buffer;
> +    ULONG           BufferLength;
> +    BOOLEAN         DoCopy = TRUE;
> +    ULONG           BytesAvailable = 0;
> +    PVOID           BytesToCopy = NULL;
> +    NDIS_STATUS     NdisStatus  = NDIS_STATUS_SUCCESS;
> +
> +    Buffer          = Request->DATA.QUERY_INFORMATION.InformationBuffer;
> +    BufferLength    = Request-
> >DATA.QUERY_INFORMATION.InformationBufferLength;
> +
> +    switch (Request->DATA.QUERY_INFORMATION.Oid) {
> +        case OID_PNP_CAPABILITIES:
> +            BytesToCopy = &Adapter->Capabilities;
> +            BytesAvailable = sizeof(Adapter->Capabilities);
>              break;
> 
>          case OID_GEN_SUPPORTED_LIST:
> -            info = &XennetSupportedOids[0];
> -            bytesAvailable = sizeof(XennetSupportedOids);
> +            BytesToCopy = &XennetSupportedOids[0];
> +            BytesAvailable = sizeof(XennetSupportedOids);
>              break;
> 
>          case OID_GEN_HARDWARE_STATUS:
> -            infoData = NdisHardwareStatusReady;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = NdisHardwareStatusReady;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MEDIA_SUPPORTED:
>          case OID_GEN_MEDIA_IN_USE:
> -            infoData = XENNET_MEDIA_TYPE;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = XENNET_MEDIA_TYPE;
> +            BytesToCopy = &Value32;
> +            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);
> +            Value32 = Adapter->MaximumFrameSize;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_VENDOR_DESCRIPTION:
> -            info = COMPANY_NAME_STR;
> -            bytesAvailable = (ULONG)strlen(info) + 1;
> +            BytesToCopy = COMPANY_NAME_STR;
> +            BytesAvailable = (ULONG)strlen(BytesToCopy) + 1;
>              break;
> 
>          case OID_GEN_VENDOR_DRIVER_VERSION:
> -            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_DRIVER_VERSION:
> -            infoData = (6 << 8) | 0;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = (6 << 8) | 0;
> +            BytesToCopy = &Value32;
> +            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);
> -
> -            }
> -
> +            Value32 = XENNET_MAC_OPTIONS;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_802_3_MULTICAST_LIST: {
> -            ULONG Count;
> -
> -            doCopy = FALSE;
> -
> -            XENVIF_VIF(MacQueryMulticastAddresses,
> +        case OID_GEN_TRANSMIT_BUFFER_SPACE:
> +        case OID_GEN_RECEIVE_BUFFER_SPACE:
> +            XENVIF_VIF(TransmitterQueryRingSize,
>                         &Adapter->VifInterface,
> -                       NULL,
> -                       &Count);
> -            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
> -
> -            if (informationBufferLength >= bytesAvailable) {
> -                NTSTATUS status;
> -
> -                status = XENVIF_VIF(MacQueryMulticastAddresses,
> -                                    &Adapter->VifInterface,
> -                                    informationBuffer,
> -                                    &Count);
> -                if (!NT_SUCCESS(status))
> -                    ndisStatus = NDIS_STATUS_FAILURE;
> -            }
> -
> +                       (PULONG)&Value32);
> +            Value32 *= Adapter->MaximumFrameSize;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> -        }
> +
>          case OID_802_3_PERMANENT_ADDRESS:
>              XENVIF_VIF(MacQueryPermanentAddress,
>                         &Adapter->VifInterface,
> -                       (PETHERNET_ADDRESS)&infoData);
> -            info = &infoData;
> -            bytesAvailable = sizeof (ETHERNET_ADDRESS);
> +                       (PETHERNET_ADDRESS)&Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_802_3_CURRENT_ADDRESS:
>              XENVIF_VIF(MacQueryCurrentAddress,
>                         &Adapter->VifInterface,
> -                       (PETHERNET_ADDRESS)&infoData);
> -            info = &infoData;
> -            bytesAvailable = sizeof (ETHERNET_ADDRESS);
> +                       (PETHERNET_ADDRESS)&Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MAXIMUM_FRAME_SIZE:
> -            infoData = Adapter->MaximumFrameSize -
> +            Value32 = Adapter->MaximumFrameSize -
>                         sizeof (ETHERNET_TAGGED_HEADER);
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_MAXIMUM_TOTAL_SIZE:
> -            infoData = Adapter->MaximumFrameSize -
> +            Value32 = Adapter->MaximumFrameSize -
>                         sizeof (ETHERNET_TAGGED_HEADER) +
>                         sizeof (ETHERNET_UNTAGGED_HEADER);
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_CURRENT_LOOKAHEAD:
> -            infoData = Adapter->CurrentLookahead;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = Adapter->CurrentLookahead;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
>          case OID_GEN_VENDOR_ID:
> -            infoData = 0x5853;
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> +            Value32 = 0x5853;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_LINK_SPEED: {
> -            ULONG64 LinkSpeed;
> -
> -            XENVIF_VIF(MacQueryState,
> -                       &Adapter->VifInterface,
> -                       NULL,
> -                       &LinkSpeed,
> -                       NULL);
> -
> -            infoData = (ULONG)(LinkSpeed / 100);
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MEDIA_CONNECT_STATUS:
> +        case OID_GEN_LINK_SPEED:
>              XENVIF_VIF(MacQueryState,
>                         &Adapter->VifInterface,
> -                       (PNET_IF_MEDIA_CONNECT_STATE)&infoData,
>                         NULL,
> +                       &Value64,
>                         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);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONGLONG);
> -            break;
> -        }
> -        case OID_GEN_RCV_OK: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONGLONG);
> +            Value32 = (ULONG)(Value64 / 100);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> -        }
> -        case OID_GEN_XMIT_ERROR: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BACKEND_ERRORS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_RCV_ERROR: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BACKEND_ERRORS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_FRONTEND_ERRORS,
> -                       &Value);
> -
> -            infoData += Value;
> -
> -            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);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_BYTES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_BYTES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_FRAMES_XMIT: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_DIRECTED_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_UNICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_MULTICAST_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_BYTES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_OCTETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        case OID_GEN_BROADCAST_FRAMES_RCV: {
> -            ULONGLONG   Value;
> -
> -            XENVIF_VIF(QueryStatistic,
> -                       &Adapter->VifInterface,
> -                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> -                       &Value);
> -
> -            infoData = Value;
> -
> -            info = &infoData;
> -            bytesAvailable = sizeof(ULONG);
> -            break;
> -        }
> -        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;
> -
> -        // 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;
> -        }
> -
> -        if (bytesWritten && doCopy) {
> -            NdisMoveMemory(informationBuffer, info, bytesWritten);
> -
> -            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> -        }
> -    }
> -
> -    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten =
> bytesWritten;
> -    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded =
> bytesNeeded;
> -    return ndisStatus;
> -}
> -#pragma warning(pop)
> -
> -NDIS_STATUS
> -AdapterReset (
> -    IN  NDIS_HANDLE     MiniportAdapterContext,
> -    OUT PBOOLEAN        AddressingReset
> -    )
> -{
> -    UNREFERENCED_PARAMETER(MiniportAdapterContext);
> -
> -
> -    *AddressingReset = FALSE;
> -
> -    return NDIS_STATUS_SUCCESS;
> -}
> -
> -//
> -// 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;
> -
> -    UNREFERENCED_PARAMETER(MiniportRestartParameters);
> -
> -    Trace("====>\n");
> -
> -    if (Adapter->Enabled) {
> -        ndisStatus = NDIS_STATUS_SUCCESS;
> -        goto done;
> -    }
> -
> -    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;
> -    }
> -
> -done:
> -    Trace("<====\n");
> -    return ndisStatus;
> -}
> -
> -//
> -// Recycle of received net buffer lists.
> -//
> -VOID
> -AdapterReturnNetBufferLists (
> -    IN  NDIS_HANDLE         MiniportAdapterContext,
> -    IN  PNET_BUFFER_LIST    NetBufferLists,
> -    IN  ULONG               ReturnFlags
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> -
> -    ReceiverReturnNetBufferLists(&Adapter->Receiver,
> -                                 NetBufferLists,
> -                                 ReturnFlags);
> -
> -    return;
> -}
> -
> -//
> -// 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
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> -
> -    TransmitterSendNetBufferLists(Adapter->Transmitter,
> -                                  NetBufferList,
> -                                  PortNumber,
> -                                  SendFlags);
> -}
> -
> -#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)
> -
> -//
> -// Sets general adapter attributes.
> -//
> -static NDIS_STATUS
> -AdapterSetGeneralAttributes (
> -    IN  PADAPTER Adapter
> -    )
> -{
> -    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
> -    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
> -    NDIS_STATUS ndisStatus;
> -
> -    NdisZeroMemory(&generalAttributes,
> -                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
> -
> -    generalAttributes.Header.Type =
> -
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
> -
> -    generalAttributes.Header.Revision =
> -                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
> -
> -    generalAttributes.Header.Size =
> -                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
> -
> -    generalAttributes.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;
> -
> -    XENVIF_VIF(MacQueryPermanentAddress,
> -               &Adapter->VifInterface,
> -               (PETHERNET_ADDRESS)&generalAttributes.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;
> -
> -    generalAttributes.SupportedOidList = XennetSupportedOids;
> -    generalAttributes.SupportedOidListLength =
> sizeof(XennetSupportedOids);
> -    adapterAttributes =
> -                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
> -
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> -
> -    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
> -    )
> -{
> -    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;
> -
> -    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;
> -    }
> -
> -    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);
> -
> -    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
> -    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
> -    supported.Header.Size = sizeof(supported);
> -
> -    supported.Checksum.IPv4Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv4Receive.IpChecksum = 1;
> -    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv4Receive.TcpChecksum = 1;
> -    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv4Receive.UdpChecksum = 1;
> -
> -    supported.Checksum.IPv6Receive.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
> -
> -    supported.Checksum.IPv6Receive.TcpChecksum = 1;
> -    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
> -
> -    supported.Checksum.IPv6Receive.UdpChecksum = 1;
> -
> -    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -               &Adapter->VifInterface,
> -               &Options);
> -
> -    supported.Checksum.IPv4Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    if (Options.OffloadIpVersion4HeaderChecksum) {
> -        supported.Checksum.IPv4Transmit.IpChecksum = 1;
> -        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion4TcpChecksum) {
> -        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
> -        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion4UdpChecksum)
> -        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
> -
> -    supported.Checksum.IPv6Transmit.Encapsulation =
> NDIS_ENCAPSULATION_IEEE_802_3;
> -
> -    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
> -
> -    if (Options.OffloadIpVersion6TcpChecksum) {
> -        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
> -        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
> -    }
> -
> -    if (Options.OffloadIpVersion6UdpChecksum)
> -        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;
> -    }
> -
> -    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;
> -    }
> -
> -    current = supported;
> -
> -    if (!(Adapter->Properties.ipv4_csum & 2))
> -        current.Checksum.IPv4Receive.IpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv4_csum & 2))
> -        current.Checksum.IPv4Receive.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv4_csum & 2))
> -        current.Checksum.IPv4Receive.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv6_csum & 2))
> -        current.Checksum.IPv6Receive.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv6_csum & 2))
> -        current.Checksum.IPv6Receive.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.ipv4_csum & 1))
> -        current.Checksum.IPv4Transmit.IpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv4_csum & 1))
> -        current.Checksum.IPv4Transmit.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv4_csum & 1))
> -        current.Checksum.IPv4Transmit.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.tcpv6_csum & 1))
> -        current.Checksum.IPv6Transmit.TcpChecksum = 0;
> -
> -    if (!(Adapter->Properties.udpv6_csum & 1))
> -        current.Checksum.IPv6Transmit.UdpChecksum = 0;
> -
> -    if (!(Adapter->Properties.lsov4)) {
> -        current.LsoV2.IPv4.MaxOffLoadSize = 0;
> -        current.LsoV2.IPv4.MinSegmentCount = 0;
> -    }
> -
> -    if (!(Adapter->Properties.lsov6)) {
> -        current.LsoV2.IPv6.MaxOffLoadSize = 0;
> -        current.LsoV2.IPv6.MinSegmentCount = 0;
> -    }
> -
> -    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof
> (NDIS_OFFLOAD))) {
> -        Adapter->Offload = current;
> -
> -        DISPLAY_OFFLOAD(current);
> -    }
> -
> -    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;
> -
> -    adapterAttributes =
> -        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> -
> -    return ndisStatus;
> -}
> -
> -static void
> -AdapterIndicateOffloadChanged (
> -    IN  PADAPTER 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;
> -    }
> -
> -    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);
> -    }
> -
> -    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);
> -
> -    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
> -
> -}
> -
> -static NDIS_STATUS
> -SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address,
> ULONG Count)
> -{
> -    NTSTATUS status;
> -
> -    status = XENVIF_VIF(MacSetMulticastAddresses,
> -                        &Adapter->VifInterface,
> -                        Address,
> -                        Count);
> -    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;
> -
> -    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        MulticastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -        goto done;
> -    }
> -
> -    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_MATCHING;
> -    else
> -        UnicastFilterLevel = XENVIF_MAC_FILTER_NONE;
> -
> -    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;
> 
> -    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_ALL;
> -    else
> -        BroadcastFilterLevel = XENVIF_MAC_FILTER_NONE;
> +        case OID_GEN_MEDIA_CONNECT_STATUS:
> +            XENVIF_VIF(MacQueryState,
> +                       &Adapter->VifInterface,
> +                       (PNET_IF_MEDIA_CONNECT_STATE)&Value32,
> +                       NULL,
> +                       NULL);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -done:
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_UNICAST,
> -               UnicastFilterLevel);
> +        case OID_GEN_MAXIMUM_SEND_PACKETS:
> +            Value32 = 16;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_MULTICAST,
> -               MulticastFilterLevel);
> +        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:
> +            Value32 = 0;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    XENVIF_VIF(MacSetFilterLevel,
> -               &Adapter->VifInterface,
> -               ETHERNET_ADDRESS_BROADCAST,
> -               BroadcastFilterLevel);
> +        case OID_802_3_MAXIMUM_LIST_SIZE:
> +            Value32 = 32;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -    return NDIS_STATUS_SUCCESS;
> -}
> +        case OID_GEN_STATISTICS:
> +            DoCopy = FALSE;
> +            BytesAvailable = sizeof(NDIS_STATISTICS_INFO);
> +            if (BufferLength >= sizeof(NDIS_STATISTICS_INFO))
> +                NdisStatus = AdapterQueryGeneralStatistics(Adapter, Buffer);
> +            break;
> 
> -//
> -// 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;
> +        case OID_802_3_MULTICAST_LIST:
> +            DoCopy = FALSE;
> +            XENVIF_VIF(MacQueryMulticastAddresses,
> +                       &Adapter->VifInterface,
> +                       NULL,
> +                       &Value32);
> +            BytesAvailable = Value32 * ETHERNET_ADDRESS_LENGTH;
> +            if (BufferLength >= BytesAvailable) {
> +                if (!NT_SUCCESS(XENVIF_VIF(MacQueryMulticastAddresses,
> +                                           &Adapter->VifInterface,
> +                                           Buffer,
> +                                           &Value32))) {
> +                    NdisStatus = NDIS_STATUS_FAILURE;
>                  }
>              }
>              break;
> 
> -        case OID_GEN_MACHINE_NAME:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +        case OID_GEN_CURRENT_PACKET_FILTER:
> +            AdapterGetPacketFilter(Adapter, &Value32);
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_CURRENT_LOOKAHEAD:
> -            bytesNeeded = sizeof(ULONG);
> -            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
> -            if (informationBufferLength == sizeof(ULONG)) {
> -                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
> -                bytesRead = sizeof(ULONG);
> -            }
> -
> +        case OID_GEN_XMIT_OK:
> +            Value64 = AdapterGetXmitOk(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
>              break;
> 
> -        case OID_GEN_CURRENT_PACKET_FILTER:
> -            bytesNeeded = sizeof(ULONG);
> -            if (informationBufferLength == sizeof(ULONG)) {
> -                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
> -                bytesRead = sizeof(ULONG);
> -            }
> -
> +        case OID_GEN_RCV_OK:
> +            Value64 = AdapterGetRcvOk(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
>              break;
> 
> -        case OID_802_3_MULTICAST_LIST:
> -            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
> -            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
> -                addressCount = informationBufferLength /
> ETHERNET_ADDRESS_LENGTH;
> +        case OID_GEN_XMIT_ERROR:
> +            Value64 = AdapterGetXmitError(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
> +            break;
> 
> -                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer,
> addressCount);
> -                if (ndisStatus == NDIS_STATUS_SUCCESS)
> -                    bytesRead = informationBufferLength;
> -            } else {
> -                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
> -            }
> +        case OID_GEN_RCV_ERROR:
> +            Value64 = AdapterGetRcvError(Adapter);
> +            BytesToCopy = &Value64;
> +            BytesAvailable = sizeof(ULONG64);
> +            break;
> 
> +        case OID_GEN_DIRECTED_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_GEN_INTERRUPT_MODERATION:
> -            ndisStatus = NDIS_STATUS_INVALID_DATA;
> +        case OID_GEN_DIRECTED_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
>              break;
> 
> -        case OID_OFFLOAD_ENCAPSULATION: {
> -            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
> +        case OID_GEN_MULTICAST_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -            bytesNeeded = sizeof(*offloadEncapsulation);
> -            if (informationBufferLength >= bytesNeeded) {
> -                XENVIF_VIF_OFFLOAD_OPTIONS Options;
> +        case OID_GEN_MULTICAST_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                bytesRead = bytesNeeded;
> -                offloadEncapsulation = informationBuffer;
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> +        case OID_GEN_BROADCAST_BYTES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON)
> {
> -                    if (offloadEncapsulation->IPv4.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +        case OID_GEN_BROADCAST_FRAMES_XMIT:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON)
> {
> -                    if (offloadEncapsulation->IPv6.EncapsulationType !=
> NDIS_ENCAPSULATION_IEEE_802_3)
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +        case OID_GEN_DIRECTED_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_UNICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                           &Adapter->VifInterface,
> -                           &Options);
> -
> -                Adapter->Transmitter->OffloadOptions.Value = 0;
> -                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation =
> 1;
> +        case OID_GEN_DIRECTED_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_UNICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.lsov4) &&
> (Options.OffloadIpVersion4LargePacket))
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4LargePacket = 1;
> +        case OID_GEN_MULTICAST_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_MULTICAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.lsov6) &&
> (Options.OffloadIpVersion6LargePacket))
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6LargePacket = 1;
> +        case OID_GEN_MULTICAST_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_MULTICAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.ipv4_csum & 1) &&
> Options.OffloadIpVersion4HeaderChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
> +        case OID_GEN_BROADCAST_BYTES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_BROADCAST_OCTETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.tcpv4_csum & 1) &&
> Options.OffloadIpVersion4TcpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
> +        case OID_GEN_BROADCAST_FRAMES_RCV:
> +            XENVIF_VIF(QueryStatistic,
> +                       &Adapter->VifInterface,
> +                       XENVIF_RECEIVER_BROADCAST_PACKETS,
> +                       &Value64);
> +            Value32 = (ULONG)Value64;
> +            BytesToCopy = &Value32;
> +            BytesAvailable = sizeof(ULONG);
> +            break;
> 
> -                if ((Adapter->Properties.udpv4_csum & 1) &&
> Options.OffloadIpVersion4UdpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
> +        case OID_GEN_INTERRUPT_MODERATION:
> +            DoCopy = FALSE;
> +            BytesAvailable =
> sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
> +            if (BufferLength >= BytesAvailable)
> +                AdapterGetInterruptModeration(Adapter, Buffer);
> +            else
> +                NdisStatus = NDIS_STATUS_FAILURE;
> +            break;
> 
> -                if ((Adapter->Properties.tcpv6_csum & 1) &&
> Options.OffloadIpVersion6TcpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
> +        case OID_PNP_QUERY_POWER:
> +            // do nothing!
> +            break;
> 
> -                if ((Adapter->Properties.udpv6_csum & 1) &&
> Options.OffloadIpVersion6UdpChecksum)
> -                    Adapter->Transmitter-
> >OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
> +        case OID_GEN_MAC_ADDRESS:
> +        case OID_GEN_MAX_LINK_SPEED:
> +        case OID_IP4_OFFLOAD_STATS:
> +        case OID_IP6_OFFLOAD_STATS:
> +        case OID_GEN_SUPPORTED_GUIDS:
> +		case OID_GEN_INIT_TIME_MS:
> +		case OID_GEN_RESET_COUNTS:
> +		case OID_GEN_MEDIA_SENSE_COUNTS:
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> 
> -                Adapter->Receiver.OffloadOptions.Value = 0;
> -                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
> +    }
> 
> -                if (Adapter->Properties.need_csum_value)
> -                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
> +    if (NdisStatus == NDIS_STATUS_SUCCESS) {
> +        Request->DATA.QUERY_INFORMATION.BytesNeeded =
> BytesAvailable;
> +        if (BytesAvailable <= BufferLength) {
> +            Request->DATA.QUERY_INFORMATION.BytesWritten =
> BytesAvailable;
> +        } else {
> +            Request->DATA.QUERY_INFORMATION.BytesWritten =
> BufferLength;
> +            NdisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
> +        }
> +        if (Request->DATA.QUERY_INFORMATION.BytesWritten && DoCopy) {
> +            RtlMoveMemory(Buffer, BytesToCopy, Request-
> >DATA.QUERY_INFORMATION.BytesWritten);
> 
> -                if (Adapter->Properties.lrov4) {
> -                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket
> = 1;
> -                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
> -                }
> +            // Its Ok to short transfers on these Oids
> +            if (Request->DATA.QUERY_INFORMATION.Oid ==
> OID_GEN_XMIT_OK ||
> +                Request->DATA.QUERY_INFORMATION.Oid == OID_GEN_RCV_OK)
> +                NdisStatus = NDIS_STATUS_SUCCESS;
> +        }
> +    }
> 
> -                if (Adapter->Properties.lrov6) {
> -                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket
> = 1;
> -                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
> -                }
> +    return NdisStatus;
> +}
> 
> -                if (Adapter->Properties.ipv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
> +NDIS_STATUS
> +AdapterOidRequest(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
> +    )
> +{
> +    NDIS_STATUS     NdisStatus;
> +
> +    switch (Request->RequestType) {
> +        case NdisRequestSetInformation:
> +            NdisStatus = AdapterSetInformation(Adapter, Request);
> +            break;
> +
> +        case NdisRequestQueryInformation:
> +        case NdisRequestQueryStatistics:
> +            NdisStatus = AdapterQueryInformation(Adapter, Request);
> +            break;
> 
> -                if (Adapter->Properties.tcpv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
> +        default:
> +            NdisStatus = NDIS_STATUS_NOT_SUPPORTED;
> +            break;
> +    };
> 
> -                if (Adapter->Properties.udpv4_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
> +    return NdisStatus;
> +}
> 
> -                if (Adapter->Properties.tcpv6_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
> +NTSTATUS
> +AdapterEnable(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    NTSTATUS        status;
> 
> -                if (Adapter->Properties.udpv6_csum & 2)
> -                    Adapter-
> >Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
> +    if (Adapter->Enabled)
> +        goto done;
> 
> -                AdapterIndicateOffloadChanged(Adapter);
> -            }
> -            break;
> -        }
> -        case OID_TCP_OFFLOAD_PARAMETERS: {
> -            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
> +    status = XENVIF_VIF(Enable,
> +                        &Adapter->VifInterface,
> +                        AdapterVifCallback,
> +                        Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    TransmitterEnable(Adapter->Transmitter);
> +    Adapter->Enabled = TRUE;
> 
> -            bytesNeeded = sizeof(*offloadParameters);
> -            if (informationBufferLength >= bytesNeeded) {
> -                bytesRead = bytesNeeded;
> -                offloadParameters = informationBuffer;
> -                ndisStatus = NDIS_STATUS_SUCCESS;
> +done:
> +    return STATUS_SUCCESS;
> 
> -#define no_change(x)  ((x) ==
> NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> 
> -                if (!no_change(offloadParameters->IPsecV1))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -
> -                if (!no_change(offloadParameters->LsoV1))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +BOOLEAN
> +AdapterDisable(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    if (!Adapter->Enabled)
> +        return FALSE;
> 
> -                if (!no_change(offloadParameters->TcpConnectionIPv4))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +    XENVIF_VIF(Disable, &Adapter->VifInterface);
> +    Adapter->Enabled = FALSE;
> +    return TRUE;
> +}
> 
> -                if (!no_change(offloadParameters->TcpConnectionIPv6))
> -                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> +VOID
> +AdapterMediaStateChange(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    NDIS_LINK_STATE                 LinkState;
> +    NDIS_STATUS_INDICATION          StatusIndication;
> 
> -                if (!no_change(offloadParameters->LsoV2IPv4)) {
> -                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +    RtlZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
> +    LinkState.Header.Type       = NDIS_OBJECT_TYPE_DEFAULT;
> +    LinkState.Header.Size       = sizeof(NDIS_LINK_STATE);
> +    LinkState.Header.Revision   = NDIS_LINK_STATE_REVISION_1;
> 
> -                    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                               &Adapter->VifInterface,
> -                               &Options);
> +    XENVIF_VIF(MacQueryState,
> +               &Adapter->VifInterface,
> +               &LinkState.MediaConnectState,
> +               &LinkState.RcvLinkSpeed,
> +               &LinkState.MediaDuplexState);
> 
> -                    if (!(Options.OffloadIpVersion4LargePacket))
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
> +        Info("LINK: STATE UNKNOWN\n");
> +    } else if (LinkState.MediaConnectState ==
> MediaConnectStateDisconnected) {
> +        Info("LINK: DOWN\n");
> +    } else {
> +        ASSERT3U(LinkState.MediaConnectState, ==,
> MediaConnectStateConnected);
> 
> -                if (!no_change(offloadParameters->LsoV2IPv6)) {
> -                    XENVIF_VIF_OFFLOAD_OPTIONS  Options;
> +        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);
> +    }
> 
> -                    XENVIF_VIF(TransmitterQueryOffloadOptions,
> -                               &Adapter->VifInterface,
> -                               &Options);
> +    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
> 
> -                    if (!(Options.OffloadIpVersion6LargePacket))
> -                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
> -                }
> +    RtlZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
> +    StatusIndication.Header.Type        =
> NDIS_OBJECT_TYPE_STATUS_INDICATION;
> +    StatusIndication.Header.Size        = sizeof (NDIS_STATUS_INDICATION);
> +    StatusIndication.Header.Revision    =
> NDIS_STATUS_INDICATION_REVISION_1;
> +    StatusIndication.SourceHandle       = Adapter->NdisHandle;
> +    StatusIndication.StatusCode         = NDIS_STATUS_LINK_STATE;
> +    StatusIndication.StatusBuffer       = &LinkState;
> +    StatusIndication.StatusBufferSize   = sizeof (NDIS_LINK_STATE);
> 
> -#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;
> -                        }
> -                    }
> +    NdisMIndicateStatusEx(Adapter->NdisHandle, &StatusIndication);
> +}
> 
> -#undef tx_enabled
> -#undef rx_enabled
> -#undef no_change
> +PXENNET_RECEIVER
> +AdapterGetReceiver(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->Receiver;
> +}
> 
> -                    if (offloadChanged)
> -                        AdapterIndicateOffloadChanged(Adapter);
> -                }
> -            } else {
> -                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
> -            }
> -            break;
> -        }
> -        default:
> -            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
> -            break;
> -    };
> +PXENNET_TRANSMITTER
> +AdapterGetTransmitter(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->Transmitter;
> +}
> 
> -    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
> -    if (ndisStatus == NDIS_STATUS_SUCCESS) {
> -        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
> -    }
> +PXENVIF_VIF_INTERFACE
> +AdapterGetVifInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return &Adapter->VifInterface;
> +}
> 
> -    return ndisStatus;
> +NDIS_HANDLE
> +AdapterGetHandle(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return Adapter->NdisHandle;
>  }
> 
> -//
> -// Sets miniport registration attributes.
> -//
> -static NDIS_STATUS
> -AdapterSetRegistrationAttributes (
> -    IN  PADAPTER Adapter
> +NTSTATUS
> +AdapterInitialize(
> +    IN  NDIS_HANDLE                 NdisHandle,
> +    OUT PXENNET_ADAPTER             *Adapter
>      )
>  {
> -    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
> -    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES
> registrationAttributes;
> -    NDIS_STATUS ndisStatus;
> +    PDEVICE_OBJECT          DeviceObject;
> +    NTSTATUS                status;
> +    NDIS_SG_DMA_DESCRIPTION DmaDescription;
> +    NDIS_STATUS             NdisStatus;
> +
> +    status = STATUS_NO_MEMORY;
> +    *Adapter = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_ADAPTER), XENNET_POOL_TAG);
> +    if (*Adapter == NULL)
> +        goto fail1;
> 
> +    RtlZeroMemory(*Adapter, sizeof(XENNET_ADAPTER));
> +    (*Adapter)->NdisHandle = NdisHandle;
> +
> +    DeviceObject = NULL;
> +    NdisMGetDeviceProperty(NdisHandle,
> +                           &DeviceObject,
> +                           NULL,
> +                           NULL,
> +                           NULL,
> +                           NULL);
> +
> +    status = QUERY_INTERFACE(DeviceObject,
> +                             XENVIF,
> +                             VIF,
> +                             XENVIF_VIF_INTERFACE_VERSION_MAX,
> +                             (PINTERFACE)&(*Adapter)->VifInterface,
> +                             sizeof ((*Adapter)->VifInterface),
> +                             FALSE);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> 
> -    NdisZeroMemory(&registrationAttributes,
> -                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
> +    status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
> -    registrationAttributes.Header.Type =
> -
> NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
> +    status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> 
> -    registrationAttributes.Header.Revision =
> -
> NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
> +    status = ReceiverInitialize(*Adapter, &(*Adapter)->Receiver);
> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> 
> -    registrationAttributes.Header.Size =
> -                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
> +    NdisStatus = AdapterGetAdvancedSettings(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail6;
> 
> -    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;
> +    NdisStatus = AdapterSetRegistrationAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail7;
> 
> -    adapterAttributes =
> -                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
> +    NdisStatus = AdapterSetGeneralAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail8;
> 
> -    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
> -                                            adapterAttributes);
> +    NdisStatus = AdapterSetOffloadAttributes(*Adapter);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail9;
> 
> -    return ndisStatus;
> -}
> +    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
> +    DmaDescription.Header.Type      =
> NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
> +    DmaDescription.Header.Size      = sizeof(NDIS_SG_DMA_DESCRIPTION);
> +    DmaDescription.Header.Revision  =
> NDIS_SG_DMA_DESCRIPTION_REVISION_1;
> +    DmaDescription.Flags            = NDIS_SG_DMA_64_BIT_ADDRESS;
> +    DmaDescription.MaximumPhysicalMapping           = 65536;
> +    DmaDescription.ProcessSGListHandler             = AdapterProcessSGList;
> +    DmaDescription.SharedMemAllocateCompleteHandler =
> AdapterAllocateComplete;
> 
> -//
> -// Shuts down adapter.
> -//
> -VOID
> -AdapterShutdown (
> -    IN  NDIS_HANDLE             MiniportAdapterContext,
> -    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
> +    NdisStatus = NdisMRegisterScatterGatherDma((*Adapter)->NdisHandle,
> +                                               &DmaDescription,
> +                                               &(*Adapter)->NdisDmaHandle);
> +    if (NdisStatus != NDIS_STATUS_SUCCESS)
> +        (*Adapter)->NdisDmaHandle = NULL;
> 
> -    UNREFERENCED_PARAMETER(ShutdownAction);
> +    status = AdapterEnable(*Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail10;
> 
> -    if (ShutdownAction != NdisShutdownBugCheck)
> -        AdapterStop(Adapter);
> +    return STATUS_SUCCESS;
> 
> -    return;
> +fail10:
> +    Error("fail10 (%08x)\n", status);
> +    if ((*Adapter)->NdisDmaHandle)
> +        NdisMDeregisterScatterGatherDma((*Adapter)->NdisDmaHandle);
> +    (*Adapter)->NdisDmaHandle = NULL;
> +fail9:
> +    Error("fail9\n");
> +fail8:
> +    Error("fail8\n");
> +fail7:
> +    Error("fail7\n");
> +fail6:
> +    Error("fail6 (%08x)\n", NdisStatus);
> +    if (NT_SUCCESS(status))
> +        status = STATUS_UNSUCCESSFUL;
> +    ReceiverTeardown((*Adapter)->Receiver);
> +    (*Adapter)->Receiver = NULL;
> +fail5:
> +    Error("fail5\n");
> +    TransmitterTeardown((*Adapter)->Transmitter);
> +    (*Adapter)->Transmitter = NULL;
> +fail4:
> +    Error("fail4\n");
> +    XENVIF_VIF(Release, &(*Adapter)->VifInterface);
> +fail3:
> +    Error("fail3\n");
> +    RtlZeroMemory(&(*Adapter)->VifInterface,
> sizeof(XENVIF_VIF_INTERFACE));
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Adapter, XENNET_POOL_TAG);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
>  }
> 
> -//
> -// 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
> -)
> +VOID
> +AdapterTeardown(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
>  {
> -    Trace("====>\n");
> +    if (Adapter->NdisDmaHandle)
> +        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
> +    Adapter->NdisDmaHandle = NULL;
> 
> -    if (!Adapter->Enabled)
> -        goto done;
> +    ReceiverTeardown(Adapter->Receiver);
> +    Adapter->Receiver = NULL;
> 
> -    XENVIF_VIF(Disable,
> -               &Adapter->VifInterface);
> +    TransmitterTeardown(Adapter->Transmitter);
> +    Adapter->Transmitter = 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, XENNET_POOL_TAG);
>  }
> +
> +//
> +//#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)
> +//
> diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
> index e64e40d..a1f4b85 100644
> --- a/src/xennet/adapter.h
> +++ b/src/xennet/adapter.h
> @@ -29,19 +29,20 @@
>   * SUCH DAMAGE.
>   */
> 
> -#pragma once
> +#ifndef _XENNET_ADAPTER_H_
> +#define _XENNET_ADAPTER_H_
> 
> -#define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
> +#define XENNET_INTERFACE_TYPE   NdisInterfaceInternal
> 
> -#define XENNET_MEDIA_TYPE               NdisMedium802_3
> +#define XENNET_MEDIA_TYPE       NdisMedium802_3
> 
> -#define XENNET_MAC_OPTIONS
> (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
> -                                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
> -                                         NDIS_MAC_OPTION_NO_LOOPBACK |          \
> -                                         NDIS_MAC_OPTION_8021P_PRIORITY |       \
> -
> NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
> +#define XENNET_MAC_OPTIONS
> (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
> +                                 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
> +                                 NDIS_MAC_OPTION_NO_LOOPBACK |          \
> +                                 NDIS_MAC_OPTION_8021P_PRIORITY |       \
> +
> NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
> 
> -typedef struct _PROPERTIES {
> +typedef struct _XENNET_PROPERTIES {
>      int ipv4_csum;
>      int tcpv4_csum;
>      int udpv4_csum;
> @@ -52,122 +53,63 @@ typedef struct _PROPERTIES {
>      int lsov6;
>      int lrov4;
>      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
> -    );
> -
> -MINIPORT_CANCEL_SEND AdapterCancelSendNetBufferLists;
> -VOID
> -AdapterCancelSendNetBufferLists (
> -    IN  NDIS_HANDLE NdisHandle,
> -    IN  PVOID       CancelId
> -    );
> +} XENNET_PROPERTIES, *PXENNET_PROPERTIES;
> 
> -MINIPORT_CHECK_FOR_HANG AdapterCheckForHang;
> -BOOLEAN
> -AdapterCheckForHang (
> -    IN  NDIS_HANDLE NdisHandle
> -    );
> -
> -VOID
> -AdapterCleanup (
> -    IN PADAPTER Adapter
> -    );
> +typedef struct _XENNET_ADAPTER  XENNET_ADAPTER,
> *PXENNET_ADAPTER;
> 
> -NDIS_STATUS
> -AdapterInitialize (
> -    IN  PADAPTER    Adapter,
> -    IN  NDIS_HANDLE AdapterHandle
> +extern NDIS_STATUS
> +AdapterOidRequest(
> +    IN  PXENNET_ADAPTER             Adapter,
> +    IN  PNDIS_OID_REQUEST           Request
>      );
> 
> -MINIPORT_OID_REQUEST AdapterOidRequest;
> -NDIS_STATUS
> -AdapterOidRequest (
> -    IN  NDIS_HANDLE         NdisHandle,
> -    IN  PNDIS_OID_REQUEST   NdisRequest
> +extern NTSTATUS
> +AdapterEnable(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_PAUSE AdapterPause;
> -NDIS_STATUS
> -AdapterPause (
> -    IN  NDIS_HANDLE                     NdisHandle,
> -    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> +extern BOOLEAN
> +AdapterDisable(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterPnPEventHandler;
> -VOID
> -AdapterPnPEventHandler (
> -    IN  NDIS_HANDLE             NdisHandle,
> -    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +extern VOID
> +AdapterMediaStateChange(
> +    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
> +#include "transmitter.h"
> +extern PXENNET_TRANSMITTER
> +AdapterGetTransmitter(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists;
> -VOID
> -AdapterReturnNetBufferLists (
> -    IN  NDIS_HANDLE         MiniportAdapterContext,
> -    IN  PNET_BUFFER_LIST    NetBufferLists,
> -    IN  ULONG               ReturnFlags
> +#include <vif_interface.h>
> +extern PXENVIF_VIF_INTERFACE
> +AdapterGetVifInterface(
> +    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 NDIS_HANDLE
> +AdapterGetHandle(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> 
> -NDIS_STATUS
> -AdapterStop (
> -    IN  PADAPTER    Adapter
> -    );
> -
> -MINIPORT_SHUTDOWN AdapterShutdown;
> -
> -VOID
> -AdapterShutdown (
> -    IN  NDIS_HANDLE             MiniportAdapterContext,
> -    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> +extern NTSTATUS
> +AdapterInitialize(
> +    IN  NDIS_HANDLE                 NdisHandle,
> +    OUT PXENNET_ADAPTER             *Adapter
>      );
> 
>  extern VOID
> -ReceiverReceivePackets(
> -    IN  PRECEIVER   Receiver,
> -    IN  PLIST_ENTRY List
> +AdapterTeardown(
> +    IN  PXENNET_ADAPTER             Adapter
>      );
> +
> +#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/driver.c b/src/xennet/driver.c
> new file mode 100644
> index 0000000..66aff1d
> --- /dev/null
> +++ b/src/xennet/driver.c
> @@ -0,0 +1,550 @@
> +/* 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 <ndis.h>
> +#include <ntstrsafe.h>
> +#include <version.h>
> +
> +#include "adapter.h"
> +#include "transmitter.h"
> +#include "receiver.h"
> +#include "registry.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> +
> +extern PULONG InitSafeBootMode;
> +
> +typedef struct _XENNET_DRIVER {
> +    PDRIVER_OBJECT              DriverObject;
> +    NDIS_HANDLE                 MiniportHandle;
> +    NTSTATUS                    (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
> +} XENNET_DRIVER;
> +
> +static XENNET_DRIVER            Driver;
> +
> +MINIPORT_CANCEL_OID_REQUEST     DriverCancelOidRequest;
> +VOID
> +DriverCancelOidRequest(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PVOID                   RequestId
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(RequestId);
> +}
> +
> +MINIPORT_CANCEL_SEND            DriverCancelSendNetBufferLists;
> +VOID
> +DriverCancelSendNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PVOID                   CancelId
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(CancelId);
> +}
> +
> +MINIPORT_CHECK_FOR_HANG DriverCheckForHang;
> +BOOLEAN
> +DriverCheckForHang(
> +    IN  NDIS_HANDLE             NdisHandle
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    return FALSE;
> +}
> +
> +MINIPORT_DEVICE_PNP_EVENT_NOTIFY DriverPnPEventHandler;
> +VOID
> +DriverPnPEventHandler(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    UNREFERENCED_PARAMETER(NetDevicePnPEvent);
> +}
> +
> +MINIPORT_RESET                  DriverReset;
> +NDIS_STATUS
> +DriverReset(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    OUT PBOOLEAN                AddressingReset
> +    )
> +{
> +    UNREFERENCED_PARAMETER(NdisHandle);
> +    *AddressingReset = FALSE;
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +MINIPORT_OID_REQUEST            DriverOidRequest;
> +NDIS_STATUS
> +DriverOidRequest(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNDIS_OID_REQUEST       NdisRequest
> +    )
> +{
> +    return AdapterOidRequest((PXENNET_ADAPTER)NdisHandle,
> NdisRequest);
> +}
> +
> +MINIPORT_PAUSE DriverPause;
> +NDIS_STATUS
> +DriverPause(
> +    IN  NDIS_HANDLE                     NdisHandle,
> +    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
> +    )
> +{
> +    UNREFERENCED_PARAMETER(MiniportPauseParameters);
> +
> +    if (AdapterDisable((PXENNET_ADAPTER)NdisHandle))
> +        AdapterMediaStateChange((PXENNET_ADAPTER)NdisHandle);
> +
> +    return NDIS_STATUS_SUCCESS;
> +}
> +
> +MINIPORT_RESTART DriverRestart;
> +NDIS_STATUS
> +DriverRestart(
> +    IN  NDIS_HANDLE                         NdisHandle,
> +    IN  PNDIS_MINIPORT_RESTART_PARAMETERS
> MiniportRestartParameters
> +    )
> +{
> +    NTSTATUS    status;
> +
> +    UNREFERENCED_PARAMETER(MiniportRestartParameters);
> +
> +    status = AdapterEnable((PXENNET_ADAPTER)NdisHandle);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return NDIS_STATUS_FAILURE;
> +}
> +
> +MINIPORT_RETURN_NET_BUFFER_LISTS DriverReturnNetBufferLists;
> +VOID
> +DriverReturnNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
> +    )
> +{
> +    PXENNET_RECEIVER            Receiver;
> +    Receiver = AdapterGetReceiver((PXENNET_ADAPTER)NdisHandle);
> +    ReceiverReturnNetBufferLists(Receiver,
> +                                 NetBufferLists,
> +                                 ReturnFlags);
> +}
> +
> +MINIPORT_SEND_NET_BUFFER_LISTS  DriverSendNetBufferLists;
> +VOID
> +DriverSendNetBufferLists(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
> +    )
> +{
> +    PXENNET_TRANSMITTER         Transmitter;
> +    Transmitter = AdapterGetTransmitter((PXENNET_ADAPTER)NdisHandle);
> +    TransmitterSendNetBufferLists(Transmitter,
> +                                  NetBufferList,
> +                                  PortNumber,
> +                                  SendFlags);
> +}
> +
> +MINIPORT_SHUTDOWN DriverShutdown;
> +VOID
> +DriverShutdown(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
> +    )
> +{
> +    UNREFERENCED_PARAMETER(ShutdownAction);
> +
> +    if (ShutdownAction != NdisShutdownBugCheck)
> +        (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
> +}
> +
> +MINIPORT_INITIALIZE             DriverInitialize;
> +NDIS_STATUS
> +DriverInitialize(
> +    IN  NDIS_HANDLE                        NdisHandle,
> +    IN  NDIS_HANDLE                        DriverContext,
> +    IN  PNDIS_MINIPORT_INIT_PARAMETERS     Parameters
> +    )
> +{
> +    NTSTATUS            status;
> +    PXENNET_ADAPTER     Adapter;
> +
> +    UNREFERENCED_PARAMETER(DriverContext);
> +    UNREFERENCED_PARAMETER(Parameters);
> +
> +    status = AdapterInitialize(NdisHandle, &Adapter);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return NDIS_STATUS_ADAPTER_NOT_FOUND;
> +}
> +
> +MINIPORT_HALT                   DriverHalt;
> +VOID
> +DriverHalt(
> +    IN  NDIS_HANDLE             NdisHandle,
> +    IN  NDIS_HALT_ACTION        HaltAction
> +    )
> +{
> +    if (NdisHandle == NULL)
> +        return;
> +
> +    UNREFERENCED_PARAMETER(HaltAction);
> +
> +    (VOID)AdapterDisable((PXENNET_ADAPTER)NdisHandle);
> +    AdapterTeardown((PXENNET_ADAPTER)NdisHandle);
> +}
> +
> +typedef struct _XENNET_CONTEXT {
> +    PDEVICE_CAPABILITIES    Capabilities;
> +    PIO_COMPLETION_ROUTINE  CompletionRoutine;
> +    PVOID                   CompletionContext;
> +    UCHAR                   CompletionControl;
> +} XENNET_CONTEXT, *PXENNET_CONTEXT;
> +
> +__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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
> +
> +    Trace("<====\n");
> +
> +    return status;
> +}
> +
> +_Dispatch_type_(IRP_MJ_PNP)
> +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 = Driver.NdisDispatchPnp(DeviceObject, Irp);
> +        break;
> +    }
> +
> +    return status;
> +}
> +
> +_Dispatch_type_(IRP_MJ_CREATE)
> +_Dispatch_type_(IRP_MJ_CLOSE)
> +_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)
> +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
> +    )
> +{
> +    Trace("====>\n");
> +
> +    if (*InitSafeBootMode > 0)
> +        goto done;
> +
> +    ASSERT3P(Driver.DriverObject, ==, DriverObject);
> +    Driver.DriverObject = NULL;
> +
> +    if (Driver.MiniportHandle)
> +        NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
> +    Driver.MiniportHandle = NULL;
> +
> +    Driver.NdisDispatchPnp = NULL;
> +
> +    RegistryTeardown();
> +
> +    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;
> +    NTSTATUS                                status;
> +
> +    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
> +
> +    Trace("====>\n");
> +
> +    if (*InitSafeBootMode > 0)
> +        return NDIS_STATUS_SUCCESS;
> +
> +    ASSERT3P(Driver.DriverObject, ==, NULL);
> +    Driver.DriverObject = DriverObject;
> +
> +    Info("XENNET %d.%d.%d (%d) (%02d.%02d.%04d)\n",
> +         MAJOR_VERSION,
> +         MINOR_VERSION,
> +         MICRO_VERSION,
> +         BUILD_NUMBER,
> +         DAY,
> +         MONTH,
> +         YEAR);
> +
> +    status = RegistryInitialize(RegistryPath);
> +
> +    ndisStatus = (NT_SUCCESS(status)) ?
> +                 NDIS_STATUS_SUCCESS :
> +                 NDIS_STATUS_FAILURE;
> +
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail1;
> +
> +    //
> +    // Register miniport with NDIS.
> +    //
> +
> +    RtlZeroMemory(&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     = DriverCancelOidRequest;
> +    mpChars.CancelSendHandler           = DriverCancelSendNetBufferLists;
> +    mpChars.CheckForHangHandlerEx       = DriverCheckForHang;
> +    mpChars.InitializeHandlerEx         = DriverInitialize;
> +    mpChars.HaltHandlerEx               = DriverHalt;
> +    mpChars.OidRequestHandler           = DriverOidRequest;
> +    mpChars.PauseHandler                = DriverPause;
> +    mpChars.DevicePnPEventNotifyHandler = DriverPnPEventHandler;
> +    mpChars.ResetHandlerEx              = DriverReset;
> +    mpChars.RestartHandler              = DriverRestart;
> +    mpChars.ReturnNetBufferListsHandler = DriverReturnNetBufferLists;
> +    mpChars.SendNetBufferListsHandler   = DriverSendNetBufferLists;
> +    mpChars.ShutdownHandlerEx           = DriverShutdown;
> +    mpChars.UnloadHandler               = DriverUnload;
> +
> +    Driver.MiniportHandle = NULL;
> +    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
> +                                             RegistryPath,
> +                                             NULL,
> +                                             &mpChars,
> +                                             &Driver.MiniportHandle);
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail2;
> +
> +    RtlZeroMemory(&ConfigurationObject, sizeof(ConfigurationObject));
> +    ConfigurationObject.Header.Type     =
> NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
> +    ConfigurationObject.Header.Size     =
> NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
> +    ConfigurationObject.Header.Revision =
> NDIS_CONFIGURATION_OBJECT_REVISION_1;
> +    ConfigurationObject.NdisHandle      = Driver.MiniportHandle;
> +    ConfigurationObject.Flags           = 0;
> +
> +    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject,
> &ConfigurationHandle);
> +    if (ndisStatus != NDIS_STATUS_SUCCESS)
> +        goto fail3;
> +
> +    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);
> +
> +    Driver.NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
> +    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
> +
> +    if (FailCreateClose != 0) {
> +        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
> +        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
> +    }
> +
> +    if (FailDeviceControl != 0) {
> +        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
> DispatchFail;
> +    }
> +
> +    Trace("<====\n");
> +    return NDIS_STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    NdisMDeregisterMiniportDriver(Driver.MiniportHandle);
> +    Driver.MiniportHandle = NULL;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    RegistryTeardown();
> +
> +fail1:
> +    Error("fail1\n");
> +
> +    Driver.DriverObject = NULL;
> +    return ndisStatus;
> +}
> +
> diff --git a/src/xennet/main.c b/src/xennet/main.c
> deleted file mode 100644
> index 6622e82..0000000
> --- a/src/xennet/main.c
> +++ /dev/null
> @@ -1,361 +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"
> -#include "registry.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;
> -    NTSTATUS status;
> -
> -    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);
> -
> -    status = RegistryInitialize(RegistryPath);
> -
> -    ndisStatus = (NT_SUCCESS(status)) ?
> -                 NDIS_STATUS_SUCCESS :
> -                 NDIS_STATUS_FAILURE;
> -
> -    if (ndisStatus != NDIS_STATUS_SUCCESS)
> -        goto fail;
> -
> -    //
> -    // 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);
> -
> -    RegistryTeardown();
> -
> -    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/miniport.c b/src/xennet/miniport.c
> deleted file mode 100644
> index a1d605f..0000000
> --- a/src/xennet/miniport.c
> +++ /dev/null
> @@ -1,297 +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.
> - */
> -
> -#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,
> -    IN  ULONG           Size,
> -    IN  BOOLEAN         Optional
> -    )
> -{
> -    UNICODE_STRING      Unicode;
> -    HANDLE              InterfacesKey;
> -    HANDLE              SubscriberKey;
> -    KEVENT              Event;
> -    IO_STATUS_BLOCK     StatusBlock;
> -    PIRP                Irp;
> -    PIO_STACK_LOCATION  StackLocation;
> -    NTSTATUS            status;
> -
> -    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));
> -
> -    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
> -                                       DeviceObject,
> -                                       NULL,
> -                                       0,
> -                                       NULL,
> -                                       &Event,
> -                                       &StatusBlock);
> -
> -    status = STATUS_UNSUCCESSFUL;
> -    if (Irp == NULL)
> -        goto fail4;
> -
> -    StackLocation = IoGetNextIrpStackLocation(Irp);
> -    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
> -
> -    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;
> -    }
> -
> -    if (!NT_SUCCESS(status)) {
> -        if (status == STATUS_NOT_SUPPORTED && Optional)
> -            goto done;
> -
> -        goto fail5;
> -    }
> -
> -    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);
> -
> -    return status;
> -}
> -
> -#define QUERY_INTERFACE(                                                                \
> -    _DeviceObject,                                                                      \
> -    _ProviderName,                                                                      \
> -    _InterfaceName,                                                                     \
> -    _Version,                                                                           \
> -    _Interface,                                                                         \
> -    _Size,                                                                              \
> -    _Optional)                                                                          \
> -    __QueryInterface((_DeviceObject),                                                   \
> -                     L ## #_ProviderName,                                               \
> -                     #_InterfaceName,                                                   \
> -                     &GUID_ ## _ProviderName ## _ ## _InterfaceName ##
> _INTERFACE,      \
> -                     (_Version),                                                        \
> -                     (_Interface),                                                      \
> -                     (_Size),                                                           \
> -                     (_Optional))
> -
> -NDIS_STATUS
> -MiniportInitialize (
> -    IN  NDIS_HANDLE                        MiniportAdapterHandle,
> -    IN  NDIS_HANDLE                        MiniportDriverContext,
> -    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
> -    )
> -{
> -    PADAPTER Adapter = NULL;
> -    NDIS_STATUS ndisStatus;
> -    PDEVICE_OBJECT DeviceObject;
> -    NTSTATUS status;
> -
> -    UNREFERENCED_PARAMETER(MiniportDriverContext);
> -    UNREFERENCED_PARAMETER(MiniportInitParameters);
> -
> -    Trace("====>\n");
> -
> -    status = AllocAdapter(&Adapter);
> -
> -    if (!NT_SUCCESS(status) || Adapter == NULL) {
> -        ndisStatus = NDIS_STATUS_RESOURCES;
> -        goto fail1;
> -    }
> -
> -    RtlZeroMemory(Adapter, sizeof (ADAPTER));
> -
> -    DeviceObject = NULL;
> -    NdisMGetDeviceProperty(MiniportAdapterHandle,
> -                           &DeviceObject,
> -                           NULL,
> -                           NULL,
> -                           NULL,
> -                           NULL);
> -
> -    status = QUERY_INTERFACE(DeviceObject,
> -                             XENVIF,
> -                             VIF,
> -                             XENVIF_VIF_INTERFACE_VERSION_MAX,
> -                             (PINTERFACE)&Adapter->VifInterface,
> -                             sizeof (Adapter->VifInterface),
> -                             FALSE);
> -
> -    if (!NT_SUCCESS(status)) {
> -        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
> -        goto fail2;
> -    }
> -
> -    ndisStatus = AdapterInitialize(Adapter, MiniportAdapterHandle);
> -    if (ndisStatus != NDIS_STATUS_SUCCESS) {
> -        goto fail3;
> -    }
> -
> -    Trace("<====\n");
> -    return ndisStatus;
> -
> -fail3:
> -    Error("fail3\n");
> -
> -    RtlZeroMemory(&Adapter->VifInterface,
> -                  sizeof (XENVIF_VIF_INTERFACE));
> -
> -fail2:
> -    Error("fail2\n");
> -
> -    ExFreePool(Adapter);
> -
> -fail1:
> -    Error("fail1\n");
> -
> -    return ndisStatus;
> -}
> -
> -//
> -// Stops adapter and frees all resources.
> -//
> -VOID
> -MiniportHalt (
> -    IN  NDIS_HANDLE             MiniportAdapterHandle,
> -    IN  NDIS_HALT_ACTION        HaltAction
> -    )
> -{
> -    PADAPTER Adapter = (PADAPTER)MiniportAdapterHandle;
> -
> -    UNREFERENCED_PARAMETER(HaltAction);
> -
> -    if (Adapter == NULL)
> -        return;
> -
> -    (VOID) AdapterStop(Adapter);
> -
> -    AdapterCleanup(Adapter);
> -
> -    RtlZeroMemory(&Adapter->VifInterface,
> -                  sizeof (XENVIF_VIF_INTERFACE));
> -
> -    ExFreePool(Adapter);
> -}
> 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..ee01a18 100644
> --- a/src/xennet/receiver.c
> +++ b/src/xennet/receiver.c
> @@ -29,103 +29,38 @@
>   * SUCH DAMAGE.
>   */
> 
> -#include "common.h"
> -
> -#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;
> -}
> +#include <ndis.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       'teNX'
> +#define IN_NDIS_MAX 1024
> 
> -PNET_BUFFER_LIST
> +static PNET_BUFFER_LIST
>  ReceiverAllocateNetBufferList(
> -    IN  PRECEIVER       Receiver,
> -    IN  PMDL            Mdl,
> -    IN  ULONG           Offset,
> -    IN  ULONG           Length
> +    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();
> -
>      NetBufferList = Receiver->GetList[Cpu];
> 
>      if (NetBufferList == NULL)
> @@ -158,16 +93,16 @@ ReceiverAllocateNetBufferList(
>      return NetBufferList;
>  }
> 
> -VOID
> +static VOID
>  ReceiverReleaseNetBufferList(
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  BOOLEAN             Cache
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  BOOLEAN                 Cache
>      )
>  {
>      if (Cache) {
> -        PNET_BUFFER_LIST    Old;
> -        PNET_BUFFER_LIST    New;
> +        PNET_BUFFER_LIST        Old;
> +        PNET_BUFFER_LIST        New;
> 
>          ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> 
> @@ -182,72 +117,9 @@ ReceiverReleaseNetBufferList(
>      }
>  }
> 
> -static FORCEINLINE ULONG
> -__ReceiverReturnNetBufferLists(
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  BOOLEAN             Cache
> -    )
> -{
> -    PADAPTER                Adapter;
> -    LIST_ENTRY              List;
> -    ULONG                   Count;
> -
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> -
> -    InitializeListHead(&List);
> -
> -    Count = 0;
> -    while (NetBufferList != NULL) {
> -        PNET_BUFFER_LIST        Next;
> -        PNET_BUFFER             NetBuffer;
> -        PMDL                    Mdl;
> -        PXENVIF_RECEIVER_PACKET Packet;
> -
> -        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> -        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> -
> -        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> -        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
> -
> -        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
> -
> -        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
> -
> -        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
> -
> -        InsertTailList(&List, &Packet->ListEntry);
> -
> -        Count++;
> -        NetBufferList = Next;
> -    }
> -
> -    if (Count != 0)
> -        XENVIF_VIF(ReceiverReturnPackets,
> -                   &Adapter->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  PXENNET_RECEIVER                        Receiver,
>      IN  PMDL                                    Mdl,
>      IN  ULONG                                   Offset,
>      IN  ULONG                                   Length,
> @@ -255,11 +127,11 @@ ReceiverReceivePacket(
>      IN  USHORT                                  TagControlInformation
>      )
>  {
> -    PADAPTER                                    Adapter;
> +    PXENNET_ADAPTER                             Adapter;
>      PNET_BUFFER_LIST                            NetBufferList;
>      NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> +    Adapter = Receiver->Adapter;
> 
>      NetBufferList = ReceiverAllocateNetBufferList(Receiver,
>                                                    Mdl,
> @@ -268,7 +140,7 @@ ReceiverReceivePacket(
>      if (NetBufferList == NULL)
>          goto fail1;
> 
> -    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
> +    NetBufferList->SourceHandle = AdapterGetHandle(Adapter);
> 
>      csumInfo.Value = 0;
> 
> @@ -281,8 +153,8 @@ ReceiverReceivePacket(
>      csumInfo.Receive.UdpChecksumSucceeded =
> Flags.UdpChecksumSucceeded;
>      csumInfo.Receive.UdpChecksumFailed = Flags.UdpChecksumFailed;
> 
> -    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo)
> = (PVOID)(ULONG_PTR)csumInfo.Value;
> -
> +    NET_BUFFER_LIST_INFO(NetBufferList,
> TcpIpChecksumNetBufferListInfo) =
> +                                            (PVOID)(ULONG_PTR)csumInfo.Value;
>      if (TagControlInformation != 0) {
>          NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
> 
> @@ -306,20 +178,67 @@ fail1:
>      return NULL;
>  }
> 
> +static FORCEINLINE ULONG
> +__ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  BOOLEAN                 Cache
> +    )
> +{
> +    PXENNET_ADAPTER             Adapter;
> +    LIST_ENTRY                  List;
> +    ULONG                       Count;
> +
> +    Adapter = Receiver->Adapter;
> +
> +    InitializeListHead(&List);
> +
> +    Count = 0;
> +    while (NetBufferList != NULL) {
> +        PNET_BUFFER_LIST        Next;
> +        PNET_BUFFER             NetBuffer;
> +        PMDL                    Mdl;
> +        PXENVIF_RECEIVER_PACKET Packet;
> +
> +        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> +        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> +
> +        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> +        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
> +
> +        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
> +
> +        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
> +
> +        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
> +
> +        InsertTailList(&List, &Packet->ListEntry);
> +
> +        Count++;
> +        NetBufferList = Next;
> +    }
> +
> +    if (Count != 0) {
> +        XENVIF_VIF(ReceiverReturnPackets,
> +                   AdapterGetVifInterface(Adapter),
> +                   &List);
> +    }
> +    return Count;
> +}
> +
>  static VOID
>  ReceiverPushPackets(
> -    IN  PRECEIVER           Receiver,
> +    IN  PXENNET_RECEIVER    Receiver,
>      IN  PNET_BUFFER_LIST    NetBufferList,
>      IN  ULONG               Count,
>      IN  BOOLEAN             LowResources
>      )
>  {
> -    PADAPTER                Adapter;
> +    PXENNET_ADAPTER         Adapter;
>      ULONG                   Flags;
>      LONG                    InNDIS;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> -
> +    Adapter = Receiver->Adapter;
>      InNDIS = Receiver->InNDIS;
> 
>      Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
> @@ -342,7 +261,7 @@ ReceiverPushPackets(
>              break;
>      }
> 
> -    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
> +    NdisMIndicateReceiveNetBufferLists(AdapterGetHandle(Adapter),
>                                         NetBufferList,
>                                         NDIS_DEFAULT_PORT_NUMBER,
>                                         Count,
> @@ -352,21 +271,34 @@ ReceiverPushPackets(
>          (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
>  }
> 
> -#define IN_NDIS_MAX 1024
> +VOID
> +ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
> +    )
> +{
> +    ULONG                   Count;
> +
> +    UNREFERENCED_PARAMETER(ReturnFlags);
> +
> +    Count = __ReceiverReturnNetBufferLists(Receiver, NetBufferLists,
> 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;
> +    PXENNET_ADAPTER     Adapter;
>      PNET_BUFFER_LIST    HeadNetBufferList;
>      PNET_BUFFER_LIST    *TailNetBufferList;
>      ULONG               Count;
>      BOOLEAN             LowResources;
> 
> -    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
> +    Adapter = Receiver->Adapter;
>      LowResources = FALSE;
> 
>  again:
> @@ -404,21 +336,26 @@ 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);
> +                       AdapterGetVifInterface(Adapter),
> +                       &PacketList);
>          }
>      }
> 
> @@ -434,3 +371,95 @@ again:
>          goto again;
>      }
>  }
> +
> +PXENVIF_VIF_OFFLOAD_OPTIONS
> +ReceiverOffloadOptions(
> +    IN  PXENNET_RECEIVER        Receiver
> +    )
> +{
> +    return &Receiver->OffloadOptions;
> +}
> +
> +NTSTATUS
> +ReceiverInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_RECEIVER        *Receiver
> +    )
> +{
> +    NTSTATUS                        status;
> +    NET_BUFFER_LIST_POOL_PARAMETERS Pool;
> +
> +    status = STATUS_NO_MEMORY;
> +    *Receiver = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_RECEIVER), RECEIVER_POOL_TAG);
> +    if (*Receiver == NULL)
> +        goto fail1;
> +
> +    RtlZeroMemory(*Receiver, sizeof(XENNET_RECEIVER));
> +    (*Receiver)->Adapter = Adapter;
> +
> +    RtlZeroMemory(&Pool, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
> +    Pool.Header.Type        = NDIS_OBJECT_TYPE_DEFAULT;
> +    Pool.Header.Size        = sizeof(NET_BUFFER_LIST_POOL_PARAMETERS);
> +    Pool.Header.Revision    =
> NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
> +    Pool.ProtocolId         = 0;
> +    Pool.ContextSize        = 0;
> +    Pool.fAllocateNetBuffer = TRUE;
> +    Pool.PoolTag            = RECEIVER_POOL_TAG;
> +
> +    (*Receiver)->NetBufferListPool =
> NdisAllocateNetBufferListPool(AdapterGetHandle(Adapter),
> +                                                                   &Pool);
> +    if ((*Receiver)->NetBufferListPool == NULL)
> +        goto fail2;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    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;
> +
> +    ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
> +}
> +
> diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
> index 1a58053..715f02e 100644
> --- a/src/xennet/receiver.h
> +++ b/src/xennet/receiver.h
> @@ -29,49 +29,42 @@
>   * 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;
> +typedef struct _XENNET_RECEIVER     XENNET_RECEIVER,
> *PXENNET_RECEIVER;
> 
> -VOID
> -ReceiverDebugDump (
> -    IN PRECEIVER Receiver
> -    );
> +#include <vif_interface.h>
> 
> -VOID
> -ReceiverCleanup (
> -    IN  PRECEIVER Receiver
> +extern VOID
> +ReceiverReturnNetBufferLists(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PNET_BUFFER_LIST        NetBufferLists,
> +    IN  ULONG                   ReturnFlags
>      );
> 
> -VOID
> -ReceiverHandleNotification (
> -    IN  PRECEIVER Receiver
> +extern VOID
> +ReceiverReceivePackets(
> +    IN  PXENNET_RECEIVER        Receiver,
> +    IN  PLIST_ENTRY             List
>      );
> 
> -NDIS_STATUS
> -ReceiverInitialize (
> -    IN  PRECEIVER   Receiver
> +extern PXENVIF_VIF_OFFLOAD_OPTIONS
> +ReceiverOffloadOptions(
> +    IN  PXENNET_RECEIVER        Receiver
>      );
> 
> -VOID
> -ReceiverReturnNetBufferLists (
> -    IN  PRECEIVER           Receiver,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  ULONG               ReturnFlags
> +#include "adapter.h"
> +extern NTSTATUS
> +ReceiverInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_RECEIVER        *Receiver
>      );
> 
> -VOID
> -ReceiverWaitForPacketReturn(
> -    IN  PRECEIVER   Receiver,
> -    IN  BOOLEAN     Locked
> +extern VOID
> +ReceiverTeardown(
> +    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..be07458 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -29,59 +29,18 @@
>   * SUCH DAMAGE.
>   */
> 
> -#include "common.h"
> +#include <ndis.h>
> +#include "transmitter.h"
> +#include "adapter.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> 
> -#pragma warning(disable:4711)
> +struct _XENNET_TRANSMITTER {
> +    PXENNET_ADAPTER             Adapter;
> +    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> +};
> 
> -NDIS_STATUS
> -TransmitterInitialize(
> -    IN  PTRANSMITTER    Transmitter,
> -    IN  PADAPTER        Adapter
> -    )
> -{
> -    Transmitter->Adapter = Adapter;
> -
> -    return NDIS_STATUS_SUCCESS;
> -}
> -
> -VOID
> -TransmitterEnable(
> -    IN  PTRANSMITTER    Transmitter
> -    )
> -{
> -    PADAPTER            Adapter = Transmitter->Adapter;
> -
> -    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> -                      &Adapter->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,
> -                      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,
> -                      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;
> -    }
> -}
> +#define TRANSMITTER_POOL_TAG    'teNX'
> 
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
> @@ -97,24 +56,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             NdisStatus
>      )
>  {
> +    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
> +
>      ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> 
> -    NET_BUFFER_LIST_STATUS(NetBufferList) =
> NDIS_STATUS_NOT_ACCEPTED;
> +    if (NdisStatus == 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;
> +    }
> +    NET_BUFFER_LIST_STATUS(NetBufferList) = NdisStatus;
> 
> -    NdisMSendNetBufferListsComplete(Transmitter->Adapter-
> >NdisAdapterHandle,
> +    NdisMSendNetBufferListsComplete(AdapterGetHandle(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                 NdisStatus
>      )
>  {
>      while (Packet != NULL) {
> @@ -135,21 +107,85 @@ TransmitterAbortPackets(
> 
>          ASSERT(ListReserved->Reference != 0);
>          if (InterlockedDecrement(&ListReserved->Reference) == 0)
> -            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
> +            TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NdisStatus);
> 
>          Packet = Next;
>      }
>  }
> +
> +static FORCEINLINE VOID
> +__OffloadOptions(
> +    IN  PNET_BUFFER_LIST            NetBufferList,
> +    OUT PXENVIF_VIF_OFFLOAD_OPTIONS Offload,
> +    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);
> +
> +    Offload->Value = 0;
> +    *TagControlInformation = 0;
> +    *MaximumSegmentSize = 0;
> +
> +    if (ChecksumInfo->Transmit.IsIPv4) {
> +        if (ChecksumInfo->Transmit.IpHeaderChecksum)
> +            Offload->OffloadIpVersion4HeaderChecksum = 1;
> +        if (ChecksumInfo->Transmit.TcpChecksum)
> +            Offload->OffloadIpVersion4TcpChecksum = 1;
> +        if (ChecksumInfo->Transmit.UdpChecksum)
> +            Offload->OffloadIpVersion4UdpChecksum = 1;
> +    }
> +
> +    if (ChecksumInfo->Transmit.IsIPv6) {
> +        if (ChecksumInfo->Transmit.TcpChecksum)
> +            Offload->OffloadIpVersion6TcpChecksum = 1;
> +        if (ChecksumInfo->Transmit.UdpChecksum)
> +            Offload->OffloadIpVersion6UdpChecksum = 1;
> +    }
> +
> +    if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
> +        Offload->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)
> +            Offload->OffloadIpVersion4LargePacket = 1;
> +        if (LargeSendInfo->LsoV2Transmit.IPVersion ==
> NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
> +            Offload->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;
> +    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
>      PXENVIF_TRANSMITTER_PACKET  HeadPacket;
>      PXENVIF_TRANSMITTER_PACKET  *TailPacket;
>      KIRQL                       Irql;
> @@ -158,21 +194,21 @@ TransmitterSendNetBufferLists(
> 
>      HeadPacket = NULL;
>      TailPacket = &HeadPacket;
> -
> +
>      if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
>          ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
>          NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
>      } else {
>          Irql = DISPATCH_LEVEL;
>      }
> -
> +
>      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;
> +        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
> +        USHORT                          TagControlInformation;
> +        USHORT                          MaximumSegmentSize;
> +        PNET_BUFFER                     NetBuffer;
> 
>          ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
>          NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> @@ -180,12 +216,7 @@ TransmitterSendNetBufferLists(
>          ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
>          RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
> 
> -        LargeSendInfo =
> (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFF
> ER_LIST_INFO(NetBufferList,
> -
> TcpLargeSendNetBufferListInfo);
> -        ChecksumInfo =
> (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_I
> NFO(NetBufferList,
> -
> TcpIpChecksumNetBufferListInfo);
> -        Ieee8021QInfo =
> (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBuff
> erList,
> -                                                                                Ieee8021QNetBufferListInfo);
> +        __OffloadOptions(NetBufferList, &Options, &TagControlInformation,
> &MaximumSegmentSize);
> 
>          NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
>          while (NetBuffer != NULL) {
> @@ -199,50 +230,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   = Options.Value & Transmitter-
> >OffloadOptions.Value;
> +            Packet->Send.TagControlInformation  = TagControlInformation;
> +            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
> 
>              ASSERT3P(Packet->Next, ==, NULL);
>              *TailPacket = Packet;
> @@ -258,65 +248,89 @@ TransmitterSendNetBufferLists(
>          NTSTATUS    status;
> 
>          status = XENVIF_VIF(TransmitterQueuePackets,
> -                            &Adapter->VifInterface,
> +                            AdapterGetVifInterface(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
> +VOID
> +TransmitterCompletePackets(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET  Packet
>      )
>  {
> -    PADAPTER                                            Adapter = Transmitter->Adapter;
> -    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO
> LargeSendInfo;
> +    __TransmitterCompletePackets(Transmitter,
> +                                 Packet,
> +                                 NDIS_STATUS_SUCCESS);
> +}
> 
> -    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
> +VOID
> +TransmitterEnable(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter-
> >Adapter);
> 
> -    LargeSendInfo =
> (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFF
> ER_LIST_INFO(NetBufferList,
> -
> TcpLargeSendNetBufferListInfo);
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> 
> -    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
> -        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> 
> -    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
> +    (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> +                      Vif,
> +                      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
> +
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
> +
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> +}
> 
> -    NdisMSendNetBufferListsComplete(Adapter->NdisAdapterHandle,
> -                                    NetBufferList,
> -                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
> +PXENVIF_VIF_OFFLOAD_OPTIONS
> +TransmitterOffloadOptions(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    return &Transmitter->OffloadOptions;
>  }
> 
> -VOID
> -TransmitterCompletePackets(
> -    IN  PTRANSMITTER                Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +NTSTATUS
> +TransmitterInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_TRANSMITTER     *Transmitter
>      )
>  {
> -    while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> -        PNET_BUFFER_RESERVED        Reserved;
> -        PNET_BUFFER_LIST            NetBufferList;
> -        PNET_BUFFER_LIST_RESERVED   ListReserved;
> +    NTSTATUS            status;
> 
> -        Next = Packet->Next;
> -        Packet->Next = NULL;
> +    status = STATUS_NO_MEMORY;
> +    *Transmitter = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(XENNET_TRANSMITTER), TRANSMITTER_POOL_TAG);
> +    if (*Transmitter == NULL)
> +        goto fail1;
> 
> -        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED,
> Packet);
> +    RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
> +    (*Transmitter)->Adapter = Adapter;
> 
> -        NetBufferList = Reserved->NetBufferList;
> -        ASSERT(NetBufferList != NULL);
> +    return STATUS_SUCCESS;
> 
> -        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> 
> -        ASSERT(ListReserved->Reference != 0);
> -        if (InterlockedDecrement(&ListReserved->Reference) == 0)
> -            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
> +}
> 
> -        Packet = Next;
> -    }
> +VOID
> +TransmitterTeardown(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
>  }
> +
> diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
> index 8dc7e8d..f99ffd3 100644
> --- a/src/xennet/transmitter.h
> +++ b/src/xennet/transmitter.h
> @@ -29,47 +29,48 @@
>   * SUCH DAMAGE.
>   */
> 
> -#pragma once
> +#ifndef _XENNET_TRANSMITTER_H_
> +#define _XENNET_TRANSMITTER_H_
> 
> -typedef struct _TRANSMITTER {
> -    PADAPTER                    Adapter;
> -    XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> -} TRANSMITTER, *PTRANSMITTER;
> +typedef struct _XENNET_TRANSMITTER  XENNET_TRANSMITTER,
> *PXENNET_TRANSMITTER;
> 
> -VOID
> -TransmitterCleanup (
> -    IN OUT PTRANSMITTER* Transmitter
> +#include <vif_interface.h>
> +
> +extern VOID
> +TransmitterSendNetBufferLists(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
>      );
> 
> -NDIS_STATUS
> -TransmitterInitialize (
> -    IN  PTRANSMITTER    Transmitter,
> -    IN  PADAPTER        Adapter
> +extern VOID
> +TransmitterCompletePackets(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET  Packet
>      );
> 
> -VOID
> -TransmitterEnable (
> -    IN  PTRANSMITTER    Transmitter
> +extern VOID
> +TransmitterEnable(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -VOID
> -TransmitterDelete (
> -    IN OUT PTRANSMITTER* Transmitter
> +extern PXENVIF_VIF_OFFLOAD_OPTIONS
> +TransmitterOffloadOptions(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -VOID
> -TransmitterSendNetBufferLists (
> -    IN  PTRANSMITTER        Transmitter,
> -    IN  PNET_BUFFER_LIST    NetBufferList,
> -    IN  NDIS_PORT_NUMBER    PortNumber,
> -    IN  ULONG               SendFlags
> +#include "adapter.h"
> +extern NTSTATUS
> +TransmitterInitialize(
> +    IN  PXENNET_ADAPTER         Adapter,
> +    OUT PXENNET_TRANSMITTER     *Transmitter
>      );
> 
> -VOID
> -TransmitterCompletePackets(
> -    IN  PTRANSMITTER                Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +extern VOID
> +TransmitterTeardown(
> +    IN  PXENNET_TRANSMITTER     Transmitter
>      );
> 
> -void TransmitterPause(PTRANSMITTER Transmitter);
> -void TransmitterUnpause(PTRANSMITTER Transmitter);
> +#endif // _XENNET_TRANSMITTER_H_
> +
> diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
> index db07e9b..4b6e780 100644
> --- a/vs2012/xennet/xennet.vcxproj
> +++ b/vs2012/xennet/xennet.vcxproj
> @@ -84,9 +84,8 @@
>  	</ItemGroup>
>  	<ItemGroup>
>  		<ClCompile Include="../../src/xennet/registry.c" />
> +		<ClCompile Include="../../src/xennet/driver.c" />
>  		<ClCompile Include="../../src/xennet/adapter.c" />
> -		<ClCompile Include="../../src/xennet/main.c" />
> -		<ClCompile Include="../../src/xennet/miniport.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 908bc2d..d890878 100644
> --- a/vs2013/xennet/xennet.vcxproj
> +++ b/vs2013/xennet/xennet.vcxproj
> @@ -115,9 +115,8 @@
>    </ItemGroup>
>    <ItemGroup>
>      <ClCompile Include="../../src/xennet/registry.c" />
> +    <ClCompile Include="../../src/xennet/driver.c" />
>      <ClCompile Include="../../src/xennet/adapter.c" />
> -    <ClCompile Include="../../src/xennet/main.c" />
> -    <ClCompile Include="../../src/xennet/miniport.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 Mon Nov 17 13:41:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:41: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 1XqMYw-0003sB-CP; Mon, 17 Nov 2014 13:41: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 1XqMYv-0003rh-Bu
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:41:49 +0000
Received: from [193.109.254.147] by server-13.bemta-14.messagelabs.com id
	0F/9D-02699-C1BF9645; Mon, 17 Nov 2014 13:41:48 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1416231705!13051784!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	UPPERCASE_25_50,received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22844 invoked from network); 17 Nov 2014 13:41:45 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:41:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901449"
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: [PATCH 2/4] Add VIF interface version 2
Thread-Index: AQHP/pcpfH6eyR4/X02VhfDeoGnIr5xk143Q
Date: Mon, 17 Nov 2014 13:41:44 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153674@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-3-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-3-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 2/4] Add VIF interface version 2
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 2/4] Add VIF interface version 2
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/cache_interface.h | 232 +++++++++++++++++++++++
>  include/vif_interface.h   | 454
> ++++++++++++++++++++++++++++++++++++++++++++--
>  src/xennet/adapter.c      |  73 +++++++-
>  src/xennet/adapter.h      |   6 +
>  src/xennet/receiver.c     |  22 ++-
>  src/xennet/transmitter.c  | 354 +++++++++++++++++++++++++++++++-----
>  src/xennet/transmitter.h  |  12 +-
>  7 files changed, 1072 insertions(+), 81 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..12599ef
> --- /dev/null
> +++ b/include/cache_interface.h
> @@ -0,0 +1,232 @@
> +/* 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
> +*/
> +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/include/vif_interface.h b/include/vif_interface.h
> index 60a3e9c..4ce61c4 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -29,6 +29,12 @@
>   * SUCH DAMAGE.
>   */
> 
> +/*! \file vif_interface.h
> +    \brief XENVIF VIF Interface
> +
> +    This interface provides access to the PV network frontend
> +*/
> +
>  #ifndef _XENVIF_VIF_INTERFACE_H
>  #define _XENVIF_VIF_INTERFACE_H
> 
> @@ -37,21 +43,39 @@
>  #include <ifdef.h>
>  #include <ethernet.h>
> 
> +/*! \struct _XENVIF_PACKET_HEADER_V1
> +    \brief Packet header information
> +*/
>  struct  _XENVIF_PACKET_HEADER_V1 {
> +    /*! Offset from beginning of packet */
>      ULONG   Offset;
> +    /*! Length of header (0 indicates a header is not present) */
>      ULONG   Length;
>  };
> 
> +/*! \struct _XENVIF_PACKET_INFO_V1
> +    \brief Packet information
> +*/
>  struct _XENVIF_PACKET_INFO_V1 {
> +    /*! Total length of all headers */
>      ULONG                           Length;
> +    /*! VLAN TCI if present (0 indicates not present) */
>      USHORT                          TagControlInformation;
> +    /*! TRUE if the packet is an IP fragment */
>      BOOLEAN                         IsAFragment;
> +    /*! Ethernet header (stripped of any VLAN tag) */
>      struct _XENVIF_PACKET_HEADER_V1 EthernetHeader;
> +    /*! LLC header (used for IPX or 802.3 IP) */
>      struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader;
> +    /*! IP header (v4 or v6) */
>      struct _XENVIF_PACKET_HEADER_V1 IpHeader;
> +    /*! IP options (v4 or v6) */
>      struct _XENVIF_PACKET_HEADER_V1 IpOptions;
> +    /*! TCP header */
>      struct _XENVIF_PACKET_HEADER_V1 TcpHeader;
> +    /*! TCP options */
>      struct _XENVIF_PACKET_HEADER_V1 TcpOptions;
> +    /*! UDP header */
>      struct _XENVIF_PACKET_HEADER_V1 UdpHeader;
>  };
> 
> @@ -61,38 +85,63 @@ typedef struct _XENVIF_PACKET_INFO_V1
> XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO
>  #pragma warning(disable:4214)   // nonstandard extension used : bit field
> types other than int
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> +    \brief Packet checksum flags
> +*/
>  struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
>      union {
>          struct {
> +            /*! IPv4 header checksum validation succeeded */
>              ULONG   IpChecksumSucceeded:1;
> +            /*! IPv4 header checksum validation failed */
>              ULONG   IpChecksumFailed:1;
> +            /*! IPv4 header checksum is present */
>              ULONG   IpChecksumPresent:1;
> +            /*! TCP checksum validation succeeded */
>              ULONG   TcpChecksumSucceeded:1;
> +            /*! TCP checksum validation failed */
>              ULONG   TcpChecksumFailed:1;
> +            /*! TCP checksum is present */
>              ULONG   TcpChecksumPresent:1;
> +            /*! UDP checksum validation succeeded */
>              ULONG   UdpChecksumSucceeded:1;
> +            /*! UDP checksum validation failed */
>              ULONG   UdpChecksumFailed:1;
> +            /*! UDP checksum is present */
>              ULONG   UdpChecksumPresent:1;
>              ULONG   Reserved:23;
>          };
> -
> +        /*! Raw representation */
>          ULONG   Value;
>      };
>  };
> 
> +
>  typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> XENVIF_PACKET_CHECKSUM_FLAGS,
> *PXENVIF_PACKET_CHECKSUM_FLAGS;
> 
>  #pragma warning(pop)
> 
> +/*! \struct _XENVIF_RECEIVER_PACKET_V1
> +    \brief Receive-side packet structure
> +*/
>  struct _XENVIF_RECEIVER_PACKET_V1 {
> +    /*! List entry used for chaining packets together */
>      LIST_ENTRY                              ListEntry;
> +    /*! Pointer to packet information */
>      struct _XENVIF_PACKET_INFO_V1           *Info;
> +    /*! Offset of start of packet in MDL */
>      ULONG                                   Offset;
> +    /*! Total length of packet */
>      ULONG                                   Length;
> +    /*! Checksum flags */
>      struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags;
> +    /*! TCP MSS if the packet contains a TCP large segment */
>      USHORT                                  MaximumSegmentSize;
> +    /*! Opaque cookie used to store context information for packet return */
>      PVOID                                   Cookie;
> +    /*! MDL referencing the initial buffer of the packet */
>      MDL                                     Mdl;
> +    /*! PFN information, which must always follow an MDL */
>      PFN_NUMBER                              __Pfn;
>  };
> 
> @@ -102,22 +151,36 @@ typedef struct _XENVIF_RECEIVER_PACKET_V1
> XENVIF_RECEIVER_PACKET, *PXENVIF_RECEI
>  #pragma warning(disable:4214)   // nonstandard extension used : bit field
> types other than int
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
> +    \brief Offload options
> +*/
>  struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 {
>      union {
>          struct {
> +            /*! Insert/strip VLAN tags */
>              USHORT  OffloadTagManipulation:1;
> +            /*! Segment/coalesce IPv4 packets containing TCP large segments */
>              USHORT  OffloadIpVersion4LargePacket:1;
> +            /*! Calculate/validate IPv4 header checksum */
>              USHORT  OffloadIpVersion4HeaderChecksum:1;
> +            /*! Calculate/validate IPv4 TCP checksum */
>              USHORT  OffloadIpVersion4TcpChecksum:1;
> +            /*! Calculate/validate IPv4 UDP checksum */
>              USHORT  OffloadIpVersion4UdpChecksum:1;
> +            /*! Segment/coalesce IPv6 packets containing TCP large segments */
>              USHORT  OffloadIpVersion6LargePacket:1;
> +            /*! Calculate/validate IPv6 TCP checksum */
>              USHORT  OffloadIpVersion6TcpChecksum:1;
> +            /*! Calculate/validate IPv6 UDP checksum */
>              USHORT  OffloadIpVersion6UdpChecksum:1;
> +            /*! Force calculation of any missing checksums on receive side */
>              USHORT  NeedChecksumValue:1;
> +            /*! Force segmentation of packets containing TCP large segments on
> receive side */
>              USHORT  NeedLargePacketSplit:1;
>              USHORT  Reserved:6;
>          };
> 
> +        /*! Raw representation */
>          USHORT  Value;
>      };
>  };
> @@ -126,28 +189,55 @@ typedef struct
> _XENVIF_VIF_OFFLOAD_OPTIONS_V1 XENVIF_VIF_OFFLOAD_OPTIONS,
> *PXENV
> 
>  #pragma warning(pop)
> 
> -// To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures the XENVIF_TRANSMITTER_PACKET
> -// structure must be at most the size of 3 pointer types.
> -
>  #pragma pack(push, 1)
> +
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
> +    \brief Packet information passed from subscriber to provider on
> +    transmit side packet send
> +
> +    To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures
> +    this structure must be at most the size of 3 pointer types.
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 {
> +    /*! Offload options for this packet */
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> -    USHORT                      MaximumSegmentSize;     // Only used if
> OffloadOptions.OffloadIpVersion[4|6]LargePacket is set
> -    USHORT                      TagControlInformation;  // Only used if
> OffloadOptions.OffloadTagManipulation is set
> +    /*! TCP MSS (used only if
> OffloadOptions.OffloadIpVersion[4|6]LargePacket is set) */
> +    USHORT                      MaximumSegmentSize;
> +    /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set)
> */
> +    USHORT                      TagControlInformation;
>  };
> 
>  typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
> XENVIF_TRANSMITTER_PACKET_SEND_INFO,
> *PXENVIF_TRANSMITTER_PACKET_SEND_INFO;
> 
> +/*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS
> +    \brief Transmit-side packet status
> +*/
> +typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS {
> +    /*! Packet was queued for the backend */
> +    XENVIF_TRANSMITTER_PACKET_PENDING = 1,
> +    /*! Packet has been successfully processed by the backend */
> +    XENVIF_TRANSMITTER_PACKET_OK,
> +    /*! Packet was dropped */
> +    XENVIF_TRANSMITTER_PACKET_DROPPED,
> +    /*! There was a problem handling the packet */
> +    XENVIF_TRANSMITTER_PACKET_ERROR
> +} XENVIF_TRANSMITTER_PACKET_STATUS,
> *PXENVIF_TRANSMITTER_PACKET_STATUS;
> +
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
> +    \brief Packet information passed from provider to subsriber on
> +    transmit side packet return
> +
> +    To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures
> +    this structure must be at most the size of 3 pointer types.
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 {
> +    /*! Ethernet address type (see \ref _ETHERNET_ADDRESS_TYPE) */
>      UCHAR   Type;
> +    /*! Send status (see \ref _XENVIF_TRANSMITTER_PACKET_STATUS) */
>      UCHAR   Status;
> -
> -#define XENVIF_TRANSMITTER_PACKET_PENDING   1
> -#define XENVIF_TRANSMITTER_PACKET_OK        2
> -#define XENVIF_TRANSMITTER_PACKET_DROPPED   3
> -#define XENVIF_TRANSMITTER_PACKET_ERROR     4
> -
> +    /*! Total length of the sent packet */
>      USHORT  PacketLength;
> +    /*! Length of packet payload after recognized headers are removed */
>      USHORT  PayloadLength;
>  };
> 
> @@ -156,7 +246,11 @@ typedef struct
> _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
> XENVIF_TRANSMITTER_
>  #pragma warning(push)
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_V1
> +    \brief Transmit-side packet structure
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_V1 {
> +    /*! Pointer used for chaining packets together */
>      struct _XENVIF_TRANSMITTER_PACKET_V1                        *Next;
>      union {
>          struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1          Send;
> @@ -164,7 +258,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)
> 
> @@ -172,64 +266,169 @@ typedef struct
> _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET,
> *PXENVIF
> 
>  C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof
> (PVOID)));
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
> +    \brief Transmit-side packet structure
> +*/
> +struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    /*! List entry used for chaining packets together */
> +    LIST_ENTRY                                  ListEntry;
> +    /*! MDL referencing the packet's buffer */
> +    PMDL                                        Mdl;
> +    /*! Offset of start of packet in MDL */
> +    ULONG                                       Offset;
> +    /*! Total length of packet */
> +    ULONG                                       Length;
> +    /*! Opaque cookie used to store context information for packet return */
> +    PVOID                                       Cookie;
> +    /*! Packet information passed down to subscriber */
> +    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    /*! Information passed up from subscriber for packet completion */
> +    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
> +};
> +
> +typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> +
> +
> +/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
> +    \brief Offsets of packet metadata relative to
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer
> +
> +    Because the transmit side packet structure is limited to 3 pointer
> +    types in size, not all information about the packet can be passed in
> +    the structure. Other information can, however, be found by applying
> +    these byte offsets to the structure pointer and then dereferencing the
> +    specified type.
> +*/
>  typedef enum _XENVIF_TRANSMITTER_PACKET_OFFSET {
> +    /*! The offset of the start of the packet within the MDL (type ULONG) */
>      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET = 0,
> +    /*! The total length of the packet (type ULONG) */
>      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
> +    /*! MDL referencing the initial buffer of the packet (type PMDL) */
>      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
>      XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT
>  } XENVIF_TRANSMITTER_PACKET_OFFSET,
> *PXENVIF_TRANSMITTER_PACKET_OFFSET;
> 
> +/*! \enum _XENVIF_VIF_STATISTIC
> +    \brief Interface statistics
> +*/
>  typedef enum _XENVIF_VIF_STATISTIC {
> +    /*! RFC 2863 ifOutDiscards */
>      XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
> +    /*! Backend component of RFC 2863 ifOutErrors */
>      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +    /*! Frontend component of RFC 2863 ifOutErrors */
>      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +    /*! RFC 2863 ifOutUcastPkts */
>      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +    /*! Total number of octets in ifOutUcastPkts */
>      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +    /*! RFC 2863 ifOutMulticastPkts */
>      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +    /*! Total number of octets in ifOutMulticastPkts */
>      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +    /*! RFC 2863 ifOutBroadcastPkts */
>      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +    /*! Total number of octets in ifOutBroadcastPkts */
>      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +    /*! RFC 2863 ifInDiscards */
>      XENVIF_RECEIVER_PACKETS_DROPPED,
> +    /*! Backend component of RFC 2863 ifInErrors */
>      XENVIF_RECEIVER_BACKEND_ERRORS,
> +    /*! Frontend component of RFC 2863 ifInErrors */
>      XENVIF_RECEIVER_FRONTEND_ERRORS,
> +    /*! RFC 2863 ifInUcastPkts */
>      XENVIF_RECEIVER_UNICAST_PACKETS,
> +    /*! Total number of octets in ifInUcastPkts */
>      XENVIF_RECEIVER_UNICAST_OCTETS,
> +    /*! RFC 2863 ifInMulticastPkts */
>      XENVIF_RECEIVER_MULTICAST_PACKETS,
> +    /*! Total number of octets in ifInMulticastPkts */
>      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +    /*! RFC 2863 ifInBroadcastPkts */
>      XENVIF_RECEIVER_BROADCAST_PACKETS,
> +    /*! Total number of octets in ifInBroadcastPkts */
>      XENVIF_RECEIVER_BROADCAST_OCTETS,
>      XENVIF_VIF_STATISTIC_COUNT
>  } XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
> 
> +/*! \enum _XENVIF_MAC_FILTER_LEVEL
> +    \brief Filter level applied to packets
> +*/
>  typedef enum _XENVIF_MAC_FILTER_LEVEL {
> +    /*! Don't filter out any packets */
>      XENVIF_MAC_FILTER_NONE = 0,
> +    /*! Filter out all packets except those with a matching destination address
> */
>      XENVIF_MAC_FILTER_MATCHING = 1,
> +    /*! Filter out all packets */
>      XENVIF_MAC_FILTER_ALL = 2
>  } XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
> 
> +/*! \enum _XENVIF_VIF_CALLBACK_TYPE
> +    \brief Type of callback (see \ref XENVIF_VIF_CALLBACK)
> +*/
>  typedef enum _XENVIF_VIF_CALLBACK_TYPE {
> +    /*! Return transmit side packets to the subscriber */
>      XENVIF_TRANSMITTER_RETURN_PACKETS = 0,
> +    /*! Queue receive side packets at the subscriber */
>      XENVIF_RECEIVER_QUEUE_PACKETS,
> +    /*! Notify the subscriber of a MAC (link) state has change */
>      XENVIF_MAC_STATE_CHANGE
>  } XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE;
> 
> +/*! \typedef XENVIF_VIF_ACQUIRE
> +    \brief Acquire a reference to the VIF interface
> +
> +    \param Interface The interface header
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_ACQUIRE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_RELEASE
> +    \brief Release a reference to the VIF interface
> +
> +    \param Interface The interface header
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RELEASE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_CALLBACK
> +    \brief Provider to subscriber callback function
> +
> +    \param Argument An optional context argument passed to the callback
> +    \param Type The callback type
> +    \param ... Additional paramaters required by \a Type
> +
> +    \b XENVIF_TRANSMITTER_RETURN_PACKETS:
> +    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
> +
> +    \b XENVIF_RECEIVER_QUEUE_PACKETS:
> +    \param List List of XENVIF_RECEIVER_PACKET
> +
> +    \b XENVIF_MAC_STATE_CHANGE:
> +    No additional arguments
> +*/
>  typedef VOID
>  (*XENVIF_VIF_CALLBACK)(
> -    IN  PVOID                       Argument,
> +    IN  PVOID                       Argument OPTIONAL,
>      IN  XENVIF_VIF_CALLBACK_TYPE    Type,
>      ...
>      );
> 
> +/*! \typedef XENVIF_VIF_ENABLE
> +    \brief Enable the VIF interface
> +
> +    All packets queued for transmit will be rejected and no packets will
> +    be queued for receive until this method completes.
> +
> +    \param Interface The interface header
> +    \param Callback The subscriber's callback function
> +    \param Argument An optional context argument passed to the callback
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_ENABLE)(
>      IN  PINTERFACE          Interface,
> @@ -237,11 +436,31 @@ typedef NTSTATUS
>      IN  PVOID               Argument OPTIONAL
>      );
> 
> +/*! \typedef XENVIF_VIF_DISABLE
> +    \brief Disable the VIF interface
> +
> +    This method will not complete until any packets queued for receive
> +    have been returned. Any packets queued for transmit may be aborted.
> +
> +    \param Interface The interface header
> +*/
>  typedef VOID
>  (*XENVIF_VIF_DISABLE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_QUERY_STATISTIC
> +    \brief Query the value of an interface statistic
> +
> +    Interface statistics are 64-bits wide and zero based. They are
> +    zeroed when the vif device object is created. They are not
> +    zeroed by this call or by any vif state change (e.g. reconnection
> +    across migration).
> +
> +    \param Interface The interface header
> +    \param Index The index of the statistic in \ref _XENVIF_VIF_STATISTIC
> +    \param Value Buffer to receive the value of the statistic
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_QUERY_STATISTIC)(
>      IN  PINTERFACE              Interface,
> @@ -249,12 +468,29 @@ typedef NTSTATUS
>      OUT PULONGLONG              Value
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS
> +    \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK
> +    (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS)
> +
> +    \param Interface The interface header
> +    \param List List of \ref _XENVIF_RECEIVER_PACKET_V1
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_RETURN_PACKETS)(
>      IN  PINTERFACE  Interface,
>      IN  PLIST_ENTRY List
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> +    \brief Set byte offset of packet information relative to
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer.
> +
> +    See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
> +
> +    \param Interface The interface header
> +    \param Type The offset type
> +    \param Value The offset value
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET)(
>      IN  PINTERFACE                          Interface,
> @@ -262,24 +498,80 @@ typedef NTSTATUS
>      IN  LONG_PTR                            Value
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> +    \brief Queue transmit side packets at the provider
> +
> +    \param Interface The interface header
> +    \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
> +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
> +    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_GET_PACKET_HEADERS
> +    \brief Get a copy of the packet headers and each the offset of each
> +
> +    \param Interface The interface header
> +*/
> +typedef NTSTATUS
> +(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> +    \brief Query the available set of transmit side offload options
> +
> +    \param Interface The interface header
> +    \param Options Buffer to receive the avilable options
> +    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS)(
>      IN  PINTERFACE                  Interface,
>      OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> +    \brief Set the required set of receive side offload options
> +
> +    \param Interface The interface header
> +    \param Options The required options
> +    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS)(
>      IN  PINTERFACE                  Interface,
>      IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> +    \brief Query the maximum size of packet containing a TCP large segment
> +    that can be handled by the transmit side
> +
> +    \param Interface The interface header
> +    \param Version The IP version (4 or 6)
> +    \param Size Buffer to receive the maximum packet size
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE)(
>      IN  PINTERFACE  Interface,
> @@ -287,18 +579,40 @@ typedef VOID
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> +    \brief Query the maximum number of transmit side packets that can
> +    be queued in the shared ring between frontend and backend
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum number of packets
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE
> +    \brief Query the maximum number of receive side packets that can
> +    be queued in the shared ring between backend and frontend
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum number of packets
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_QUERY_RING_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
> +    \brief Query the current MAC (link) state
> +
> +    \param Interface The interface header
> +    \param MediaConnectState Buffer to receive the current connection
> state
> +    \param LinkSpeed Buffer to receive the current link speed in Gbps
> +    \param MediaDuplexState Buffer to receive the current duplex state
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_STATE)(
>      IN  PINTERFACE                  Interface,
> @@ -307,24 +621,58 @@ typedef VOID
>      OUT PNET_IF_MEDIA_DUPLEX_STATE  MediaDuplexState OPTIONAL
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE
> +    \brief Query the maximum MAC (i.e. on the wire) frame size (not
> +    including CRC)
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum frame size
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS
> +    \brief Query the permanent MAC address (set by the toolstack)
> +
> +    \param Interface The interface header
> +    \param Address Buffer to receive the permanent address
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS)(
>      IN  PINTERFACE          Interface,
>      OUT PETHERNET_ADDRESS   Address
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS
> +    \brief Query the current MAC address (may be set by the guest)
> +
> +    The guest OS may override the MAC address using the registry. If this
> +    is not done then the current address will be identical to the
> +    permanent address.
> +
> +    \param Interface The interface header
> +    \param Address Buffer to receive the current address
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS)(
>      IN  PINTERFACE          Interface,
>      OUT PETHERNET_ADDRESS   Address
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES
> +    \brief Query the current set of active multicast addresses
> +
> +    \param Interface The interface header
> +    \param Address An optional buffer to receive the set of addresses
> +    \param Count A buffer to receive the number of active addresses
> +
> +    Call this method with \a Address set to NULL to get the \a Count,
> +    which can then be used to allocate a buffer of suitable size to receive
> +    the array of addresses.
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES)(
>      IN      PINTERFACE          Interface,
> @@ -332,6 +680,16 @@ typedef NTSTATUS
>      IN OUT  PULONG              Count
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
> +    \brief Update the set of active multicast addresses
> +
> +    \param Interface The interface header
> +    \param Address An optional buffer containing the set of addresses
> +    \param Count The number of addresses in the buffer
> +
> +    The \a Address buffer may only by NULL if \a Count is zero, in which
> +    case the set of active multicast addresses will be cleared.
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES)(
>      IN  PINTERFACE          Interface,
> @@ -339,6 +697,14 @@ typedef NTSTATUS
>      IN  ULONG               Count
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_SET_FILTER_LEVEL
> +    \brief Set a filter level for a given type of packet
> +
> +    \param Interface The interface header
> +    \param Type The destination address type of the packet
> +    (see \ref _ETHERNET_ADDRESS_TYPE)
> +    \param Level The new filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_SET_FILTER_LEVEL)(
>      IN  PINTERFACE              Interface,
> @@ -346,6 +712,14 @@ typedef NTSTATUS
>      IN  XENVIF_MAC_FILTER_LEVEL Level
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_FILTER_LEVEL
> +    \brief Query the current filter level for a given type of packet
> +
> +    \param Interface The interface header
> +    \param Type The destination address type of the packet
> +    (see \ref _ETHERNET_ADDRESS_TYPE)
> +    \param Level Buffer to receive the filter level (see \ref
> _XENVIF_MAC_FILTER_LEVEL)
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_QUERY_FILTER_LEVEL)(
>      IN  PINTERFACE                  Interface,
> @@ -368,7 +742,34 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> ReceiverSetOffloadOptions;
>      XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
>      XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> TransmitterSetPacketOffset;
> -    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> TransmitterQueuePackets;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> 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_V1 XENVIF_VIF_INTERFACE_V1,
> *PXENVIF_VIF_INTERFACE_V1;
> +
> +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_SET_PACKET_OFFSET
> TransmitterSetPacketOffset; // obsolete
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;    // obsolete
>      XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> TransmitterQueryOffloadOptions;
>      XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> TransmitterQueryLargePacketSize;
>      XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> TransmitterQueryRingSize;
> @@ -380,16 +781,29 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
> MacSetMulticastAddresses;
>      XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
>      XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
> TransmitterQueuePacketsV2;
> +    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
> TransmitterGetPacketHeaders;
>  };
> 
> -typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2,
> *PXENVIF_VIF_INTERFACE_V2;
> 
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +
> +/*! \def XENVIF_VIF
> +    \brief Macro to assist in method invocation
> +*/
>  #define XENVIF_VIF(_Method, _Interface, ...)    \
>      (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
> 
> +/*! \def XENVIF_VIF_VERSION
> +    \brief Macro to assist in getting interface version in use
> +*/
> +#define XENVIF_VIF_VERSION(_Interface)          \
> +    ((_Interface)->Interface.Version)
> +
>  #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/xennet/adapter.c b/src/xennet/adapter.c
> index 6b32d1a..e3d6e05 100644
> --- a/src/xennet/adapter.c
> +++ b/src/xennet/adapter.c
> @@ -41,6 +41,7 @@
> 
>  struct _XENNET_ADAPTER {
>      XENVIF_VIF_INTERFACE        VifInterface;
> +    XENBUS_CACHE_INTERFACE      CacheInterface;
> 
>      BOOLEAN                     Enabled;
>      ULONG                       MaximumFrameSize;
> @@ -171,14 +172,30 @@ AdapterVifCallback(
>      va_start(Arguments, Type);
> 
>      switch (Type) {
> -    case XENVIF_TRANSMITTER_RETURN_PACKETS: {
> -        PXENVIF_TRANSMITTER_PACKET HeadPacket;
> +    case XENVIF_TRANSMITTER_RETURN_PACKETS:
> +        switch (XENVIF_VIF_VERSION(&Adapter->VifInterface)) {

You should not need to do this. Newer subscribers should only every use the latest version of any API (and should only bind to the matching PDO name).

> +        case 1: {
> +            PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
> +
> +            HeadPacket = va_arg(Arguments,
> PXENVIF_TRANSMITTER_PACKET_V1);
> +
> +            TransmitterCompletePacketsV1(Adapter->Transmitter, HeadPacket);
> +            break;
> +        }
> +        case 2: {
> +            PLIST_ENTRY List;
> 
> -        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
> +            List = va_arg(Arguments, PLIST_ENTRY);
> 
> -        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
> +            TransmitterCompletePacketsV2(Adapter->Transmitter, List);
> +            break;
> +        }
> +        default:
> +            ASSERT(FALSE);
> +            break;
> +        }
>          break;
> -    }
> +
>      case XENVIF_RECEIVER_QUEUE_PACKETS: {
>          PLIST_ENTRY List;
> 
> @@ -1986,6 +2003,14 @@ AdapterGetVifInterface(
>      return &Adapter->VifInterface;
>  }
> 
> +PXENBUS_CACHE_INTERFACE
> +AdapterGetCacheInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return &Adapter->CacheInterface;
> +}
> +
>  NDIS_HANDLE
>  AdapterGetHandle(
>      IN  PXENNET_ADAPTER             Adapter
> @@ -2026,14 +2051,39 @@ AdapterInitialize(
>                               VIF,
>                               XENVIF_VIF_INTERFACE_VERSION_MAX,
>                               (PINTERFACE)&(*Adapter)->VifInterface,
> -                             sizeof ((*Adapter)->VifInterface),
> +                             sizeof (XENVIF_VIF_INTERFACE_V2),
> +                             FALSE);
> +    if (!NT_SUCCESS(status)) {
> +        Trace("QUERY_INTERFACE (VIF v2) failed (%08x)\n", status);
> +        status = QUERY_INTERFACE(DeviceObject,
> +                                 XENVIF,
> +                                 VIF,
> +                                 XENVIF_VIF_INTERFACE_VERSION_MIN,
> +                                 (PINTERFACE)&(*Adapter)->VifInterface,
> +                                 sizeof (XENVIF_VIF_INTERFACE_V1),
> +                                 FALSE);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +    }
> +    Trace("VIF interface version %u\n", (*Adapter)-
> >VifInterface.Interface.Version);
> +
> +    status = QUERY_INTERFACE(DeviceObject,
> +                             XENBUS,
> +                             CACHE,
> +                             XENBUS_CACHE_INTERFACE_VERSION_MAX,
> +                             (PINTERFACE)&(*Adapter)->CacheInterface,
> +                             sizeof (XENBUS_CACHE_INTERFACE),
>                               FALSE);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail2a;
> 
>      status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
>      if (!NT_SUCCESS(status))
>          goto fail3;
> +
> +    status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3a;
> 
>      status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
>      if (!NT_SUCCESS(status))
> @@ -2103,9 +2153,15 @@ fail5:
>      (*Adapter)->Transmitter = NULL;
>  fail4:
>      Error("fail4\n");
> +    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
> +fail3a:
> +    Error("fail3a\n");
>      XENVIF_VIF(Release, &(*Adapter)->VifInterface);
>  fail3:
>      Error("fail3\n");
> +    RtlZeroMemory(&(*Adapter)->CacheInterface,
> sizeof(XENBUS_CACHE_INTERFACE));
> +fail2a:
> +    Error("fail2a\n");
>      RtlZeroMemory(&(*Adapter)->VifInterface,
> sizeof(XENVIF_VIF_INTERFACE));
>  fail2:
>      Error("fail2\n");
> @@ -2130,6 +2186,9 @@ AdapterTeardown(
>      TransmitterTeardown(Adapter->Transmitter);
>      Adapter->Transmitter = 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 a1f4b85..02eb6fd 100644
> --- a/src/xennet/adapter.h
> +++ b/src/xennet/adapter.h
> @@ -96,6 +96,12 @@ AdapterGetVifInterface(
>      IN  PXENNET_ADAPTER             Adapter
>      );
> 
> +#include <cache_interface.h>
> +extern PXENBUS_CACHE_INTERFACE
> +AdapterGetCacheInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    );
> +
>  extern NDIS_HANDLE
>  AdapterGetHandle(
>      IN  PXENNET_ADAPTER             Adapter
> diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
> index ee01a18..e09db55 100644
> --- a/src/xennet/receiver.c
> +++ b/src/xennet/receiver.c
> @@ -38,6 +38,7 @@
> 
>  struct _XENNET_RECEIVER {
>      PXENNET_ADAPTER             Adapter;
> +    PXENVIF_VIF_INTERFACE       VifInterface;
>      NDIS_HANDLE                 NetBufferListPool;
>      PNET_BUFFER_LIST            PutList;
>      PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
> @@ -185,12 +186,9 @@ __ReceiverReturnNetBufferLists(
>      IN  BOOLEAN                 Cache
>      )
>  {
> -    PXENNET_ADAPTER             Adapter;
>      LIST_ENTRY                  List;
>      ULONG                       Count;
> 
> -    Adapter = Receiver->Adapter;
> -
>      InitializeListHead(&List);
> 
>      Count = 0;
> @@ -220,7 +218,7 @@ __ReceiverReturnNetBufferLists(
> 
>      if (Count != 0) {
>          XENVIF_VIF(ReceiverReturnPackets,
> -                   AdapterGetVifInterface(Adapter),
> +                   Receiver->VifInterface,
>                     &List);
>      }
>      return Count;
> @@ -292,13 +290,11 @@ ReceiverReceivePackets(
>      IN  PLIST_ENTRY             List
>      )
>  {
> -    PXENNET_ADAPTER     Adapter;
>      PNET_BUFFER_LIST    HeadNetBufferList;
>      PNET_BUFFER_LIST    *TailNetBufferList;
>      ULONG               Count;
>      BOOLEAN             LowResources;
> 
> -    Adapter = Receiver->Adapter;
>      LowResources = FALSE;
> 
>  again:
> @@ -354,7 +350,7 @@ again:
>              InsertTailList(&PacketList, &Packet->ListEntry);
> 
>              XENVIF_VIF(ReceiverReturnPackets,
> -                       AdapterGetVifInterface(Adapter),
> +                       Receiver->VifInterface,
>                         &PacketList);
>          }
>      }
> @@ -411,8 +407,17 @@ ReceiverInitialize(
>      if ((*Receiver)->NetBufferListPool == NULL)
>          goto fail2;
> 
> +    (*Receiver)->VifInterface = AdapterGetVifInterface(Adapter);
> +    status = XENVIF_VIF(Acquire, (*Receiver)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
>      return STATUS_SUCCESS;
> 
> +fail3:
> +    Error("fail3\n");
> +    NdisFreeNetBufferListPool((*Receiver)->NetBufferListPool);
> +    (*Receiver)->NetBufferListPool = NULL;
>  fail2:
>      Error("fail2\n");
>      ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
> @@ -460,6 +465,9 @@ ReceiverTeardown(
>      NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
>      Receiver->NetBufferListPool = NULL;
> 
> +    XENVIF_VIF(Release, Receiver->VifInterface);
> +    Receiver->VifInterface = NULL;
> +
>      ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
>  }
> 
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index be07458..9bf730c 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -37,11 +37,84 @@
> 
>  struct _XENNET_TRANSMITTER {
>      PXENNET_ADAPTER             Adapter;
> +    PXENVIF_VIF_INTERFACE       VifInterface;
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> +
> +    PXENBUS_CACHE_INTERFACE     CacheInterface;
> +    PXENBUS_CACHE               Cache;
>  };
> 
>  #define TRANSMITTER_POOL_TAG    'teNX'
> 
> +static NTSTATUS
> +__PacketCtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +__PacketDtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +__PacketAcquire(
> +    IN  PVOID           Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static VOID
> +__PacketRelease(
> +    IN  PVOID           Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}

I think you need to implement these. You call the Get and Put methods below with a FALSE locked argument which suggests that you're not guaranteeing that the allocation/freeing code inside the cache cannot be re-entered.

> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> +__TransmitterGetPacket(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->Cache != NULL);
> +
> +    return XENBUS_CACHE(Get,
> +                        Transmitter->CacheInterface,
> +                        Transmitter->Cache,
> +                        FALSE);
> +}
> +
> +static FORCEINLINE VOID
> +__TransmitterPutPacket(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->Cache != NULL);
> +
> +    XENBUS_CACHE(Put,
> +                 Transmitter->CacheInterface,
> +                 Transmitter->Cache,
> +                 Packet,
> +                 FALSE);
> +}
> +
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
>  } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
> @@ -49,8 +122,8 @@ 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;
> +    XENVIF_TRANSMITTER_PACKET_V1    Packet;
> +    PNET_BUFFER_LIST                NetBufferList;
>  } NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
> 
>  C_ASSERT(sizeof (NET_BUFFER_RESERVED) <=
> RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
> @@ -83,17 +156,17 @@ TransmitterCompleteNetBufferList(
>  }
> 
>  static VOID
> -__TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
> -    IN  NDIS_STATUS                 NdisStatus
> +__TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet,
> +    IN  NDIS_STATUS                     NdisStatus
>      )
>  {
>      while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> -        PNET_BUFFER_RESERVED        Reserved;
> -        PNET_BUFFER_LIST            NetBufferList;
> -        PNET_BUFFER_LIST_RESERVED   ListReserved;
> +        PXENVIF_TRANSMITTER_PACKET_V1   Next;
> +        PNET_BUFFER_RESERVED            Reserved;
> +        PNET_BUFFER_LIST                NetBufferList;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> 
>          Next = Packet->Next;
>          Packet->Next = NULL;
> @@ -112,7 +185,38 @@ __TransmitterCompletePackets(
>          Packet = Next;
>      }
>  }
> -

You should not need the above function since you can assert xennet is using v2 of the interface, since it should only bind to a Xenvif that exports v2.

> +
> +static VOID
> +__TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PLIST_ENTRY                 List,
> +    IN  NDIS_STATUS                 NdisStatus
> +    )
> +{
> +    while (!IsListEmpty(List)) {
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +        PNET_BUFFER_LIST                NetBufferList;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> +
> +        ListEntry = RemoveHeadList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
> +        NetBufferList = Packet->Cookie;
> +        ASSERT(NetBufferList != NULL);
> +
> +        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +
> +        ASSERT(ListReserved->Reference != 0);
> +        if (InterlockedDecrement(&ListReserved->Reference) == 0)
> +            TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NdisStatus);
> +
> +        __TransmitterPutPacket(Transmitter, Packet);
> +    }
> +}
> +
>  static FORCEINLINE VOID
>  __OffloadOptions(
>      IN  PNET_BUFFER_LIST            NetBufferList,
> @@ -177,31 +281,18 @@ __OffloadOptions(
>      }
>  }
> 
> -VOID
> -TransmitterSendNetBufferLists(
> +static FORCEINLINE VOID
> +__TransmitterSendNetBufferListsV1(
>      IN  PXENNET_TRANSMITTER     Transmitter,
> -    IN  PNET_BUFFER_LIST        NetBufferList,
> -    IN  NDIS_PORT_NUMBER        PortNumber,
> -    IN  ULONG                   SendFlags
> +    IN  PNET_BUFFER_LIST        NetBufferList
>      )
>  {
> -    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
> -    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
> -    KIRQL                       Irql;
> -
> -    UNREFERENCED_PARAMETER(PortNumber);
> +    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
> 
>      HeadPacket = NULL;
>      TailPacket = &HeadPacket;
> -
> -    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
> -        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
> -        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
> -    } else {
> -        Irql = DISPATCH_LEVEL;
> -    }
> -
> +
>      while (NetBufferList != NULL) {
>          PNET_BUFFER_LIST                ListNext;
>          PNET_BUFFER_LIST_RESERVED       ListReserved;
> @@ -220,8 +311,8 @@ TransmitterSendNetBufferLists(
> 
>          NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
>          while (NetBuffer != NULL) {
> -            PNET_BUFFER_RESERVED        Reserved;
> -            PXENVIF_TRANSMITTER_PACKET  Packet;
> +            PNET_BUFFER_RESERVED            Reserved;
> +            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> 
>              Reserved =
> (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
>              RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
> @@ -248,24 +339,146 @@ TransmitterSendNetBufferLists(
>          NTSTATUS    status;
> 
>          status = XENVIF_VIF(TransmitterQueuePackets,
> -                            AdapterGetVifInterface(Adapter),
> +                            Transmitter->VifInterface,
>                              HeadPacket);
>          if (!NT_SUCCESS(status))
> -            __TransmitterCompletePackets(Transmitter, HeadPacket,
> NDIS_STATUS_NOT_ACCEPTED);
> +            __TransmitterCompletePacketsV1(Transmitter, HeadPacket,
> NDIS_STATUS_NOT_ACCEPTED);
>      }
> +}
> 

Again, you don't need the above function.

> +static FORCEINLINE VOID
> +__TransmitterSendNetBufferListsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList
> +    )
> +{
> +    LIST_ENTRY          List;
> +
> +    InitializeListHead(&List);
> +
> +    while (NetBufferList != NULL) {
> +        PNET_BUFFER_LIST                ListNext;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> +        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
> +        USHORT                          TagControlInformation;
> +        USHORT                          MaximumSegmentSize;
> +        PNET_BUFFER                     NetBuffer;
> +
> +        ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> +        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> +
> +        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +        RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
> +
> +        __OffloadOptions(NetBufferList, &Options, &TagControlInformation,
> &MaximumSegmentSize);
> +
> +        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> +        while (NetBuffer != NULL) {
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +            Packet = __TransmitterGetPacket(Transmitter);
> +            if (Packet == NULL) {
> +                while (ListReserved->Reference--) {
> +                    PLIST_ENTRY     ListEntry;
> +
> +                    ListEntry = RemoveTailList(&List);
> +                    ASSERT3U(ListEntry, !=, &List);
> +
> +                    Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +                    __TransmitterPutPacket(Transmitter, Packet);
> +                }
> +                TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NDIS_STATUS_NOT_ACCEPTED);
> +                break;
> +            }
> +
> +            Packet->Cookie = NetBufferList;
> +            ListReserved->Reference++;
> +
> +            Packet->Send.OffloadOptions.Value   = Options.Value & Transmitter-
> >OffloadOptions.Value;
> +            Packet->Send.TagControlInformation  = TagControlInformation;
> +            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
> +            Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
> +            Packet->Offset                      =
> NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
> +            Packet->Length                      =
> NET_BUFFER_DATA_LENGTH(NetBuffer);
> +            RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> +
> +            InsertTailList(&List, &Packet->ListEntry);
> +
> +            NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
> +        }
> +
> +        NetBufferList = ListNext;
> +    }
> +
> +    if (!IsListEmpty(&List)) {
> +        NTSTATUS    status;
> +
> +        status = XENVIF_VIF(TransmitterQueuePacketsV2,
> +                            Transmitter->VifInterface,
> +                            &List);
> +        if (!NT_SUCCESS(status))
> +            __TransmitterCompletePacketsV2(Transmitter, &List,
> NDIS_STATUS_NOT_ACCEPTED);
> +    }
> +}
> +
> +VOID
> +TransmitterSendNetBufferLists(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
> +    )
> +{
> +    KIRQL                       Irql;
> +
> +    UNREFERENCED_PARAMETER(PortNumber);
> +
> +    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
> +        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
> +        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
> +    } else {
> +        Irql = DISPATCH_LEVEL;
> +    }
> +
> +    switch (XENVIF_VIF_VERSION(Transmitter->VifInterface)) {
> +    case 1:
> +        __TransmitterSendNetBufferListsV1(Transmitter, NetBufferList);
> +        break;
> +
> +    case 2:
> +        __TransmitterSendNetBufferListsV2(Transmitter, NetBufferList);

Only need this case.

> +        break;
> +
> +    default:
> +        ASSERT(FALSE);
> +        break;
> +    }
> +
>      NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
>  }
> 
>  VOID
> -TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
>      )
>  {
> -    __TransmitterCompletePackets(Transmitter,
> -                                 Packet,
> -                                 NDIS_STATUS_SUCCESS);
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 1);
> +    __TransmitterCompletePacketsV1(Transmitter,
> +                                   Packet,
> +                                   NDIS_STATUS_SUCCESS);
> +}
> +

Don't need the above function.

> +VOID
> +TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    __TransmitterCompletePacketsV2(Transmitter,
> +                                   List,
> +                                   NDIS_STATUS_SUCCESS);
>  }
> 
>  VOID
> @@ -273,22 +486,23 @@ TransmitterEnable(
>      IN  PXENNET_TRANSMITTER     Transmitter
>      )
>  {
> -    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter-
> >Adapter);
> +    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) != 1)
> +        return;
> 
>      (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> -                      Vif,
> +                      Transmitter->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,
> -                      Vif,
> +                      Transmitter->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,
> -                      Vif,
> +                      Transmitter->VifInterface,
>                        XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
> 
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
> 
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> @@ -318,8 +532,47 @@ TransmitterInitialize(
>      RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
>      (*Transmitter)->Adapter = Adapter;
> 
> +    (*Transmitter)->VifInterface = AdapterGetVifInterface(Adapter);
> +    status = XENVIF_VIF(Acquire, (*Transmitter)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
> +        goto done;
> +
> +    (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
> +    status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
> +    status = XENBUS_CACHE(Create,
> +                          (*Transmitter)->CacheInterface,
> +                          "packets",
> +                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
> +                          32,
> +                          __PacketCtor,
> +                          __PacketDtor,
> +                          __PacketAcquire,
> +                          __PacketRelease,
> +                          *Transmitter,
> +                          &(*Transmitter)->Cache);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
> +done:
>      return STATUS_SUCCESS;
> 
> +fail4:
> +    Error("fail4\n");
> +    XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
> +    (*Transmitter)->CacheInterface = NULL;
> +fail3:
> +    Error("fail3\n");
> +    XENVIF_VIF(Release, (*Transmitter)->VifInterface);
> +    (*Transmitter)->VifInterface = NULL;
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
>  fail1:
>      Error("fail1 (%08x)\n", status);
>      return status;
> @@ -331,6 +584,19 @@ TransmitterTeardown(
>      IN  PXENNET_TRANSMITTER     Transmitter
>      )
>  {
> +    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
> +        goto done;
> +
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >Cache);
> +    Transmitter->Cache = NULL;
> +
> +    XENBUS_CACHE(Release, Transmitter->CacheInterface);
> +    Transmitter->CacheInterface = NULL;
> +
> +done:
> +    XENVIF_VIF(Release, Transmitter->VifInterface);
> +    Transmitter->VifInterface = NULL;
> +
>      ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
>  }
> 
> diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
> index f99ffd3..adf3b4c 100644
> --- a/src/xennet/transmitter.h
> +++ b/src/xennet/transmitter.h
> @@ -45,9 +45,15 @@ TransmitterSendNetBufferLists(
>      );
> 
>  extern VOID
> -TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
> +    );
> +
> +extern VOID
> +TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
>      );
> 
>  extern VOID

You're missing a change to the INF file to bind to the new PDO name.

  Paul

> --
> 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 Mon Nov 17 13:41:50 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:41: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 1XqMYw-0003sB-CP; Mon, 17 Nov 2014 13:41: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 1XqMYv-0003rh-Bu
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:41:49 +0000
Received: from [193.109.254.147] by server-13.bemta-14.messagelabs.com id
	0F/9D-02699-C1BF9645; Mon, 17 Nov 2014 13:41:48 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1416231705!13051784!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG,
	UPPERCASE_25_50,received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 22844 invoked from network); 17 Nov 2014 13:41:45 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:41:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901449"
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: [PATCH 2/4] Add VIF interface version 2
Thread-Index: AQHP/pcpfH6eyR4/X02VhfDeoGnIr5xk143Q
Date: Mon, 17 Nov 2014 13:41:44 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153674@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-3-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-3-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 2/4] Add VIF interface version 2
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 2/4] Add VIF interface version 2
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/cache_interface.h | 232 +++++++++++++++++++++++
>  include/vif_interface.h   | 454
> ++++++++++++++++++++++++++++++++++++++++++++--
>  src/xennet/adapter.c      |  73 +++++++-
>  src/xennet/adapter.h      |   6 +
>  src/xennet/receiver.c     |  22 ++-
>  src/xennet/transmitter.c  | 354 +++++++++++++++++++++++++++++++-----
>  src/xennet/transmitter.h  |  12 +-
>  7 files changed, 1072 insertions(+), 81 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..12599ef
> --- /dev/null
> +++ b/include/cache_interface.h
> @@ -0,0 +1,232 @@
> +/* 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
> +*/
> +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/include/vif_interface.h b/include/vif_interface.h
> index 60a3e9c..4ce61c4 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -29,6 +29,12 @@
>   * SUCH DAMAGE.
>   */
> 
> +/*! \file vif_interface.h
> +    \brief XENVIF VIF Interface
> +
> +    This interface provides access to the PV network frontend
> +*/
> +
>  #ifndef _XENVIF_VIF_INTERFACE_H
>  #define _XENVIF_VIF_INTERFACE_H
> 
> @@ -37,21 +43,39 @@
>  #include <ifdef.h>
>  #include <ethernet.h>
> 
> +/*! \struct _XENVIF_PACKET_HEADER_V1
> +    \brief Packet header information
> +*/
>  struct  _XENVIF_PACKET_HEADER_V1 {
> +    /*! Offset from beginning of packet */
>      ULONG   Offset;
> +    /*! Length of header (0 indicates a header is not present) */
>      ULONG   Length;
>  };
> 
> +/*! \struct _XENVIF_PACKET_INFO_V1
> +    \brief Packet information
> +*/
>  struct _XENVIF_PACKET_INFO_V1 {
> +    /*! Total length of all headers */
>      ULONG                           Length;
> +    /*! VLAN TCI if present (0 indicates not present) */
>      USHORT                          TagControlInformation;
> +    /*! TRUE if the packet is an IP fragment */
>      BOOLEAN                         IsAFragment;
> +    /*! Ethernet header (stripped of any VLAN tag) */
>      struct _XENVIF_PACKET_HEADER_V1 EthernetHeader;
> +    /*! LLC header (used for IPX or 802.3 IP) */
>      struct _XENVIF_PACKET_HEADER_V1 LLCSnapHeader;
> +    /*! IP header (v4 or v6) */
>      struct _XENVIF_PACKET_HEADER_V1 IpHeader;
> +    /*! IP options (v4 or v6) */
>      struct _XENVIF_PACKET_HEADER_V1 IpOptions;
> +    /*! TCP header */
>      struct _XENVIF_PACKET_HEADER_V1 TcpHeader;
> +    /*! TCP options */
>      struct _XENVIF_PACKET_HEADER_V1 TcpOptions;
> +    /*! UDP header */
>      struct _XENVIF_PACKET_HEADER_V1 UdpHeader;
>  };
> 
> @@ -61,38 +85,63 @@ typedef struct _XENVIF_PACKET_INFO_V1
> XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO
>  #pragma warning(disable:4214)   // nonstandard extension used : bit field
> types other than int
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> +    \brief Packet checksum flags
> +*/
>  struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
>      union {
>          struct {
> +            /*! IPv4 header checksum validation succeeded */
>              ULONG   IpChecksumSucceeded:1;
> +            /*! IPv4 header checksum validation failed */
>              ULONG   IpChecksumFailed:1;
> +            /*! IPv4 header checksum is present */
>              ULONG   IpChecksumPresent:1;
> +            /*! TCP checksum validation succeeded */
>              ULONG   TcpChecksumSucceeded:1;
> +            /*! TCP checksum validation failed */
>              ULONG   TcpChecksumFailed:1;
> +            /*! TCP checksum is present */
>              ULONG   TcpChecksumPresent:1;
> +            /*! UDP checksum validation succeeded */
>              ULONG   UdpChecksumSucceeded:1;
> +            /*! UDP checksum validation failed */
>              ULONG   UdpChecksumFailed:1;
> +            /*! UDP checksum is present */
>              ULONG   UdpChecksumPresent:1;
>              ULONG   Reserved:23;
>          };
> -
> +        /*! Raw representation */
>          ULONG   Value;
>      };
>  };
> 
> +
>  typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> XENVIF_PACKET_CHECKSUM_FLAGS,
> *PXENVIF_PACKET_CHECKSUM_FLAGS;
> 
>  #pragma warning(pop)
> 
> +/*! \struct _XENVIF_RECEIVER_PACKET_V1
> +    \brief Receive-side packet structure
> +*/
>  struct _XENVIF_RECEIVER_PACKET_V1 {
> +    /*! List entry used for chaining packets together */
>      LIST_ENTRY                              ListEntry;
> +    /*! Pointer to packet information */
>      struct _XENVIF_PACKET_INFO_V1           *Info;
> +    /*! Offset of start of packet in MDL */
>      ULONG                                   Offset;
> +    /*! Total length of packet */
>      ULONG                                   Length;
> +    /*! Checksum flags */
>      struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 Flags;
> +    /*! TCP MSS if the packet contains a TCP large segment */
>      USHORT                                  MaximumSegmentSize;
> +    /*! Opaque cookie used to store context information for packet return */
>      PVOID                                   Cookie;
> +    /*! MDL referencing the initial buffer of the packet */
>      MDL                                     Mdl;
> +    /*! PFN information, which must always follow an MDL */
>      PFN_NUMBER                              __Pfn;
>  };
> 
> @@ -102,22 +151,36 @@ typedef struct _XENVIF_RECEIVER_PACKET_V1
> XENVIF_RECEIVER_PACKET, *PXENVIF_RECEI
>  #pragma warning(disable:4214)   // nonstandard extension used : bit field
> types other than int
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1
> +    \brief Offload options
> +*/
>  struct _XENVIF_VIF_OFFLOAD_OPTIONS_V1 {
>      union {
>          struct {
> +            /*! Insert/strip VLAN tags */
>              USHORT  OffloadTagManipulation:1;
> +            /*! Segment/coalesce IPv4 packets containing TCP large segments */
>              USHORT  OffloadIpVersion4LargePacket:1;
> +            /*! Calculate/validate IPv4 header checksum */
>              USHORT  OffloadIpVersion4HeaderChecksum:1;
> +            /*! Calculate/validate IPv4 TCP checksum */
>              USHORT  OffloadIpVersion4TcpChecksum:1;
> +            /*! Calculate/validate IPv4 UDP checksum */
>              USHORT  OffloadIpVersion4UdpChecksum:1;
> +            /*! Segment/coalesce IPv6 packets containing TCP large segments */
>              USHORT  OffloadIpVersion6LargePacket:1;
> +            /*! Calculate/validate IPv6 TCP checksum */
>              USHORT  OffloadIpVersion6TcpChecksum:1;
> +            /*! Calculate/validate IPv6 UDP checksum */
>              USHORT  OffloadIpVersion6UdpChecksum:1;
> +            /*! Force calculation of any missing checksums on receive side */
>              USHORT  NeedChecksumValue:1;
> +            /*! Force segmentation of packets containing TCP large segments on
> receive side */
>              USHORT  NeedLargePacketSplit:1;
>              USHORT  Reserved:6;
>          };
> 
> +        /*! Raw representation */
>          USHORT  Value;
>      };
>  };
> @@ -126,28 +189,55 @@ typedef struct
> _XENVIF_VIF_OFFLOAD_OPTIONS_V1 XENVIF_VIF_OFFLOAD_OPTIONS,
> *PXENV
> 
>  #pragma warning(pop)
> 
> -// To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures the XENVIF_TRANSMITTER_PACKET
> -// structure must be at most the size of 3 pointer types.
> -
>  #pragma pack(push, 1)
> +
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
> +    \brief Packet information passed from subscriber to provider on
> +    transmit side packet send
> +
> +    To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures
> +    this structure must be at most the size of 3 pointer types.
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1 {
> +    /*! Offload options for this packet */
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> -    USHORT                      MaximumSegmentSize;     // Only used if
> OffloadOptions.OffloadIpVersion[4|6]LargePacket is set
> -    USHORT                      TagControlInformation;  // Only used if
> OffloadOptions.OffloadTagManipulation is set
> +    /*! TCP MSS (used only if
> OffloadOptions.OffloadIpVersion[4|6]LargePacket is set) */
> +    USHORT                      MaximumSegmentSize;
> +    /*! VLAN TCI (used only if OffloadOptions.OffloadTagManipulation is set)
> */
> +    USHORT                      TagControlInformation;
>  };
> 
>  typedef struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1
> XENVIF_TRANSMITTER_PACKET_SEND_INFO,
> *PXENVIF_TRANSMITTER_PACKET_SEND_INFO;
> 
> +/*! \enum _XENVIF_TRANSMITTER_PACKET_STATUS
> +    \brief Transmit-side packet status
> +*/
> +typedef enum _XENVIF_TRANSMITTER_PACKET_STATUS {
> +    /*! Packet was queued for the backend */
> +    XENVIF_TRANSMITTER_PACKET_PENDING = 1,
> +    /*! Packet has been successfully processed by the backend */
> +    XENVIF_TRANSMITTER_PACKET_OK,
> +    /*! Packet was dropped */
> +    XENVIF_TRANSMITTER_PACKET_DROPPED,
> +    /*! There was a problem handling the packet */
> +    XENVIF_TRANSMITTER_PACKET_ERROR
> +} XENVIF_TRANSMITTER_PACKET_STATUS,
> *PXENVIF_TRANSMITTER_PACKET_STATUS;
> +
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
> +    \brief Packet information passed from provider to subsriber on
> +    transmit side packet return
> +
> +    To fit into the reserved space in NDIS_PACKET and NET_BUFFER
> structures
> +    this structure must be at most the size of 3 pointer types.
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1 {
> +    /*! Ethernet address type (see \ref _ETHERNET_ADDRESS_TYPE) */
>      UCHAR   Type;
> +    /*! Send status (see \ref _XENVIF_TRANSMITTER_PACKET_STATUS) */
>      UCHAR   Status;
> -
> -#define XENVIF_TRANSMITTER_PACKET_PENDING   1
> -#define XENVIF_TRANSMITTER_PACKET_OK        2
> -#define XENVIF_TRANSMITTER_PACKET_DROPPED   3
> -#define XENVIF_TRANSMITTER_PACKET_ERROR     4
> -
> +    /*! Total length of the sent packet */
>      USHORT  PacketLength;
> +    /*! Length of packet payload after recognized headers are removed */
>      USHORT  PayloadLength;
>  };
> 
> @@ -156,7 +246,11 @@ typedef struct
> _XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO_V1
> XENVIF_TRANSMITTER_
>  #pragma warning(push)
>  #pragma warning(disable:4201)   // nonstandard extension used : nameless
> struct/union
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKET_V1
> +    \brief Transmit-side packet structure
> +*/
>  struct _XENVIF_TRANSMITTER_PACKET_V1 {
> +    /*! Pointer used for chaining packets together */
>      struct _XENVIF_TRANSMITTER_PACKET_V1                        *Next;
>      union {
>          struct _XENVIF_TRANSMITTER_PACKET_SEND_INFO_V1          Send;
> @@ -164,7 +258,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)
> 
> @@ -172,64 +266,169 @@ typedef struct
> _XENVIF_TRANSMITTER_PACKET_V1 XENVIF_TRANSMITTER_PACKET,
> *PXENVIF
> 
>  C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof
> (PVOID)));
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
> +    \brief Transmit-side packet structure
> +*/
> +struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    /*! List entry used for chaining packets together */
> +    LIST_ENTRY                                  ListEntry;
> +    /*! MDL referencing the packet's buffer */
> +    PMDL                                        Mdl;
> +    /*! Offset of start of packet in MDL */
> +    ULONG                                       Offset;
> +    /*! Total length of packet */
> +    ULONG                                       Length;
> +    /*! Opaque cookie used to store context information for packet return */
> +    PVOID                                       Cookie;
> +    /*! Packet information passed down to subscriber */
> +    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    /*! Information passed up from subscriber for packet completion */
> +    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
> +};
> +
> +typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> +
> +
> +/*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
> +    \brief Offsets of packet metadata relative to
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer
> +
> +    Because the transmit side packet structure is limited to 3 pointer
> +    types in size, not all information about the packet can be passed in
> +    the structure. Other information can, however, be found by applying
> +    these byte offsets to the structure pointer and then dereferencing the
> +    specified type.
> +*/
>  typedef enum _XENVIF_TRANSMITTER_PACKET_OFFSET {
> +    /*! The offset of the start of the packet within the MDL (type ULONG) */
>      XENVIF_TRANSMITTER_PACKET_OFFSET_OFFSET = 0,
> +    /*! The total length of the packet (type ULONG) */
>      XENVIF_TRANSMITTER_PACKET_LENGTH_OFFSET,
> +    /*! MDL referencing the initial buffer of the packet (type PMDL) */
>      XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
>      XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT
>  } XENVIF_TRANSMITTER_PACKET_OFFSET,
> *PXENVIF_TRANSMITTER_PACKET_OFFSET;
> 
> +/*! \enum _XENVIF_VIF_STATISTIC
> +    \brief Interface statistics
> +*/
>  typedef enum _XENVIF_VIF_STATISTIC {
> +    /*! RFC 2863 ifOutDiscards */
>      XENVIF_TRANSMITTER_PACKETS_DROPPED = 0,
> +    /*! Backend component of RFC 2863 ifOutErrors */
>      XENVIF_TRANSMITTER_BACKEND_ERRORS,
> +    /*! Frontend component of RFC 2863 ifOutErrors */
>      XENVIF_TRANSMITTER_FRONTEND_ERRORS,
> +    /*! RFC 2863 ifOutUcastPkts */
>      XENVIF_TRANSMITTER_UNICAST_PACKETS,
> +    /*! Total number of octets in ifOutUcastPkts */
>      XENVIF_TRANSMITTER_UNICAST_OCTETS,
> +    /*! RFC 2863 ifOutMulticastPkts */
>      XENVIF_TRANSMITTER_MULTICAST_PACKETS,
> +    /*! Total number of octets in ifOutMulticastPkts */
>      XENVIF_TRANSMITTER_MULTICAST_OCTETS,
> +    /*! RFC 2863 ifOutBroadcastPkts */
>      XENVIF_TRANSMITTER_BROADCAST_PACKETS,
> +    /*! Total number of octets in ifOutBroadcastPkts */
>      XENVIF_TRANSMITTER_BROADCAST_OCTETS,
> +    /*! RFC 2863 ifInDiscards */
>      XENVIF_RECEIVER_PACKETS_DROPPED,
> +    /*! Backend component of RFC 2863 ifInErrors */
>      XENVIF_RECEIVER_BACKEND_ERRORS,
> +    /*! Frontend component of RFC 2863 ifInErrors */
>      XENVIF_RECEIVER_FRONTEND_ERRORS,
> +    /*! RFC 2863 ifInUcastPkts */
>      XENVIF_RECEIVER_UNICAST_PACKETS,
> +    /*! Total number of octets in ifInUcastPkts */
>      XENVIF_RECEIVER_UNICAST_OCTETS,
> +    /*! RFC 2863 ifInMulticastPkts */
>      XENVIF_RECEIVER_MULTICAST_PACKETS,
> +    /*! Total number of octets in ifInMulticastPkts */
>      XENVIF_RECEIVER_MULTICAST_OCTETS,
> +    /*! RFC 2863 ifInBroadcastPkts */
>      XENVIF_RECEIVER_BROADCAST_PACKETS,
> +    /*! Total number of octets in ifInBroadcastPkts */
>      XENVIF_RECEIVER_BROADCAST_OCTETS,
>      XENVIF_VIF_STATISTIC_COUNT
>  } XENVIF_VIF_STATISTIC, *PXENVIF_VIF_STATISTIC;
> 
> +/*! \enum _XENVIF_MAC_FILTER_LEVEL
> +    \brief Filter level applied to packets
> +*/
>  typedef enum _XENVIF_MAC_FILTER_LEVEL {
> +    /*! Don't filter out any packets */
>      XENVIF_MAC_FILTER_NONE = 0,
> +    /*! Filter out all packets except those with a matching destination address
> */
>      XENVIF_MAC_FILTER_MATCHING = 1,
> +    /*! Filter out all packets */
>      XENVIF_MAC_FILTER_ALL = 2
>  } XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
> 
> +/*! \enum _XENVIF_VIF_CALLBACK_TYPE
> +    \brief Type of callback (see \ref XENVIF_VIF_CALLBACK)
> +*/
>  typedef enum _XENVIF_VIF_CALLBACK_TYPE {
> +    /*! Return transmit side packets to the subscriber */
>      XENVIF_TRANSMITTER_RETURN_PACKETS = 0,
> +    /*! Queue receive side packets at the subscriber */
>      XENVIF_RECEIVER_QUEUE_PACKETS,
> +    /*! Notify the subscriber of a MAC (link) state has change */
>      XENVIF_MAC_STATE_CHANGE
>  } XENVIF_VIF_CALLBACK_TYPE, *PXENVIF_VIF_CALLBACK_TYPE;
> 
> +/*! \typedef XENVIF_VIF_ACQUIRE
> +    \brief Acquire a reference to the VIF interface
> +
> +    \param Interface The interface header
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_ACQUIRE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_RELEASE
> +    \brief Release a reference to the VIF interface
> +
> +    \param Interface The interface header
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RELEASE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_CALLBACK
> +    \brief Provider to subscriber callback function
> +
> +    \param Argument An optional context argument passed to the callback
> +    \param Type The callback type
> +    \param ... Additional paramaters required by \a Type
> +
> +    \b XENVIF_TRANSMITTER_RETURN_PACKETS:
> +    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1
> +
> +    \b XENVIF_RECEIVER_QUEUE_PACKETS:
> +    \param List List of XENVIF_RECEIVER_PACKET
> +
> +    \b XENVIF_MAC_STATE_CHANGE:
> +    No additional arguments
> +*/
>  typedef VOID
>  (*XENVIF_VIF_CALLBACK)(
> -    IN  PVOID                       Argument,
> +    IN  PVOID                       Argument OPTIONAL,
>      IN  XENVIF_VIF_CALLBACK_TYPE    Type,
>      ...
>      );
> 
> +/*! \typedef XENVIF_VIF_ENABLE
> +    \brief Enable the VIF interface
> +
> +    All packets queued for transmit will be rejected and no packets will
> +    be queued for receive until this method completes.
> +
> +    \param Interface The interface header
> +    \param Callback The subscriber's callback function
> +    \param Argument An optional context argument passed to the callback
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_ENABLE)(
>      IN  PINTERFACE          Interface,
> @@ -237,11 +436,31 @@ typedef NTSTATUS
>      IN  PVOID               Argument OPTIONAL
>      );
> 
> +/*! \typedef XENVIF_VIF_DISABLE
> +    \brief Disable the VIF interface
> +
> +    This method will not complete until any packets queued for receive
> +    have been returned. Any packets queued for transmit may be aborted.
> +
> +    \param Interface The interface header
> +*/
>  typedef VOID
>  (*XENVIF_VIF_DISABLE)(
>      IN  PINTERFACE  Interface
>      );
> 
> +/*! \typedef XENVIF_VIF_QUERY_STATISTIC
> +    \brief Query the value of an interface statistic
> +
> +    Interface statistics are 64-bits wide and zero based. They are
> +    zeroed when the vif device object is created. They are not
> +    zeroed by this call or by any vif state change (e.g. reconnection
> +    across migration).
> +
> +    \param Interface The interface header
> +    \param Index The index of the statistic in \ref _XENVIF_VIF_STATISTIC
> +    \param Value Buffer to receive the value of the statistic
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_QUERY_STATISTIC)(
>      IN  PINTERFACE              Interface,
> @@ -249,12 +468,29 @@ typedef NTSTATUS
>      OUT PULONGLONG              Value
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_RETURN_PACKETS
> +    \brief Return packets queues for receive by \ref XENVIF_VIF_CALLBACK
> +    (Type = \ref XENVIF_RECEIVER_QUEUE_PACKETS)
> +
> +    \param Interface The interface header
> +    \param List List of \ref _XENVIF_RECEIVER_PACKET_V1
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_RETURN_PACKETS)(
>      IN  PINTERFACE  Interface,
>      IN  PLIST_ENTRY List
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> +    \brief Set byte offset of packet information relative to
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer.
> +
> +    See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
> +
> +    \param Interface The interface header
> +    \param Type The offset type
> +    \param Value The offset value
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET)(
>      IN  PINTERFACE                          Interface,
> @@ -262,24 +498,80 @@ typedef NTSTATUS
>      IN  LONG_PTR                            Value
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> +    \brief Queue transmit side packets at the provider
> +
> +    \param Interface The interface header
> +    \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
> +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
> +    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_GET_PACKET_HEADERS
> +    \brief Get a copy of the packet headers and each the offset of each
> +
> +    \param Interface The interface header
> +*/
> +typedef NTSTATUS
> +(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> +    \brief Query the available set of transmit side offload options
> +
> +    \param Interface The interface header
> +    \param Options Buffer to receive the avilable options
> +    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS)(
>      IN  PINTERFACE                  Interface,
>      OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> +    \brief Set the required set of receive side offload options
> +
> +    \param Interface The interface header
> +    \param Options The required options
> +    (see \ref _XENVIF_VIF_OFFLOAD_OPTIONS_V1)
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS)(
>      IN  PINTERFACE                  Interface,
>      IN  XENVIF_VIF_OFFLOAD_OPTIONS  Options
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> +    \brief Query the maximum size of packet containing a TCP large segment
> +    that can be handled by the transmit side
> +
> +    \param Interface The interface header
> +    \param Version The IP version (4 or 6)
> +    \param Size Buffer to receive the maximum packet size
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE)(
>      IN  PINTERFACE  Interface,
> @@ -287,18 +579,40 @@ typedef VOID
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> +    \brief Query the maximum number of transmit side packets that can
> +    be queued in the shared ring between frontend and backend
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum number of packets
> +*/
>  typedef VOID
>  (*XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_RECEIVER_QUERY_RING_SIZE
> +    \brief Query the maximum number of receive side packets that can
> +    be queued in the shared ring between backend and frontend
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum number of packets
> +*/
>  typedef VOID
>  (*XENVIF_VIF_RECEIVER_QUERY_RING_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_STATE
> +    \brief Query the current MAC (link) state
> +
> +    \param Interface The interface header
> +    \param MediaConnectState Buffer to receive the current connection
> state
> +    \param LinkSpeed Buffer to receive the current link speed in Gbps
> +    \param MediaDuplexState Buffer to receive the current duplex state
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_STATE)(
>      IN  PINTERFACE                  Interface,
> @@ -307,24 +621,58 @@ typedef VOID
>      OUT PNET_IF_MEDIA_DUPLEX_STATE  MediaDuplexState OPTIONAL
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE
> +    \brief Query the maximum MAC (i.e. on the wire) frame size (not
> +    including CRC)
> +
> +    \param Interface The interface header
> +    \param Size Buffer to receive the maximum frame size
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_MAXIMUM_FRAME_SIZE)(
>      IN  PINTERFACE  Interface,
>      OUT PULONG      Size
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS
> +    \brief Query the permanent MAC address (set by the toolstack)
> +
> +    \param Interface The interface header
> +    \param Address Buffer to receive the permanent address
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_PERMANENT_ADDRESS)(
>      IN  PINTERFACE          Interface,
>      OUT PETHERNET_ADDRESS   Address
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS
> +    \brief Query the current MAC address (may be set by the guest)
> +
> +    The guest OS may override the MAC address using the registry. If this
> +    is not done then the current address will be identical to the
> +    permanent address.
> +
> +    \param Interface The interface header
> +    \param Address Buffer to receive the current address
> +*/
>  typedef VOID
>  (*XENVIF_VIF_MAC_QUERY_CURRENT_ADDRESS)(
>      IN  PINTERFACE          Interface,
>      OUT PETHERNET_ADDRESS   Address
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES
> +    \brief Query the current set of active multicast addresses
> +
> +    \param Interface The interface header
> +    \param Address An optional buffer to receive the set of addresses
> +    \param Count A buffer to receive the number of active addresses
> +
> +    Call this method with \a Address set to NULL to get the \a Count,
> +    which can then be used to allocate a buffer of suitable size to receive
> +    the array of addresses.
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_QUERY_MULTICAST_ADDRESSES)(
>      IN      PINTERFACE          Interface,
> @@ -332,6 +680,16 @@ typedef NTSTATUS
>      IN OUT  PULONG              Count
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
> +    \brief Update the set of active multicast addresses
> +
> +    \param Interface The interface header
> +    \param Address An optional buffer containing the set of addresses
> +    \param Count The number of addresses in the buffer
> +
> +    The \a Address buffer may only by NULL if \a Count is zero, in which
> +    case the set of active multicast addresses will be cleared.
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES)(
>      IN  PINTERFACE          Interface,
> @@ -339,6 +697,14 @@ typedef NTSTATUS
>      IN  ULONG               Count
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_SET_FILTER_LEVEL
> +    \brief Set a filter level for a given type of packet
> +
> +    \param Interface The interface header
> +    \param Type The destination address type of the packet
> +    (see \ref _ETHERNET_ADDRESS_TYPE)
> +    \param Level The new filter level (see \ref _XENVIF_MAC_FILTER_LEVEL)
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_SET_FILTER_LEVEL)(
>      IN  PINTERFACE              Interface,
> @@ -346,6 +712,14 @@ typedef NTSTATUS
>      IN  XENVIF_MAC_FILTER_LEVEL Level
>      );
> 
> +/*! \typedef XENVIF_VIF_MAC_QUERY_FILTER_LEVEL
> +    \brief Query the current filter level for a given type of packet
> +
> +    \param Interface The interface header
> +    \param Type The destination address type of the packet
> +    (see \ref _ETHERNET_ADDRESS_TYPE)
> +    \param Level Buffer to receive the filter level (see \ref
> _XENVIF_MAC_FILTER_LEVEL)
> +*/
>  typedef NTSTATUS
>  (*XENVIF_VIF_MAC_QUERY_FILTER_LEVEL)(
>      IN  PINTERFACE                  Interface,
> @@ -368,7 +742,34 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> ReceiverSetOffloadOptions;
>      XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
>      XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> TransmitterSetPacketOffset;
> -    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> TransmitterQueuePackets;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> 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_V1 XENVIF_VIF_INTERFACE_V1,
> *PXENVIF_VIF_INTERFACE_V1;
> +
> +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_SET_PACKET_OFFSET
> TransmitterSetPacketOffset; // obsolete
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;    // obsolete
>      XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> TransmitterQueryOffloadOptions;
>      XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> TransmitterQueryLargePacketSize;
>      XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> TransmitterQueryRingSize;
> @@ -380,16 +781,29 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_MAC_SET_MULTICAST_ADDRESSES
> MacSetMulticastAddresses;
>      XENVIF_VIF_MAC_SET_FILTER_LEVEL                 MacSetFilterLevel;
>      XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
> TransmitterQueuePacketsV2;
> +    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
> TransmitterGetPacketHeaders;
>  };
> 
> -typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2,
> *PXENVIF_VIF_INTERFACE_V2;
> 
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +
> +/*! \def XENVIF_VIF
> +    \brief Macro to assist in method invocation
> +*/
>  #define XENVIF_VIF(_Method, _Interface, ...)    \
>      (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
> 
> +/*! \def XENVIF_VIF_VERSION
> +    \brief Macro to assist in getting interface version in use
> +*/
> +#define XENVIF_VIF_VERSION(_Interface)          \
> +    ((_Interface)->Interface.Version)
> +
>  #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/xennet/adapter.c b/src/xennet/adapter.c
> index 6b32d1a..e3d6e05 100644
> --- a/src/xennet/adapter.c
> +++ b/src/xennet/adapter.c
> @@ -41,6 +41,7 @@
> 
>  struct _XENNET_ADAPTER {
>      XENVIF_VIF_INTERFACE        VifInterface;
> +    XENBUS_CACHE_INTERFACE      CacheInterface;
> 
>      BOOLEAN                     Enabled;
>      ULONG                       MaximumFrameSize;
> @@ -171,14 +172,30 @@ AdapterVifCallback(
>      va_start(Arguments, Type);
> 
>      switch (Type) {
> -    case XENVIF_TRANSMITTER_RETURN_PACKETS: {
> -        PXENVIF_TRANSMITTER_PACKET HeadPacket;
> +    case XENVIF_TRANSMITTER_RETURN_PACKETS:
> +        switch (XENVIF_VIF_VERSION(&Adapter->VifInterface)) {

You should not need to do this. Newer subscribers should only every use the latest version of any API (and should only bind to the matching PDO name).

> +        case 1: {
> +            PXENVIF_TRANSMITTER_PACKET_V1 HeadPacket;
> +
> +            HeadPacket = va_arg(Arguments,
> PXENVIF_TRANSMITTER_PACKET_V1);
> +
> +            TransmitterCompletePacketsV1(Adapter->Transmitter, HeadPacket);
> +            break;
> +        }
> +        case 2: {
> +            PLIST_ENTRY List;
> 
> -        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
> +            List = va_arg(Arguments, PLIST_ENTRY);
> 
> -        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
> +            TransmitterCompletePacketsV2(Adapter->Transmitter, List);
> +            break;
> +        }
> +        default:
> +            ASSERT(FALSE);
> +            break;
> +        }
>          break;
> -    }
> +
>      case XENVIF_RECEIVER_QUEUE_PACKETS: {
>          PLIST_ENTRY List;
> 
> @@ -1986,6 +2003,14 @@ AdapterGetVifInterface(
>      return &Adapter->VifInterface;
>  }
> 
> +PXENBUS_CACHE_INTERFACE
> +AdapterGetCacheInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    )
> +{
> +    return &Adapter->CacheInterface;
> +}
> +
>  NDIS_HANDLE
>  AdapterGetHandle(
>      IN  PXENNET_ADAPTER             Adapter
> @@ -2026,14 +2051,39 @@ AdapterInitialize(
>                               VIF,
>                               XENVIF_VIF_INTERFACE_VERSION_MAX,
>                               (PINTERFACE)&(*Adapter)->VifInterface,
> -                             sizeof ((*Adapter)->VifInterface),
> +                             sizeof (XENVIF_VIF_INTERFACE_V2),
> +                             FALSE);
> +    if (!NT_SUCCESS(status)) {
> +        Trace("QUERY_INTERFACE (VIF v2) failed (%08x)\n", status);
> +        status = QUERY_INTERFACE(DeviceObject,
> +                                 XENVIF,
> +                                 VIF,
> +                                 XENVIF_VIF_INTERFACE_VERSION_MIN,
> +                                 (PINTERFACE)&(*Adapter)->VifInterface,
> +                                 sizeof (XENVIF_VIF_INTERFACE_V1),
> +                                 FALSE);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +    }
> +    Trace("VIF interface version %u\n", (*Adapter)-
> >VifInterface.Interface.Version);
> +
> +    status = QUERY_INTERFACE(DeviceObject,
> +                             XENBUS,
> +                             CACHE,
> +                             XENBUS_CACHE_INTERFACE_VERSION_MAX,
> +                             (PINTERFACE)&(*Adapter)->CacheInterface,
> +                             sizeof (XENBUS_CACHE_INTERFACE),
>                               FALSE);
>      if (!NT_SUCCESS(status))
> -        goto fail2;
> +        goto fail2a;
> 
>      status = XENVIF_VIF(Acquire, &(*Adapter)->VifInterface);
>      if (!NT_SUCCESS(status))
>          goto fail3;
> +
> +    status = XENBUS_CACHE(Acquire, &(*Adapter)->CacheInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3a;
> 
>      status = TransmitterInitialize(*Adapter, &(*Adapter)->Transmitter);
>      if (!NT_SUCCESS(status))
> @@ -2103,9 +2153,15 @@ fail5:
>      (*Adapter)->Transmitter = NULL;
>  fail4:
>      Error("fail4\n");
> +    XENBUS_CACHE(Release, &(*Adapter)->CacheInterface);
> +fail3a:
> +    Error("fail3a\n");
>      XENVIF_VIF(Release, &(*Adapter)->VifInterface);
>  fail3:
>      Error("fail3\n");
> +    RtlZeroMemory(&(*Adapter)->CacheInterface,
> sizeof(XENBUS_CACHE_INTERFACE));
> +fail2a:
> +    Error("fail2a\n");
>      RtlZeroMemory(&(*Adapter)->VifInterface,
> sizeof(XENVIF_VIF_INTERFACE));
>  fail2:
>      Error("fail2\n");
> @@ -2130,6 +2186,9 @@ AdapterTeardown(
>      TransmitterTeardown(Adapter->Transmitter);
>      Adapter->Transmitter = 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 a1f4b85..02eb6fd 100644
> --- a/src/xennet/adapter.h
> +++ b/src/xennet/adapter.h
> @@ -96,6 +96,12 @@ AdapterGetVifInterface(
>      IN  PXENNET_ADAPTER             Adapter
>      );
> 
> +#include <cache_interface.h>
> +extern PXENBUS_CACHE_INTERFACE
> +AdapterGetCacheInterface(
> +    IN  PXENNET_ADAPTER             Adapter
> +    );
> +
>  extern NDIS_HANDLE
>  AdapterGetHandle(
>      IN  PXENNET_ADAPTER             Adapter
> diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
> index ee01a18..e09db55 100644
> --- a/src/xennet/receiver.c
> +++ b/src/xennet/receiver.c
> @@ -38,6 +38,7 @@
> 
>  struct _XENNET_RECEIVER {
>      PXENNET_ADAPTER             Adapter;
> +    PXENVIF_VIF_INTERFACE       VifInterface;
>      NDIS_HANDLE                 NetBufferListPool;
>      PNET_BUFFER_LIST            PutList;
>      PNET_BUFFER_LIST            GetList[MAXIMUM_PROCESSORS];
> @@ -185,12 +186,9 @@ __ReceiverReturnNetBufferLists(
>      IN  BOOLEAN                 Cache
>      )
>  {
> -    PXENNET_ADAPTER             Adapter;
>      LIST_ENTRY                  List;
>      ULONG                       Count;
> 
> -    Adapter = Receiver->Adapter;
> -
>      InitializeListHead(&List);
> 
>      Count = 0;
> @@ -220,7 +218,7 @@ __ReceiverReturnNetBufferLists(
> 
>      if (Count != 0) {
>          XENVIF_VIF(ReceiverReturnPackets,
> -                   AdapterGetVifInterface(Adapter),
> +                   Receiver->VifInterface,
>                     &List);
>      }
>      return Count;
> @@ -292,13 +290,11 @@ ReceiverReceivePackets(
>      IN  PLIST_ENTRY             List
>      )
>  {
> -    PXENNET_ADAPTER     Adapter;
>      PNET_BUFFER_LIST    HeadNetBufferList;
>      PNET_BUFFER_LIST    *TailNetBufferList;
>      ULONG               Count;
>      BOOLEAN             LowResources;
> 
> -    Adapter = Receiver->Adapter;
>      LowResources = FALSE;
> 
>  again:
> @@ -354,7 +350,7 @@ again:
>              InsertTailList(&PacketList, &Packet->ListEntry);
> 
>              XENVIF_VIF(ReceiverReturnPackets,
> -                       AdapterGetVifInterface(Adapter),
> +                       Receiver->VifInterface,
>                         &PacketList);
>          }
>      }
> @@ -411,8 +407,17 @@ ReceiverInitialize(
>      if ((*Receiver)->NetBufferListPool == NULL)
>          goto fail2;
> 
> +    (*Receiver)->VifInterface = AdapterGetVifInterface(Adapter);
> +    status = XENVIF_VIF(Acquire, (*Receiver)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
>      return STATUS_SUCCESS;
> 
> +fail3:
> +    Error("fail3\n");
> +    NdisFreeNetBufferListPool((*Receiver)->NetBufferListPool);
> +    (*Receiver)->NetBufferListPool = NULL;
>  fail2:
>      Error("fail2\n");
>      ExFreePoolWithTag(*Receiver, RECEIVER_POOL_TAG);
> @@ -460,6 +465,9 @@ ReceiverTeardown(
>      NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
>      Receiver->NetBufferListPool = NULL;
> 
> +    XENVIF_VIF(Release, Receiver->VifInterface);
> +    Receiver->VifInterface = NULL;
> +
>      ExFreePoolWithTag(Receiver, RECEIVER_POOL_TAG);
>  }
> 
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index be07458..9bf730c 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -37,11 +37,84 @@
> 
>  struct _XENNET_TRANSMITTER {
>      PXENNET_ADAPTER             Adapter;
> +    PXENVIF_VIF_INTERFACE       VifInterface;
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> +
> +    PXENBUS_CACHE_INTERFACE     CacheInterface;
> +    PXENBUS_CACHE               Cache;
>  };
> 
>  #define TRANSMITTER_POOL_TAG    'teNX'
> 
> +static NTSTATUS
> +__PacketCtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +__PacketDtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +__PacketAcquire(
> +    IN  PVOID           Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static VOID
> +__PacketRelease(
> +    IN  PVOID           Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}

I think you need to implement these. You call the Get and Put methods below with a FALSE locked argument which suggests that you're not guaranteeing that the allocation/freeing code inside the cache cannot be re-entered.

> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> +__TransmitterGetPacket(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->Cache != NULL);
> +
> +    return XENBUS_CACHE(Get,
> +                        Transmitter->CacheInterface,
> +                        Transmitter->Cache,
> +                        FALSE);
> +}
> +
> +static FORCEINLINE VOID
> +__TransmitterPutPacket(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->Cache != NULL);
> +
> +    XENBUS_CACHE(Put,
> +                 Transmitter->CacheInterface,
> +                 Transmitter->Cache,
> +                 Packet,
> +                 FALSE);
> +}
> +
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
>  } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
> @@ -49,8 +122,8 @@ 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;
> +    XENVIF_TRANSMITTER_PACKET_V1    Packet;
> +    PNET_BUFFER_LIST                NetBufferList;
>  } NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
> 
>  C_ASSERT(sizeof (NET_BUFFER_RESERVED) <=
> RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
> @@ -83,17 +156,17 @@ TransmitterCompleteNetBufferList(
>  }
> 
>  static VOID
> -__TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet,
> -    IN  NDIS_STATUS                 NdisStatus
> +__TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet,
> +    IN  NDIS_STATUS                     NdisStatus
>      )
>  {
>      while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> -        PNET_BUFFER_RESERVED        Reserved;
> -        PNET_BUFFER_LIST            NetBufferList;
> -        PNET_BUFFER_LIST_RESERVED   ListReserved;
> +        PXENVIF_TRANSMITTER_PACKET_V1   Next;
> +        PNET_BUFFER_RESERVED            Reserved;
> +        PNET_BUFFER_LIST                NetBufferList;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> 
>          Next = Packet->Next;
>          Packet->Next = NULL;
> @@ -112,7 +185,38 @@ __TransmitterCompletePackets(
>          Packet = Next;
>      }
>  }
> -

You should not need the above function since you can assert xennet is using v2 of the interface, since it should only bind to a Xenvif that exports v2.

> +
> +static VOID
> +__TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER         Transmitter,
> +    IN  PLIST_ENTRY                 List,
> +    IN  NDIS_STATUS                 NdisStatus
> +    )
> +{
> +    while (!IsListEmpty(List)) {
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +        PNET_BUFFER_LIST                NetBufferList;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> +
> +        ListEntry = RemoveHeadList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
> +        NetBufferList = Packet->Cookie;
> +        ASSERT(NetBufferList != NULL);
> +
> +        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +
> +        ASSERT(ListReserved->Reference != 0);
> +        if (InterlockedDecrement(&ListReserved->Reference) == 0)
> +            TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NdisStatus);
> +
> +        __TransmitterPutPacket(Transmitter, Packet);
> +    }
> +}
> +
>  static FORCEINLINE VOID
>  __OffloadOptions(
>      IN  PNET_BUFFER_LIST            NetBufferList,
> @@ -177,31 +281,18 @@ __OffloadOptions(
>      }
>  }
> 
> -VOID
> -TransmitterSendNetBufferLists(
> +static FORCEINLINE VOID
> +__TransmitterSendNetBufferListsV1(
>      IN  PXENNET_TRANSMITTER     Transmitter,
> -    IN  PNET_BUFFER_LIST        NetBufferList,
> -    IN  NDIS_PORT_NUMBER        PortNumber,
> -    IN  ULONG                   SendFlags
> +    IN  PNET_BUFFER_LIST        NetBufferList
>      )
>  {
> -    PXENNET_ADAPTER             Adapter = Transmitter->Adapter;
> -    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
> -    KIRQL                       Irql;
> -
> -    UNREFERENCED_PARAMETER(PortNumber);
> +    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +    PXENVIF_TRANSMITTER_PACKET_V1   *TailPacket;
> 
>      HeadPacket = NULL;
>      TailPacket = &HeadPacket;
> -
> -    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
> -        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
> -        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
> -    } else {
> -        Irql = DISPATCH_LEVEL;
> -    }
> -
> +
>      while (NetBufferList != NULL) {
>          PNET_BUFFER_LIST                ListNext;
>          PNET_BUFFER_LIST_RESERVED       ListReserved;
> @@ -220,8 +311,8 @@ TransmitterSendNetBufferLists(
> 
>          NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
>          while (NetBuffer != NULL) {
> -            PNET_BUFFER_RESERVED        Reserved;
> -            PXENVIF_TRANSMITTER_PACKET  Packet;
> +            PNET_BUFFER_RESERVED            Reserved;
> +            PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> 
>              Reserved =
> (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
>              RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
> @@ -248,24 +339,146 @@ TransmitterSendNetBufferLists(
>          NTSTATUS    status;
> 
>          status = XENVIF_VIF(TransmitterQueuePackets,
> -                            AdapterGetVifInterface(Adapter),
> +                            Transmitter->VifInterface,
>                              HeadPacket);
>          if (!NT_SUCCESS(status))
> -            __TransmitterCompletePackets(Transmitter, HeadPacket,
> NDIS_STATUS_NOT_ACCEPTED);
> +            __TransmitterCompletePacketsV1(Transmitter, HeadPacket,
> NDIS_STATUS_NOT_ACCEPTED);
>      }
> +}
> 

Again, you don't need the above function.

> +static FORCEINLINE VOID
> +__TransmitterSendNetBufferListsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList
> +    )
> +{
> +    LIST_ENTRY          List;
> +
> +    InitializeListHead(&List);
> +
> +    while (NetBufferList != NULL) {
> +        PNET_BUFFER_LIST                ListNext;
> +        PNET_BUFFER_LIST_RESERVED       ListReserved;
> +        XENVIF_VIF_OFFLOAD_OPTIONS      Options;
> +        USHORT                          TagControlInformation;
> +        USHORT                          MaximumSegmentSize;
> +        PNET_BUFFER                     NetBuffer;
> +
> +        ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
> +        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
> +
> +        ListReserved =
> (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(N
> etBufferList);
> +        RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
> +
> +        __OffloadOptions(NetBufferList, &Options, &TagControlInformation,
> &MaximumSegmentSize);
> +
> +        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
> +        while (NetBuffer != NULL) {
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +            Packet = __TransmitterGetPacket(Transmitter);
> +            if (Packet == NULL) {
> +                while (ListReserved->Reference--) {
> +                    PLIST_ENTRY     ListEntry;
> +
> +                    ListEntry = RemoveTailList(&List);
> +                    ASSERT3U(ListEntry, !=, &List);
> +
> +                    Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +                    __TransmitterPutPacket(Transmitter, Packet);
> +                }
> +                TransmitterCompleteNetBufferList(Transmitter, NetBufferList,
> NDIS_STATUS_NOT_ACCEPTED);
> +                break;
> +            }
> +
> +            Packet->Cookie = NetBufferList;
> +            ListReserved->Reference++;
> +
> +            Packet->Send.OffloadOptions.Value   = Options.Value & Transmitter-
> >OffloadOptions.Value;
> +            Packet->Send.TagControlInformation  = TagControlInformation;
> +            Packet->Send.MaximumSegmentSize     = MaximumSegmentSize;
> +            Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
> +            Packet->Offset                      =
> NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
> +            Packet->Length                      =
> NET_BUFFER_DATA_LENGTH(NetBuffer);
> +            RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> +
> +            InsertTailList(&List, &Packet->ListEntry);
> +
> +            NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
> +        }
> +
> +        NetBufferList = ListNext;
> +    }
> +
> +    if (!IsListEmpty(&List)) {
> +        NTSTATUS    status;
> +
> +        status = XENVIF_VIF(TransmitterQueuePacketsV2,
> +                            Transmitter->VifInterface,
> +                            &List);
> +        if (!NT_SUCCESS(status))
> +            __TransmitterCompletePacketsV2(Transmitter, &List,
> NDIS_STATUS_NOT_ACCEPTED);
> +    }
> +}
> +
> +VOID
> +TransmitterSendNetBufferLists(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PNET_BUFFER_LIST        NetBufferList,
> +    IN  NDIS_PORT_NUMBER        PortNumber,
> +    IN  ULONG                   SendFlags
> +    )
> +{
> +    KIRQL                       Irql;
> +
> +    UNREFERENCED_PARAMETER(PortNumber);
> +
> +    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
> +        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
> +        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
> +    } else {
> +        Irql = DISPATCH_LEVEL;
> +    }
> +
> +    switch (XENVIF_VIF_VERSION(Transmitter->VifInterface)) {
> +    case 1:
> +        __TransmitterSendNetBufferListsV1(Transmitter, NetBufferList);
> +        break;
> +
> +    case 2:
> +        __TransmitterSendNetBufferListsV2(Transmitter, NetBufferList);

Only need this case.

> +        break;
> +
> +    default:
> +        ASSERT(FALSE);
> +        break;
> +    }
> +
>      NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
>  }
> 
>  VOID
> -TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
>      )
>  {
> -    __TransmitterCompletePackets(Transmitter,
> -                                 Packet,
> -                                 NDIS_STATUS_SUCCESS);
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 1);
> +    __TransmitterCompletePacketsV1(Transmitter,
> +                                   Packet,
> +                                   NDIS_STATUS_SUCCESS);
> +}
> +

Don't need the above function.

> +VOID
> +TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    __TransmitterCompletePacketsV2(Transmitter,
> +                                   List,
> +                                   NDIS_STATUS_SUCCESS);
>  }
> 
>  VOID
> @@ -273,22 +486,23 @@ TransmitterEnable(
>      IN  PXENNET_TRANSMITTER     Transmitter
>      )
>  {
> -    PXENVIF_VIF_INTERFACE   Vif = AdapterGetVifInterface(Transmitter-
> >Adapter);
> +    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) != 1)
> +        return;
> 
>      (VOID) XENVIF_VIF(TransmitterSetPacketOffset,
> -                      Vif,
> +                      Transmitter->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,
> -                      Vif,
> +                      Transmitter->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,
> -                      Vif,
> +                      Transmitter->VifInterface,
>                        XENVIF_TRANSMITTER_PACKET_MDL_OFFSET,
> 
> (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
> 
> (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL));
> @@ -318,8 +532,47 @@ TransmitterInitialize(
>      RtlZeroMemory(*Transmitter, sizeof(XENNET_TRANSMITTER));
>      (*Transmitter)->Adapter = Adapter;
> 
> +    (*Transmitter)->VifInterface = AdapterGetVifInterface(Adapter);
> +    status = XENVIF_VIF(Acquire, (*Transmitter)->VifInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
> +        goto done;
> +
> +    (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
> +    status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
> +    status = XENBUS_CACHE(Create,
> +                          (*Transmitter)->CacheInterface,
> +                          "packets",
> +                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
> +                          32,
> +                          __PacketCtor,
> +                          __PacketDtor,
> +                          __PacketAcquire,
> +                          __PacketRelease,
> +                          *Transmitter,
> +                          &(*Transmitter)->Cache);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
> +done:
>      return STATUS_SUCCESS;
> 
> +fail4:
> +    Error("fail4\n");
> +    XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
> +    (*Transmitter)->CacheInterface = NULL;
> +fail3:
> +    Error("fail3\n");
> +    XENVIF_VIF(Release, (*Transmitter)->VifInterface);
> +    (*Transmitter)->VifInterface = NULL;
> +fail2:
> +    Error("fail2\n");
> +    ExFreePoolWithTag(*Transmitter, TRANSMITTER_POOL_TAG);
>  fail1:
>      Error("fail1 (%08x)\n", status);
>      return status;
> @@ -331,6 +584,19 @@ TransmitterTeardown(
>      IN  PXENNET_TRANSMITTER     Transmitter
>      )
>  {
> +    if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
> +        goto done;
> +
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >Cache);
> +    Transmitter->Cache = NULL;
> +
> +    XENBUS_CACHE(Release, Transmitter->CacheInterface);
> +    Transmitter->CacheInterface = NULL;
> +
> +done:
> +    XENVIF_VIF(Release, Transmitter->VifInterface);
> +    Transmitter->VifInterface = NULL;
> +
>      ExFreePoolWithTag(Transmitter, TRANSMITTER_POOL_TAG);
>  }
> 
> diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
> index f99ffd3..adf3b4c 100644
> --- a/src/xennet/transmitter.h
> +++ b/src/xennet/transmitter.h
> @@ -45,9 +45,15 @@ TransmitterSendNetBufferLists(
>      );
> 
>  extern VOID
> -TransmitterCompletePackets(
> -    IN  PXENNET_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +TransmitterCompletePacketsV1(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Packet
> +    );
> +
> +extern VOID
> +TransmitterCompletePacketsV2(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
>      );
> 
>  extern VOID

You're missing a change to the INF file to bind to the new PDO name.

  Paul

> --
> 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 Mon Nov 17 13:48:42 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:48:42 +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 1XqMfa-00040J-UV; Mon, 17 Nov 2014 13:48:42 +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 1XqMfa-00040D-42
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:48:42 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	B4/D3-02954-9BCF9645; Mon, 17 Nov 2014 13:48:41 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-27.messagelabs.com!1416232120!8419543!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1737 invoked from network); 17 Nov 2014 13:48:40 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:48:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901669"
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: [PATCH 3/4] Pullup headers and calculate hash over IP
	addresses and Ports
Thread-Index: AQHP/pcpEKSYpXWOMECqxmoK/Ztey5xk3GbA
Date: Mon, 17 Nov 2014 13:48:39 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115368C@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-4-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-4-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 3/4] Pullup headers and calculate hash
 over IP addresses and 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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 3/4] Pullup headers and calculate hash over IP addresses
> and Ports
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h   |  2 ++
>  src/xennet/toeplitzhash.h | 71
> ++++++++++++++++++++++++++++++++++++++++++
>  src/xennet/transmitter.c  | 79
> +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 152 insertions(+)
>  create mode 100644 src/xennet/toeplitzhash.h
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 4ce61c4..83e3846 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
>      ULONG                                       Length;
>      /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Hash value calculated from packet's headers */
> +    ULONGLONG                                   HashValue;
>      /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
>      /*! Information passed up from subscriber for packet completion */
> diff --git a/src/xennet/toeplitzhash.h b/src/xennet/toeplitzhash.h
> new file mode 100644
> index 0000000..df9e924
> --- /dev/null
> +++ b/src/xennet/toeplitzhash.h
> @@ -0,0 +1,71 @@
> +/* 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_TOEPLITZ_HASH_H
> +#define _XENVIF_TOEPLITZ_HASH_H
> +
> +static const UCHAR ToeplitzKey[] = {
> +    0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
> +    0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
> +    0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
> +    0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
> +    0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
> +};
> +
> +static FORCEINLINE ULONG
> +ToeplitzHash(
> +    IN  PUCHAR              Input,
> +    IN  ULONG               Length
> +    )
> +{
> +    ULONG                   Bit, Byte;
> +    ULONG                   Keyword;
> +    ULONG                   HashValue;
> +    const UCHAR*            Next;
> +
> +    Next = ToeplitzKey + sizeof(ULONG);
> +    Keyword = RtlUlongByteSwap(*(PULONG)ToeplitzKey);
> +    HashValue = 0;
> +
> +    for (Byte = 0; Byte < Length; ++Byte) {
> +        for (Bit = 0; Bit < 8; ++Bit) {
> +            if (Input[Byte] & (1 << (8 - Bit)))
> +                HashValue ^= Keyword;
> +            Keyword = (Keyword << 1) | ((*Next) >> (8 - Bit) & 1);
> +        }
> +        ++Next;
> +    }
> +
> +    return HashValue;
> +}

Why such an expensive hash? You don't need to use Toeplitz.

  Paul

> +
> +#endif // _XENVIF_TOEPLITZ_HASH_H
> +
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index 9bf730c..e408364 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -32,6 +32,8 @@
>  #include <ndis.h>
>  #include "transmitter.h"
>  #include "adapter.h"
> +#include "toeplitzhash.h"
> +#include <tcpip.h>
>  #include "dbg_print.h"
>  #include "assert.h"
> 
> @@ -281,6 +283,82 @@ __OffloadOptions(
>      }
>  }
> 
> +static FORCEINLINE ULONGLONG
> +__TransmitterCalculateHash(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    UCHAR               Buffer[1024];
> +    UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 +
> sizeof(USHORT)*2
> +    PUCHAR              Ptr;
> +    XENVIF_PACKET_INFO  Info;
> +    NTSTATUS            status;
> +
> +    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
> +
> +    status = XENVIF_VIF(TransmitterGetPacketHeaders,
> +                        Transmitter->VifInterface,
> +                        Packet->Mdl,
> +                        Packet->Offset,
> +                        Packet->Length,
> +                        Buffer,
> +                        sizeof(Buffer),
> +                        &Info);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    Ptr = HashOver;
> +    if (Info.IpHeader.Length) {
> +        PIP_HEADER  IpHeader;
> +
> +        IpHeader = (PIP_HEADER)(Buffer + Info.IpHeader.Offset);
> +
> +        if (IpHeader->Version == 4) {
> +            RtlCopyMemory(Ptr, &IpHeader->Version4.SourceAddress,
> sizeof(IPV4_ADDRESS));
> +            Ptr += sizeof(IPV4_ADDRESS);
> +            RtlCopyMemory(Ptr, &IpHeader->Version4.DestinationAddress,
> sizeof(IPV4_ADDRESS));
> +            Ptr += sizeof(IPV4_ADDRESS);
> +        } else if (IpHeader->Version == 6) {
> +            RtlCopyMemory(Ptr, &IpHeader->Version6.SourceAddress,
> sizeof(IPV6_ADDRESS));
> +            Ptr += sizeof(IPV6_ADDRESS);
> +            RtlCopyMemory(Ptr, &IpHeader->Version6.DestinationAddress,
> sizeof(IPV6_ADDRESS));
> +            Ptr += sizeof(IPV6_ADDRESS);
> +        }
> +    }
> +    if (Info.TcpHeader.Length) {
> +        PTCP_HEADER TcpHeader;
> +
> +        TcpHeader = (PTCP_HEADER)(Buffer + Info.TcpHeader.Offset);
> +
> +        *(PUSHORT)Ptr = TcpHeader->SourcePort;
> +        Ptr += sizeof(USHORT);
> +        *(PUSHORT)Ptr = TcpHeader->DestinationPort;
> +        Ptr += sizeof(USHORT);
> +    } else if (Info.UdpHeader.Length) {
> +        PUDP_HEADER UdpHeader;
> +
> +        UdpHeader = (PUDP_HEADER)(Buffer + Info.UdpHeader.Offset);
> +
> +        *(PUSHORT)Ptr = UdpHeader->SourcePort;
> +        Ptr += sizeof(USHORT);
> +        *(PUSHORT)Ptr = UdpHeader->DestinationPort;
> +        Ptr += sizeof(USHORT);
> +    }
> +    if (Ptr - HashOver == 0)
> +        goto done;
> +
> +    return ToeplitzHash(HashOver, (ULONG)(Ptr - HashOver));
> +
> +done:
> +    return 0;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return 0;
> +}
> +
>  static FORCEINLINE VOID
>  __TransmitterSendNetBufferListsV1(
>      IN  PXENNET_TRANSMITTER     Transmitter,
> @@ -400,6 +478,7 @@ __TransmitterSendNetBufferListsV2(
>              Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
>              Packet->Offset                      =
> NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
>              Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
> +            Packet->HashValue                   =
> __TransmitterCalculateHash(Transmitter, Packet);
>              RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> 
>              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 Mon Nov 17 13:48:42 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:48:42 +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 1XqMfa-00040J-UV; Mon, 17 Nov 2014 13:48:42 +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 1XqMfa-00040D-42
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:48:42 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	B4/D3-02954-9BCF9645; Mon, 17 Nov 2014 13:48:41 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-27.messagelabs.com!1416232120!8419543!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 1737 invoked from network); 17 Nov 2014 13:48:40 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:48:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901669"
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: [PATCH 3/4] Pullup headers and calculate hash over IP
	addresses and Ports
Thread-Index: AQHP/pcpEKSYpXWOMECqxmoK/Ztey5xk3GbA
Date: Mon, 17 Nov 2014 13:48:39 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115368C@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-4-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-4-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 3/4] Pullup headers and calculate hash
 over IP addresses and 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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 3/4] Pullup headers and calculate hash over IP addresses
> and Ports
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h   |  2 ++
>  src/xennet/toeplitzhash.h | 71
> ++++++++++++++++++++++++++++++++++++++++++
>  src/xennet/transmitter.c  | 79
> +++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 152 insertions(+)
>  create mode 100644 src/xennet/toeplitzhash.h
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 4ce61c4..83e3846 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
>      ULONG                                       Length;
>      /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Hash value calculated from packet's headers */
> +    ULONGLONG                                   HashValue;
>      /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
>      /*! Information passed up from subscriber for packet completion */
> diff --git a/src/xennet/toeplitzhash.h b/src/xennet/toeplitzhash.h
> new file mode 100644
> index 0000000..df9e924
> --- /dev/null
> +++ b/src/xennet/toeplitzhash.h
> @@ -0,0 +1,71 @@
> +/* 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_TOEPLITZ_HASH_H
> +#define _XENVIF_TOEPLITZ_HASH_H
> +
> +static const UCHAR ToeplitzKey[] = {
> +    0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
> +    0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
> +    0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
> +    0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
> +    0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
> +};
> +
> +static FORCEINLINE ULONG
> +ToeplitzHash(
> +    IN  PUCHAR              Input,
> +    IN  ULONG               Length
> +    )
> +{
> +    ULONG                   Bit, Byte;
> +    ULONG                   Keyword;
> +    ULONG                   HashValue;
> +    const UCHAR*            Next;
> +
> +    Next = ToeplitzKey + sizeof(ULONG);
> +    Keyword = RtlUlongByteSwap(*(PULONG)ToeplitzKey);
> +    HashValue = 0;
> +
> +    for (Byte = 0; Byte < Length; ++Byte) {
> +        for (Bit = 0; Bit < 8; ++Bit) {
> +            if (Input[Byte] & (1 << (8 - Bit)))
> +                HashValue ^= Keyword;
> +            Keyword = (Keyword << 1) | ((*Next) >> (8 - Bit) & 1);
> +        }
> +        ++Next;
> +    }
> +
> +    return HashValue;
> +}

Why such an expensive hash? You don't need to use Toeplitz.

  Paul

> +
> +#endif // _XENVIF_TOEPLITZ_HASH_H
> +
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index 9bf730c..e408364 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -32,6 +32,8 @@
>  #include <ndis.h>
>  #include "transmitter.h"
>  #include "adapter.h"
> +#include "toeplitzhash.h"
> +#include <tcpip.h>
>  #include "dbg_print.h"
>  #include "assert.h"
> 
> @@ -281,6 +283,82 @@ __OffloadOptions(
>      }
>  }
> 
> +static FORCEINLINE ULONGLONG
> +__TransmitterCalculateHash(
> +    IN  PXENNET_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    UCHAR               Buffer[1024];
> +    UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 +
> sizeof(USHORT)*2
> +    PUCHAR              Ptr;
> +    XENVIF_PACKET_INFO  Info;
> +    NTSTATUS            status;
> +
> +    RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
> +
> +    status = XENVIF_VIF(TransmitterGetPacketHeaders,
> +                        Transmitter->VifInterface,
> +                        Packet->Mdl,
> +                        Packet->Offset,
> +                        Packet->Length,
> +                        Buffer,
> +                        sizeof(Buffer),
> +                        &Info);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    Ptr = HashOver;
> +    if (Info.IpHeader.Length) {
> +        PIP_HEADER  IpHeader;
> +
> +        IpHeader = (PIP_HEADER)(Buffer + Info.IpHeader.Offset);
> +
> +        if (IpHeader->Version == 4) {
> +            RtlCopyMemory(Ptr, &IpHeader->Version4.SourceAddress,
> sizeof(IPV4_ADDRESS));
> +            Ptr += sizeof(IPV4_ADDRESS);
> +            RtlCopyMemory(Ptr, &IpHeader->Version4.DestinationAddress,
> sizeof(IPV4_ADDRESS));
> +            Ptr += sizeof(IPV4_ADDRESS);
> +        } else if (IpHeader->Version == 6) {
> +            RtlCopyMemory(Ptr, &IpHeader->Version6.SourceAddress,
> sizeof(IPV6_ADDRESS));
> +            Ptr += sizeof(IPV6_ADDRESS);
> +            RtlCopyMemory(Ptr, &IpHeader->Version6.DestinationAddress,
> sizeof(IPV6_ADDRESS));
> +            Ptr += sizeof(IPV6_ADDRESS);
> +        }
> +    }
> +    if (Info.TcpHeader.Length) {
> +        PTCP_HEADER TcpHeader;
> +
> +        TcpHeader = (PTCP_HEADER)(Buffer + Info.TcpHeader.Offset);
> +
> +        *(PUSHORT)Ptr = TcpHeader->SourcePort;
> +        Ptr += sizeof(USHORT);
> +        *(PUSHORT)Ptr = TcpHeader->DestinationPort;
> +        Ptr += sizeof(USHORT);
> +    } else if (Info.UdpHeader.Length) {
> +        PUDP_HEADER UdpHeader;
> +
> +        UdpHeader = (PUDP_HEADER)(Buffer + Info.UdpHeader.Offset);
> +
> +        *(PUSHORT)Ptr = UdpHeader->SourcePort;
> +        Ptr += sizeof(USHORT);
> +        *(PUSHORT)Ptr = UdpHeader->DestinationPort;
> +        Ptr += sizeof(USHORT);
> +    }
> +    if (Ptr - HashOver == 0)
> +        goto done;
> +
> +    return ToeplitzHash(HashOver, (ULONG)(Ptr - HashOver));
> +
> +done:
> +    return 0;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return 0;
> +}
> +
>  static FORCEINLINE VOID
>  __TransmitterSendNetBufferListsV1(
>      IN  PXENNET_TRANSMITTER     Transmitter,
> @@ -400,6 +478,7 @@ __TransmitterSendNetBufferListsV2(
>              Packet->Mdl                         = NET_BUFFER_CURRENT_MDL(NetBuffer);
>              Packet->Offset                      =
> NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer);
>              Packet->Length                      = NET_BUFFER_DATA_LENGTH(NetBuffer);
> +            Packet->HashValue                   =
> __TransmitterCalculateHash(Transmitter, Packet);
>              RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> 
>              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 Mon Nov 17 13:51:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:51: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 1XqMiQ-00046E-HU; Mon, 17 Nov 2014 13:51:38 +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 1XqMiP-000467-LN
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:51:37 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	AB/E7-22777-76DF9645; Mon, 17 Nov 2014 13:51:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-206.messagelabs.com!1416232294!8912724!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6968 invoked from network); 17 Nov 2014 13:51:35 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-16.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:51:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901797"
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: [PATCH 4/4] Use a cache for header buffers, to fix a 'function
	uses too much stack' warning
Thread-Index: AQHP/pcpUNV1qI+wf0qm3NluQIW2bpxk3Z1Q
Date: Mon, 17 Nov 2014 13:51:29 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111536A1@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-5-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-5-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 4/4] Use a cache for header buffers,
 to fix a 'function uses too much stack' warning
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 4/4] Use a cache for header buffers, to fix a 'function uses
> too much stack' warning
> 
> Tweak GetPacketHeaders interface call to pass less parameters.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  16 +++---
>  src/xennet/transmitter.c | 142
> ++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 136 insertions(+), 22 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 83e3846..5662293 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -528,16 +528,18 @@ typedef NTSTATUS
>      \brief Get a copy of the packet headers and each the offset of each
> 
>      \param Interface The interface header
> +    \param Packet The packet
> +    \param HeaderBuffer Buffer to receive a copy of the headers
> +    \param HeaderLength Length in bytes of Buffer
> +    \param Info Location to receive offsets of headers into Buffer
>  */
>  typedef NTSTATUS
>  (*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> -    IN  PINTERFACE          Interface,
> -    IN  PMDL                Mdl,
> -    IN  ULONG               Offset,
> -    IN  ULONG               Length,
> -    OUT PVOID               HeaderBuffer,
> -    IN  ULONG               HeaderLength,
> -    OUT PXENVIF_PACKET_INFO Info
> +    IN  PINTERFACE                      Interface,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet,
> +    OUT PVOID                           HeaderBuffer,
> +    IN  ULONG                           HeaderLength,
> +    OUT PXENVIF_PACKET_INFO             Info
>      );
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index e408364..4738eed 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -43,10 +43,13 @@ struct _XENNET_TRANSMITTER {
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> 
>      PXENBUS_CACHE_INTERFACE     CacheInterface;
> -    PXENBUS_CACHE               Cache;
> +    PXENBUS_CACHE               PacketCache;
> +    PXENBUS_CACHE               BufferCache;
> +    KSPIN_LOCK                  Lock;
>  };
> 
>  #define TRANSMITTER_POOL_TAG    'teNX'
> +#define BUFFER_SIZE             PAGE_SIZE
> 
>  static NTSTATUS
>  __PacketCtor(
> @@ -74,7 +77,8 @@ __PacketAcquire(
>      IN  PVOID           Argument
>      )
>  {
> -    UNREFERENCED_PARAMETER(Argument);
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
>  }
> 
>  static VOID
> @@ -82,7 +86,47 @@ __PacketRelease(
>      IN  PVOID           Argument
>      )
>  {
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
> +}

Ah, I see you implemented the locking here. This needs to be moved to patch #2.

  Paul

> +
> +static NTSTATUS
> +__BufferCtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, BUFFER_SIZE);
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +__BufferDtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
>      UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +__BufferAcquire(
> +    IN  PVOID           Argument
> +    )
> +{
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
> +}
> +
> +static VOID
> +__BufferRelease(
> +    IN  PVOID           Argument
> +    )
> +{
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
>  }
> 
>  static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> @@ -92,11 +136,11 @@ __TransmitterGetPacket(
>  {
>      ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
>      ASSERT(Transmitter->CacheInterface != NULL);
> -    ASSERT(Transmitter->Cache != NULL);
> +    ASSERT(Transmitter->PacketCache != NULL);
> 
>      return XENBUS_CACHE(Get,
>                          Transmitter->CacheInterface,
> -                        Transmitter->Cache,
> +                        Transmitter->PacketCache,
>                          FALSE);
>  }
> 
> @@ -108,15 +152,47 @@ __TransmitterPutPacket(
>  {
>      ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
>      ASSERT(Transmitter->CacheInterface != NULL);
> -    ASSERT(Transmitter->Cache != NULL);
> +    ASSERT(Transmitter->PacketCache != NULL);
> 
>      XENBUS_CACHE(Put,
>                   Transmitter->CacheInterface,
> -                 Transmitter->Cache,
> +                 Transmitter->PacketCache,
>                   Packet,
>                   FALSE);
>  }
> 
> +static FORCEINLINE PVOID
> +__TransmitterGetBuffer(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->BufferCache != NULL);
> +
> +    return XENBUS_CACHE(Get,
> +                        Transmitter->CacheInterface,
> +                        Transmitter->BufferCache,
> +                        FALSE);
> +}
> +
> +static FORCEINLINE VOID
> +__TransmitterPutBuffer(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PVOID                   Buffer
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->BufferCache != NULL);
> +
> +    XENBUS_CACHE(Put,
> +                 Transmitter->CacheInterface,
> +                 Transmitter->BufferCache,
> +                 Buffer,
> +                 FALSE);
> +}
> +
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
>  } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
> @@ -289,24 +365,27 @@ __TransmitterCalculateHash(
>      IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
>      )
>  {
> -    UCHAR               Buffer[1024];
> +    PUCHAR              Buffer;
>      UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 +
> sizeof(USHORT)*2
>      PUCHAR              Ptr;
>      XENVIF_PACKET_INFO  Info;
>      NTSTATUS            status;
> 
> +    status = STATUS_NO_MEMORY;
> +    Buffer = __TransmitterGetBuffer(Transmitter);
> +    if (Buffer == NULL)
> +        goto fail1;
> +
>      RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
> 
>      status = XENVIF_VIF(TransmitterGetPacketHeaders,
>                          Transmitter->VifInterface,
> -                        Packet->Mdl,
> -                        Packet->Offset,
> -                        Packet->Length,
> +                        Packet,
>                          Buffer,
> -                        sizeof(Buffer),
> +                        BUFFER_SIZE,
>                          &Info);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> 
>      Ptr = HashOver;
>      if (Info.IpHeader.Length) {
> @@ -345,6 +424,9 @@ __TransmitterCalculateHash(
>          *(PUSHORT)Ptr = UdpHeader->DestinationPort;
>          Ptr += sizeof(USHORT);
>      }
> +
> +    __TransmitterPutBuffer(Transmitter, Buffer);
> +
>      if (Ptr - HashOver == 0)
>          goto done;
> 
> @@ -353,6 +435,11 @@ __TransmitterCalculateHash(
>  done:
>      return 0;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    __TransmitterPutBuffer(Transmitter, Buffer);
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -619,6 +706,7 @@ TransmitterInitialize(
>      if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
>          goto done;
> 
> +    KeInitializeSpinLock(&(*Transmitter)->Lock);
>      (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
>      status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
>      if (!NT_SUCCESS(status))
> @@ -634,19 +722,38 @@ TransmitterInitialize(
>                            __PacketAcquire,
>                            __PacketRelease,
>                            *Transmitter,
> -                          &(*Transmitter)->Cache);
> +                          &(*Transmitter)->PacketCache);
>      if (!NT_SUCCESS(status))
>          goto fail4;
> 
> +    status = XENBUS_CACHE(Create,
> +                          (*Transmitter)->CacheInterface,
> +                          "buffers",
> +                          BUFFER_SIZE,
> +                          4,
> +                          __BufferCtor,
> +                          __BufferDtor,
> +                          __BufferAcquire,
> +                          __BufferRelease,
> +                          *Transmitter,
> +                          &(*Transmitter)->BufferCache);
> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> +
>  done:
>      return STATUS_SUCCESS;
> 
> +fail5:
> +    Error("fail5\n");
> +    XENBUS_CACHE(Destroy, (*Transmitter)->CacheInterface,
> (*Transmitter)->PacketCache);
> +    (*Transmitter)->PacketCache = NULL;
>  fail4:
>      Error("fail4\n");
>      XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
>      (*Transmitter)->CacheInterface = NULL;
>  fail3:
>      Error("fail3\n");
> +    RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK));
>      XENVIF_VIF(Release, (*Transmitter)->VifInterface);
>      (*Transmitter)->VifInterface = NULL;
>  fail2:
> @@ -666,12 +773,17 @@ TransmitterTeardown(
>      if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
>          goto done;
> 
> -    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >Cache);
> -    Transmitter->Cache = NULL;
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >BufferCache);
> +    Transmitter->BufferCache = NULL;
> +
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >PacketCache);
> +    Transmitter->PacketCache = NULL;
> 
>      XENBUS_CACHE(Release, Transmitter->CacheInterface);
>      Transmitter->CacheInterface = NULL;
> 
> +    RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK));
> +
>  done:
>      XENVIF_VIF(Release, Transmitter->VifInterface);
>      Transmitter->VifInterface = NULL;
> --
> 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 Mon Nov 17 13:51:38 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 13:51: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 1XqMiQ-00046E-HU; Mon, 17 Nov 2014 13:51:38 +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 1XqMiP-000467-LN
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 13:51:37 +0000
Received: from [85.158.139.211] by server-11.bemta-5.messagelabs.com id
	AB/E7-22777-76DF9645; Mon, 17 Nov 2014 13:51:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-16.tower-206.messagelabs.com!1416232294!8912724!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 6968 invoked from network); 17 Nov 2014 13:51:35 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-16.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 13:51:35 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26901797"
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: [PATCH 4/4] Use a cache for header buffers, to fix a 'function
	uses too much stack' warning
Thread-Index: AQHP/pcpUNV1qI+wf0qm3NluQIW2bpxk3Z1Q
Date: Mon, 17 Nov 2014 13:51:29 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111536A1@AMSPEX01CL01.citrite.net>
References: <1415810330-1152-1-git-send-email-owen.smith@citrix.com>
	<1415810330-1152-5-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810330-1152-5-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 4/4] Use a cache for header buffers,
 to fix a 'function uses too much stack' warning
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 4/4] Use a cache for header buffers, to fix a 'function uses
> too much stack' warning
> 
> Tweak GetPacketHeaders interface call to pass less parameters.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  16 +++---
>  src/xennet/transmitter.c | 142
> ++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 136 insertions(+), 22 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 83e3846..5662293 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -528,16 +528,18 @@ typedef NTSTATUS
>      \brief Get a copy of the packet headers and each the offset of each
> 
>      \param Interface The interface header
> +    \param Packet The packet
> +    \param HeaderBuffer Buffer to receive a copy of the headers
> +    \param HeaderLength Length in bytes of Buffer
> +    \param Info Location to receive offsets of headers into Buffer
>  */
>  typedef NTSTATUS
>  (*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> -    IN  PINTERFACE          Interface,
> -    IN  PMDL                Mdl,
> -    IN  ULONG               Offset,
> -    IN  ULONG               Length,
> -    OUT PVOID               HeaderBuffer,
> -    IN  ULONG               HeaderLength,
> -    OUT PXENVIF_PACKET_INFO Info
> +    IN  PINTERFACE                      Interface,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet,
> +    OUT PVOID                           HeaderBuffer,
> +    IN  ULONG                           HeaderLength,
> +    OUT PXENVIF_PACKET_INFO             Info
>      );
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
> index e408364..4738eed 100644
> --- a/src/xennet/transmitter.c
> +++ b/src/xennet/transmitter.c
> @@ -43,10 +43,13 @@ struct _XENNET_TRANSMITTER {
>      XENVIF_VIF_OFFLOAD_OPTIONS  OffloadOptions;
> 
>      PXENBUS_CACHE_INTERFACE     CacheInterface;
> -    PXENBUS_CACHE               Cache;
> +    PXENBUS_CACHE               PacketCache;
> +    PXENBUS_CACHE               BufferCache;
> +    KSPIN_LOCK                  Lock;
>  };
> 
>  #define TRANSMITTER_POOL_TAG    'teNX'
> +#define BUFFER_SIZE             PAGE_SIZE
> 
>  static NTSTATUS
>  __PacketCtor(
> @@ -74,7 +77,8 @@ __PacketAcquire(
>      IN  PVOID           Argument
>      )
>  {
> -    UNREFERENCED_PARAMETER(Argument);
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
>  }
> 
>  static VOID
> @@ -82,7 +86,47 @@ __PacketRelease(
>      IN  PVOID           Argument
>      )
>  {
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
> +}

Ah, I see you implemented the locking here. This needs to be moved to patch #2.

  Paul

> +
> +static NTSTATUS
> +__BufferCtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, BUFFER_SIZE);
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +__BufferDtor(
> +    IN  PVOID           Argument,
> +    IN  PVOID           Object
> +    )
> +{
>      UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +__BufferAcquire(
> +    IN  PVOID           Argument
> +    )
> +{
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeAcquireSpinLockAtDpcLevel(&Transmitter->Lock);
> +}
> +
> +static VOID
> +__BufferRelease(
> +    IN  PVOID           Argument
> +    )
> +{
> +    PXENNET_TRANSMITTER Transmitter = Argument;
> +    KeReleaseSpinLockFromDpcLevel(&Transmitter->Lock);
>  }
> 
>  static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> @@ -92,11 +136,11 @@ __TransmitterGetPacket(
>  {
>      ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
>      ASSERT(Transmitter->CacheInterface != NULL);
> -    ASSERT(Transmitter->Cache != NULL);
> +    ASSERT(Transmitter->PacketCache != NULL);
> 
>      return XENBUS_CACHE(Get,
>                          Transmitter->CacheInterface,
> -                        Transmitter->Cache,
> +                        Transmitter->PacketCache,
>                          FALSE);
>  }
> 
> @@ -108,15 +152,47 @@ __TransmitterPutPacket(
>  {
>      ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
>      ASSERT(Transmitter->CacheInterface != NULL);
> -    ASSERT(Transmitter->Cache != NULL);
> +    ASSERT(Transmitter->PacketCache != NULL);
> 
>      XENBUS_CACHE(Put,
>                   Transmitter->CacheInterface,
> -                 Transmitter->Cache,
> +                 Transmitter->PacketCache,
>                   Packet,
>                   FALSE);
>  }
> 
> +static FORCEINLINE PVOID
> +__TransmitterGetBuffer(
> +    IN  PXENNET_TRANSMITTER     Transmitter
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->BufferCache != NULL);
> +
> +    return XENBUS_CACHE(Get,
> +                        Transmitter->CacheInterface,
> +                        Transmitter->BufferCache,
> +                        FALSE);
> +}
> +
> +static FORCEINLINE VOID
> +__TransmitterPutBuffer(
> +    IN  PXENNET_TRANSMITTER     Transmitter,
> +    IN  PVOID                   Buffer
> +    )
> +{
> +    ASSERT3U(XENVIF_VIF_VERSION(Transmitter->VifInterface), ==, 2);
> +    ASSERT(Transmitter->CacheInterface != NULL);
> +    ASSERT(Transmitter->BufferCache != NULL);
> +
> +    XENBUS_CACHE(Put,
> +                 Transmitter->CacheInterface,
> +                 Transmitter->BufferCache,
> +                 Buffer,
> +                 FALSE);
> +}
> +
>  typedef struct _NET_BUFFER_LIST_RESERVED {
>      LONG    Reference;
>  } NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
> @@ -289,24 +365,27 @@ __TransmitterCalculateHash(
>      IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
>      )
>  {
> -    UCHAR               Buffer[1024];
> +    PUCHAR              Buffer;
>      UCHAR               HashOver[40]; // sizeof(IPV6_ADDRESS)*2 +
> sizeof(USHORT)*2
>      PUCHAR              Ptr;
>      XENVIF_PACKET_INFO  Info;
>      NTSTATUS            status;
> 
> +    status = STATUS_NO_MEMORY;
> +    Buffer = __TransmitterGetBuffer(Transmitter);
> +    if (Buffer == NULL)
> +        goto fail1;
> +
>      RtlZeroMemory(&Info, sizeof(XENVIF_PACKET_INFO));
> 
>      status = XENVIF_VIF(TransmitterGetPacketHeaders,
>                          Transmitter->VifInterface,
> -                        Packet->Mdl,
> -                        Packet->Offset,
> -                        Packet->Length,
> +                        Packet,
>                          Buffer,
> -                        sizeof(Buffer),
> +                        BUFFER_SIZE,
>                          &Info);
>      if (!NT_SUCCESS(status))
> -        goto fail1;
> +        goto fail2;
> 
>      Ptr = HashOver;
>      if (Info.IpHeader.Length) {
> @@ -345,6 +424,9 @@ __TransmitterCalculateHash(
>          *(PUSHORT)Ptr = UdpHeader->DestinationPort;
>          Ptr += sizeof(USHORT);
>      }
> +
> +    __TransmitterPutBuffer(Transmitter, Buffer);
> +
>      if (Ptr - HashOver == 0)
>          goto done;
> 
> @@ -353,6 +435,11 @@ __TransmitterCalculateHash(
>  done:
>      return 0;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    __TransmitterPutBuffer(Transmitter, Buffer);
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -619,6 +706,7 @@ TransmitterInitialize(
>      if (XENVIF_VIF_VERSION((*Transmitter)->VifInterface) == 1)
>          goto done;
> 
> +    KeInitializeSpinLock(&(*Transmitter)->Lock);
>      (*Transmitter)->CacheInterface = AdapterGetCacheInterface(Adapter);
>      status = XENBUS_CACHE(Acquire, (*Transmitter)->CacheInterface);
>      if (!NT_SUCCESS(status))
> @@ -634,19 +722,38 @@ TransmitterInitialize(
>                            __PacketAcquire,
>                            __PacketRelease,
>                            *Transmitter,
> -                          &(*Transmitter)->Cache);
> +                          &(*Transmitter)->PacketCache);
>      if (!NT_SUCCESS(status))
>          goto fail4;
> 
> +    status = XENBUS_CACHE(Create,
> +                          (*Transmitter)->CacheInterface,
> +                          "buffers",
> +                          BUFFER_SIZE,
> +                          4,
> +                          __BufferCtor,
> +                          __BufferDtor,
> +                          __BufferAcquire,
> +                          __BufferRelease,
> +                          *Transmitter,
> +                          &(*Transmitter)->BufferCache);
> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> +
>  done:
>      return STATUS_SUCCESS;
> 
> +fail5:
> +    Error("fail5\n");
> +    XENBUS_CACHE(Destroy, (*Transmitter)->CacheInterface,
> (*Transmitter)->PacketCache);
> +    (*Transmitter)->PacketCache = NULL;
>  fail4:
>      Error("fail4\n");
>      XENBUS_CACHE(Release, (*Transmitter)->CacheInterface);
>      (*Transmitter)->CacheInterface = NULL;
>  fail3:
>      Error("fail3\n");
> +    RtlZeroMemory(&(*Transmitter)->Lock, sizeof(KSPIN_LOCK));
>      XENVIF_VIF(Release, (*Transmitter)->VifInterface);
>      (*Transmitter)->VifInterface = NULL;
>  fail2:
> @@ -666,12 +773,17 @@ TransmitterTeardown(
>      if (XENVIF_VIF_VERSION(Transmitter->VifInterface) == 1)
>          goto done;
> 
> -    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >Cache);
> -    Transmitter->Cache = NULL;
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >BufferCache);
> +    Transmitter->BufferCache = NULL;
> +
> +    XENBUS_CACHE(Destroy, Transmitter->CacheInterface, Transmitter-
> >PacketCache);
> +    Transmitter->PacketCache = NULL;
> 
>      XENBUS_CACHE(Release, Transmitter->CacheInterface);
>      Transmitter->CacheInterface = NULL;
> 
> +    RtlZeroMemory(&Transmitter->Lock, sizeof(KSPIN_LOCK));
> +
>  done:
>      XENVIF_VIF(Release, Transmitter->VifInterface);
>      Transmitter->VifInterface = NULL;
> --
> 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 Mon Nov 17 14:22:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:22:54 +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 1XqNCg-00054e-1s; Mon, 17 Nov 2014 14:22:54 +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 1XqNCe-00054Z-LU
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:22:52 +0000
Received: from [193.109.254.147] by server-1.bemta-14.messagelabs.com id
	AB/45-02559-BB40A645; Mon, 17 Nov 2014 14:22:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-27.messagelabs.com!1416234169!13071520!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4055 invoked from network); 17 Nov 2014 14:22:50 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:22:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26903519"
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: [PATCH 01/10] Rework transmitter packet code to use an
	internal cache of objects
Thread-Index: AQHP/pc0YPaj6+C/C0+mHHNccv7JtJxk4PGw
Date: Mon, 17 Nov 2014 14:22:48 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111536ED@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-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 01/10] Rework transmitter packet code to
 use an internal cache of objects
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 01/10] Rework transmitter packet code to use an internal
> cache of objects
> 
> Use XENVIF_TRANSMITTER_PACKET_V2 for queueing packets, with a
> translation on entry and exit through the interface (for v1)
> Renames XENVIF_TRANSMITTER_PACKET to
> XENVIF_TRANSMITTER_PACKET_V1
> XENVIF_TRANSMITTER_PACKET_V2 is allocated from a cache and not
> included inline in the miniport reserved area of a NET_BUFFER, like
> XENVIF_TRANSMITTER_PACKET_V1.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  37 ++--
>  src/xenvif/transmitter.c | 477 ++++++++++++++++++++++++++++++++-----
> ----------
>  src/xenvif/transmitter.h |   6 +-
>  src/xenvif/vif.c         |  12 +-
>  src/xenvif/vif.h         |   4 +-
>  5 files changed, 368 insertions(+), 168 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 498ed8f..8bde731 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,9 +265,24 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1
> XENVIF_TRANSMITTER_PACKET, *PXENVIF
> 
>  C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof
> (PVOID)));
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
> +    \brief Transmit-side packet structure
> +*/
> +struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    LIST_ENTRY                                  ListEntry;
> +    PMDL                                        Mdl;
> +    ULONG                                       Offset;
> +    ULONG                                       Length;
> +    PVOID                                       Cookie;
> +    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
> +};
> +
> +typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> +

No. The typedef should make V2 the new XENVIF_TRANSMITTER_PACKET - there should be no need for a suffix as a subscriber should only ever use the latest versions of the types anyway.

>  /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
>      \brief Offsets of packet metadata relative to
> -    XENVIF_TRANSMITTER_PACKET pointer
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer
> 
>      Because the transmit side packet structure is limited to 3 pointer
>      types in size, not all information about the packet can be passed in
> @@ -380,10 +395,10 @@ typedef VOID
>      \param ... Additional paramaters required by \a Type
> 
>      \b XENVIF_TRANSMITTER_RETURN_PACKETS:
> -    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
> +    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1

Really? How are v2 packets returned?

> 
>      \b XENVIF_RECEIVER_QUEUE_PACKETS:
> -    \param List List of XENVIF_TRANSMITTER_PACKET
> +    \param List List of XENVIF_RECEIVER_PACKET
> 
>      \b XENVIF_MAC_STATE_CHANGE:
>      No additional arguments
> @@ -459,7 +474,7 @@ typedef VOID
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
>      \brief Set byte offset of packet information relative to
> -    XENVIF_TRANSMITTER_PACKET pointer.
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer.
> 
>      See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
> 
> @@ -474,16 +489,16 @@ typedef NTSTATUS
>      IN  LONG_PTR                            Value
>      );
> 
> -/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
>      \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
> +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
> +    IN  PINTERFACE                      Interface,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
>      );
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> @@ -694,7 +709,7 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> ReceiverSetOffloadOptions;
>      XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
>      XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> TransmitterSetPacketOffset;
> -    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> TransmitterQueuePackets;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;
>      XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> TransmitterQueryOffloadOptions;
>      XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> TransmitterQueryLargePacketSize;
>      XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> TransmitterQueryRingSize;

Where's the v2 interface?

> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 8125a5a..38e4cb2 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -88,7 +88,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_V2       Packet;
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
>      PUCHAR                              StartVa;
>      XENVIF_PACKET_INFO                  Info;
> @@ -100,8 +100,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;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;

Why do you need a tail pointer for a doubly linked list?

>  } XENVIF_TRANSMITTER_PACKET_LIST,
> *PXENVIF_TRANSMITTER_PACKET_LIST;
> 
>  typedef struct _XENVIF_TRANSMITTER_RING {
> @@ -118,7 +118,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
>      BOOLEAN                         Connected;
>      BOOLEAN                         Enabled;
>      BOOLEAN                         Stopped;
> -    PXENVIF_TRANSMITTER_PACKET      Lock;
> +    PLIST_ENTRY                     Lock;
>      PKTHREAD                        LockThread;
>      XENVIF_TRANSMITTER_PACKET_LIST  Queued;
>      XENVIF_TRANSMITTER_STATE        State;
> @@ -133,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;
> @@ -146,6 +146,7 @@ struct _XENVIF_TRANSMITTER {
>      PXENVIF_FRONTEND            Frontend;
>      XENBUS_CACHE_INTERFACE      CacheInterface;
>      XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
> +    PXENBUS_CACHE               PacketCache;
>      LIST_ENTRY                  List;
>      LONG_PTR
> Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
>      ULONG                       DisableIpVersion4Gso;
> @@ -362,7 +363,7 @@ __TransmitterGetFragment(
>                          TRUE);
>  }
> 
> -static FORCEINLINE
> +static FORCEINLINE VOID
>  __TransmitterPutFragment(
>      IN  PXENVIF_TRANSMITTER_RING        Ring,
>      IN  PXENVIF_TRANSMITTER_FRAGMENT    Fragment
> @@ -387,6 +388,67 @@ __TransmitterPutFragment(
>                   TRUE);
>  }
> 
> +static NTSTATUS
> +TransmitterPacketCtor(
> +    IN  PVOID                       Argument,
> +    IN  PVOID                       Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));

You should not need to zero the buffer. The object cache will zero on allocation. You should zero before calling the cache Put.

> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +TransmitterPacketDtor(
> +    IN  PVOID                       Argument,
> +    IN  PVOID                       Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +TransmitterPacketLock(
> +    IN  PVOID                       Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static VOID
> +TransmitterPacketUnlock(
> +    IN  PVOID                       Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> +__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_V2   Packet
> +    )
> +{
> +    XENBUS_CACHE(Put,
> +                 &Transmitter->CacheInterface,
> +                 Transmitter->PacketCache,
> +                 Packet,
> +                 TRUE);
> +}
> +
>  static VOID
>  TransmitterRingDebugCallback(
>      IN  PVOID                   Argument,
> @@ -523,25 +585,25 @@ fail1:
>      return FALSE;
>  }
> 
> -#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
> -        do {                                                        \
> -            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
> -                                                                    \
> -            ASSERT(Packet != NULL);                                 \
> -            (*Reference)++;                                         \
> +#define INCREMENT_PACKET_REFERENCE(_Packet)                                 \
> +        do {                                                                \
> +            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)-
> >ListEntry.Flink; \
> +                                                                            \
> +            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);                                         \
> +#define DECREMENT_PACKET_REFERENCE(_Packet)                                 \
> +        do {                                                                \
> +            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)-
> >ListEntry.Flink; \
> +                                                                            \
> +            ASSERT(Packet != NULL);                                         \
> +            ASSERT(*Reference != 0);                                        \
> +            --(*Reference);                                                 \
>          } while (FALSE)
> 
> -#define PACKET_REFERENCE(_Packet)                                   \
> -        (*(PULONG_PTR)&(_Packet)->Next)
> +#define PACKET_REFERENCE(_Packet)                                           \
> +        (*(PULONG_PTR)&(_Packet)->ListEntry.Flink)
> 
>  static FORCEINLINE NTSTATUS
>  __TransmitterRingCopyPayload(
> @@ -551,7 +613,7 @@ __TransmitterRingCopyPayload(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      XENVIF_PACKET_PAYLOAD           Payload;
>      PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
>      PXENVIF_TRANSMITTER_BUFFER      Buffer;
> @@ -698,7 +760,7 @@ __TransmitterRingGrantPayload(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      PMDL                            Mdl;
>      ULONG                           Offset;
> @@ -845,7 +907,7 @@ __TransmitterRingPrepareHeader(
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_MAC                     Mac;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      PXENVIF_PACKET_INFO             Info;
>      PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> @@ -1122,7 +1184,7 @@ __TransmitterRingUnprepareFragments(
>      while (State->Count != 0) {
>          PLIST_ENTRY                     ListEntry;
>          PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> -        PXENVIF_TRANSMITTER_PACKET      Packet;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>          --State->Count;
> 
> @@ -1178,19 +1240,10 @@ __TransmitterRingUnprepareFragments(
> 
>  static FORCEINLINE NTSTATUS
>  __TransmitterRingPreparePacket(
> -    IN  PXENVIF_TRANSMITTER_RING    Ring,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +    IN  PXENVIF_TRANSMITTER_RING        Ring,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   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;
> @@ -1198,7 +1251,7 @@ __TransmitterRingPreparePacket(
>      NTSTATUS                        status;
> 
>      ASSERT(IsZeroMemory(&Ring->State, sizeof
> (XENVIF_TRANSMITTER_STATE)));
> -    ASSERT3P(Packet->Next, ==, NULL);
> +    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> 
>      Transmitter = Ring->Transmitter;
> 
> @@ -1211,16 +1264,9 @@ __TransmitterRingPreparePacket(
> 
>      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);
> @@ -1325,18 +1371,15 @@ fail1:
>      ASSERT(IsZeroMemory(&Ring->State, sizeof
> (XENVIF_TRANSMITTER_STATE)));
> 
>      return status;
> -
> -#undef  OFFSET
> -#undef  OFFSET_EXISTS
>  }
> 
> -static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
>  __TransmitterRingUnpreparePacket(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>      State = &Ring->State;
>      Packet = State->Packet;
> @@ -1695,7 +1738,7 @@ __TransmitterRingPostFragments(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      RING_IDX                        req_prod;
>      RING_IDX                        rsp_cons;
> @@ -1920,8 +1963,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_V2   Packet
>      )
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
> @@ -1980,9 +2023,9 @@ __TransmitterRingCompletePacket(
>          }
>      }
> 
> -    *Ring->Completed.TailPacket = Packet;
> -    ASSERT3P(Packet->Next, ==, NULL);
> -    Ring->Completed.TailPacket = &Packet->Next;
> +    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> +    ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
> +    InsertTailList(&Ring->Completed, &Packet->ListEntry);
> 
>      Ring->PacketsCompleted++;
>  }
> @@ -2019,7 +2062,7 @@ TransmitterRingPoll(
>              netif_tx_response_t             *rsp;
>              uint16_t                        id;
>              PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> -            PXENVIF_TRANSMITTER_PACKET      Packet;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>              rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
>              rsp_cons++;
> @@ -2164,30 +2207,30 @@ __TransmitterRingPushRequests(
> 
>  static FORCEINLINE ULONG
>  __TransmitterReversePacketList(
> -    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
> +    IN  PLIST_ENTRY                 *Entry
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> +    PLIST_ENTRY                     HeadEntry;
>      ULONG                           Count;
> 
> -    HeadPacket = NULL;
> +    HeadEntry = NULL;
>      Count = 0;
> 
> -    while (*Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> +    while (*Entry != NULL) {
> +        PLIST_ENTRY     Next;
> 
> -        ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) ==
> 0);
> +        ASSERT(((ULONG_PTR)*Entry & XENVIF_TRANSMITTER_LOCK_BIT) ==
> 0);
> 
> -        Next = (*Packet)->Next;
> +        Next = (*Entry)->Flink;
> 
> -        (*Packet)->Next = HeadPacket;
> -        HeadPacket = *Packet;
> +        (*Entry)->Flink = HeadEntry;
> +        HeadEntry = *Entry;
> 
> -        *Packet = Next;
> +        *Entry = Next;
>          Count++;
>      }
> 
> -    *Packet = HeadPacket;
> +    *Entry = HeadEntry;

Are packets singly linked or doubly linked on the way into this function?

> 
>      return Count;
>  }
> @@ -2199,8 +2242,8 @@ TransmitterRingSwizzle(
>  {
>      ULONG_PTR                       Old;
>      ULONG_PTR                       New;
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;
>      ULONG                           Count;
> 
>      ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
> @@ -2209,21 +2252,21 @@ TransmitterRingSwizzle(
>      Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock,
> (PVOID)New);
> 
>      ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
> -    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> +    HeadEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> 
> -    if (HeadPacket == NULL)
> +    if (HeadEntry == 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);
> +    TailEntry = &HeadEntry->Flink;
> +    Count = __TransmitterReversePacketList(&HeadEntry);
> +    ASSERT3P(*TailEntry, ==, NULL);
> 
> -    *(Ring->Queued.TailPacket) = HeadPacket;
> -    Ring->Queued.TailPacket = TailPacket;
> +    *(Ring->Queued.TailEntry) = HeadEntry;
> +    Ring->Queued.TailEntry = TailEntry;
>      Ring->PacketsQueued += Count;

I'm confused. Why is the locked list not doubly linked?

I'll defer reviewing the rest until v2.

  Paul

>  }
> 
> @@ -2240,8 +2283,9 @@ TransmitterRingSchedule(
>      State = &Ring->State;
> 
>      for (;;) {
> -        PXENVIF_TRANSMITTER_PACKET  Packet;
> -        NTSTATUS                    status;
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +        NTSTATUS                        status;
> 
>          if (State->Count != 0) {
>              status = __TransmitterRingPostFragments(Ring);
> @@ -2290,19 +2334,20 @@ TransmitterRingSchedule(
>              continue;
>          }
> 
> -        Packet = Ring->Queued.HeadPacket;
> -
> -        if (Packet == NULL)
> +        ListEntry = Ring->Queued.HeadEntry;
> +        if (ListEntry == NULL)
>              break;
> 
> -        if (Packet->Next == NULL) {
> -            Ring->Queued.HeadPacket = NULL;
> -            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
> +        if (ListEntry->Flink == NULL) {
> +            Ring->Queued.HeadEntry = NULL;
> +            Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
>          } else {
> -            Ring->Queued.HeadPacket = Packet->Next;
> -            Packet->Next = NULL;
> +            Ring->Queued.HeadEntry = ListEntry->Flink;
> +            ListEntry->Flink = NULL;
>          }
> 
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
>          status = __TransmitterRingPreparePacket(Ring, Packet);
>          if (!NT_SUCCESS(status)) {
>              PXENVIF_TRANSMITTER Transmitter;
> @@ -2330,11 +2375,46 @@ TransmitterRingSchedule(
>          ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring-
> >PacketsGranted + Ring->PacketsFaked);
>      }
> 
> -    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring-
> >Queued.TailPacket == &Ring->Queued.HeadPacket));
> +    ASSERT(IMPLY(Ring->Queued.HeadEntry == NULL, Ring-
> >Queued.TailEntry == &Ring->Queued.HeadEntry));
> 
>      __TransmitterRingPushRequests(Ring);
>  }
> 
> +static VOID
> +TransmitterReturnPackets(
> +    IN  PXENVIF_TRANSMITTER         Transmitter,
> +    IN  PLIST_ENTRY                 List
> +    )
> +{
> +    PXENVIF_FRONTEND                Frontend;
> +    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> +
> +    HeadPacket = NULL;
> +    NextPacket = NULL;
> +    while (!IsListEmpty(List)) {
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +        ListEntry = RemoveTailList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
> +        HeadPacket = Packet->Cookie;
> +        HeadPacket->Next = NextPacket;
> +        HeadPacket->Completion = Packet->Completion;
> +
> +        __TransmitterPutPacket(Transmitter, Packet);
> +        NextPacket = HeadPacket;
> +    }
> +
> +    Frontend = Transmitter->Frontend;
> +
> +
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> +                                HeadPacket);
> +}
> +
>  static FORCEINLINE BOOLEAN
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __TransmitterRingTryAcquireLock(
> @@ -2427,16 +2507,29 @@ __TransmitterRingTryReleaseLock(
>  }
> 
>  static FORCEINLINE VOID
> +__AppendTailList(
> +    IN OUT PLIST_ENTRY              List,
> +    IN OUT PLIST_ENTRY              Apendee
> +    )
> +{
> +    PLIST_ENTRY HeadEntry = Apendee->Flink;
> +
> +    if (!IsListEmpty(Apendee)) {
> +        RemoveEntryList(Apendee);
> +        InitializeListHead(Apendee);
> +        AppendTailList(List, HeadEntry);
> +    }
> +}
> +
> +static FORCEINLINE VOID
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __TransmitterRingReleaseLock(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> -
> -    HeadPacket = NULL;
> -    TailPacket = &HeadPacket;
> +    LIST_ENTRY          List;
> +
> +    InitializeListHead(&List);
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
> 
> @@ -2449,22 +2542,11 @@ __TransmitterRingReleaseLock(
>          TransmitterRingSwizzle(Ring);
>          TransmitterRingSchedule(Ring);
> 
> -        *TailPacket = Ring->Completed.HeadPacket;
> -        TailPacket = Ring->Completed.TailPacket;
> -
> -        Ring->Completed.HeadPacket = NULL;
> -        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
> +        __AppendTailList(&List, &Ring->Completed);
>      } while (!__TransmitterRingTryReleaseLock(Ring));
> 
> -    if (HeadPacket != NULL) {
> -        PXENVIF_TRANSMITTER Transmitter;
> -        PXENVIF_FRONTEND    Frontend;
> -
> -        Transmitter = Ring->Transmitter;
> -        Frontend = Transmitter->Frontend;
> -
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                    HeadPacket);
> +    if (!IsListEmpty(&List)) {
> +        TransmitterReturnPackets(Ring->Transmitter, &List);
>      }
>  }
> 
> @@ -2624,8 +2706,8 @@ __TransmitterRingInitialize(
> 
>      (*Ring)->Transmitter = Transmitter;
>      (*Ring)->Index = Index;
> -    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
> -    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
> +    (*Ring)->Queued.TailEntry = &(*Ring)->Queued.HeadEntry;
> +    InitializeListHead(&(*Ring)->Completed);
> 
>      status = RtlStringCbPrintfA(Name,
>                                  sizeof (Name),
> @@ -2756,8 +2838,8 @@ fail3:
>  fail2:
>      Error("fail2\n");
> 
> -    (*Ring)->Queued.TailPacket = NULL;
> -    (*Ring)->Completed.TailPacket = NULL;
> +    (*Ring)->Queued.TailEntry = NULL;
> +    RtlZeroMemory(&(*Ring)->Completed, sizeof(LIST_ENTRY));
>      (*Ring)->Index = 0;
>      (*Ring)->Transmitter = NULL;
> 
> @@ -2910,7 +2992,7 @@ __TransmitterRingDisable(
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PCHAR                           Buffer;
>      XenbusState                     State;
>      ULONG                           Attempt;
> @@ -2929,14 +3011,15 @@ __TransmitterRingDisable(
> 
>      // Put any packet back on the head of the queue
>      if (Packet != NULL) {
> -        ASSERT3P(Packet->Next, ==, NULL);
> +        ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> +        ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
> 
> -        Packet->Next = Ring->Queued.HeadPacket;
> +        Packet->ListEntry.Flink = Ring->Queued.HeadEntry;
> 
> -        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
> -            Ring->Queued.TailPacket = &Packet->Next;
> +        if (Ring->Queued.TailEntry == &Ring->Queued.HeadEntry)
> +            Ring->Queued.TailEntry = &Packet->ListEntry.Flink;
> 
> -        Ring->Queued.HeadPacket = Packet;
> +        Ring->Queued.HeadEntry = &Packet->ListEntry;
>      }
> 
>      Ring->AddressIndex = 0;
> @@ -3076,11 +3159,11 @@ __TransmitterRingTeardown(
>                   Ring->BufferCache);
>      Ring->BufferCache = NULL;
> 
> -    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
> -    Ring->Queued.TailPacket = NULL;
> +    ASSERT3P(Ring->Queued.TailEntry, ==, &Ring->Queued.HeadEntry);
> +    Ring->Queued.TailEntry = NULL;
> 
> -    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;
> @@ -3092,24 +3175,40 @@ __TransmitterRingTeardown(
>  static FORCEINLINE VOID
>  __TransmitterRingQueuePackets(
>      IN  PXENVIF_TRANSMITTER_RING    Ring,
> -    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
> +    IN  PLIST_ENTRY                 List
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> +    PLIST_ENTRY                     ListEntry;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;
>      ULONG_PTR                       Old;
>      ULONG_PTR                       LockBit;
>      ULONG_PTR                       New;
> 
> -    TailPacket = &HeadPacket->Next;
> -    (VOID) __TransmitterReversePacketList(&HeadPacket);
> -    ASSERT3P(*TailPacket, ==, NULL);
> +    ListEntry = RemoveTailList(List);
> +    ASSERT3P(ListEntry, !=, List);
> +
> +    ListEntry->Flink = NULL;
> +    ListEntry->Blink = NULL;
> +    HeadEntry = ListEntry;
> +
> +    TailEntry = &ListEntry->Flink;
> +    while (!IsListEmpty(List)) {
> +        ListEntry = RemoveTailList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        ListEntry->Flink = HeadEntry;
> +        ListEntry->Blink = NULL;
> +        HeadEntry = ListEntry;
> +    }
> +    ASSERT3P(*TailEntry, ==, NULL);
> 
>      do {
>          Old = (ULONG_PTR)Ring->Lock;
>          LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
> 
> -        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> -        New = (ULONG_PTR)HeadPacket;
> +        *TailEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> +        New = (ULONG_PTR)HeadEntry;
>          ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
>          New |= LockBit;
>      } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock,
> (PVOID)New, (PVOID)Old) != Old);
> @@ -3128,33 +3227,35 @@ __TransmitterRingAbortPackets(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PLIST_ENTRY                     ListEntry;
> 
>      __TransmitterRingAcquireLock(Ring);
> 
>      TransmitterRingSwizzle(Ring);
> 
> -    Packet = Ring->Queued.HeadPacket;
> +    ListEntry = Ring->Queued.HeadEntry;
> 
> -    Ring->Queued.HeadPacket = NULL;
> -    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
> +    Ring->Queued.HeadEntry = NULL;
> +    Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
> 
> -    while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> +    while (ListEntry != NULL) {
> +        PLIST_ENTRY                     Next;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
> -        Next = Packet->Next;
> -        Packet->Next = NULL;
> +        Next = ListEntry->Flink;
> +        ListEntry->Flink = NULL;
> 
>          // Fake that we prapared and sent this packet
>          Ring->PacketsPrepared++;
>          Ring->PacketsSent++;
>          Ring->PacketsFaked++;
> 
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
>          Packet->Completion.Status =
> XENVIF_TRANSMITTER_PACKET_DROPPED;
> 
>          __TransmitterRingCompletePacket(Ring, Packet);
> 
> -        Packet = Next;
> +        ListEntry = Next;
>      }
> 
>      ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring-
> >PacketsUnprepared);
> @@ -3264,13 +3365,27 @@ TransmitterInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail3;
> 
> +    status = XENBUS_CACHE(Create,
> +                          &(*Transmitter)->CacheInterface,
> +                          "packet_cache",
> +                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
> +                          0,
> +                          TransmitterPacketCtor,
> +                          TransmitterPacketDtor,
> +                          TransmitterPacketLock,
> +                          TransmitterPacketUnlock,
> +                          *Transmitter,
> +                          &(*Transmitter)->PacketCache);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
>      Index = 0;
>      while (Index < Count) {
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
>          if (!NT_SUCCESS(status))
> -            goto fail4;
> +            goto fail5;
> 
>          InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
>          Index++;
> @@ -3278,8 +3393,8 @@ TransmitterInitialize(
> 
>      return STATUS_SUCCESS;
> 
> -fail4:
> -    Error("fail4\n");
> +fail5:
> +    Error("fail5\n");
> 
>      while (!IsListEmpty(&(*Transmitter)->List)) {
>          PLIST_ENTRY                 ListEntry;
> @@ -3297,6 +3412,14 @@ fail4:
>      }
>      ASSERT3U(Index, ==, 0);
> 
> +    XENBUS_CACHE(Destroy,
> +                 &(*Transmitter)->CacheInterface,
> +                 (*Transmitter)->PacketCache);
> +    (*Transmitter)->PacketCache = NULL;
> +
> +fail4:
> +    Error("fail4\n");
> +
>      XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
> 
>  fail3:
> @@ -3530,6 +3653,11 @@ TransmitterTeardown(
>          __TransmitterRingTeardown(Ring);
>      }
> 
> +    XENBUS_CACHE(Destroy,
> +                 &Transmitter->CacheInterface,
> +                 Transmitter->PacketCache);
> +    Transmitter->PacketCache = NULL;
> +
>      XENBUS_CACHE(Release, &Transmitter->CacheInterface);
> 
>      XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
> @@ -3620,20 +3748,77 @@ fail1:
>  }
> 
>  VOID
> -TransmitterQueuePackets(
> -    IN  PXENVIF_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
> +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;
>      PLIST_ENTRY                     ListEntry;
>      PXENVIF_TRANSMITTER_RING        Ring;
> 
> +    InitializeListHead(&List);
> +    while (HeadPacket != NULL) {
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +        Packet = __TransmitterGetPacket(Transmitter);
> +        if (Packet == NULL) {
> +            Warning("Out-of-cached-packets\n");
> +            break;
> +        }
> +
> +        Packet->Cookie = HeadPacket;
> +        RtlCopyMemory(&Packet->Send, &HeadPacket->Send, sizeof(Packet-
> >Send));
> +        RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> +
> +        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;
> +    }
> +
>      // 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);
> 
> -    __TransmitterRingQueuePackets(Ring, HeadPacket);
> +    __TransmitterRingQueuePackets(Ring, &List);
> +
> +    // if HeadPacket != NULL, errors occured and need returning
> +    if (HeadPacket != NULL) {
> +        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> +        PXENVIF_FRONTEND                Frontend;
> +
> +        Frontend = Transmitter->Frontend;
> +
> +        Packet = HeadPacket;
> +        while (Packet != NULL) {
> +            Packet->Completion.Status =
> XENVIF_TRANSMITTER_PACKET_DROPPED;
> +            Packet = Packet->Next;
> +        }
> +
> +
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> +                                    HeadPacket);
> +    }
> +
> +#undef OFFSET
> +#undef OFFSET_EXISTS
>  }
> 
>  VOID
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 5ffb590..661eeae 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -107,9 +107,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..d6da258 100644
> --- a/src/xenvif/vif.c
> +++ b/src/xenvif/vif.c
> @@ -276,8 +276,8 @@ VifReceiverReturnPackets(
> 
>  static NTSTATUS
>  VifTransmitterQueuePackets(
> -    IN  PINTERFACE                  Interface,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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);
> 
> @@ -784,8 +784,8 @@ VifReceiverQueuePackets(
> 
>  VOID
>  VifTransmitterReturnPackets(
> -    IN  PXENVIF_VIF_CONTEXT         Context,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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..0ef6687 100644
> --- a/src/xenvif/vif.h
> +++ b/src/xenvif/vif.h
> @@ -70,8 +70,8 @@ VifReceiverQueuePackets(
> 
>  extern VOID
>  VifTransmitterReturnPackets(
> -    IN  PXENVIF_VIF_CONTEXT         Context,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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 Mon Nov 17 14:22:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:22:54 +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 1XqNCg-00054e-1s; Mon, 17 Nov 2014 14:22:54 +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 1XqNCe-00054Z-LU
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:22:52 +0000
Received: from [193.109.254.147] by server-1.bemta-14.messagelabs.com id
	AB/45-02559-BB40A645; Mon, 17 Nov 2014 14:22:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-27.messagelabs.com!1416234169!13071520!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 4055 invoked from network); 17 Nov 2014 14:22:50 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-4.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:22:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26903519"
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: [PATCH 01/10] Rework transmitter packet code to use an
	internal cache of objects
Thread-Index: AQHP/pc0YPaj6+C/C0+mHHNccv7JtJxk4PGw
Date: Mon, 17 Nov 2014 14:22:48 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111536ED@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-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 01/10] Rework transmitter packet code to
 use an internal cache of objects
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 01/10] Rework transmitter packet code to use an internal
> cache of objects
> 
> Use XENVIF_TRANSMITTER_PACKET_V2 for queueing packets, with a
> translation on entry and exit through the interface (for v1)
> Renames XENVIF_TRANSMITTER_PACKET to
> XENVIF_TRANSMITTER_PACKET_V1
> XENVIF_TRANSMITTER_PACKET_V2 is allocated from a cache and not
> included inline in the miniport reserved area of a NET_BUFFER, like
> XENVIF_TRANSMITTER_PACKET_V1.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  37 ++--
>  src/xenvif/transmitter.c | 477 ++++++++++++++++++++++++++++++++-----
> ----------
>  src/xenvif/transmitter.h |   6 +-
>  src/xenvif/vif.c         |  12 +-
>  src/xenvif/vif.h         |   4 +-
>  5 files changed, 368 insertions(+), 168 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 498ed8f..8bde731 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,9 +265,24 @@ typedef struct _XENVIF_TRANSMITTER_PACKET_V1
> XENVIF_TRANSMITTER_PACKET, *PXENVIF
> 
>  C_ASSERT(sizeof (struct _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof
> (PVOID)));
> 
> +/*! \struct _XENVIF_TRANSMITTER_PACKER_V2
> +    \brief Transmit-side packet structure
> +*/
> +struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    LIST_ENTRY                                  ListEntry;
> +    PMDL                                        Mdl;
> +    ULONG                                       Offset;
> +    ULONG                                       Length;
> +    PVOID                                       Cookie;
> +    XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
> +};
> +
> +typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> +

No. The typedef should make V2 the new XENVIF_TRANSMITTER_PACKET - there should be no need for a suffix as a subscriber should only ever use the latest versions of the types anyway.

>  /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
>      \brief Offsets of packet metadata relative to
> -    XENVIF_TRANSMITTER_PACKET pointer
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer
> 
>      Because the transmit side packet structure is limited to 3 pointer
>      types in size, not all information about the packet can be passed in
> @@ -380,10 +395,10 @@ typedef VOID
>      \param ... Additional paramaters required by \a Type
> 
>      \b XENVIF_TRANSMITTER_RETURN_PACKETS:
> -    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET
> +    \param Head The head of a chain of XENVIF_TRANSMITTER_PACKET_V1

Really? How are v2 packets returned?

> 
>      \b XENVIF_RECEIVER_QUEUE_PACKETS:
> -    \param List List of XENVIF_TRANSMITTER_PACKET
> +    \param List List of XENVIF_RECEIVER_PACKET
> 
>      \b XENVIF_MAC_STATE_CHANGE:
>      No additional arguments
> @@ -459,7 +474,7 @@ typedef VOID
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
>      \brief Set byte offset of packet information relative to
> -    XENVIF_TRANSMITTER_PACKET pointer.
> +    XENVIF_TRANSMITTER_PACKET_V1 pointer.
> 
>      See \ref _XENVIF_TRANSMITTER_PACKET_OFFSET.
> 
> @@ -474,16 +489,16 @@ typedef NTSTATUS
>      IN  LONG_PTR                            Value
>      );
> 
> -/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> +/*! \typedef XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
>      \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
> +(*XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1)(
> +    IN  PINTERFACE                      Interface,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V1   Head
>      );
> 
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> @@ -694,7 +709,7 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_RECEIVER_SET_OFFLOAD_OPTIONS
> ReceiverSetOffloadOptions;
>      XENVIF_VIF_RECEIVER_QUERY_RING_SIZE             ReceiverQueryRingSize;
>      XENVIF_VIF_TRANSMITTER_SET_PACKET_OFFSET
> TransmitterSetPacketOffset;
> -    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS
> TransmitterQueuePackets;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;
>      XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
> TransmitterQueryOffloadOptions;
>      XENVIF_VIF_TRANSMITTER_QUERY_LARGE_PACKET_SIZE
> TransmitterQueryLargePacketSize;
>      XENVIF_VIF_TRANSMITTER_QUERY_RING_SIZE
> TransmitterQueryRingSize;

Where's the v2 interface?

> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 8125a5a..38e4cb2 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -88,7 +88,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_V2       Packet;
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO Send;
>      PUCHAR                              StartVa;
>      XENVIF_PACKET_INFO                  Info;
> @@ -100,8 +100,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;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;

Why do you need a tail pointer for a doubly linked list?

>  } XENVIF_TRANSMITTER_PACKET_LIST,
> *PXENVIF_TRANSMITTER_PACKET_LIST;
> 
>  typedef struct _XENVIF_TRANSMITTER_RING {
> @@ -118,7 +118,7 @@ typedef struct _XENVIF_TRANSMITTER_RING {
>      BOOLEAN                         Connected;
>      BOOLEAN                         Enabled;
>      BOOLEAN                         Stopped;
> -    PXENVIF_TRANSMITTER_PACKET      Lock;
> +    PLIST_ENTRY                     Lock;
>      PKTHREAD                        LockThread;
>      XENVIF_TRANSMITTER_PACKET_LIST  Queued;
>      XENVIF_TRANSMITTER_STATE        State;
> @@ -133,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;
> @@ -146,6 +146,7 @@ struct _XENVIF_TRANSMITTER {
>      PXENVIF_FRONTEND            Frontend;
>      XENBUS_CACHE_INTERFACE      CacheInterface;
>      XENBUS_RANGE_SET_INTERFACE  RangeSetInterface;
> +    PXENBUS_CACHE               PacketCache;
>      LIST_ENTRY                  List;
>      LONG_PTR
> Offset[XENVIF_TRANSMITTER_PACKET_OFFSET_COUNT];
>      ULONG                       DisableIpVersion4Gso;
> @@ -362,7 +363,7 @@ __TransmitterGetFragment(
>                          TRUE);
>  }
> 
> -static FORCEINLINE
> +static FORCEINLINE VOID
>  __TransmitterPutFragment(
>      IN  PXENVIF_TRANSMITTER_RING        Ring,
>      IN  PXENVIF_TRANSMITTER_FRAGMENT    Fragment
> @@ -387,6 +388,67 @@ __TransmitterPutFragment(
>                   TRUE);
>  }
> 
> +static NTSTATUS
> +TransmitterPacketCtor(
> +    IN  PVOID                       Argument,
> +    IN  PVOID                       Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    RtlZeroMemory(Object, sizeof(XENVIF_TRANSMITTER_PACKET_V2));

You should not need to zero the buffer. The object cache will zero on allocation. You should zero before calling the cache Put.

> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +TransmitterPacketDtor(
> +    IN  PVOID                       Argument,
> +    IN  PVOID                       Object
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +    UNREFERENCED_PARAMETER(Object);
> +}
> +
> +static VOID
> +TransmitterPacketLock(
> +    IN  PVOID                       Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static VOID
> +TransmitterPacketUnlock(
> +    IN  PVOID                       Argument
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Argument);
> +}
> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
> +__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_V2   Packet
> +    )
> +{
> +    XENBUS_CACHE(Put,
> +                 &Transmitter->CacheInterface,
> +                 Transmitter->PacketCache,
> +                 Packet,
> +                 TRUE);
> +}
> +
>  static VOID
>  TransmitterRingDebugCallback(
>      IN  PVOID                   Argument,
> @@ -523,25 +585,25 @@ fail1:
>      return FALSE;
>  }
> 
> -#define INCREMENT_PACKET_REFERENCE(_Packet)                         \
> -        do {                                                        \
> -            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)->Next;    \
> -                                                                    \
> -            ASSERT(Packet != NULL);                                 \
> -            (*Reference)++;                                         \
> +#define INCREMENT_PACKET_REFERENCE(_Packet)                                 \
> +        do {                                                                \
> +            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)-
> >ListEntry.Flink; \
> +                                                                            \
> +            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);                                         \
> +#define DECREMENT_PACKET_REFERENCE(_Packet)                                 \
> +        do {                                                                \
> +            PULONG_PTR Reference = (PULONG_PTR)&(_Packet)-
> >ListEntry.Flink; \
> +                                                                            \
> +            ASSERT(Packet != NULL);                                         \
> +            ASSERT(*Reference != 0);                                        \
> +            --(*Reference);                                                 \
>          } while (FALSE)
> 
> -#define PACKET_REFERENCE(_Packet)                                   \
> -        (*(PULONG_PTR)&(_Packet)->Next)
> +#define PACKET_REFERENCE(_Packet)                                           \
> +        (*(PULONG_PTR)&(_Packet)->ListEntry.Flink)
> 
>  static FORCEINLINE NTSTATUS
>  __TransmitterRingCopyPayload(
> @@ -551,7 +613,7 @@ __TransmitterRingCopyPayload(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      XENVIF_PACKET_PAYLOAD           Payload;
>      PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
>      PXENVIF_TRANSMITTER_BUFFER      Buffer;
> @@ -698,7 +760,7 @@ __TransmitterRingGrantPayload(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      PMDL                            Mdl;
>      ULONG                           Offset;
> @@ -845,7 +907,7 @@ __TransmitterRingPrepareHeader(
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_MAC                     Mac;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      PXENVIF_PACKET_INFO             Info;
>      PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> @@ -1122,7 +1184,7 @@ __TransmitterRingUnprepareFragments(
>      while (State->Count != 0) {
>          PLIST_ENTRY                     ListEntry;
>          PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> -        PXENVIF_TRANSMITTER_PACKET      Packet;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>          --State->Count;
> 
> @@ -1178,19 +1240,10 @@ __TransmitterRingUnprepareFragments(
> 
>  static FORCEINLINE NTSTATUS
>  __TransmitterRingPreparePacket(
> -    IN  PXENVIF_TRANSMITTER_RING    Ring,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Packet
> +    IN  PXENVIF_TRANSMITTER_RING        Ring,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   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;
> @@ -1198,7 +1251,7 @@ __TransmitterRingPreparePacket(
>      NTSTATUS                        status;
> 
>      ASSERT(IsZeroMemory(&Ring->State, sizeof
> (XENVIF_TRANSMITTER_STATE)));
> -    ASSERT3P(Packet->Next, ==, NULL);
> +    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> 
>      Transmitter = Ring->Transmitter;
> 
> @@ -1211,16 +1264,9 @@ __TransmitterRingPreparePacket(
> 
>      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);
> @@ -1325,18 +1371,15 @@ fail1:
>      ASSERT(IsZeroMemory(&Ring->State, sizeof
> (XENVIF_TRANSMITTER_STATE)));
> 
>      return status;
> -
> -#undef  OFFSET
> -#undef  OFFSET_EXISTS
>  }
> 
> -static FORCEINLINE PXENVIF_TRANSMITTER_PACKET
> +static FORCEINLINE PXENVIF_TRANSMITTER_PACKET_V2
>  __TransmitterRingUnpreparePacket(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>      State = &Ring->State;
>      Packet = State->Packet;
> @@ -1695,7 +1738,7 @@ __TransmitterRingPostFragments(
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
>      PXENVIF_TRANSMITTER_STATE       State;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PXENVIF_PACKET_PAYLOAD          Payload;
>      RING_IDX                        req_prod;
>      RING_IDX                        rsp_cons;
> @@ -1920,8 +1963,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_V2   Packet
>      )
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
> @@ -1980,9 +2023,9 @@ __TransmitterRingCompletePacket(
>          }
>      }
> 
> -    *Ring->Completed.TailPacket = Packet;
> -    ASSERT3P(Packet->Next, ==, NULL);
> -    Ring->Completed.TailPacket = &Packet->Next;
> +    ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> +    ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
> +    InsertTailList(&Ring->Completed, &Packet->ListEntry);
> 
>      Ring->PacketsCompleted++;
>  }
> @@ -2019,7 +2062,7 @@ TransmitterRingPoll(
>              netif_tx_response_t             *rsp;
>              uint16_t                        id;
>              PXENVIF_TRANSMITTER_FRAGMENT    Fragment;
> -            PXENVIF_TRANSMITTER_PACKET      Packet;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
>              rsp = RING_GET_RESPONSE(&Ring->Front, rsp_cons);
>              rsp_cons++;
> @@ -2164,30 +2207,30 @@ __TransmitterRingPushRequests(
> 
>  static FORCEINLINE ULONG
>  __TransmitterReversePacketList(
> -    IN  PXENVIF_TRANSMITTER_PACKET  *Packet
> +    IN  PLIST_ENTRY                 *Entry
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> +    PLIST_ENTRY                     HeadEntry;
>      ULONG                           Count;
> 
> -    HeadPacket = NULL;
> +    HeadEntry = NULL;
>      Count = 0;
> 
> -    while (*Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> +    while (*Entry != NULL) {
> +        PLIST_ENTRY     Next;
> 
> -        ASSERT(((ULONG_PTR)*Packet & XENVIF_TRANSMITTER_LOCK_BIT) ==
> 0);
> +        ASSERT(((ULONG_PTR)*Entry & XENVIF_TRANSMITTER_LOCK_BIT) ==
> 0);
> 
> -        Next = (*Packet)->Next;
> +        Next = (*Entry)->Flink;
> 
> -        (*Packet)->Next = HeadPacket;
> -        HeadPacket = *Packet;
> +        (*Entry)->Flink = HeadEntry;
> +        HeadEntry = *Entry;
> 
> -        *Packet = Next;
> +        *Entry = Next;
>          Count++;
>      }
> 
> -    *Packet = HeadPacket;
> +    *Entry = HeadEntry;

Are packets singly linked or doubly linked on the way into this function?

> 
>      return Count;
>  }
> @@ -2199,8 +2242,8 @@ TransmitterRingSwizzle(
>  {
>      ULONG_PTR                       Old;
>      ULONG_PTR                       New;
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;
>      ULONG                           Count;
> 
>      ASSERT3P(Ring->LockThread, ==, KeGetCurrentThread());
> @@ -2209,21 +2252,21 @@ TransmitterRingSwizzle(
>      Old = (ULONG_PTR)InterlockedExchangePointer(&Ring->Lock,
> (PVOID)New);
> 
>      ASSERT(Old & XENVIF_TRANSMITTER_LOCK_BIT);
> -    HeadPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> +    HeadEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> 
> -    if (HeadPacket == NULL)
> +    if (HeadEntry == 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);
> +    TailEntry = &HeadEntry->Flink;
> +    Count = __TransmitterReversePacketList(&HeadEntry);
> +    ASSERT3P(*TailEntry, ==, NULL);
> 
> -    *(Ring->Queued.TailPacket) = HeadPacket;
> -    Ring->Queued.TailPacket = TailPacket;
> +    *(Ring->Queued.TailEntry) = HeadEntry;
> +    Ring->Queued.TailEntry = TailEntry;
>      Ring->PacketsQueued += Count;

I'm confused. Why is the locked list not doubly linked?

I'll defer reviewing the rest until v2.

  Paul

>  }
> 
> @@ -2240,8 +2283,9 @@ TransmitterRingSchedule(
>      State = &Ring->State;
> 
>      for (;;) {
> -        PXENVIF_TRANSMITTER_PACKET  Packet;
> -        NTSTATUS                    status;
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +        NTSTATUS                        status;
> 
>          if (State->Count != 0) {
>              status = __TransmitterRingPostFragments(Ring);
> @@ -2290,19 +2334,20 @@ TransmitterRingSchedule(
>              continue;
>          }
> 
> -        Packet = Ring->Queued.HeadPacket;
> -
> -        if (Packet == NULL)
> +        ListEntry = Ring->Queued.HeadEntry;
> +        if (ListEntry == NULL)
>              break;
> 
> -        if (Packet->Next == NULL) {
> -            Ring->Queued.HeadPacket = NULL;
> -            Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
> +        if (ListEntry->Flink == NULL) {
> +            Ring->Queued.HeadEntry = NULL;
> +            Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
>          } else {
> -            Ring->Queued.HeadPacket = Packet->Next;
> -            Packet->Next = NULL;
> +            Ring->Queued.HeadEntry = ListEntry->Flink;
> +            ListEntry->Flink = NULL;
>          }
> 
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
>          status = __TransmitterRingPreparePacket(Ring, Packet);
>          if (!NT_SUCCESS(status)) {
>              PXENVIF_TRANSMITTER Transmitter;
> @@ -2330,11 +2375,46 @@ TransmitterRingSchedule(
>          ASSERT3U(Ring->PacketsPrepared, ==, Ring->PacketsCopied + Ring-
> >PacketsGranted + Ring->PacketsFaked);
>      }
> 
> -    ASSERT(IMPLY(Ring->Queued.HeadPacket == NULL, Ring-
> >Queued.TailPacket == &Ring->Queued.HeadPacket));
> +    ASSERT(IMPLY(Ring->Queued.HeadEntry == NULL, Ring-
> >Queued.TailEntry == &Ring->Queued.HeadEntry));
> 
>      __TransmitterRingPushRequests(Ring);
>  }
> 
> +static VOID
> +TransmitterReturnPackets(
> +    IN  PXENVIF_TRANSMITTER         Transmitter,
> +    IN  PLIST_ENTRY                 List
> +    )
> +{
> +    PXENVIF_FRONTEND                Frontend;
> +    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> +
> +    HeadPacket = NULL;
> +    NextPacket = NULL;
> +    while (!IsListEmpty(List)) {
> +        PLIST_ENTRY                     ListEntry;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +        ListEntry = RemoveTailList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +
> +        HeadPacket = Packet->Cookie;
> +        HeadPacket->Next = NextPacket;
> +        HeadPacket->Completion = Packet->Completion;
> +
> +        __TransmitterPutPacket(Transmitter, Packet);
> +        NextPacket = HeadPacket;
> +    }
> +
> +    Frontend = Transmitter->Frontend;
> +
> +
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> +                                HeadPacket);
> +}
> +
>  static FORCEINLINE BOOLEAN
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __TransmitterRingTryAcquireLock(
> @@ -2427,16 +2507,29 @@ __TransmitterRingTryReleaseLock(
>  }
> 
>  static FORCEINLINE VOID
> +__AppendTailList(
> +    IN OUT PLIST_ENTRY              List,
> +    IN OUT PLIST_ENTRY              Apendee
> +    )
> +{
> +    PLIST_ENTRY HeadEntry = Apendee->Flink;
> +
> +    if (!IsListEmpty(Apendee)) {
> +        RemoveEntryList(Apendee);
> +        InitializeListHead(Apendee);
> +        AppendTailList(List, HeadEntry);
> +    }
> +}
> +
> +static FORCEINLINE VOID
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __TransmitterRingReleaseLock(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> -
> -    HeadPacket = NULL;
> -    TailPacket = &HeadPacket;
> +    LIST_ENTRY          List;
> +
> +    InitializeListHead(&List);
> 
>      ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
> 
> @@ -2449,22 +2542,11 @@ __TransmitterRingReleaseLock(
>          TransmitterRingSwizzle(Ring);
>          TransmitterRingSchedule(Ring);
> 
> -        *TailPacket = Ring->Completed.HeadPacket;
> -        TailPacket = Ring->Completed.TailPacket;
> -
> -        Ring->Completed.HeadPacket = NULL;
> -        Ring->Completed.TailPacket = &Ring->Completed.HeadPacket;
> +        __AppendTailList(&List, &Ring->Completed);
>      } while (!__TransmitterRingTryReleaseLock(Ring));
> 
> -    if (HeadPacket != NULL) {
> -        PXENVIF_TRANSMITTER Transmitter;
> -        PXENVIF_FRONTEND    Frontend;
> -
> -        Transmitter = Ring->Transmitter;
> -        Frontend = Transmitter->Frontend;
> -
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                    HeadPacket);
> +    if (!IsListEmpty(&List)) {
> +        TransmitterReturnPackets(Ring->Transmitter, &List);
>      }
>  }
> 
> @@ -2624,8 +2706,8 @@ __TransmitterRingInitialize(
> 
>      (*Ring)->Transmitter = Transmitter;
>      (*Ring)->Index = Index;
> -    (*Ring)->Queued.TailPacket = &(*Ring)->Queued.HeadPacket;
> -    (*Ring)->Completed.TailPacket = &(*Ring)->Completed.HeadPacket;
> +    (*Ring)->Queued.TailEntry = &(*Ring)->Queued.HeadEntry;
> +    InitializeListHead(&(*Ring)->Completed);
> 
>      status = RtlStringCbPrintfA(Name,
>                                  sizeof (Name),
> @@ -2756,8 +2838,8 @@ fail3:
>  fail2:
>      Error("fail2\n");
> 
> -    (*Ring)->Queued.TailPacket = NULL;
> -    (*Ring)->Completed.TailPacket = NULL;
> +    (*Ring)->Queued.TailEntry = NULL;
> +    RtlZeroMemory(&(*Ring)->Completed, sizeof(LIST_ENTRY));
>      (*Ring)->Index = 0;
>      (*Ring)->Transmitter = NULL;
> 
> @@ -2910,7 +2992,7 @@ __TransmitterRingDisable(
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PXENVIF_TRANSMITTER_PACKET_V2   Packet;
>      PCHAR                           Buffer;
>      XenbusState                     State;
>      ULONG                           Attempt;
> @@ -2929,14 +3011,15 @@ __TransmitterRingDisable(
> 
>      // Put any packet back on the head of the queue
>      if (Packet != NULL) {
> -        ASSERT3P(Packet->Next, ==, NULL);
> +        ASSERT3P(Packet->ListEntry.Flink, ==, NULL);
> +        ASSERT3P(Packet->ListEntry.Blink, ==, NULL);
> 
> -        Packet->Next = Ring->Queued.HeadPacket;
> +        Packet->ListEntry.Flink = Ring->Queued.HeadEntry;
> 
> -        if (Ring->Queued.TailPacket == &Ring->Queued.HeadPacket)
> -            Ring->Queued.TailPacket = &Packet->Next;
> +        if (Ring->Queued.TailEntry == &Ring->Queued.HeadEntry)
> +            Ring->Queued.TailEntry = &Packet->ListEntry.Flink;
> 
> -        Ring->Queued.HeadPacket = Packet;
> +        Ring->Queued.HeadEntry = &Packet->ListEntry;
>      }
> 
>      Ring->AddressIndex = 0;
> @@ -3076,11 +3159,11 @@ __TransmitterRingTeardown(
>                   Ring->BufferCache);
>      Ring->BufferCache = NULL;
> 
> -    ASSERT3P(Ring->Queued.TailPacket, ==, &Ring->Queued.HeadPacket);
> -    Ring->Queued.TailPacket = NULL;
> +    ASSERT3P(Ring->Queued.TailEntry, ==, &Ring->Queued.HeadEntry);
> +    Ring->Queued.TailEntry = NULL;
> 
> -    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;
> @@ -3092,24 +3175,40 @@ __TransmitterRingTeardown(
>  static FORCEINLINE VOID
>  __TransmitterRingQueuePackets(
>      IN  PXENVIF_TRANSMITTER_RING    Ring,
> -    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
> +    IN  PLIST_ENTRY                 List
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      *TailPacket;
> +    PLIST_ENTRY                     ListEntry;
> +    PLIST_ENTRY                     HeadEntry;
> +    PLIST_ENTRY                     *TailEntry;
>      ULONG_PTR                       Old;
>      ULONG_PTR                       LockBit;
>      ULONG_PTR                       New;
> 
> -    TailPacket = &HeadPacket->Next;
> -    (VOID) __TransmitterReversePacketList(&HeadPacket);
> -    ASSERT3P(*TailPacket, ==, NULL);
> +    ListEntry = RemoveTailList(List);
> +    ASSERT3P(ListEntry, !=, List);
> +
> +    ListEntry->Flink = NULL;
> +    ListEntry->Blink = NULL;
> +    HeadEntry = ListEntry;
> +
> +    TailEntry = &ListEntry->Flink;
> +    while (!IsListEmpty(List)) {
> +        ListEntry = RemoveTailList(List);
> +        ASSERT3P(ListEntry, !=, List);
> +
> +        ListEntry->Flink = HeadEntry;
> +        ListEntry->Blink = NULL;
> +        HeadEntry = ListEntry;
> +    }
> +    ASSERT3P(*TailEntry, ==, NULL);
> 
>      do {
>          Old = (ULONG_PTR)Ring->Lock;
>          LockBit = Old & XENVIF_TRANSMITTER_LOCK_BIT;
> 
> -        *TailPacket = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> -        New = (ULONG_PTR)HeadPacket;
> +        *TailEntry = (PVOID)(Old & ~XENVIF_TRANSMITTER_LOCK_BIT);
> +        New = (ULONG_PTR)HeadEntry;
>          ASSERT((New & XENVIF_TRANSMITTER_LOCK_BIT) == 0);
>          New |= LockBit;
>      } while ((ULONG_PTR)InterlockedCompareExchangePointer(&Ring->Lock,
> (PVOID)New, (PVOID)Old) != Old);
> @@ -3128,33 +3227,35 @@ __TransmitterRingAbortPackets(
>      IN  PXENVIF_TRANSMITTER_RING    Ring
>      )
>  {
> -    PXENVIF_TRANSMITTER_PACKET      Packet;
> +    PLIST_ENTRY                     ListEntry;
> 
>      __TransmitterRingAcquireLock(Ring);
> 
>      TransmitterRingSwizzle(Ring);
> 
> -    Packet = Ring->Queued.HeadPacket;
> +    ListEntry = Ring->Queued.HeadEntry;
> 
> -    Ring->Queued.HeadPacket = NULL;
> -    Ring->Queued.TailPacket = &Ring->Queued.HeadPacket;
> +    Ring->Queued.HeadEntry = NULL;
> +    Ring->Queued.TailEntry = &Ring->Queued.HeadEntry;
> 
> -    while (Packet != NULL) {
> -        PXENVIF_TRANSMITTER_PACKET  Next;
> +    while (ListEntry != NULL) {
> +        PLIST_ENTRY                     Next;
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
> -        Next = Packet->Next;
> -        Packet->Next = NULL;
> +        Next = ListEntry->Flink;
> +        ListEntry->Flink = NULL;
> 
>          // Fake that we prapared and sent this packet
>          Ring->PacketsPrepared++;
>          Ring->PacketsSent++;
>          Ring->PacketsFaked++;
> 
> +        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
>          Packet->Completion.Status =
> XENVIF_TRANSMITTER_PACKET_DROPPED;
> 
>          __TransmitterRingCompletePacket(Ring, Packet);
> 
> -        Packet = Next;
> +        ListEntry = Next;
>      }
> 
>      ASSERT3U(Ring->PacketsSent, ==, Ring->PacketsPrepared - Ring-
> >PacketsUnprepared);
> @@ -3264,13 +3365,27 @@ TransmitterInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail3;
> 
> +    status = XENBUS_CACHE(Create,
> +                          &(*Transmitter)->CacheInterface,
> +                          "packet_cache",
> +                          sizeof(XENVIF_TRANSMITTER_PACKET_V2),
> +                          0,
> +                          TransmitterPacketCtor,
> +                          TransmitterPacketDtor,
> +                          TransmitterPacketLock,
> +                          TransmitterPacketUnlock,
> +                          *Transmitter,
> +                          &(*Transmitter)->PacketCache);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
>      Index = 0;
>      while (Index < Count) {
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
>          if (!NT_SUCCESS(status))
> -            goto fail4;
> +            goto fail5;
> 
>          InsertTailList(&(*Transmitter)->List, &Ring->ListEntry);
>          Index++;
> @@ -3278,8 +3393,8 @@ TransmitterInitialize(
> 
>      return STATUS_SUCCESS;
> 
> -fail4:
> -    Error("fail4\n");
> +fail5:
> +    Error("fail5\n");
> 
>      while (!IsListEmpty(&(*Transmitter)->List)) {
>          PLIST_ENTRY                 ListEntry;
> @@ -3297,6 +3412,14 @@ fail4:
>      }
>      ASSERT3U(Index, ==, 0);
> 
> +    XENBUS_CACHE(Destroy,
> +                 &(*Transmitter)->CacheInterface,
> +                 (*Transmitter)->PacketCache);
> +    (*Transmitter)->PacketCache = NULL;
> +
> +fail4:
> +    Error("fail4\n");
> +
>      XENBUS_CACHE(Release, &(*Transmitter)->CacheInterface);
> 
>  fail3:
> @@ -3530,6 +3653,11 @@ TransmitterTeardown(
>          __TransmitterRingTeardown(Ring);
>      }
> 
> +    XENBUS_CACHE(Destroy,
> +                 &Transmitter->CacheInterface,
> +                 Transmitter->PacketCache);
> +    Transmitter->PacketCache = NULL;
> +
>      XENBUS_CACHE(Release, &Transmitter->CacheInterface);
> 
>      XENBUS_RANGE_SET(Release, &Transmitter->RangeSetInterface);
> @@ -3620,20 +3748,77 @@ fail1:
>  }
> 
>  VOID
> -TransmitterQueuePackets(
> -    IN  PXENVIF_TRANSMITTER         Transmitter,
> -    IN  PXENVIF_TRANSMITTER_PACKET  HeadPacket
> +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;
>      PLIST_ENTRY                     ListEntry;
>      PXENVIF_TRANSMITTER_RING        Ring;
> 
> +    InitializeListHead(&List);
> +    while (HeadPacket != NULL) {
> +        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +
> +        Packet = __TransmitterGetPacket(Transmitter);
> +        if (Packet == NULL) {
> +            Warning("Out-of-cached-packets\n");
> +            break;
> +        }
> +
> +        Packet->Cookie = HeadPacket;
> +        RtlCopyMemory(&Packet->Send, &HeadPacket->Send, sizeof(Packet-
> >Send));
> +        RtlZeroMemory(&Packet->Completion, sizeof(Packet->Completion));
> +
> +        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;
> +    }
> +
>      // 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);
> 
> -    __TransmitterRingQueuePackets(Ring, HeadPacket);
> +    __TransmitterRingQueuePackets(Ring, &List);
> +
> +    // if HeadPacket != NULL, errors occured and need returning
> +    if (HeadPacket != NULL) {
> +        PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> +        PXENVIF_FRONTEND                Frontend;
> +
> +        Frontend = Transmitter->Frontend;
> +
> +        Packet = HeadPacket;
> +        while (Packet != NULL) {
> +            Packet->Completion.Status =
> XENVIF_TRANSMITTER_PACKET_DROPPED;
> +            Packet = Packet->Next;
> +        }
> +
> +
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> +                                    HeadPacket);
> +    }
> +
> +#undef OFFSET
> +#undef OFFSET_EXISTS
>  }
> 
>  VOID
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 5ffb590..661eeae 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -107,9 +107,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..d6da258 100644
> --- a/src/xenvif/vif.c
> +++ b/src/xenvif/vif.c
> @@ -276,8 +276,8 @@ VifReceiverReturnPackets(
> 
>  static NTSTATUS
>  VifTransmitterQueuePackets(
> -    IN  PINTERFACE                  Interface,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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);
> 
> @@ -784,8 +784,8 @@ VifReceiverQueuePackets(
> 
>  VOID
>  VifTransmitterReturnPackets(
> -    IN  PXENVIF_VIF_CONTEXT         Context,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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..0ef6687 100644
> --- a/src/xenvif/vif.h
> +++ b/src/xenvif/vif.h
> @@ -70,8 +70,8 @@ VifReceiverQueuePackets(
> 
>  extern VOID
>  VifTransmitterReturnPackets(
> -    IN  PXENVIF_VIF_CONTEXT         Context,
> -    IN  PXENVIF_TRANSMITTER_PACKET  Head
> +    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 Mon Nov 17 14:32:29 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:32:29 +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 1XqNLx-0005Dk-5t; Mon, 17 Nov 2014 14:32:29 +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 1XqNLv-0005Da-Aw
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:32:27 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	B3/3B-25714-AF60A645; Mon, 17 Nov 2014 14:32:26 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-206.messagelabs.com!1416234745!11781069!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12894 invoked from network); 17 Nov 2014 14:32:25 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:32:25 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26903913"
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: [PATCH 02/10] Add VIF interface version 2
Thread-Index: AQHP/pc0aR4tWkdAsE+ZD1zTSoaMv5xk5vzw
Date: Mon, 17 Nov 2014 14:32:23 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115370D@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-3-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-3-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 02/10] Add VIF interface version 2
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 02/10] Add VIF interface version 2
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  84 ++++++++++++++++++++++--
>  src/xenvif/transmitter.c | 164
> ++++++++++++++++++++++++++++++++++++++++-------
>  src/xenvif/transmitter.h |  17 +++++
>  src/xenvif/vif.c         | 145
> +++++++++++++++++++++++++++++++++++++++--
>  src/xenvif/vif.h         |  11 ++++
>  5 files changed, 386 insertions(+), 35 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 8bde731..4ce61c4 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -116,6 +116,7 @@ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
>      };
>  };
> 
> +

Needless whitespace change.

>  typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> XENVIF_PACKET_CHECKSUM_FLAGS,
> *PXENVIF_PACKET_CHECKSUM_FLAGS;
> 
>  #pragma warning(pop)
> @@ -269,17 +270,25 @@ C_ASSERT(sizeof (struct
> _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
>      \brief Transmit-side packet structure
>  */
>  struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    /*! List entry used for chaining packets together */
>      LIST_ENTRY                                  ListEntry;
> +    /*! MDL referencing the packet's buffer */
>      PMDL                                        Mdl;
> +    /*! Offset of start of packet in MDL */
>      ULONG                                       Offset;
> +    /*! Total length of packet */
>      ULONG                                       Length;
> +    /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    /*! Information passed up from subscriber for packet completion */
>      XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
>  };
> 
>  typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> 
> +

Another needless whitespace change.

>  /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
>      \brief Offsets of packet metadata relative to
>      XENVIF_TRANSMITTER_PACKET_V1 pointer
> @@ -501,6 +510,34 @@ typedef NTSTATUS
>      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_GET_PACKET_HEADERS
> +    \brief Get a copy of the packet headers and each the offset of each
> +
> +    \param Interface The interface header
> +*/
> +typedef NTSTATUS
> +(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
>      \brief Query the available set of transmit side offload options
> 
> @@ -694,10 +731,6 @@ typedef NTSTATUS
>  DEFINE_GUID(GUID_XENVIF_VIF_INTERFACE,
>  0x76f279cd, 0xca11, 0x418b, 0x92, 0xe8, 0xc5, 0x7f, 0x77, 0xde, 0xe, 0x2e);
> 
> -/*! \struct _XENVIF_VIF_INTERFACE_V1
> -    \brief VIF interface version 1
> -    \ingroup interfaces
> -*/
>  struct _XENVIF_VIF_INTERFACE_V1 {
>      INTERFACE                                       Interface;
>      XENVIF_VIF_ACQUIRE                              Acquire;
> @@ -723,17 +756,54 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
>  };
> 
> -typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE_V1,
> *PXENVIF_VIF_INTERFACE_V1;
> +
> +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_SET_PACKET_OFFSET
> TransmitterSetPacketOffset; // obsolete
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;    // obsolete

You should never need to include obsolete fields in a new version of the interface.

> +    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;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
> TransmitterQueuePacketsV2;

No V2 suffix required.

> +    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
> TransmitterGetPacketHeaders;
> +};
> +
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2,
> *PXENVIF_VIF_INTERFACE_V2;
> +

No. 

> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> 
>  /*! \def XENVIF_VIF
> -    \brief Macro at assist in method invocation
> +    \brief Macro to assist in method invocation

Whitespace change?

>  */
>  #define XENVIF_VIF(_Method, _Interface, ...)    \
>      (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
> 
> +/*! \def XENVIF_VIF_VERSION
> +    \brief Macro to assist in getting interface version in use
> +*/
> +#define XENVIF_VIF_VERSION(_Interface)          \
> +    ((_Interface)->Interface.Version)
> +

Should not be needed. The subscriber should know!

>  #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

All the above should be in patch #1.

> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 38e4cb2..6fd542e 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2386,33 +2386,44 @@ TransmitterReturnPackets(
>      IN  PLIST_ENTRY                 List
>      )
>  {
> -    PXENVIF_FRONTEND                Frontend;
> -    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> +    PXENVIF_VIF_CONTEXT             Context;
> +
> +    Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
> 
> -    HeadPacket = NULL;
> -    NextPacket = NULL;
> -    while (!IsListEmpty(List)) {
> -        PLIST_ENTRY                     ListEntry;
> -        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +    switch (VifGetVersion(Context)) {
> +    case 1: {
> +        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> 
> -        ListEntry = RemoveTailList(List);
> -        ASSERT3P(ListEntry, !=, List);
> +        HeadPacket = NULL;
> +        NextPacket = NULL;
> +        while (!IsListEmpty(List)) {
> +            PLIST_ENTRY                     ListEntry;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
> -        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +            ListEntry = RemoveTailList(List);
> +            ASSERT3P(ListEntry, !=, List);
> 
> -        HeadPacket = Packet->Cookie;
> -        HeadPacket->Next = NextPacket;
> -        HeadPacket->Completion = Packet->Completion;
> +            Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> 
> -        __TransmitterPutPacket(Transmitter, Packet);
> -        NextPacket = HeadPacket;
> -    }
> +            HeadPacket = Packet->Cookie;
> +            HeadPacket->Next = NextPacket;
> +            HeadPacket->Completion = Packet->Completion;
> 
> -    Frontend = Transmitter->Frontend;
> +            __TransmitterPutPacket(Transmitter, Packet);
> +            NextPacket = HeadPacket;
> +        }
> 
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                HeadPacket);
> +        VifTransmitterReturnPackets(Context, HeadPacket);
> +        break;
> +    }
> +    case 2:
> +        VifTransmitterReturnPacketsV2(Context, List);
> +        break;
> +    default:
> +        ASSERT(FALSE);
> +        break;
> +    }
>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -3803,9 +3814,9 @@ TransmitterQueuePacketsV1(
>      // if HeadPacket != NULL, errors occured and need returning
>      if (HeadPacket != NULL) {
>          PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> -        PXENVIF_FRONTEND                Frontend;
> +        PXENVIF_VIF_CONTEXT             Context;
> 
> -        Frontend = Transmitter->Frontend;
> +        Context = PdoGetVifContext(FrontendGetPdo(Transmitter-
> >Frontend));
> 
>          Packet = HeadPacket;
>          while (Packet != NULL) {
> @@ -3813,8 +3824,7 @@ TransmitterQueuePacketsV1(
>              Packet = Packet->Next;
>          }
> 
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                    HeadPacket);
> +        VifTransmitterReturnPackets(Context, HeadPacket);
>      }
> 
>  #undef OFFSET
> @@ -3822,6 +3832,112 @@ TransmitterQueuePacketsV1(
>  }
> 
>  VOID
> +TransmitterQueuePacketsV2(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PLIST_ENTRY         List
> +    )
> +{
> +    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);
> +
> +    __TransmitterRingQueuePackets(Ring, List);
> +}
> +
> +static BOOLEAN
> +TransmitterHeaderPullup(
> +    IN  PVOID                   Argument,
> +    IN  PUCHAR                  DestinationVa,
> +    IN  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  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    )
> +{
> +    XENVIF_PACKET_PAYLOAD   Payload;
> +    NTSTATUS                status;
> +
> +    UNREFERENCED_PARAMETER(Transmitter);
> +
> +    Payload.Mdl = Mdl;
> +    Payload.Offset = Offset;
> +    Payload.Length = Length;
> +
> +    status = ParsePacket(HeaderBuffer,
> +                         TransmitterHeaderPullup,
> +                         &HeaderLength,
> +                         &Payload,
> +                         Info);
> +    return status;
> +}
> +
> +VOID
>  TransmitterAbortPackets(
>      IN  PXENVIF_TRANSMITTER Transmitter
>      )
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 661eeae..c359c20 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -113,6 +113,23 @@ TransmitterQueuePacketsV1(
>      );
> 
>  extern VOID
> +TransmitterQueuePacketsV2(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PLIST_ENTRY         List
> +    );
> +
> +extern NTSTATUS
> +TransmitterGetPacketHeaders(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
> +extern VOID
>  TransmitterQueryOffloadOptions(
>      IN  PXENVIF_TRANSMITTER         Transmitter,
>      OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
> diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
> index d6da258..8c1156a 100644
> --- a/src/xenvif/vif.c
> +++ b/src/xenvif/vif.c
> @@ -46,6 +46,7 @@ struct _XENVIF_VIF_CONTEXT {
>      PXENVIF_PDO                 Pdo;
>      XENVIF_MRSW_LOCK            Lock;
>      LONG                        References;
> +    ULONG                       Version;
>      PXENVIF_FRONTEND            Frontend;
>      BOOLEAN                     Enabled;
>      XENVIF_VIF_CALLBACK         Callback;
> @@ -302,6 +303,75 @@ fail1:
>      return status;
>  }
> 
> +static NTSTATUS
> +VifTransmitterQueuePacketsV2(

No V2 suffix. Only V1 functions should be suffixed and then the function names should use a 'Version1' suffix.

> +    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;
> +
> +    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context-
> >Frontend),
> +                              List);
> +
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return status;
> +}
> +
> +static NTSTATUS
> +VifTransmitterGetPacketHeaders(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    )
> +{
> +    PXENVIF_VIF_CONTEXT Context = Interface->Context;
> +    NTSTATUS            status;
> +
> +    AcquireMrswLockShared(&Context->Lock);
> +
> +    status = STATUS_UNSUCCESSFUL;
> +    if (Context->Enabled == FALSE)
> +        goto fail1;
> +
> +    status =
> TransmitterGetPacketHeaders(FrontendGetTransmitter(Context-
> >Frontend),
> +                                         Mdl,
> +                                         Offset,
> +                                         Length,
> +                                         HeaderBuffer,
> +                                         HeaderLength,
> +                                         Info);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +fail1:
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return status;
> +}
> +
>  static VOID
>  VifTransmitterQueryOffloadOptions(
>      IN  PINTERFACE                  Interface,
> @@ -560,7 +630,9 @@ VifAcquire(
>      if (Context->References++ != 0)
>          goto done;
> 
> -    Trace("====>\n");
> +    Trace("====> (%u)\n", Interface->Version);
> +
> +    Context->Version = Interface->Version;
> 
>      status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
>      if (!NT_SUCCESS(status))
> @@ -577,7 +649,7 @@ VifAcquire(
> 
>      Context->Frontend = PdoGetFrontend(Context->Pdo);
> 
> -    Trace("<====\n");
> +    Trace("<==== (%u)\n", Interface->Version);
> 
>  done:
>      ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
> @@ -612,7 +684,7 @@ VifRelease(
>      if (--Context->References > 0)
>          goto done;
> 
> -    Trace("====>\n");
> +    Trace("====> (%u)\n", Interface->Version);
> 
>      ASSERT(!Context->Enabled);
> 
> @@ -625,7 +697,9 @@ VifRelease(
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Trace("<====\n");
> +    Context->Version = 0;
> +
> +    Trace("<==== (%u)\n", Interface->Version);
> 
>  done:
>      ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
> @@ -656,6 +730,33 @@ 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,
> +    VifTransmitterSetPacketOffset,
> +    VifTransmitterQueuePackets,
> +    VifTransmitterQueryOffloadOptions,
> +    VifTransmitterQueryLargePacketSize,
> +    VifTransmitterQueryRingSize,
> +    VifMacQueryState,
> +    VifMacQueryMaximumFrameSize,
> +    VifMacQueryPermanentAddress,
> +    VifMacQueryCurrentAddress,
> +    VifMacQueryMulticastAddresses,
> +    VifMacSetMulticastAddresses,
> +    VifMacSetFilterLevel,
> +    VifMacQueryFilterLevel,
> +    VifTransmitterQueuePacketsV2,
> +    VifTransmitterGetPacketHeaders
> +};
> +
>  NTSTATUS
>  VifInitialize(
>      IN  PXENVIF_PDO         Pdo,
> @@ -737,6 +838,23 @@ 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;
> @@ -793,6 +911,25 @@ VifTransmitterReturnPackets(
>                        Head);
>  }
> 
> +VOID
> +VifTransmitterReturnPacketsV2(
> +    IN  PXENVIF_VIF_CONTEXT Context,
> +    IN  PLIST_ENTRY         List
> +    )
> +{
> +    Context->Callback(Context->Argument,
> +                      XENVIF_TRANSMITTER_RETURN_PACKETS,
> +                      List);
> +}
> +
> +ULONG
> +VifGetVersion(
> +    IN  PXENVIF_VIF_CONTEXT Context
> +    )
> +{
> +    return Context->Version;
> +}
> +
>  extern PXENVIF_THREAD
>  VifGetMacThread(
>      IN  PXENVIF_VIF_CONTEXT Context
> diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
> index 0ef6687..fe0f9e4 100644
> --- a/src/xenvif/vif.h
> +++ b/src/xenvif/vif.h
> @@ -74,10 +74,21 @@ VifTransmitterReturnPackets(
>      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 Mon Nov 17 14:32:29 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:32:29 +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 1XqNLx-0005Dk-5t; Mon, 17 Nov 2014 14:32:29 +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 1XqNLv-0005Da-Aw
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:32:27 +0000
Received: from [85.158.139.211] by server-12.bemta-5.messagelabs.com id
	B3/3B-25714-AF60A645; Mon, 17 Nov 2014 14:32:26 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-206.messagelabs.com!1416234745!11781069!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 12894 invoked from network); 17 Nov 2014 14:32:25 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:32:25 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26903913"
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: [PATCH 02/10] Add VIF interface version 2
Thread-Index: AQHP/pc0aR4tWkdAsE+ZD1zTSoaMv5xk5vzw
Date: Mon, 17 Nov 2014 14:32:23 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD01115370D@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-3-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-3-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 02/10] Add VIF interface version 2
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 02/10] Add VIF interface version 2
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  include/vif_interface.h  |  84 ++++++++++++++++++++++--
>  src/xenvif/transmitter.c | 164
> ++++++++++++++++++++++++++++++++++++++++-------
>  src/xenvif/transmitter.h |  17 +++++
>  src/xenvif/vif.c         | 145
> +++++++++++++++++++++++++++++++++++++++--
>  src/xenvif/vif.h         |  11 ++++
>  5 files changed, 386 insertions(+), 35 deletions(-)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 8bde731..4ce61c4 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -116,6 +116,7 @@ struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1 {
>      };
>  };
> 
> +

Needless whitespace change.

>  typedef struct _XENVIF_PACKET_CHECKSUM_FLAGS_V1
> XENVIF_PACKET_CHECKSUM_FLAGS,
> *PXENVIF_PACKET_CHECKSUM_FLAGS;
> 
>  #pragma warning(pop)
> @@ -269,17 +270,25 @@ C_ASSERT(sizeof (struct
> _XENVIF_TRANSMITTER_PACKET_V1) <= (3 * sizeof (PVOID)));
>      \brief Transmit-side packet structure
>  */
>  struct _XENVIF_TRANSMITTER_PACKET_V2 {
> +    /*! List entry used for chaining packets together */
>      LIST_ENTRY                                  ListEntry;
> +    /*! MDL referencing the packet's buffer */
>      PMDL                                        Mdl;
> +    /*! Offset of start of packet in MDL */
>      ULONG                                       Offset;
> +    /*! Total length of packet */
>      ULONG                                       Length;
> +    /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
> +    /*! Information passed up from subscriber for packet completion */
>      XENVIF_TRANSMITTER_PACKET_COMPLETION_INFO   Completion;
>  };
> 
>  typedef struct _XENVIF_TRANSMITTER_PACKET_V2
> XENVIF_TRANSMITTER_PACKET_V2, *PXENVIF_TRANSMITTER_PACKET_V2;
> 
> +

Another needless whitespace change.

>  /*! \enum _XENVIF_TRANSMITTER_PACKET_OFFSET
>      \brief Offsets of packet metadata relative to
>      XENVIF_TRANSMITTER_PACKET_V1 pointer
> @@ -501,6 +510,34 @@ typedef NTSTATUS
>      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_GET_PACKET_HEADERS
> +    \brief Get a copy of the packet headers and each the offset of each
> +
> +    \param Interface The interface header
> +*/
> +typedef NTSTATUS
> +(*XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS)(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
>  /*! \typedef XENVIF_VIF_TRANSMITTER_QUERY_OFFLOAD_OPTIONS
>      \brief Query the available set of transmit side offload options
> 
> @@ -694,10 +731,6 @@ typedef NTSTATUS
>  DEFINE_GUID(GUID_XENVIF_VIF_INTERFACE,
>  0x76f279cd, 0xca11, 0x418b, 0x92, 0xe8, 0xc5, 0x7f, 0x77, 0xde, 0xe, 0x2e);
> 
> -/*! \struct _XENVIF_VIF_INTERFACE_V1
> -    \brief VIF interface version 1
> -    \ingroup interfaces
> -*/
>  struct _XENVIF_VIF_INTERFACE_V1 {
>      INTERFACE                                       Interface;
>      XENVIF_VIF_ACQUIRE                              Acquire;
> @@ -723,17 +756,54 @@ struct _XENVIF_VIF_INTERFACE_V1 {
>      XENVIF_VIF_MAC_QUERY_FILTER_LEVEL               MacQueryFilterLevel;
>  };
> 
> -typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> +typedef struct _XENVIF_VIF_INTERFACE_V1 XENVIF_VIF_INTERFACE_V1,
> *PXENVIF_VIF_INTERFACE_V1;
> +
> +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_SET_PACKET_OFFSET
> TransmitterSetPacketOffset; // obsolete
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V1
> TransmitterQueuePackets;    // obsolete

You should never need to include obsolete fields in a new version of the interface.

> +    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;
> +    XENVIF_VIF_TRANSMITTER_QUEUE_PACKETS_V2
> TransmitterQueuePacketsV2;

No V2 suffix required.

> +    XENVIF_VIF_TRANSMITTER_GET_PACKET_HEADERS
> TransmitterGetPacketHeaders;
> +};
> +
> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE_V2,
> *PXENVIF_VIF_INTERFACE_V2;
> +

No. 

> +typedef struct _XENVIF_VIF_INTERFACE_V2 XENVIF_VIF_INTERFACE,
> *PXENVIF_VIF_INTERFACE;
> 
>  /*! \def XENVIF_VIF
> -    \brief Macro at assist in method invocation
> +    \brief Macro to assist in method invocation

Whitespace change?

>  */
>  #define XENVIF_VIF(_Method, _Interface, ...)    \
>      (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
> 
> +/*! \def XENVIF_VIF_VERSION
> +    \brief Macro to assist in getting interface version in use
> +*/
> +#define XENVIF_VIF_VERSION(_Interface)          \
> +    ((_Interface)->Interface.Version)
> +

Should not be needed. The subscriber should know!

>  #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

All the above should be in patch #1.

> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 38e4cb2..6fd542e 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2386,33 +2386,44 @@ TransmitterReturnPackets(
>      IN  PLIST_ENTRY                 List
>      )
>  {
> -    PXENVIF_FRONTEND                Frontend;
> -    PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> -    PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> +    PXENVIF_VIF_CONTEXT             Context;
> +
> +    Context = PdoGetVifContext(FrontendGetPdo(Transmitter->Frontend));
> 
> -    HeadPacket = NULL;
> -    NextPacket = NULL;
> -    while (!IsListEmpty(List)) {
> -        PLIST_ENTRY                     ListEntry;
> -        PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +    switch (VifGetVersion(Context)) {
> +    case 1: {
> +        PXENVIF_TRANSMITTER_PACKET_V1   HeadPacket;
> +        PXENVIF_TRANSMITTER_PACKET_V1   NextPacket;
> 
> -        ListEntry = RemoveTailList(List);
> -        ASSERT3P(ListEntry, !=, List);
> +        HeadPacket = NULL;
> +        NextPacket = NULL;
> +        while (!IsListEmpty(List)) {
> +            PLIST_ENTRY                     ListEntry;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> 
> -        Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +            ListEntry = RemoveTailList(List);
> +            ASSERT3P(ListEntry, !=, List);
> 
> -        HeadPacket = Packet->Cookie;
> -        HeadPacket->Next = NextPacket;
> -        HeadPacket->Completion = Packet->Completion;
> +            Packet = CONTAINING_RECORD(ListEntry,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> 
> -        __TransmitterPutPacket(Transmitter, Packet);
> -        NextPacket = HeadPacket;
> -    }
> +            HeadPacket = Packet->Cookie;
> +            HeadPacket->Next = NextPacket;
> +            HeadPacket->Completion = Packet->Completion;
> 
> -    Frontend = Transmitter->Frontend;
> +            __TransmitterPutPacket(Transmitter, Packet);
> +            NextPacket = HeadPacket;
> +        }
> 
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                HeadPacket);
> +        VifTransmitterReturnPackets(Context, HeadPacket);
> +        break;
> +    }
> +    case 2:
> +        VifTransmitterReturnPacketsV2(Context, List);
> +        break;
> +    default:
> +        ASSERT(FALSE);
> +        break;
> +    }
>  }
> 
>  static FORCEINLINE BOOLEAN
> @@ -3803,9 +3814,9 @@ TransmitterQueuePacketsV1(
>      // if HeadPacket != NULL, errors occured and need returning
>      if (HeadPacket != NULL) {
>          PXENVIF_TRANSMITTER_PACKET_V1   Packet;
> -        PXENVIF_FRONTEND                Frontend;
> +        PXENVIF_VIF_CONTEXT             Context;
> 
> -        Frontend = Transmitter->Frontend;
> +        Context = PdoGetVifContext(FrontendGetPdo(Transmitter-
> >Frontend));
> 
>          Packet = HeadPacket;
>          while (Packet != NULL) {
> @@ -3813,8 +3824,7 @@ TransmitterQueuePacketsV1(
>              Packet = Packet->Next;
>          }
> 
> -
> VifTransmitterReturnPackets(PdoGetVifContext(FrontendGetPdo(Frontend
> )),
> -                                    HeadPacket);
> +        VifTransmitterReturnPackets(Context, HeadPacket);
>      }
> 
>  #undef OFFSET
> @@ -3822,6 +3832,112 @@ TransmitterQueuePacketsV1(
>  }
> 
>  VOID
> +TransmitterQueuePacketsV2(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PLIST_ENTRY         List
> +    )
> +{
> +    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);
> +
> +    __TransmitterRingQueuePackets(Ring, List);
> +}
> +
> +static BOOLEAN
> +TransmitterHeaderPullup(
> +    IN  PVOID                   Argument,
> +    IN  PUCHAR                  DestinationVa,
> +    IN  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  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    )
> +{
> +    XENVIF_PACKET_PAYLOAD   Payload;
> +    NTSTATUS                status;
> +
> +    UNREFERENCED_PARAMETER(Transmitter);
> +
> +    Payload.Mdl = Mdl;
> +    Payload.Offset = Offset;
> +    Payload.Length = Length;
> +
> +    status = ParsePacket(HeaderBuffer,
> +                         TransmitterHeaderPullup,
> +                         &HeaderLength,
> +                         &Payload,
> +                         Info);
> +    return status;
> +}
> +
> +VOID
>  TransmitterAbortPackets(
>      IN  PXENVIF_TRANSMITTER Transmitter
>      )
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 661eeae..c359c20 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -113,6 +113,23 @@ TransmitterQueuePacketsV1(
>      );
> 
>  extern VOID
> +TransmitterQueuePacketsV2(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PLIST_ENTRY         List
> +    );
> +
> +extern NTSTATUS
> +TransmitterGetPacketHeaders(
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    );
> +
> +extern VOID
>  TransmitterQueryOffloadOptions(
>      IN  PXENVIF_TRANSMITTER         Transmitter,
>      OUT PXENVIF_VIF_OFFLOAD_OPTIONS Options
> diff --git a/src/xenvif/vif.c b/src/xenvif/vif.c
> index d6da258..8c1156a 100644
> --- a/src/xenvif/vif.c
> +++ b/src/xenvif/vif.c
> @@ -46,6 +46,7 @@ struct _XENVIF_VIF_CONTEXT {
>      PXENVIF_PDO                 Pdo;
>      XENVIF_MRSW_LOCK            Lock;
>      LONG                        References;
> +    ULONG                       Version;
>      PXENVIF_FRONTEND            Frontend;
>      BOOLEAN                     Enabled;
>      XENVIF_VIF_CALLBACK         Callback;
> @@ -302,6 +303,75 @@ fail1:
>      return status;
>  }
> 
> +static NTSTATUS
> +VifTransmitterQueuePacketsV2(

No V2 suffix. Only V1 functions should be suffixed and then the function names should use a 'Version1' suffix.

> +    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;
> +
> +    TransmitterQueuePacketsV2(FrontendGetTransmitter(Context-
> >Frontend),
> +                              List);
> +
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return status;
> +}
> +
> +static NTSTATUS
> +VifTransmitterGetPacketHeaders(
> +    IN  PINTERFACE          Interface,
> +    IN  PMDL                Mdl,
> +    IN  ULONG               Offset,
> +    IN  ULONG               Length,
> +    OUT PVOID               HeaderBuffer,
> +    IN  ULONG               HeaderLength,
> +    OUT PXENVIF_PACKET_INFO Info
> +    )
> +{
> +    PXENVIF_VIF_CONTEXT Context = Interface->Context;
> +    NTSTATUS            status;
> +
> +    AcquireMrswLockShared(&Context->Lock);
> +
> +    status = STATUS_UNSUCCESSFUL;
> +    if (Context->Enabled == FALSE)
> +        goto fail1;
> +
> +    status =
> TransmitterGetPacketHeaders(FrontendGetTransmitter(Context-
> >Frontend),
> +                                         Mdl,
> +                                         Offset,
> +                                         Length,
> +                                         HeaderBuffer,
> +                                         HeaderLength,
> +                                         Info);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +fail1:
> +    ReleaseMrswLockShared(&Context->Lock);
> +
> +    return status;
> +}
> +
>  static VOID
>  VifTransmitterQueryOffloadOptions(
>      IN  PINTERFACE                  Interface,
> @@ -560,7 +630,9 @@ VifAcquire(
>      if (Context->References++ != 0)
>          goto done;
> 
> -    Trace("====>\n");
> +    Trace("====> (%u)\n", Interface->Version);
> +
> +    Context->Version = Interface->Version;
> 
>      status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
>      if (!NT_SUCCESS(status))
> @@ -577,7 +649,7 @@ VifAcquire(
> 
>      Context->Frontend = PdoGetFrontend(Context->Pdo);
> 
> -    Trace("<====\n");
> +    Trace("<==== (%u)\n", Interface->Version);
> 
>  done:
>      ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
> @@ -612,7 +684,7 @@ VifRelease(
>      if (--Context->References > 0)
>          goto done;
> 
> -    Trace("====>\n");
> +    Trace("====> (%u)\n", Interface->Version);
> 
>      ASSERT(!Context->Enabled);
> 
> @@ -625,7 +697,9 @@ VifRelease(
> 
>      XENBUS_SUSPEND(Release, &Context->SuspendInterface);
> 
> -    Trace("<====\n");
> +    Context->Version = 0;
> +
> +    Trace("<==== (%u)\n", Interface->Version);
> 
>  done:
>      ReleaseMrswLockExclusive(&Context->Lock, Irql, FALSE);
> @@ -656,6 +730,33 @@ 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,
> +    VifTransmitterSetPacketOffset,
> +    VifTransmitterQueuePackets,
> +    VifTransmitterQueryOffloadOptions,
> +    VifTransmitterQueryLargePacketSize,
> +    VifTransmitterQueryRingSize,
> +    VifMacQueryState,
> +    VifMacQueryMaximumFrameSize,
> +    VifMacQueryPermanentAddress,
> +    VifMacQueryCurrentAddress,
> +    VifMacQueryMulticastAddresses,
> +    VifMacSetMulticastAddresses,
> +    VifMacSetFilterLevel,
> +    VifMacQueryFilterLevel,
> +    VifTransmitterQueuePacketsV2,
> +    VifTransmitterGetPacketHeaders
> +};
> +
>  NTSTATUS
>  VifInitialize(
>      IN  PXENVIF_PDO         Pdo,
> @@ -737,6 +838,23 @@ 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;
> @@ -793,6 +911,25 @@ VifTransmitterReturnPackets(
>                        Head);
>  }
> 
> +VOID
> +VifTransmitterReturnPacketsV2(
> +    IN  PXENVIF_VIF_CONTEXT Context,
> +    IN  PLIST_ENTRY         List
> +    )
> +{
> +    Context->Callback(Context->Argument,
> +                      XENVIF_TRANSMITTER_RETURN_PACKETS,
> +                      List);
> +}
> +
> +ULONG
> +VifGetVersion(
> +    IN  PXENVIF_VIF_CONTEXT Context
> +    )
> +{
> +    return Context->Version;
> +}
> +
>  extern PXENVIF_THREAD
>  VifGetMacThread(
>      IN  PXENVIF_VIF_CONTEXT Context
> diff --git a/src/xenvif/vif.h b/src/xenvif/vif.h
> index 0ef6687..fe0f9e4 100644
> --- a/src/xenvif/vif.h
> +++ b/src/xenvif/vif.h
> @@ -74,10 +74,21 @@ VifTransmitterReturnPackets(
>      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 Mon Nov 17 14:35:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:35:45 +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 1XqNP7-0005GI-Ev; Mon, 17 Nov 2014 14:35:45 +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 1XqNP6-0005GB-0F
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:35:44 +0000
Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id
	14/33-26858-EB70A645; Mon, 17 Nov 2014 14:35:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1416234942!11853380!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15010 invoked from network); 17 Nov 2014 14:35:42 -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;
	17 Nov 2014 14:35:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904044"
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: [PATCH 03/10] Store maximum number of queues allowed
Thread-Index: AQHP/pczE86czbWkkE6R3FQE/Wq3ypxk6cWw
Date: Mon, 17 Nov 2014 14:35:41 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153725@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-4-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-4-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 03/10] Store maximum number of queues
	allowed
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 03/10] Store maximum number of queues allowed
> 
> Read "MultiQueueMaxQueues" from parameters key to determine in-guest
> limit to multi-queue support.
> The maximum number of queues used will be the smallest of;
> 
> "HKLM/CurrentControlSet/Services/XENVIF/Parameters/MultiQueueMaxQu
> eues",
>   "device/vif/<number>/multi-queue-max-queues" and
>   number of guest vCPUs
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/driver.c | 36 ++++++++++++++++++++++++++++++++++++
>  src/xenvif/driver.h |  5 +++++
>  2 files changed, 41 insertions(+)
> 
> diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
> index 6f81620..b1fbb79 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               QueueMax;

Is this the index of the last queue or the maximum number of queues? The name should be clearer.

>  } XENVIF_DRIVER, *PXENVIF_DRIVER;
> 
>  static XENVIF_DRIVER    Driver;
> @@ -123,6 +124,33 @@ DriverGetAddressesKey(
>      return __DriverGetAddressesKey();
>  }
> 
> +static FORCEINLINE VOID
> +__DriverSetQueueMax(
> +    IN  ULONG       Count
> +    )
> +{
> +    ULONG   Processors;
> +
> +    Processors = KeQueryActiveProcessorCount(NULL);
> +    Driver.QueueMax = Count > Processors ? Processors : Count;

No. This function should a simple setting function. Do the query for actual number of processors in the caller.

> +}
> +
> +static FORCEINLINE ULONG
> +__DriverGetQueueMax(
> +    VOID
> +    )
> +{
> +    return Driver.QueueMax;
> +}
> +
> +ULONG
> +DriverGetQueueMax(
> +    VOID
> +    )
> +{
> +    return __DriverGetQueueMax();
> +}
> +
>  DRIVER_UNLOAD       DriverUnload;
> 
>  VOID
> @@ -254,6 +282,7 @@ DriverEntry(
>      HANDLE              ParametersKey;
>      HANDLE              AddressesKey;
>      ULONG               Index;
> +    ULONG               Queues;
>      NTSTATUS            status;
> 
>      ASSERT3P(__DriverGetDriverObject(), ==, NULL);
> @@ -304,6 +333,13 @@ DriverEntry(
> 
>      __DriverSetAddressesKey(AddressesKey);
> 
> +    status = RegistryQueryDwordValue(ParametersKey,
> +                                     "MultiQueueMaxQueues",
> +                                     &Queues);
> +    if (!NT_SUCCESS(status))
> +        Queues = MAXIMUM_PROCESSORS;
> +    __DriverSetQueueMax(Queues);
> +
>      RegistryCloseKey(ServiceKey);
> 
>      DriverObject->DriverExtension->AddDevice = AddDevice;
> diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
> index cdef7d1..9375930 100644
> --- a/src/xenvif/driver.h
> +++ b/src/xenvif/driver.h
> @@ -52,6 +52,11 @@ DriverGetAliasesKey(
>      VOID
>      );
> 
> +extern ULONG
> +DriverGetQueueMax(
> +    VOID
> +    );
> +

Again, need a clearer name.

  Paul

>  typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
>  typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
> 
> --
> 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 Mon Nov 17 14:35:45 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:35:45 +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 1XqNP7-0005GI-Ev; Mon, 17 Nov 2014 14:35:45 +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 1XqNP6-0005GB-0F
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:35:44 +0000
Received: from [85.158.137.68] by server-5.bemta-3.messagelabs.com id
	14/33-26858-EB70A645; Mon, 17 Nov 2014 14:35:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1416234942!11853380!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15010 invoked from network); 17 Nov 2014 14:35:42 -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;
	17 Nov 2014 14:35:42 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904044"
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: [PATCH 03/10] Store maximum number of queues allowed
Thread-Index: AQHP/pczE86czbWkkE6R3FQE/Wq3ypxk6cWw
Date: Mon, 17 Nov 2014 14:35:41 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153725@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-4-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-4-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 03/10] Store maximum number of queues
	allowed
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 03/10] Store maximum number of queues allowed
> 
> Read "MultiQueueMaxQueues" from parameters key to determine in-guest
> limit to multi-queue support.
> The maximum number of queues used will be the smallest of;
> 
> "HKLM/CurrentControlSet/Services/XENVIF/Parameters/MultiQueueMaxQu
> eues",
>   "device/vif/<number>/multi-queue-max-queues" and
>   number of guest vCPUs
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/driver.c | 36 ++++++++++++++++++++++++++++++++++++
>  src/xenvif/driver.h |  5 +++++
>  2 files changed, 41 insertions(+)
> 
> diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
> index 6f81620..b1fbb79 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               QueueMax;

Is this the index of the last queue or the maximum number of queues? The name should be clearer.

>  } XENVIF_DRIVER, *PXENVIF_DRIVER;
> 
>  static XENVIF_DRIVER    Driver;
> @@ -123,6 +124,33 @@ DriverGetAddressesKey(
>      return __DriverGetAddressesKey();
>  }
> 
> +static FORCEINLINE VOID
> +__DriverSetQueueMax(
> +    IN  ULONG       Count
> +    )
> +{
> +    ULONG   Processors;
> +
> +    Processors = KeQueryActiveProcessorCount(NULL);
> +    Driver.QueueMax = Count > Processors ? Processors : Count;

No. This function should a simple setting function. Do the query for actual number of processors in the caller.

> +}
> +
> +static FORCEINLINE ULONG
> +__DriverGetQueueMax(
> +    VOID
> +    )
> +{
> +    return Driver.QueueMax;
> +}
> +
> +ULONG
> +DriverGetQueueMax(
> +    VOID
> +    )
> +{
> +    return __DriverGetQueueMax();
> +}
> +
>  DRIVER_UNLOAD       DriverUnload;
> 
>  VOID
> @@ -254,6 +282,7 @@ DriverEntry(
>      HANDLE              ParametersKey;
>      HANDLE              AddressesKey;
>      ULONG               Index;
> +    ULONG               Queues;
>      NTSTATUS            status;
> 
>      ASSERT3P(__DriverGetDriverObject(), ==, NULL);
> @@ -304,6 +333,13 @@ DriverEntry(
> 
>      __DriverSetAddressesKey(AddressesKey);
> 
> +    status = RegistryQueryDwordValue(ParametersKey,
> +                                     "MultiQueueMaxQueues",
> +                                     &Queues);
> +    if (!NT_SUCCESS(status))
> +        Queues = MAXIMUM_PROCESSORS;
> +    __DriverSetQueueMax(Queues);
> +
>      RegistryCloseKey(ServiceKey);
> 
>      DriverObject->DriverExtension->AddDevice = AddDevice;
> diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
> index cdef7d1..9375930 100644
> --- a/src/xenvif/driver.h
> +++ b/src/xenvif/driver.h
> @@ -52,6 +52,11 @@ DriverGetAliasesKey(
>      VOID
>      );
> 
> +extern ULONG
> +DriverGetQueueMax(
> +    VOID
> +    );
> +

Again, need a clearer name.

  Paul

>  typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
>  typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
> 
> --
> 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 Mon Nov 17 14:38:41 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:38: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 1XqNRx-0005H0-NE; Mon, 17 Nov 2014 14:38:41 +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 1XqNRw-0005Gv-5o
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:38:40 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	14/49-24532-F680A645; Mon, 17 Nov 2014 14:38:39 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1416235118!13300737!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23671 invoked from network); 17 Nov 2014 14:38:38 -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 Nov 2014 14:38:38 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904140"
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: [PATCH 04/10] Create a transmitter/receiver ring per max-queue
Thread-Index: AQHP/pczBuWF3+oIE0yUAdU71gbS+Jxk6nkQ
Date: Mon, 17 Nov 2014 14:38:37 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153744@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-5-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-5-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 04/10] Create a transmitter/receiver ring
	per max-queue
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 04/10] Create a transmitter/receiver ring per max-queue
> 
> Reads "multi-queue-max-queues" from xenstore for frontend to report.
> Creates a transmitter and receiver ring per queue (queues above 0 are not
> used)
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/frontend.c    | 57
> ++++++++++++++++++++++++++++++++++++++----------
>  src/xenvif/frontend.h    |  5 +++++
>  src/xenvif/receiver.c    |  3 +--
>  src/xenvif/receiver.h    |  1 -
>  src/xenvif/transmitter.c |  3 +--
>  src/xenvif/transmitter.h |  1 -
>  6 files changed, 53 insertions(+), 17 deletions(-)
> 
> diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
> index 305faaf..9a6cbde 100644
> --- a/src/xenvif/frontend.c
> +++ b/src/xenvif/frontend.c
> @@ -64,6 +64,7 @@ struct _XENVIF_FRONTEND {
> 
>      PCHAR                       BackendPath;
>      USHORT                      BackendDomain;
> +    ULONG                       MultiQueueCount;

Just 'QueueCount'?

> 
>      PXENVIF_GRANTER             Granter;
>      PXENVIF_NOTIFIER            Notifier;
> @@ -203,6 +204,22 @@ FrontendGetBackendDomain(
>      return __FrontendGetBackendDomain(Frontend);
>  }
> 
> +static FORCEINLINE ULONG
> +__FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    )
> +{
> +    return Frontend->MultiQueueCount;
> +}
> +
> +ULONG
> +FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    )
> +{
> +    return __FrontendGetQueueCount(Frontend);
> +}
> +
>  #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
>  static FORCEINLINE _Type                                \
>  __FrontendGet ## _Function(                             \
> @@ -1285,6 +1302,7 @@ __FrontendConnect(
>      PCHAR                   Path = __FrontendGetBackendPath(Frontend);
>      XenbusState             State;
>      ULONG                   Attempt;
> +    PCHAR                   Buffer;
>      NTSTATUS                status;
> 
>      Trace("====>\n");
> @@ -1302,6 +1320,21 @@ __FrontendConnect(
>      if (!NT_SUCCESS(status))
>          goto fail2;
> 
> +    status = XENBUS_STORE(Read,
> +                          &Frontend->StoreInterface,
> +                          NULL,
> +                          __FrontendGetBackendPath(Frontend),
> +                          "multi-queue-max-queues",
> +                          &Buffer);
> +    if (NT_SUCCESS(status)) {
> +        Frontend->MultiQueueCount = (ULONG)strtol(Buffer, NULL, 10);
> +        XENBUS_STORE(Free,
> +                     &Frontend->StoreInterface,
> +                     Buffer);
> +    } else {
> +        Frontend->MultiQueueCount = 1;
> +    }
> +
>      status = GranterConnect(__FrontendGetGranter(Frontend));
>      if (!NT_SUCCESS(status))
>          goto fail3;
> @@ -1458,6 +1491,8 @@ __FrontendDisconnect(
>      MacDisconnect(__FrontendGetMac(Frontend));
>      GranterDisconnect(__FrontendGetGranter(Frontend));
> 
> +    Frontend->MultiQueueCount = 0;
> +
>      XENBUS_DEBUG(Deregister,
>                   &Frontend->DebugInterface,
>                   Frontend->DebugCallback);
> @@ -1894,19 +1929,19 @@ FrontendInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail6;
> 
> -    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
> +    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
>      if (!NT_SUCCESS(status))
>          goto fail7;
> 
> -    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
> +    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);

As previously discussed, I think it would be a lot cleaner to precede this series with something that drops the notifier object altogether.

  Paul

>      if (!NT_SUCCESS(status))
>          goto fail8;
> 
> -    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
> +    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
>      if (!NT_SUCCESS(status))
>          goto fail9;
> 
> -    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
> +    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
>      if (!NT_SUCCESS(status))
>          goto fail10;
> 
> @@ -1944,14 +1979,14 @@ fail10:
>  fail9:
>      Error("fail9\n");
> 
> -    MacTeardown(__FrontendGetMac(*Frontend));
> -    (*Frontend)->Mac = NULL;
> +    NotifierTeardown(__FrontendGetNotifier(*Frontend));
> +    (*Frontend)->Notifier = NULL;
> 
>  fail8:
>      Error("fail8\n");
> 
> -    NotifierTeardown(__FrontendGetNotifier(*Frontend));
> -    (*Frontend)->Notifier = NULL;
> +    MacTeardown(__FrontendGetMac(*Frontend));
> +    (*Frontend)->Mac = NULL;
> 
>  fail7:
>      Error("fail7\n");
> @@ -2040,12 +2075,12 @@ FrontendTeardown(
>      ReceiverTeardown(__FrontendGetReceiver(Frontend));
>      Frontend->Receiver = NULL;
> 
> -    MacTeardown(__FrontendGetMac(Frontend));
> -    Frontend->Mac = NULL;
> -
>      NotifierTeardown(__FrontendGetNotifier(Frontend));
>      Frontend->Notifier = NULL;
> 
> +    MacTeardown(__FrontendGetMac(Frontend));
> +    Frontend->Mac = NULL;
> +
>      GranterTeardown(__FrontendGetGranter(Frontend));
>      Frontend->Granter = NULL;
> 
> diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
> index 60c085a..20cd390 100644
> --- a/src/xenvif/frontend.h
> +++ b/src/xenvif/frontend.h
> @@ -112,6 +112,11 @@ FrontendGetBackendDomain(
>      IN  PXENVIF_FRONTEND    Frontend
>      );
> 
> +extern ULONG
> +FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    );
> +
>  #include "granter.h"
> 
>  extern PXENVIF_GRANTER
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 88ee07c..626feed 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2298,7 +2298,6 @@ ReceiverDebugCallback(
>  NTSTATUS
>  ReceiverInitialize(
>      IN  PXENVIF_FRONTEND    Frontend,
> -    IN  ULONG               Count,
>      OUT PXENVIF_RECEIVER    *Receiver
>      )
>  {
> @@ -2385,7 +2384,7 @@ ReceiverInitialize(
>          goto fail2;
> 
>      Index = 0;
> -    while (Index < Count) {
> +    while (Index < DriverGetQueueMax()) {
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
> diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
> index 0497c5b..8009858 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 6fd542e..bea46f1 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3308,7 +3308,6 @@ TransmitterDebugCallback(
>  NTSTATUS
>  TransmitterInitialize(
>      IN  PXENVIF_FRONTEND    Frontend,
> -    IN  ULONG               Count,
>      OUT PXENVIF_TRANSMITTER *Transmitter
>      )
>  {
> @@ -3391,7 +3390,7 @@ TransmitterInitialize(
>          goto fail4;
> 
>      Index = 0;
> -    while (Index < Count) {
> +    while (Index < DriverGetQueueMax()) {
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index c359c20..7e10603 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 Mon Nov 17 14:38:41 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:38: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 1XqNRx-0005H0-NE; Mon, 17 Nov 2014 14:38:41 +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 1XqNRw-0005Gv-5o
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:38:40 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	14/49-24532-F680A645; Mon, 17 Nov 2014 14:38:39 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-4.tower-21.messagelabs.com!1416235118!13300737!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 23671 invoked from network); 17 Nov 2014 14:38:38 -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 Nov 2014 14:38:38 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904140"
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: [PATCH 04/10] Create a transmitter/receiver ring per max-queue
Thread-Index: AQHP/pczBuWF3+oIE0yUAdU71gbS+Jxk6nkQ
Date: Mon, 17 Nov 2014 14:38:37 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153744@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-5-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-5-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 04/10] Create a transmitter/receiver ring
	per max-queue
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 04/10] Create a transmitter/receiver ring per max-queue
> 
> Reads "multi-queue-max-queues" from xenstore for frontend to report.
> Creates a transmitter and receiver ring per queue (queues above 0 are not
> used)
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/frontend.c    | 57
> ++++++++++++++++++++++++++++++++++++++----------
>  src/xenvif/frontend.h    |  5 +++++
>  src/xenvif/receiver.c    |  3 +--
>  src/xenvif/receiver.h    |  1 -
>  src/xenvif/transmitter.c |  3 +--
>  src/xenvif/transmitter.h |  1 -
>  6 files changed, 53 insertions(+), 17 deletions(-)
> 
> diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
> index 305faaf..9a6cbde 100644
> --- a/src/xenvif/frontend.c
> +++ b/src/xenvif/frontend.c
> @@ -64,6 +64,7 @@ struct _XENVIF_FRONTEND {
> 
>      PCHAR                       BackendPath;
>      USHORT                      BackendDomain;
> +    ULONG                       MultiQueueCount;

Just 'QueueCount'?

> 
>      PXENVIF_GRANTER             Granter;
>      PXENVIF_NOTIFIER            Notifier;
> @@ -203,6 +204,22 @@ FrontendGetBackendDomain(
>      return __FrontendGetBackendDomain(Frontend);
>  }
> 
> +static FORCEINLINE ULONG
> +__FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    )
> +{
> +    return Frontend->MultiQueueCount;
> +}
> +
> +ULONG
> +FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    )
> +{
> +    return __FrontendGetQueueCount(Frontend);
> +}
> +
>  #define DEFINE_FRONTEND_GET_FUNCTION(_Function, _Type)  \
>  static FORCEINLINE _Type                                \
>  __FrontendGet ## _Function(                             \
> @@ -1285,6 +1302,7 @@ __FrontendConnect(
>      PCHAR                   Path = __FrontendGetBackendPath(Frontend);
>      XenbusState             State;
>      ULONG                   Attempt;
> +    PCHAR                   Buffer;
>      NTSTATUS                status;
> 
>      Trace("====>\n");
> @@ -1302,6 +1320,21 @@ __FrontendConnect(
>      if (!NT_SUCCESS(status))
>          goto fail2;
> 
> +    status = XENBUS_STORE(Read,
> +                          &Frontend->StoreInterface,
> +                          NULL,
> +                          __FrontendGetBackendPath(Frontend),
> +                          "multi-queue-max-queues",
> +                          &Buffer);
> +    if (NT_SUCCESS(status)) {
> +        Frontend->MultiQueueCount = (ULONG)strtol(Buffer, NULL, 10);
> +        XENBUS_STORE(Free,
> +                     &Frontend->StoreInterface,
> +                     Buffer);
> +    } else {
> +        Frontend->MultiQueueCount = 1;
> +    }
> +
>      status = GranterConnect(__FrontendGetGranter(Frontend));
>      if (!NT_SUCCESS(status))
>          goto fail3;
> @@ -1458,6 +1491,8 @@ __FrontendDisconnect(
>      MacDisconnect(__FrontendGetMac(Frontend));
>      GranterDisconnect(__FrontendGetGranter(Frontend));
> 
> +    Frontend->MultiQueueCount = 0;
> +
>      XENBUS_DEBUG(Deregister,
>                   &Frontend->DebugInterface,
>                   Frontend->DebugCallback);
> @@ -1894,19 +1929,19 @@ FrontendInitialize(
>      if (!NT_SUCCESS(status))
>          goto fail6;
> 
> -    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);
> +    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
>      if (!NT_SUCCESS(status))
>          goto fail7;
> 
> -    status = MacInitialize(*Frontend, &(*Frontend)->Mac);
> +    status = NotifierInitialize(*Frontend, &(*Frontend)->Notifier);

As previously discussed, I think it would be a lot cleaner to precede this series with something that drops the notifier object altogether.

  Paul

>      if (!NT_SUCCESS(status))
>          goto fail8;
> 
> -    status = ReceiverInitialize(*Frontend, 1, &(*Frontend)->Receiver);
> +    status = ReceiverInitialize(*Frontend, &(*Frontend)->Receiver);
>      if (!NT_SUCCESS(status))
>          goto fail9;
> 
> -    status = TransmitterInitialize(*Frontend, 1, &(*Frontend)->Transmitter);
> +    status = TransmitterInitialize(*Frontend, &(*Frontend)->Transmitter);
>      if (!NT_SUCCESS(status))
>          goto fail10;
> 
> @@ -1944,14 +1979,14 @@ fail10:
>  fail9:
>      Error("fail9\n");
> 
> -    MacTeardown(__FrontendGetMac(*Frontend));
> -    (*Frontend)->Mac = NULL;
> +    NotifierTeardown(__FrontendGetNotifier(*Frontend));
> +    (*Frontend)->Notifier = NULL;
> 
>  fail8:
>      Error("fail8\n");
> 
> -    NotifierTeardown(__FrontendGetNotifier(*Frontend));
> -    (*Frontend)->Notifier = NULL;
> +    MacTeardown(__FrontendGetMac(*Frontend));
> +    (*Frontend)->Mac = NULL;
> 
>  fail7:
>      Error("fail7\n");
> @@ -2040,12 +2075,12 @@ FrontendTeardown(
>      ReceiverTeardown(__FrontendGetReceiver(Frontend));
>      Frontend->Receiver = NULL;
> 
> -    MacTeardown(__FrontendGetMac(Frontend));
> -    Frontend->Mac = NULL;
> -
>      NotifierTeardown(__FrontendGetNotifier(Frontend));
>      Frontend->Notifier = NULL;
> 
> +    MacTeardown(__FrontendGetMac(Frontend));
> +    Frontend->Mac = NULL;
> +
>      GranterTeardown(__FrontendGetGranter(Frontend));
>      Frontend->Granter = NULL;
> 
> diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
> index 60c085a..20cd390 100644
> --- a/src/xenvif/frontend.h
> +++ b/src/xenvif/frontend.h
> @@ -112,6 +112,11 @@ FrontendGetBackendDomain(
>      IN  PXENVIF_FRONTEND    Frontend
>      );
> 
> +extern ULONG
> +FrontendGetQueueCount(
> +    IN  PXENVIF_FRONTEND    Frontend
> +    );
> +
>  #include "granter.h"
> 
>  extern PXENVIF_GRANTER
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 88ee07c..626feed 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2298,7 +2298,6 @@ ReceiverDebugCallback(
>  NTSTATUS
>  ReceiverInitialize(
>      IN  PXENVIF_FRONTEND    Frontend,
> -    IN  ULONG               Count,
>      OUT PXENVIF_RECEIVER    *Receiver
>      )
>  {
> @@ -2385,7 +2384,7 @@ ReceiverInitialize(
>          goto fail2;
> 
>      Index = 0;
> -    while (Index < Count) {
> +    while (Index < DriverGetQueueMax()) {
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          status = __ReceiverRingInitialize(*Receiver, Index, &Ring);
> diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
> index 0497c5b..8009858 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 6fd542e..bea46f1 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3308,7 +3308,6 @@ TransmitterDebugCallback(
>  NTSTATUS
>  TransmitterInitialize(
>      IN  PXENVIF_FRONTEND    Frontend,
> -    IN  ULONG               Count,
>      OUT PXENVIF_TRANSMITTER *Transmitter
>      )
>  {
> @@ -3391,7 +3390,7 @@ TransmitterInitialize(
>          goto fail4;
> 
>      Index = 0;
> -    while (Index < Count) {
> +    while (Index < DriverGetQueueMax()) {
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          status = __TransmitterRingInitialize(*Transmitter, Index, &Ring);
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index c359c20..7e10603 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 Mon Nov 17 14:40:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:40:49 +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 1XqNU0-0005Hn-Tu; Mon, 17 Nov 2014 14:40:48 +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 1XqNTy-0005Hi-WA
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:40:47 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	20/9D-24532-EE80A645; Mon, 17 Nov 2014 14:40:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1416235244!13349686!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20426 invoked from network); 17 Nov 2014 14:40:44 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:40:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904233"
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: [PATCH 05/10] Split notifier into a list of queues.
Thread-Index: AQHP/pc1tZWN6WJQdEKpdWS4DNR5Upxk60Qg
Date: Mon, 17 Nov 2014 14:40:43 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153755@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-6-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-6-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 05/10] Split notifier into a list of
	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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 05/10] Split notifier into a list of queues.
> 
> Move event channel registration to a list item, with 1 item per
> max-queue.
> 

Please get rid of the notifier object. Have the receiver code own the event channel in the non-split case. Have receiver and transmitter own their own in the split case then the move the event channel from the receiver/transmitter struct to the per-ring struct when multi-queue support is added.

  Paul

> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/notifier.c    | 686 +++++++++++++++++++++++++++++++++-------
> -------
>  src/xenvif/notifier.h    |  12 +-
>  src/xenvif/receiver.c    |  11 +-
>  src/xenvif/receiver.h    |   3 +-
>  src/xenvif/transmitter.c |   9 +-
>  src/xenvif/transmitter.h |   3 +-
>  6 files changed, 512 insertions(+), 212 deletions(-)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index fc6725a..02a11d8 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -52,19 +52,26 @@ typedef enum _XENVIF_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;
> +    LIST_ENTRY                  List;
>      XENBUS_STORE_INTERFACE      StoreInterface;
>      XENBUS_DEBUG_INTERFACE      DebugInterface;
>      PXENBUS_DEBUG_CALLBACK      DebugCallback;
>  };
> 
> +typedef struct _XENVIF_NOTIFIER_QUEUE {
> +    PXENVIF_NOTIFIER            Notifier;
> +    LIST_ENTRY                  ListEntry;
> +    ULONG                       Index;
> +    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];
> +} XENVIF_NOTIFIER_QUEUE, *PXENVIF_NOTIFIER_QUEUE;
> +
>  #define XENVIF_NOTIFIER_TAG 'ITON'
> 
>  static FORCEINLINE PVOID
> @@ -84,22 +91,24 @@ __NotifierFree(
>  }
> 
>  static FORCEINLINE BOOLEAN
> -__NotifierUnmask(
> -    IN  PXENVIF_NOTIFIER        Notifier,
> +__NotifierQueueUnmask(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue,
>      IN  XENVIF_NOTIFIER_EVTCHN  Index
>      )
>  {
> +    PXENVIF_NOTIFIER            Notifier;
>      PXENVIF_FRONTEND            Frontend;
>      BOOLEAN                     Pending;
> 
> +    Notifier = Queue->Notifier;
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
> 
> -    Pending = (Notifier->Connected) ?
> +    Pending = (Notifier->Connected && Queue->Channel[Index]) ?
>                XENBUS_EVTCHN(Unmask,
>                              &Notifier->EvtchnInterface,
> -                            Notifier->Channel[Index],
> +                            Queue->Channel[Index],
>                              FALSE) :
>                FALSE;
> 
> @@ -114,14 +123,15 @@ __drv_minIRQL(DISPATCH_LEVEL)
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __drv_sameIRQL
>  static VOID
> -NotifierDpc(
> +NotifierQueueDpc(
>      IN  PKDPC               Dpc,
>      IN  PVOID               Context,
>      IN  PVOID               Argument1,
>      IN  PVOID               Argument2
>      )
>  {
> -    PXENVIF_NOTIFIER        Notifier = Context;
> +    PXENVIF_NOTIFIER_QUEUE  Queue = Context;
> +    PXENVIF_NOTIFIER        Notifier;
>      XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
>      PXENVIF_FRONTEND        Frontend;
>      BOOLEAN                 Pending;
> @@ -129,24 +139,25 @@ NotifierDpc(
>      UNREFERENCED_PARAMETER(Dpc);
>      UNREFERENCED_PARAMETER(Argument2);
> 
> -    ASSERT(Notifier != NULL);
> +    ASSERT(Queue != NULL);
> 
> +    Notifier = Queue->Notifier;
>      Frontend = Notifier->Frontend;
> 
>      do {
>          if (Notifier->Enabled) {
>              switch (Index) {
>              case XENVIF_NOTIFIER_EVTCHN_TX:
> -                TransmitterNotify(FrontendGetTransmitter(Frontend));
> +                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue-
> >Index);
>                  break;
> 
>              case XENVIF_NOTIFIER_EVTCHN_RX:
> -                ReceiverNotify(FrontendGetReceiver(Frontend));
> +                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
>                  break;
> 
>              case XENVIF_NOTIFIER_EVTCHN_COMBINED:
> -                TransmitterNotify(FrontendGetTransmitter(Frontend));
> -                ReceiverNotify(FrontendGetReceiver(Frontend));
> +                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue-
> >Index);
> +                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
>                  break;
> 
>              default:
> @@ -155,88 +166,345 @@ NotifierDpc(
>              }
>          }
> 
> -        Pending = __NotifierUnmask(Notifier, Index);
> +        Pending = __NotifierQueueUnmask(Queue, Index);
>      } while (Pending);
>  }
> 
>  static FORCEINLINE BOOLEAN
> -__NotifierEvtchnCallback(
> -    IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  XENVIF_NOTIFIER_EVTCHN     Index
> +__NotifierQueueEvtchnCallback(
> +    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
> +    IN  XENVIF_NOTIFIER_EVTCHN      Index
>      )
>  {
> -    Notifier->Events[Index]++;
> +    Queue->Events[Index]++;
> 
> -    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
> +    if (KeInsertQueueDpc(&Queue->Dpc[Index],
>                           (PVOID)(ULONG_PTR)Index,
>                           NULL))
> -        Notifier->Dpcs[Index]++;
> +        Queue->Dpcs[Index]++;
> 
>      return TRUE;
>  }
> 
> -#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
> +#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)
> \
>                                                                          \
> -KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
> +KSERVICE_ROUTINE    NotifierQueue ## _Type ## EvtchnCallback;           \
>                                                                          \
>  BOOLEAN                                                                 \
> -Notifier ## _Type ## EvtchnCallback(                                    \
> +NotifierQueue ## _Type ## EvtchnCallback(                               \
>      IN  PKINTERRUPT         InterruptObject,                            \
>      IN  PVOID               Argument                                    \
>      )                                                                   \
>  {                                                                       \
> -    PXENVIF_NOTIFIER        Notifier = Argument;                        \
> +    PXENVIF_NOTIFIER_QUEUE  Queue = Argument;                           \
>                                                                          \
>      UNREFERENCED_PARAMETER(InterruptObject);                            \
>                                                                          \
> -    ASSERT(Notifier != NULL);                                           \
> -    return __NotifierEvtchnCallback(Notifier,                           \
> +    ASSERT(Queue != NULL);                                              \
> +    return __NotifierQueueEvtchnCallback(Queue,                         \
>                                      XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
>  }
> 
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
> 
> -#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
> +#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
> 
> -#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
> -    Notifier ## _Type ## EvtchnCallback,
> +#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)   \
> +    NotifierQueue ## _Type ## EvtchnCallback,
> 
> -PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
> +PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
>  };
> 
> -#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
> +#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
> 
> -C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> +C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> 
>  static VOID
> -NotifierDebugCallback(
> -    IN  PVOID           Argument,
> -    IN  BOOLEAN         Crashing
> +NotifierQueueDebugCallback(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
>      )
>  {
> -    PXENVIF_NOTIFIER    Notifier = Argument;
> -    PXENVIF_FRONTEND    Frontend;
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
>      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",
> +                     "[%u][%s]: Events = %lu Dpcs = %lu\n",
> +                     Queue->Index,
>                       ((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]);
> +                     Queue->Events[Index],
> +                     Queue->Dpcs[Index]);
> +}
> +
> +static NTSTATUS
> +NotifierQueueInitialize(
> +    IN  PXENVIF_NOTIFIER        Notifier,
> +    IN  ULONG                   QueueIndex,
> +    OUT PXENVIF_NOTIFIER_QUEUE  *Queue
> +    )
> +{
> +    ULONG       Index;
> +    NTSTATUS    status;
> +
> +    *Queue = __NotifierAllocate(sizeof (XENVIF_NOTIFIER_QUEUE));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Queue == NULL)
> +        goto fail1;
> +
> +    (*Queue)->Notifier = Notifier;
> +    (*Queue)->Index = QueueIndex;
> +
> +    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
> +        KeInitializeDpc(&(*Queue)->Dpc[Index],
> +                        NotifierQueueDpc,
> +                        *Queue);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> +
> +static NTSTATUS
> +NotifierQueueConnect(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER        Notifier;
> +    PXENVIF_FRONTEND        Frontend;
> +    LONG                    Index;
> +    NTSTATUS                status;
> +
> +    Notifier = Queue->Notifier;
> +    Frontend = Notifier->Frontend;
> +
> +    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
> +        PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
> +        BOOLEAN             Pending;
> +
> +        Queue->Channel[Index] = XENBUS_EVTCHN(Open,
> +                                              &Notifier->EvtchnInterface,
> +                                              XENBUS_EVTCHN_TYPE_UNBOUND,
> +                                              Callback,
> +                                              Queue,
> +                                              FrontendGetBackendDomain(Frontend),
> +                                              TRUE);
> +
> +        status = STATUS_UNSUCCESSFUL;
> +        if (Queue->Channel[Index] == NULL)
> +            goto fail1;
> +
> +        Pending = XENBUS_EVTCHN(Unmask,
> +                                &Notifier->EvtchnInterface,
> +                                Queue->Channel[Index],
> +                                FALSE);
> +        if (Pending)
> +            XENBUS_EVTCHN(Trigger,
> +                          &Notifier->EvtchnInterface,
> +                          Queue->Channel[Index]);
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    while (--Index >= 0) {
> +        XENBUS_EVTCHN(Close,
> +                      &Notifier->EvtchnInterface,
> +                      Queue->Channel[Index]);
> +        Queue->Channel[Index] = NULL;
> +
> +        Queue->Events[Index] = 0;
> +    }
> +
> +    return status;
> +}
> +
> +static NTSTATUS
> +NotifierQueueStoreWrite(
> +    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
> +    IN  PXENBUS_STORE_TRANSACTION   Transaction
> +    )
> +{
> +    PXENVIF_NOTIFIER                Notifier = Queue->Notifier;
> +    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,
> +                             Queue->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;
> +}
> +
> +static NTSTATUS
> +NotifierQueueEnable(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
> +    ULONG               Index;
> +
> +    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(&Queue->Dpc[Index],
> +                             (PVOID)(ULONG_PTR)Index,
> +                             NULL))
> +            Queue->Dpcs[Index]++;
> +    }
> +
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +NotifierQueueDisconnect(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
> +    LONG                Index;
> +
> +    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    while (--Index >= 0) {
> +        if (Queue->Channel[Index] == NULL)
> +            continue;
> +
> +        XENBUS_EVTCHN(Close,
> +                      &Notifier->EvtchnInterface,
> +                      Queue->Channel[Index]);
> +        Queue->Channel[Index] = NULL;
> +
> +        Queue->Events[Index] = 0;
> +    }
> +}
> +
> +static VOID
> +NotifierQueueTeardown(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    LONG        Index;
> +
> +    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    while (--Index >= 0) {
> +        Queue->Dpcs[Index] = 0;
> +        RtlZeroMemory(&Queue->Dpc[Index], sizeof (KDPC));
> +    }
> +
> +    Queue->Notifier = NULL;
> +    Queue->Index = 0;
> +
> +    ASSERT(IsZeroMemory(Queue, sizeof (XENVIF_NOTIFIER_QUEUE)));
> +
> +    __NotifierFree(Queue);
> +}
> +
> +static VOID
> +NotifierDebugCallback(
> +    IN  PVOID           Argument,
> +    IN  BOOLEAN         Crashing
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Argument;
> +    PLIST_ENTRY         ListEntry;
> +
> +    UNREFERENCED_PARAMETER(Crashing);
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        NotifierQueueDebugCallback(Queue);
> +    }
>  }
> 
>  NTSTATUS
> @@ -266,13 +534,41 @@ NotifierInitialize(
>      (*Notifier)->Frontend = Frontend;
> 
>      KeInitializeSpinLock(&(*Notifier)->Lock);
> -    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
> -        KeInitializeDpc(&(*Notifier)->Dpc[Index],
> -                        NotifierDpc,
> -                        *Notifier);
> +    InitializeListHead(&(*Notifier)->List);
> +
> +    Index = 0;
> +    while (Index < DriverGetQueueMax()) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        status = NotifierQueueInitialize(*Notifier, Index, &Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +
> +        InsertTailList(&(*Notifier)->List, &Queue->ListEntry);
> +        Index++;
> +    }
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    while (!IsListEmpty(&(*Notifier)->List)) {
> +        PLIST_ENTRY             ListEntry;
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        ListEntry = RemoveTailList(&(*Notifier)->List);
> +        ASSERT3P(ListEntry, !=, &(*Notifier)->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +
> +        NotifierQueueTeardown(Queue);
> +        --Index;
> +    }
> +    ASSERT3U(Index, ==, 0);
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -285,7 +581,7 @@ NotifierConnect(
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> -    LONG                    Index;
> +    PLIST_ENTRY             ListEntry;
>      PCHAR                   Buffer;
>      NTSTATUS                status;
> 
> @@ -308,32 +604,6 @@ NotifierConnect(
>      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",
> @@ -341,7 +611,7 @@ NotifierConnect(
>                            Notifier,
>                            &Notifier->DebugCallback);
>      if (!NT_SUCCESS(status))
> -        goto fail5;
> +        goto fail4;
> 
>      status = XENBUS_STORE(Read,
>                            &Notifier->StoreInterface,
> @@ -359,6 +629,20 @@ NotifierConnect(
>                       Buffer);
>      }
> 
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +
> +        status = NotifierQueueConnect(Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail5;
> +    }
> +
>      Notifier->Connected = TRUE;
>      KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
> 
> @@ -367,20 +651,19 @@ NotifierConnect(
>  fail5:
>      Error("fail5\n");
> 
> -    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -fail4:
> -    Error("fail4\n");
> -
> -    while (--Index >= 0) {
> -        XENBUS_EVTCHN(Close,
> -                      &Notifier->EvtchnInterface,
> -                      Notifier->Channel[Index]);
> -        Notifier->Channel[Index] = NULL;
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> 
> -        Notifier->Events[Index] = 0;
> +        NotifierQueueDisconnect(Queue);
>      }
> 
> +fail4:
> +    Error("fail4\n");
> +
>      XENBUS_STORE(Release, &Notifier->StoreInterface);
> 
>  fail3:
> @@ -408,54 +691,20 @@ NotifierStoreWrite(
>      )
>  {
>      PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
> -    ULONG                           Index;
> +    PLIST_ENTRY                     ListEntry;
>      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);
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -            Node = "";
> -            break;
> -        }
> -
> -        Port = XENBUS_EVTCHN(GetPort,
> -                             &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> -
> -        status = XENBUS_STORE(Printf,
> -                              &Notifier->StoreInterface,
> -                              Transaction,
> -                              FrontendGetPath(Frontend),
> -                              Node,
> -                              "%u",
> -                              Port);
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index > FrontendGetQueueCount(Frontend))
> +            continue;
> 
> +        status = NotifierQueueStoreWrite(Queue,
> +                                         Transaction);
>          if (!NT_SUCCESS(status))
>              goto fail1;
>      }
> @@ -473,44 +722,34 @@ NotifierEnable(
>      IN  PXENVIF_NOTIFIER    Notifier
>      )
>  {
> -    ULONG                   Index;
> +    PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +    NTSTATUS                status;
> +
> +    Frontend = Notifier->Frontend;
> 
>      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);
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -            break;
> -        }
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index > FrontendGetQueueCount(Frontend))
> +            continue;
> 
> -        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
> -                             (PVOID)(ULONG_PTR)Index,
> -                             NULL))
> -            Notifier->Dpcs[Index]++;
> +        status = NotifierQueueEnable(Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
>      }
> 
>      return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
>  }
> 
>  VOID
> @@ -528,7 +767,7 @@ NotifierDisconnect(
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> -    LONG                    Index;
> +    PLIST_ENTRY             ListEntry;
> 
>      Frontend = Notifier->Frontend;
> 
> @@ -544,14 +783,16 @@ NotifierDisconnect(
>                   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;
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -        Notifier->Events[Index] = 0;
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +
> +        NotifierQueueDisconnect(Queue);
>      }
> 
>      XENBUS_STORE(Release, &Notifier->StoreInterface);
> @@ -568,15 +809,21 @@ 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));
> +    while (!IsListEmpty(&Notifier->List)) {
> +        PLIST_ENTRY             ListEntry;
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        ListEntry = RemoveTailList(&Notifier->List);
> +        ASSERT3P(ListEntry, !=, &Notifier->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +
> +        NotifierQueueTeardown(Queue);
>      }
> 
>      Notifier->Frontend = NULL;
> @@ -590,6 +837,7 @@ NotifierTeardown(
>      RtlZeroMemory(&Notifier->EvtchnInterface,
>                    sizeof (XENBUS_EVTCHN_INTERFACE));
> 
> +    RtlZeroMemory(&Notifier->List, sizeof(LIST_ENTRY));
>      RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
> 
>      ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
> @@ -600,85 +848,125 @@ NotifierTeardown(
>  static FORCEINLINE VOID
>  __NotifierSend(
>      IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  ULONG               Index
> +    IN  ULONG               Index,
> +    IN  ULONG               QueueIndex
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> +    PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> 
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLock(&Notifier->Lock, &Irql);
> 
> -    if (Notifier->Connected)
> +    if (!Notifier->Connected)
> +        goto done;
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +        if (Queue->Index != QueueIndex)
> +            continue;
> +
>          (VOID) XENBUS_EVTCHN(Send,
>                               &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> +                             Queue->Channel[Index]);
> +        break;
> +    }
> 
> +done:
>      KeReleaseSpinLock(&Notifier->Lock, Irql);
>  }
> 
>  VOID
>  NotifierSendTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
>      else
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  VOID
>  NotifierSendRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
>      else
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  static FORCEINLINE VOID
>  __NotifierTrigger(
>      IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  ULONG               Index
> +    IN  ULONG               Index,
> +    IN  ULONG               QueueIndex
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> +    PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> 
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLock(&Notifier->Lock, &Irql);
> 
> -    if (Notifier->Connected)
> +    if (!Notifier->Connected)
> +        goto done;
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +        if (Queue->Index != QueueIndex)
> +            continue;
> +
>          (VOID) XENBUS_EVTCHN(Trigger,
>                               &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> +                             Queue->Channel[Index]);
> +        break;
> +    }
> 
> +done:
>      KeReleaseSpinLock(&Notifier->Lock, Irql);
>  }
> 
>  VOID
>  NotifierTriggerTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
>      else
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  VOID
>  NotifierTriggerRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
>      else
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
> index 2f06a6f..fd28060 100644
> --- a/src/xenvif/notifier.h
> +++ b/src/xenvif/notifier.h
> @@ -78,22 +78,26 @@ NotifierTeardown(
> 
>  extern VOID
>  NotifierSendTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierSendRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierTriggerTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierTriggerRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  #endif  // _XENVIF_NOTIFIER_H
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 626feed..85ebcf9 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -1397,7 +1397,7 @@ __ReceiverRingReturnPacket(
>              Receiver = Ring->Receiver;
>              Frontend = Receiver->Frontend;
> 
> -            NotifierTriggerRx(FrontendGetNotifier(Frontend));
> +            NotifierTriggerRx(FrontendGetNotifier(Frontend), Ring->Index);
>          }
> 
>          if (!Locked)
> @@ -1477,7 +1477,7 @@ __ReceiverRingPushRequests(
>          Receiver = Ring->Receiver;
>          Frontend = Receiver->Frontend;
> 
> -        NotifierSendRx(FrontendGetNotifier(Frontend));
> +        NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
>      }
> 
>      Ring->RequestsPushed = Ring->RequestsPosted;
> @@ -1869,7 +1869,7 @@ ReceiverRingWatchdog(
> 
>                  // Try to move things along
>                  ReceiverRingPoll(Ring);
> -                NotifierSendRx(FrontendGetNotifier(Frontend));
> +                NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
>              }
> 
>              KeMemoryBarrier();
> @@ -2941,7 +2941,8 @@ ReceiverWaitForPackets(
> 
>  VOID
>  ReceiverNotify(
> -    IN  PXENVIF_RECEIVER    Receiver
> +    IN  PXENVIF_RECEIVER    Receiver,
> +    IN  ULONG               Index
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> @@ -2952,6 +2953,8 @@ ReceiverNotify(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> 
>          __ReceiverRingNotify(Ring);
>      }
> diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
> index 8009858..1505887 100644
> --- a/src/xenvif/receiver.h
> +++ b/src/xenvif/receiver.h
> @@ -79,7 +79,8 @@ ReceiverTeardown(
> 
>  extern VOID
>  ReceiverNotify(
> -    IN  PXENVIF_RECEIVER    Receiver
> +    IN  PXENVIF_RECEIVER    Receiver,
> +    IN  ULONG               Index
>      );
> 
>  extern VOID
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index bea46f1..477fecc 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2195,7 +2195,7 @@ __TransmitterRingPushRequests(
>          Transmitter = Ring->Transmitter;
>          Frontend = Transmitter->Frontend;
> 
> -        NotifierSendTx(FrontendGetNotifier(Frontend));
> +        NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
>      }
> 
>      Ring->RequestsPushed = Ring->RequestsPosted;
> @@ -2624,7 +2624,7 @@ TransmitterRingWatchdog(
>                               Ring->DebugCallback);
> 
>                  // Try to move things along
> -                NotifierSendTx(FrontendGetNotifier(Frontend));
> +                NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
>                  TransmitterRingPoll(Ring);
>              }
> 
> @@ -3972,7 +3972,8 @@ TransmitterQueryRingSize(
> 
>  VOID
>  TransmitterNotify(
> -    IN  PXENVIF_TRANSMITTER Transmitter
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  ULONG               Index
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> @@ -3983,6 +3984,8 @@ TransmitterNotify(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> 
>          __TransmitterRingNotify(Ring);
>      }
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 7e10603..3e56b34 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -79,7 +79,8 @@ TransmitterTeardown(
> 
>  extern VOID
>  TransmitterNotify(
> -    IN  PXENVIF_TRANSMITTER Transmitter
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  ULONG               Index
>      );
> 
>  extern VOID
> --
> 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 Mon Nov 17 14:40:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:40:49 +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 1XqNU0-0005Hn-Tu; Mon, 17 Nov 2014 14:40:48 +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 1XqNTy-0005Hi-WA
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:40:47 +0000
Received: from [85.158.143.35] by server-2.bemta-4.messagelabs.com id
	20/9D-24532-EE80A645; Mon, 17 Nov 2014 14:40:46 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-10.tower-21.messagelabs.com!1416235244!13349686!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 20426 invoked from network); 17 Nov 2014 14:40:44 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-10.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:40:44 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904233"
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: [PATCH 05/10] Split notifier into a list of queues.
Thread-Index: AQHP/pc1tZWN6WJQdEKpdWS4DNR5Upxk60Qg
Date: Mon, 17 Nov 2014 14:40:43 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153755@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-6-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-6-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 05/10] Split notifier into a list of
	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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 05/10] Split notifier into a list of queues.
> 
> Move event channel registration to a list item, with 1 item per
> max-queue.
> 

Please get rid of the notifier object. Have the receiver code own the event channel in the non-split case. Have receiver and transmitter own their own in the split case then the move the event channel from the receiver/transmitter struct to the per-ring struct when multi-queue support is added.

  Paul

> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/notifier.c    | 686 +++++++++++++++++++++++++++++++++-------
> -------
>  src/xenvif/notifier.h    |  12 +-
>  src/xenvif/receiver.c    |  11 +-
>  src/xenvif/receiver.h    |   3 +-
>  src/xenvif/transmitter.c |   9 +-
>  src/xenvif/transmitter.h |   3 +-
>  6 files changed, 512 insertions(+), 212 deletions(-)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index fc6725a..02a11d8 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -52,19 +52,26 @@ typedef enum _XENVIF_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;
> +    LIST_ENTRY                  List;
>      XENBUS_STORE_INTERFACE      StoreInterface;
>      XENBUS_DEBUG_INTERFACE      DebugInterface;
>      PXENBUS_DEBUG_CALLBACK      DebugCallback;
>  };
> 
> +typedef struct _XENVIF_NOTIFIER_QUEUE {
> +    PXENVIF_NOTIFIER            Notifier;
> +    LIST_ENTRY                  ListEntry;
> +    ULONG                       Index;
> +    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];
> +} XENVIF_NOTIFIER_QUEUE, *PXENVIF_NOTIFIER_QUEUE;
> +
>  #define XENVIF_NOTIFIER_TAG 'ITON'
> 
>  static FORCEINLINE PVOID
> @@ -84,22 +91,24 @@ __NotifierFree(
>  }
> 
>  static FORCEINLINE BOOLEAN
> -__NotifierUnmask(
> -    IN  PXENVIF_NOTIFIER        Notifier,
> +__NotifierQueueUnmask(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue,
>      IN  XENVIF_NOTIFIER_EVTCHN  Index
>      )
>  {
> +    PXENVIF_NOTIFIER            Notifier;
>      PXENVIF_FRONTEND            Frontend;
>      BOOLEAN                     Pending;
> 
> +    Notifier = Queue->Notifier;
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLockAtDpcLevel(&Notifier->Lock);
> 
> -    Pending = (Notifier->Connected) ?
> +    Pending = (Notifier->Connected && Queue->Channel[Index]) ?
>                XENBUS_EVTCHN(Unmask,
>                              &Notifier->EvtchnInterface,
> -                            Notifier->Channel[Index],
> +                            Queue->Channel[Index],
>                              FALSE) :
>                FALSE;
> 
> @@ -114,14 +123,15 @@ __drv_minIRQL(DISPATCH_LEVEL)
>  __drv_requiresIRQL(DISPATCH_LEVEL)
>  __drv_sameIRQL
>  static VOID
> -NotifierDpc(
> +NotifierQueueDpc(
>      IN  PKDPC               Dpc,
>      IN  PVOID               Context,
>      IN  PVOID               Argument1,
>      IN  PVOID               Argument2
>      )
>  {
> -    PXENVIF_NOTIFIER        Notifier = Context;
> +    PXENVIF_NOTIFIER_QUEUE  Queue = Context;
> +    PXENVIF_NOTIFIER        Notifier;
>      XENVIF_NOTIFIER_EVTCHN  Index = (ULONG_PTR)Argument1;
>      PXENVIF_FRONTEND        Frontend;
>      BOOLEAN                 Pending;
> @@ -129,24 +139,25 @@ NotifierDpc(
>      UNREFERENCED_PARAMETER(Dpc);
>      UNREFERENCED_PARAMETER(Argument2);
> 
> -    ASSERT(Notifier != NULL);
> +    ASSERT(Queue != NULL);
> 
> +    Notifier = Queue->Notifier;
>      Frontend = Notifier->Frontend;
> 
>      do {
>          if (Notifier->Enabled) {
>              switch (Index) {
>              case XENVIF_NOTIFIER_EVTCHN_TX:
> -                TransmitterNotify(FrontendGetTransmitter(Frontend));
> +                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue-
> >Index);
>                  break;
> 
>              case XENVIF_NOTIFIER_EVTCHN_RX:
> -                ReceiverNotify(FrontendGetReceiver(Frontend));
> +                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
>                  break;
> 
>              case XENVIF_NOTIFIER_EVTCHN_COMBINED:
> -                TransmitterNotify(FrontendGetTransmitter(Frontend));
> -                ReceiverNotify(FrontendGetReceiver(Frontend));
> +                TransmitterNotify(FrontendGetTransmitter(Frontend), Queue-
> >Index);
> +                ReceiverNotify(FrontendGetReceiver(Frontend), Queue->Index);
>                  break;
> 
>              default:
> @@ -155,88 +166,345 @@ NotifierDpc(
>              }
>          }
> 
> -        Pending = __NotifierUnmask(Notifier, Index);
> +        Pending = __NotifierQueueUnmask(Queue, Index);
>      } while (Pending);
>  }
> 
>  static FORCEINLINE BOOLEAN
> -__NotifierEvtchnCallback(
> -    IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  XENVIF_NOTIFIER_EVTCHN     Index
> +__NotifierQueueEvtchnCallback(
> +    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
> +    IN  XENVIF_NOTIFIER_EVTCHN      Index
>      )
>  {
> -    Notifier->Events[Index]++;
> +    Queue->Events[Index]++;
> 
> -    if (KeInsertQueueDpc(&Notifier->Dpc[Index],
> +    if (KeInsertQueueDpc(&Queue->Dpc[Index],
>                           (PVOID)(ULONG_PTR)Index,
>                           NULL))
> -        Notifier->Dpcs[Index]++;
> +        Queue->Dpcs[Index]++;
> 
>      return TRUE;
>  }
> 
> -#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)                   \
> +#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)
> \
>                                                                          \
> -KSERVICE_ROUTINE    Notifier ## _Type ## EvtchnCallback;                \
> +KSERVICE_ROUTINE    NotifierQueue ## _Type ## EvtchnCallback;           \
>                                                                          \
>  BOOLEAN                                                                 \
> -Notifier ## _Type ## EvtchnCallback(                                    \
> +NotifierQueue ## _Type ## EvtchnCallback(                               \
>      IN  PKINTERRUPT         InterruptObject,                            \
>      IN  PVOID               Argument                                    \
>      )                                                                   \
>  {                                                                       \
> -    PXENVIF_NOTIFIER        Notifier = Argument;                        \
> +    PXENVIF_NOTIFIER_QUEUE  Queue = Argument;                           \
>                                                                          \
>      UNREFERENCED_PARAMETER(InterruptObject);                            \
>                                                                          \
> -    ASSERT(Notifier != NULL);                                           \
> -    return __NotifierEvtchnCallback(Notifier,                           \
> +    ASSERT(Queue != NULL);                                              \
> +    return __NotifierQueueEvtchnCallback(Queue,                         \
>                                      XENVIF_NOTIFIER_EVTCHN_ ## _Type);  \
>  }
> 
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
> -DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
> +DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
> 
> -#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
> +#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
> 
> -#define DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(_Type)   \
> -    Notifier ## _Type ## EvtchnCallback,
> +#define DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(_Type)   \
> +    NotifierQueue ## _Type ## EvtchnCallback,
> 
> -PKSERVICE_ROUTINE   NotifierEvtchnCallback[] = {
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(COMBINED)
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(RX)
> -    DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK(TX)
> +PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[] = {
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(COMBINED)
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(RX)
> +    DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK(TX)
>  };
> 
> -#undef DEFINE_XENVIF_NOTIFIER_EVTCHN_CALLBACK
> +#undef DEFINE_XENVIF_NOTIFIER_QUEUE_EVTCHN_CALLBACK
> 
> -C_ASSERT(ARRAYSIZE(NotifierEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> +C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> 
>  static VOID
> -NotifierDebugCallback(
> -    IN  PVOID           Argument,
> -    IN  BOOLEAN         Crashing
> +NotifierQueueDebugCallback(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
>      )
>  {
> -    PXENVIF_NOTIFIER    Notifier = Argument;
> -    PXENVIF_FRONTEND    Frontend;
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
>      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",
> +                     "[%u][%s]: Events = %lu Dpcs = %lu\n",
> +                     Queue->Index,
>                       ((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]);
> +                     Queue->Events[Index],
> +                     Queue->Dpcs[Index]);
> +}
> +
> +static NTSTATUS
> +NotifierQueueInitialize(
> +    IN  PXENVIF_NOTIFIER        Notifier,
> +    IN  ULONG                   QueueIndex,
> +    OUT PXENVIF_NOTIFIER_QUEUE  *Queue
> +    )
> +{
> +    ULONG       Index;
> +    NTSTATUS    status;
> +
> +    *Queue = __NotifierAllocate(sizeof (XENVIF_NOTIFIER_QUEUE));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Queue == NULL)
> +        goto fail1;
> +
> +    (*Queue)->Notifier = Notifier;
> +    (*Queue)->Index = QueueIndex;
> +
> +    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
> +        KeInitializeDpc(&(*Queue)->Dpc[Index],
> +                        NotifierQueueDpc,
> +                        *Queue);
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
> +}
> +
> +static NTSTATUS
> +NotifierQueueConnect(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER        Notifier;
> +    PXENVIF_FRONTEND        Frontend;
> +    LONG                    Index;
> +    NTSTATUS                status;
> +
> +    Notifier = Queue->Notifier;
> +    Frontend = Notifier->Frontend;
> +
> +    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
> +        PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
> +        BOOLEAN             Pending;
> +
> +        Queue->Channel[Index] = XENBUS_EVTCHN(Open,
> +                                              &Notifier->EvtchnInterface,
> +                                              XENBUS_EVTCHN_TYPE_UNBOUND,
> +                                              Callback,
> +                                              Queue,
> +                                              FrontendGetBackendDomain(Frontend),
> +                                              TRUE);
> +
> +        status = STATUS_UNSUCCESSFUL;
> +        if (Queue->Channel[Index] == NULL)
> +            goto fail1;
> +
> +        Pending = XENBUS_EVTCHN(Unmask,
> +                                &Notifier->EvtchnInterface,
> +                                Queue->Channel[Index],
> +                                FALSE);
> +        if (Pending)
> +            XENBUS_EVTCHN(Trigger,
> +                          &Notifier->EvtchnInterface,
> +                          Queue->Channel[Index]);
> +    }
> +
> +    return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    while (--Index >= 0) {
> +        XENBUS_EVTCHN(Close,
> +                      &Notifier->EvtchnInterface,
> +                      Queue->Channel[Index]);
> +        Queue->Channel[Index] = NULL;
> +
> +        Queue->Events[Index] = 0;
> +    }
> +
> +    return status;
> +}
> +
> +static NTSTATUS
> +NotifierQueueStoreWrite(
> +    IN  PXENVIF_NOTIFIER_QUEUE      Queue,
> +    IN  PXENBUS_STORE_TRANSACTION   Transaction
> +    )
> +{
> +    PXENVIF_NOTIFIER                Notifier = Queue->Notifier;
> +    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,
> +                             Queue->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;
> +}
> +
> +static NTSTATUS
> +NotifierQueueEnable(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
> +    ULONG               Index;
> +
> +    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(&Queue->Dpc[Index],
> +                             (PVOID)(ULONG_PTR)Index,
> +                             NULL))
> +            Queue->Dpcs[Index]++;
> +    }
> +
> +    return STATUS_SUCCESS;
> +}
> +
> +static VOID
> +NotifierQueueDisconnect(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Queue->Notifier;
> +    LONG                Index;
> +
> +    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    while (--Index >= 0) {
> +        if (Queue->Channel[Index] == NULL)
> +            continue;
> +
> +        XENBUS_EVTCHN(Close,
> +                      &Notifier->EvtchnInterface,
> +                      Queue->Channel[Index]);
> +        Queue->Channel[Index] = NULL;
> +
> +        Queue->Events[Index] = 0;
> +    }
> +}
> +
> +static VOID
> +NotifierQueueTeardown(
> +    IN  PXENVIF_NOTIFIER_QUEUE  Queue
> +    )
> +{
> +    LONG        Index;
> +
> +    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    while (--Index >= 0) {
> +        Queue->Dpcs[Index] = 0;
> +        RtlZeroMemory(&Queue->Dpc[Index], sizeof (KDPC));
> +    }
> +
> +    Queue->Notifier = NULL;
> +    Queue->Index = 0;
> +
> +    ASSERT(IsZeroMemory(Queue, sizeof (XENVIF_NOTIFIER_QUEUE)));
> +
> +    __NotifierFree(Queue);
> +}
> +
> +static VOID
> +NotifierDebugCallback(
> +    IN  PVOID           Argument,
> +    IN  BOOLEAN         Crashing
> +    )
> +{
> +    PXENVIF_NOTIFIER    Notifier = Argument;
> +    PLIST_ENTRY         ListEntry;
> +
> +    UNREFERENCED_PARAMETER(Crashing);
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        NotifierQueueDebugCallback(Queue);
> +    }
>  }
> 
>  NTSTATUS
> @@ -266,13 +534,41 @@ NotifierInitialize(
>      (*Notifier)->Frontend = Frontend;
> 
>      KeInitializeSpinLock(&(*Notifier)->Lock);
> -    for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++)
> -        KeInitializeDpc(&(*Notifier)->Dpc[Index],
> -                        NotifierDpc,
> -                        *Notifier);
> +    InitializeListHead(&(*Notifier)->List);
> +
> +    Index = 0;
> +    while (Index < DriverGetQueueMax()) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        status = NotifierQueueInitialize(*Notifier, Index, &Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> +
> +        InsertTailList(&(*Notifier)->List, &Queue->ListEntry);
> +        Index++;
> +    }
> 
>      return STATUS_SUCCESS;
> 
> +fail2:
> +    Error("fail2\n");
> +
> +    while (!IsListEmpty(&(*Notifier)->List)) {
> +        PLIST_ENTRY             ListEntry;
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        ListEntry = RemoveTailList(&(*Notifier)->List);
> +        ASSERT3P(ListEntry, !=, &(*Notifier)->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +
> +        NotifierQueueTeardown(Queue);
> +        --Index;
> +    }
> +    ASSERT3U(Index, ==, 0);
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -285,7 +581,7 @@ NotifierConnect(
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> -    LONG                    Index;
> +    PLIST_ENTRY             ListEntry;
>      PCHAR                   Buffer;
>      NTSTATUS                status;
> 
> @@ -308,32 +604,6 @@ NotifierConnect(
>      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",
> @@ -341,7 +611,7 @@ NotifierConnect(
>                            Notifier,
>                            &Notifier->DebugCallback);
>      if (!NT_SUCCESS(status))
> -        goto fail5;
> +        goto fail4;
> 
>      status = XENBUS_STORE(Read,
>                            &Notifier->StoreInterface,
> @@ -359,6 +629,20 @@ NotifierConnect(
>                       Buffer);
>      }
> 
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +
> +        status = NotifierQueueConnect(Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail5;
> +    }
> +
>      Notifier->Connected = TRUE;
>      KeReleaseSpinLockFromDpcLevel(&Notifier->Lock);
> 
> @@ -367,20 +651,19 @@ NotifierConnect(
>  fail5:
>      Error("fail5\n");
> 
> -    Index = XENVIF_NOTIFIER_EVTCHN_COUNT;
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -fail4:
> -    Error("fail4\n");
> -
> -    while (--Index >= 0) {
> -        XENBUS_EVTCHN(Close,
> -                      &Notifier->EvtchnInterface,
> -                      Notifier->Channel[Index]);
> -        Notifier->Channel[Index] = NULL;
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> 
> -        Notifier->Events[Index] = 0;
> +        NotifierQueueDisconnect(Queue);
>      }
> 
> +fail4:
> +    Error("fail4\n");
> +
>      XENBUS_STORE(Release, &Notifier->StoreInterface);
> 
>  fail3:
> @@ -408,54 +691,20 @@ NotifierStoreWrite(
>      )
>  {
>      PXENVIF_FRONTEND                Frontend = Notifier->Frontend;
> -    ULONG                           Index;
> +    PLIST_ENTRY                     ListEntry;
>      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);
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -            Node = "";
> -            break;
> -        }
> -
> -        Port = XENBUS_EVTCHN(GetPort,
> -                             &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> -
> -        status = XENBUS_STORE(Printf,
> -                              &Notifier->StoreInterface,
> -                              Transaction,
> -                              FrontendGetPath(Frontend),
> -                              Node,
> -                              "%u",
> -                              Port);
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index > FrontendGetQueueCount(Frontend))
> +            continue;
> 
> +        status = NotifierQueueStoreWrite(Queue,
> +                                         Transaction);
>          if (!NT_SUCCESS(status))
>              goto fail1;
>      }
> @@ -473,44 +722,34 @@ NotifierEnable(
>      IN  PXENVIF_NOTIFIER    Notifier
>      )
>  {
> -    ULONG                   Index;
> +    PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +    NTSTATUS                status;
> +
> +    Frontend = Notifier->Frontend;
> 
>      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);
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -            break;
> -        }
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index > FrontendGetQueueCount(Frontend))
> +            continue;
> 
> -        if (KeInsertQueueDpc(&Notifier->Dpc[Index],
> -                             (PVOID)(ULONG_PTR)Index,
> -                             NULL))
> -            Notifier->Dpcs[Index]++;
> +        status = NotifierQueueEnable(Queue);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
>      }
> 
>      return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +    return status;
>  }
> 
>  VOID
> @@ -528,7 +767,7 @@ NotifierDisconnect(
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> -    LONG                    Index;
> +    PLIST_ENTRY             ListEntry;
> 
>      Frontend = Notifier->Frontend;
> 
> @@ -544,14 +783,16 @@ NotifierDisconnect(
>                   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;
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> 
> -        Notifier->Events[Index] = 0;
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +
> +        NotifierQueueDisconnect(Queue);
>      }
> 
>      XENBUS_STORE(Release, &Notifier->StoreInterface);
> @@ -568,15 +809,21 @@ 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));
> +    while (!IsListEmpty(&Notifier->List)) {
> +        PLIST_ENTRY             ListEntry;
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        ListEntry = RemoveTailList(&Notifier->List);
> +        ASSERT3P(ListEntry, !=, &Notifier->List);
> +
> +        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +
> +        NotifierQueueTeardown(Queue);
>      }
> 
>      Notifier->Frontend = NULL;
> @@ -590,6 +837,7 @@ NotifierTeardown(
>      RtlZeroMemory(&Notifier->EvtchnInterface,
>                    sizeof (XENBUS_EVTCHN_INTERFACE));
> 
> +    RtlZeroMemory(&Notifier->List, sizeof(LIST_ENTRY));
>      RtlZeroMemory(&Notifier->Lock, sizeof (KSPIN_LOCK));
> 
>      ASSERT(IsZeroMemory(Notifier, sizeof (XENVIF_NOTIFIER)));
> @@ -600,85 +848,125 @@ NotifierTeardown(
>  static FORCEINLINE VOID
>  __NotifierSend(
>      IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  ULONG               Index
> +    IN  ULONG               Index,
> +    IN  ULONG               QueueIndex
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> +    PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> 
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLock(&Notifier->Lock, &Irql);
> 
> -    if (Notifier->Connected)
> +    if (!Notifier->Connected)
> +        goto done;
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +        if (Queue->Index != QueueIndex)
> +            continue;
> +
>          (VOID) XENBUS_EVTCHN(Send,
>                               &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> +                             Queue->Channel[Index]);
> +        break;
> +    }
> 
> +done:
>      KeReleaseSpinLock(&Notifier->Lock, Irql);
>  }
> 
>  VOID
>  NotifierSendTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
>      else
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  VOID
>  NotifierSendRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
>      else
> -        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierSend(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  static FORCEINLINE VOID
>  __NotifierTrigger(
>      IN  PXENVIF_NOTIFIER    Notifier,
> -    IN  ULONG               Index
> +    IN  ULONG               Index,
> +    IN  ULONG               QueueIndex
>      )
>  {
>      PXENVIF_FRONTEND        Frontend;
> +    PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> 
>      Frontend = Notifier->Frontend;
> 
>      KeAcquireSpinLock(&Notifier->Lock, &Irql);
> 
> -    if (Notifier->Connected)
> +    if (!Notifier->Connected)
> +        goto done;
> +
> +    for (ListEntry = Notifier->List.Flink;
> +         ListEntry != &Notifier->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_NOTIFIER_QUEUE  Queue;
> +
> +        Queue = CONTAINING_RECORD(ListEntry, XENVIF_NOTIFIER_QUEUE,
> ListEntry);
> +        if (Queue->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> +        if (Queue->Index != QueueIndex)
> +            continue;
> +
>          (VOID) XENBUS_EVTCHN(Trigger,
>                               &Notifier->EvtchnInterface,
> -                             Notifier->Channel[Index]);
> +                             Queue->Channel[Index]);
> +        break;
> +    }
> 
> +done:
>      KeReleaseSpinLock(&Notifier->Lock, Irql);
>  }
> 
>  VOID
>  NotifierTriggerTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_TX, Queue);
>      else
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> 
>  VOID
>  NotifierTriggerRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      )
>  {
>      if (Notifier->Split)
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_RX, Queue);
>      else
> -        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED);
> +        __NotifierTrigger(Notifier, XENVIF_NOTIFIER_EVTCHN_COMBINED,
> Queue);
>  }
> diff --git a/src/xenvif/notifier.h b/src/xenvif/notifier.h
> index 2f06a6f..fd28060 100644
> --- a/src/xenvif/notifier.h
> +++ b/src/xenvif/notifier.h
> @@ -78,22 +78,26 @@ NotifierTeardown(
> 
>  extern VOID
>  NotifierSendTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierSendRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierTriggerTx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  extern VOID
>  NotifierTriggerRx(
> -    IN  PXENVIF_NOTIFIER    Notifier
> +    IN  PXENVIF_NOTIFIER    Notifier,
> +    IN  ULONG               Queue
>      );
> 
>  #endif  // _XENVIF_NOTIFIER_H
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 626feed..85ebcf9 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -1397,7 +1397,7 @@ __ReceiverRingReturnPacket(
>              Receiver = Ring->Receiver;
>              Frontend = Receiver->Frontend;
> 
> -            NotifierTriggerRx(FrontendGetNotifier(Frontend));
> +            NotifierTriggerRx(FrontendGetNotifier(Frontend), Ring->Index);
>          }
> 
>          if (!Locked)
> @@ -1477,7 +1477,7 @@ __ReceiverRingPushRequests(
>          Receiver = Ring->Receiver;
>          Frontend = Receiver->Frontend;
> 
> -        NotifierSendRx(FrontendGetNotifier(Frontend));
> +        NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
>      }
> 
>      Ring->RequestsPushed = Ring->RequestsPosted;
> @@ -1869,7 +1869,7 @@ ReceiverRingWatchdog(
> 
>                  // Try to move things along
>                  ReceiverRingPoll(Ring);
> -                NotifierSendRx(FrontendGetNotifier(Frontend));
> +                NotifierSendRx(FrontendGetNotifier(Frontend), Ring->Index);
>              }
> 
>              KeMemoryBarrier();
> @@ -2941,7 +2941,8 @@ ReceiverWaitForPackets(
> 
>  VOID
>  ReceiverNotify(
> -    IN  PXENVIF_RECEIVER    Receiver
> +    IN  PXENVIF_RECEIVER    Receiver,
> +    IN  ULONG               Index
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> @@ -2952,6 +2953,8 @@ ReceiverNotify(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> 
>          __ReceiverRingNotify(Ring);
>      }
> diff --git a/src/xenvif/receiver.h b/src/xenvif/receiver.h
> index 8009858..1505887 100644
> --- a/src/xenvif/receiver.h
> +++ b/src/xenvif/receiver.h
> @@ -79,7 +79,8 @@ ReceiverTeardown(
> 
>  extern VOID
>  ReceiverNotify(
> -    IN  PXENVIF_RECEIVER    Receiver
> +    IN  PXENVIF_RECEIVER    Receiver,
> +    IN  ULONG               Index
>      );
> 
>  extern VOID
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index bea46f1..477fecc 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2195,7 +2195,7 @@ __TransmitterRingPushRequests(
>          Transmitter = Ring->Transmitter;
>          Frontend = Transmitter->Frontend;
> 
> -        NotifierSendTx(FrontendGetNotifier(Frontend));
> +        NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
>      }
> 
>      Ring->RequestsPushed = Ring->RequestsPosted;
> @@ -2624,7 +2624,7 @@ TransmitterRingWatchdog(
>                               Ring->DebugCallback);
> 
>                  // Try to move things along
> -                NotifierSendTx(FrontendGetNotifier(Frontend));
> +                NotifierSendTx(FrontendGetNotifier(Frontend), Ring->Index);
>                  TransmitterRingPoll(Ring);
>              }
> 
> @@ -3972,7 +3972,8 @@ TransmitterQueryRingSize(
> 
>  VOID
>  TransmitterNotify(
> -    IN  PXENVIF_TRANSMITTER Transmitter
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  ULONG               Index
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> @@ -3983,6 +3984,8 @@ TransmitterNotify(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> 
>          __TransmitterRingNotify(Ring);
>      }
> diff --git a/src/xenvif/transmitter.h b/src/xenvif/transmitter.h
> index 7e10603..3e56b34 100644
> --- a/src/xenvif/transmitter.h
> +++ b/src/xenvif/transmitter.h
> @@ -79,7 +79,8 @@ TransmitterTeardown(
> 
>  extern VOID
>  TransmitterNotify(
> -    IN  PXENVIF_TRANSMITTER Transmitter
> +    IN  PXENVIF_TRANSMITTER Transmitter,
> +    IN  ULONG               Index
>      );
> 
>  extern VOID
> --
> 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 Mon Nov 17 14:42:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:42:44 +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 1XqNVs-0005Pc-GQ; Mon, 17 Nov 2014 14:42:44 +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 1XqNVr-0005O9-IP
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:42:43 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	55/8F-09842-2690A645; Mon, 17 Nov 2014 14:42:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-21.messagelabs.com!1416235361!6040279!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 32616 invoked from network); 17 Nov 2014 14:42:41 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-13.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:42:41 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904296"
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: [PATCH 06/10] Dont call through to inactive queues
Thread-Index: AQHP/pc0KzNC4xBhBESyoWViBYsneJxk7C2A
Date: Mon, 17 Nov 2014 14:42:40 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153772@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-7-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-7-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 06/10] Dont call through to inactive
	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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 06/10] Dont call through to inactive queues
> 
> Queues where Index >= QueueCount are inactive, and should not
> Connect, Disconnect, Enable, Disable or write to the store.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

In isolation, this is fine.

  Paul.

> ---
>  include/vif_interface.h  |  2 ++
>  src/xenvif/receiver.c    | 22 ++++++++++++++++++++++
>  src/xenvif/transmitter.c | 26 ++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 4ce61c4..83e3846 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
>      ULONG                                       Length;
>      /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Hash value calculated from packet's headers */
> +    ULONGLONG                                   HashValue;
>      /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
>      /*! Information passed up from subscriber for packet completion */
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 85ebcf9..4d7f19b 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2477,6 +2477,8 @@ ReceiverConnect(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingConnect(Ring);
>          if (!NT_SUCCESS(status))
> @@ -2509,6 +2511,8 @@ fail3:
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisconnect(Ring);
> 
> @@ -2668,6 +2672,8 @@ ReceiverStoreWrite(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingStoreWrite(Ring, Transaction);
>          if (!NT_SUCCESS(status))
> @@ -2714,6 +2720,8 @@ ReceiverEnable(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingEnable(Ring);
>          if (!NT_SUCCESS(status))
> @@ -2731,6 +2739,8 @@ fail1:
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisable(Ring);
>      }
> @@ -2744,6 +2754,9 @@ ReceiverDisable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Receiver->Frontend;
> 
>      for (ListEntry = Receiver->List.Blink;
>           ListEntry != &Receiver->List;
> @@ -2751,6 +2764,8 @@ ReceiverDisable(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisable(Ring);
>      }
> @@ -2777,6 +2792,8 @@ ReceiverDisconnect(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisconnect(Ring);
>      }
> @@ -2842,6 +2859,9 @@ ReceiverSetOffloadOptions(
>      )
>  {
>      PLIST_ENTRY                     ListEntry;
> +    PXENVIF_FRONTEND                Frontend;
> +
> +    Frontend = Receiver->Frontend;
> 
>      if (Receiver->AllowGsoPackets == 0) {
>          Warning("RECEIVER GSO DISALLOWED\n");
> @@ -2855,6 +2875,8 @@ ReceiverSetOffloadOptions(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingSetOffloadOptions(Ring, Options);
>      }
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 477fecc..c5b05b3 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3494,6 +3494,8 @@ TransmitterConnect(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __TransmitterRingConnect(Ring);
>          if (!NT_SUCCESS(status))
> @@ -3526,6 +3528,8 @@ fail3:
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisconnect(Ring);
> 
> @@ -3553,6 +3557,9 @@ TransmitterStoreWrite(
>  {
>      PLIST_ENTRY                     ListEntry;
>      NTSTATUS                        status;
> +    PXENVIF_FRONTEND                Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Flink;
>           ListEntry != &Transmitter->List;
> @@ -3560,6 +3567,8 @@ TransmitterStoreWrite(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __TransmitterRingStoreWrite(Ring, Transaction);
>          if (!NT_SUCCESS(status))
> @@ -3580,6 +3589,9 @@ TransmitterEnable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Flink;
>           ListEntry != &Transmitter->List;
> @@ -3587,6 +3599,8 @@ TransmitterEnable(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingEnable(Ring);
>      }
> @@ -3600,6 +3614,9 @@ TransmitterDisable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Blink;
>           ListEntry != &Transmitter->List;
> @@ -3607,6 +3624,8 @@ TransmitterDisable(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisable(Ring);
>      }
> @@ -3633,6 +3652,8 @@ TransmitterDisconnect(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisconnect(Ring);
>      }
> @@ -3943,6 +3964,9 @@ TransmitterAbortPackets(
>  {
>      PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
> @@ -3952,6 +3976,8 @@ TransmitterAbortPackets(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingAbortPackets(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 Mon Nov 17 14:42:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:42:44 +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 1XqNVs-0005Pc-GQ; Mon, 17 Nov 2014 14:42:44 +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 1XqNVr-0005O9-IP
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:42:43 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	55/8F-09842-2690A645; Mon, 17 Nov 2014 14:42:42 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-21.messagelabs.com!1416235361!6040279!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 32616 invoked from network); 17 Nov 2014 14:42:41 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-13.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:42:41 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904296"
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: [PATCH 06/10] Dont call through to inactive queues
Thread-Index: AQHP/pc0KzNC4xBhBESyoWViBYsneJxk7C2A
Date: Mon, 17 Nov 2014 14:42:40 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153772@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-7-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-7-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 06/10] Dont call through to inactive
	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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 06/10] Dont call through to inactive queues
> 
> Queues where Index >= QueueCount are inactive, and should not
> Connect, Disconnect, Enable, Disable or write to the store.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

In isolation, this is fine.

  Paul.

> ---
>  include/vif_interface.h  |  2 ++
>  src/xenvif/receiver.c    | 22 ++++++++++++++++++++++
>  src/xenvif/transmitter.c | 26 ++++++++++++++++++++++++++
>  3 files changed, 50 insertions(+)
> 
> diff --git a/include/vif_interface.h b/include/vif_interface.h
> index 4ce61c4..83e3846 100644
> --- a/include/vif_interface.h
> +++ b/include/vif_interface.h
> @@ -280,6 +280,8 @@ struct _XENVIF_TRANSMITTER_PACKET_V2 {
>      ULONG                                       Length;
>      /*! Opaque cookie used to store context information for packet return */
>      PVOID                                       Cookie;
> +    /*! Hash value calculated from packet's headers */
> +    ULONGLONG                                   HashValue;
>      /*! Packet information passed down to subscriber */
>      XENVIF_TRANSMITTER_PACKET_SEND_INFO         Send;
>      /*! Information passed up from subscriber for packet completion */
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 85ebcf9..4d7f19b 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2477,6 +2477,8 @@ ReceiverConnect(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingConnect(Ring);
>          if (!NT_SUCCESS(status))
> @@ -2509,6 +2511,8 @@ fail3:
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisconnect(Ring);
> 
> @@ -2668,6 +2672,8 @@ ReceiverStoreWrite(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingStoreWrite(Ring, Transaction);
>          if (!NT_SUCCESS(status))
> @@ -2714,6 +2720,8 @@ ReceiverEnable(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __ReceiverRingEnable(Ring);
>          if (!NT_SUCCESS(status))
> @@ -2731,6 +2739,8 @@ fail1:
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisable(Ring);
>      }
> @@ -2744,6 +2754,9 @@ ReceiverDisable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Receiver->Frontend;
> 
>      for (ListEntry = Receiver->List.Blink;
>           ListEntry != &Receiver->List;
> @@ -2751,6 +2764,8 @@ ReceiverDisable(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisable(Ring);
>      }
> @@ -2777,6 +2792,8 @@ ReceiverDisconnect(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingDisconnect(Ring);
>      }
> @@ -2842,6 +2859,9 @@ ReceiverSetOffloadOptions(
>      )
>  {
>      PLIST_ENTRY                     ListEntry;
> +    PXENVIF_FRONTEND                Frontend;
> +
> +    Frontend = Receiver->Frontend;
> 
>      if (Receiver->AllowGsoPackets == 0) {
>          Warning("RECEIVER GSO DISALLOWED\n");
> @@ -2855,6 +2875,8 @@ ReceiverSetOffloadOptions(
>          PXENVIF_RECEIVER_RING   Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __ReceiverRingSetOffloadOptions(Ring, Options);
>      }
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index 477fecc..c5b05b3 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3494,6 +3494,8 @@ TransmitterConnect(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __TransmitterRingConnect(Ring);
>          if (!NT_SUCCESS(status))
> @@ -3526,6 +3528,8 @@ fail3:
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisconnect(Ring);
> 
> @@ -3553,6 +3557,9 @@ TransmitterStoreWrite(
>  {
>      PLIST_ENTRY                     ListEntry;
>      NTSTATUS                        status;
> +    PXENVIF_FRONTEND                Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Flink;
>           ListEntry != &Transmitter->List;
> @@ -3560,6 +3567,8 @@ TransmitterStoreWrite(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          status = __TransmitterRingStoreWrite(Ring, Transaction);
>          if (!NT_SUCCESS(status))
> @@ -3580,6 +3589,9 @@ TransmitterEnable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Flink;
>           ListEntry != &Transmitter->List;
> @@ -3587,6 +3599,8 @@ TransmitterEnable(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingEnable(Ring);
>      }
> @@ -3600,6 +3614,9 @@ TransmitterDisable(
>      )
>  {
>      PLIST_ENTRY             ListEntry;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      for (ListEntry = Transmitter->List.Blink;
>           ListEntry != &Transmitter->List;
> @@ -3607,6 +3624,8 @@ TransmitterDisable(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisable(Ring);
>      }
> @@ -3633,6 +3652,8 @@ TransmitterDisconnect(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingDisconnect(Ring);
>      }
> @@ -3943,6 +3964,9 @@ TransmitterAbortPackets(
>  {
>      PLIST_ENTRY             ListEntry;
>      KIRQL                   Irql;
> +    PXENVIF_FRONTEND        Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> 
>      KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
> @@ -3952,6 +3976,8 @@ TransmitterAbortPackets(
>          PXENVIF_TRANSMITTER_RING    Ring;
> 
>          Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index >= FrontendGetQueueCount(Frontend))
> +            continue;
> 
>          __TransmitterRingAbortPackets(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 Mon Nov 17 14:50:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:50: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 1XqNd8-0005uG-W3; Mon, 17 Nov 2014 14:50:14 +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 1XqNd7-0005tw-AW
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:50:13 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	EA/EF-25727-42B0A645; Mon, 17 Nov 2014 14:50:12 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1416235811!11857198!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14245 invoked from network); 17 Nov 2014 14:50:11 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:50:11 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904933"
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: [PATCH 07/10] Write queue values under <frontend>/queue-<id>
	and "multi-queue-num-queues"
Thread-Index: AQHP/pc0nwhXxM+nmEuSyCHj2zEFY5xk7KWw
Date: Mon, 17 Nov 2014 14:50:10 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153799@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-8-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-8-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 07/10] Write queue values under
 <frontend>/queue-<id> and "multi-queue-num-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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 07/10] Write queue values under <frontend>/queue-<id>
> and "multi-queue-num-queues"
> 
> When multi-queues are used, queue event-channel and ring-refs are written
> under
> "device/vif/<number>/queue-<id>". When the number of active queues is
> 1, write
> the event-channel and ring-refs inder "device/vif/<number>" as before.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/frontend.c    | 34 ++++++++++++++++++++++++++++++++++
>  src/xenvif/frontend.h    |  8 ++++++++
>  src/xenvif/notifier.c    |  8 +++++++-
>  src/xenvif/receiver.c    |  6 +++++-
>  src/xenvif/transmitter.c |  6 +++++-
>  5 files changed, 59 insertions(+), 3 deletions(-)
> 
> diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
> index 9a6cbde..846b051 100644
> --- a/src/xenvif/frontend.c
> +++ b/src/xenvif/frontend.c
> @@ -156,6 +156,30 @@ FrontendGetPath(
>      return __FrontendGetPath(Frontend);
>  }
> 
> +PCHAR
> +FrontendGetQueuePath(
> +    IN  PXENVIF_FRONTEND    Frontend,
> +    IN  ULONG               Index,
> +    IN  PCHAR               Buffer,
> +    IN  ULONG               Length
> +    )
> +{
> +    if (Frontend->MultiQueueCount == 1) {
> +        return __FrontendGetPath(Frontend);

No need for an 'else'.

> +    } else {
> +        NTSTATUS    status;
> +
> +        status = RtlStringCbPrintfA(Buffer,
> +                                    Length,
> +                                    "%s/queue-%u",
> +                                    __FrontendGetPath(Frontend),
> +                                    Index);
> +        ASSERT(NT_SUCCESS(status));
> +
> +        return Buffer;
> +    }

Any chance that a set of const char * could be prepped at start of day rather than generating this path on the fly? Then you would net need to pass the buffer in.

  Paul

> +}
> +
>  static FORCEINLINE PCHAR
>  __FrontendGetPrefix(
>      IN  PXENVIF_FRONTEND    Frontend
> @@ -1380,6 +1404,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,
> diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
> index 20cd390..75cb4a0 100644
> --- a/src/xenvif/frontend.h
> +++ b/src/xenvif/frontend.h
> @@ -103,6 +103,14 @@ FrontendGetPath(
>      );
> 
>  extern PCHAR
> +FrontendGetQueuePath(
> +    IN  PXENVIF_FRONTEND    Frontend,
> +    IN  ULONG               Index,
> +    IN  PCHAR               Buffer,
> +    IN  ULONG               Length
> +    );
> +
> +extern PCHAR
>  FrontendGetBackendPath(
>      IN  PXENVIF_FRONTEND    Frontend
>      );
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 02a11d8..573ffaa 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -224,6 +224,8 @@ PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[]
> = {
> 
>  C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> 
> +#define MAX_BUFFER      128
> +
>  static VOID
>  NotifierQueueDebugCallback(
>      IN  PXENVIF_NOTIFIER_QUEUE  Queue
> @@ -346,6 +348,7 @@ NotifierQueueStoreWrite(
>      for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
>          PCHAR   Node;
>          ULONG   Port;
> +        CHAR    Buffer[MAX_BUFFER];
> 
>          switch (Index) {
>          case XENVIF_NOTIFIER_EVTCHN_COMBINED:
> @@ -383,7 +386,10 @@ NotifierQueueStoreWrite(
>          status = XENBUS_STORE(Printf,
>                                &Notifier->StoreInterface,
>                                Transaction,
> -                              FrontendGetPath(Frontend),
> +                              FrontendGetQueuePath(Frontend,
> +                                                   Queue->Index,
> +                                                   Buffer,
> +                                                   sizeof(Buffer)),
>                                Node,
>                                "%u",
>                                Port);
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 4d7f19b..01ab248 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2101,6 +2101,7 @@ __ReceiverRingStoreWrite(
>  {
>      PXENVIF_RECEIVER                Receiver;
>      PXENVIF_FRONTEND                Frontend;
> +    CHAR                            Buffer[MAXNAMELEN];
>      NTSTATUS                        status;
> 
>      Receiver = Ring->Receiver;
> @@ -2109,7 +2110,10 @@ __ReceiverRingStoreWrite(
>      status = XENBUS_STORE(Printf,
>                            &Receiver->StoreInterface,
>                            Transaction,
> -                          FrontendGetPath(Frontend),
> +                          FrontendGetQueuePath(Frontend,
> +                                               Ring->Index,
> +                                               Buffer,
> +                                               sizeof(Buffer)),
>                            "rx-ring-ref",
>                            "%u",
>                            GranterGetReference(FrontendGetGranter(Frontend),
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index c5b05b3..f1a3e9e 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2956,6 +2956,7 @@ __TransmitterRingStoreWrite(
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
> +    CHAR                            Buffer[MAXNAMELEN];
>      NTSTATUS                        status;
> 
>      Transmitter = Ring->Transmitter;
> @@ -2964,7 +2965,10 @@ __TransmitterRingStoreWrite(
>      status = XENBUS_STORE(Printf,
>                            &Transmitter->StoreInterface,
>                            Transaction,
> -                          FrontendGetPath(Frontend),
> +                          FrontendGetQueuePath(Frontend,
> +                                               Ring->Index,
> +                                               Buffer,
> +                                               sizeof(Buffer)),
>                            "tx-ring-ref",
>                            "%u",
>                            GranterGetReference(FrontendGetGranter(Frontend),
> --
> 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 Mon Nov 17 14:50:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:50: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 1XqNd8-0005uG-W3; Mon, 17 Nov 2014 14:50:14 +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 1XqNd7-0005tw-AW
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:50:13 +0000
Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id
	EA/EF-25727-42B0A645; Mon, 17 Nov 2014 14:50:12 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-31.messagelabs.com!1416235811!11857198!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 14245 invoked from network); 17 Nov 2014 14:50:11 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:50:11 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26904933"
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: [PATCH 07/10] Write queue values under <frontend>/queue-<id>
	and "multi-queue-num-queues"
Thread-Index: AQHP/pc0nwhXxM+nmEuSyCHj2zEFY5xk7KWw
Date: Mon, 17 Nov 2014 14:50:10 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD011153799@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-8-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-8-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 07/10] Write queue values under
 <frontend>/queue-<id> and "multi-queue-num-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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 07/10] Write queue values under <frontend>/queue-<id>
> and "multi-queue-num-queues"
> 
> When multi-queues are used, queue event-channel and ring-refs are written
> under
> "device/vif/<number>/queue-<id>". When the number of active queues is
> 1, write
> the event-channel and ring-refs inder "device/vif/<number>" as before.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/frontend.c    | 34 ++++++++++++++++++++++++++++++++++
>  src/xenvif/frontend.h    |  8 ++++++++
>  src/xenvif/notifier.c    |  8 +++++++-
>  src/xenvif/receiver.c    |  6 +++++-
>  src/xenvif/transmitter.c |  6 +++++-
>  5 files changed, 59 insertions(+), 3 deletions(-)
> 
> diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
> index 9a6cbde..846b051 100644
> --- a/src/xenvif/frontend.c
> +++ b/src/xenvif/frontend.c
> @@ -156,6 +156,30 @@ FrontendGetPath(
>      return __FrontendGetPath(Frontend);
>  }
> 
> +PCHAR
> +FrontendGetQueuePath(
> +    IN  PXENVIF_FRONTEND    Frontend,
> +    IN  ULONG               Index,
> +    IN  PCHAR               Buffer,
> +    IN  ULONG               Length
> +    )
> +{
> +    if (Frontend->MultiQueueCount == 1) {
> +        return __FrontendGetPath(Frontend);

No need for an 'else'.

> +    } else {
> +        NTSTATUS    status;
> +
> +        status = RtlStringCbPrintfA(Buffer,
> +                                    Length,
> +                                    "%s/queue-%u",
> +                                    __FrontendGetPath(Frontend),
> +                                    Index);
> +        ASSERT(NT_SUCCESS(status));
> +
> +        return Buffer;
> +    }

Any chance that a set of const char * could be prepped at start of day rather than generating this path on the fly? Then you would net need to pass the buffer in.

  Paul

> +}
> +
>  static FORCEINLINE PCHAR
>  __FrontendGetPrefix(
>      IN  PXENVIF_FRONTEND    Frontend
> @@ -1380,6 +1404,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,
> diff --git a/src/xenvif/frontend.h b/src/xenvif/frontend.h
> index 20cd390..75cb4a0 100644
> --- a/src/xenvif/frontend.h
> +++ b/src/xenvif/frontend.h
> @@ -103,6 +103,14 @@ FrontendGetPath(
>      );
> 
>  extern PCHAR
> +FrontendGetQueuePath(
> +    IN  PXENVIF_FRONTEND    Frontend,
> +    IN  ULONG               Index,
> +    IN  PCHAR               Buffer,
> +    IN  ULONG               Length
> +    );
> +
> +extern PCHAR
>  FrontendGetBackendPath(
>      IN  PXENVIF_FRONTEND    Frontend
>      );
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 02a11d8..573ffaa 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -224,6 +224,8 @@ PKSERVICE_ROUTINE   NotifierQueueEvtchnCallback[]
> = {
> 
>  C_ASSERT(ARRAYSIZE(NotifierQueueEvtchnCallback) ==
> XENVIF_NOTIFIER_EVTCHN_COUNT);
> 
> +#define MAX_BUFFER      128
> +
>  static VOID
>  NotifierQueueDebugCallback(
>      IN  PXENVIF_NOTIFIER_QUEUE  Queue
> @@ -346,6 +348,7 @@ NotifierQueueStoreWrite(
>      for (Index = 0; Index < XENVIF_NOTIFIER_EVTCHN_COUNT; Index++) {
>          PCHAR   Node;
>          ULONG   Port;
> +        CHAR    Buffer[MAX_BUFFER];
> 
>          switch (Index) {
>          case XENVIF_NOTIFIER_EVTCHN_COMBINED:
> @@ -383,7 +386,10 @@ NotifierQueueStoreWrite(
>          status = XENBUS_STORE(Printf,
>                                &Notifier->StoreInterface,
>                                Transaction,
> -                              FrontendGetPath(Frontend),
> +                              FrontendGetQueuePath(Frontend,
> +                                                   Queue->Index,
> +                                                   Buffer,
> +                                                   sizeof(Buffer)),
>                                Node,
>                                "%u",
>                                Port);
> diff --git a/src/xenvif/receiver.c b/src/xenvif/receiver.c
> index 4d7f19b..01ab248 100644
> --- a/src/xenvif/receiver.c
> +++ b/src/xenvif/receiver.c
> @@ -2101,6 +2101,7 @@ __ReceiverRingStoreWrite(
>  {
>      PXENVIF_RECEIVER                Receiver;
>      PXENVIF_FRONTEND                Frontend;
> +    CHAR                            Buffer[MAXNAMELEN];
>      NTSTATUS                        status;
> 
>      Receiver = Ring->Receiver;
> @@ -2109,7 +2110,10 @@ __ReceiverRingStoreWrite(
>      status = XENBUS_STORE(Printf,
>                            &Receiver->StoreInterface,
>                            Transaction,
> -                          FrontendGetPath(Frontend),
> +                          FrontendGetQueuePath(Frontend,
> +                                               Ring->Index,
> +                                               Buffer,
> +                                               sizeof(Buffer)),
>                            "rx-ring-ref",
>                            "%u",
>                            GranterGetReference(FrontendGetGranter(Frontend),
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index c5b05b3..f1a3e9e 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -2956,6 +2956,7 @@ __TransmitterRingStoreWrite(
>  {
>      PXENVIF_TRANSMITTER             Transmitter;
>      PXENVIF_FRONTEND                Frontend;
> +    CHAR                            Buffer[MAXNAMELEN];
>      NTSTATUS                        status;
> 
>      Transmitter = Ring->Transmitter;
> @@ -2964,7 +2965,10 @@ __TransmitterRingStoreWrite(
>      status = XENBUS_STORE(Printf,
>                            &Transmitter->StoreInterface,
>                            Transaction,
> -                          FrontendGetPath(Frontend),
> +                          FrontendGetQueuePath(Frontend,
> +                                               Ring->Index,
> +                                               Buffer,
> +                                               sizeof(Buffer)),
>                            "tx-ring-ref",
>                            "%u",
>                            GranterGetReference(FrontendGetGranter(Frontend),
> --
> 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 Mon Nov 17 14:53:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:53: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 1XqNg3-0006Dy-JK; Mon, 17 Nov 2014 14:53:15 +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 1XqNg2-0006Dl-Hp
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:53:14 +0000
Received: from [85.158.139.211] by server-1.bemta-5.messagelabs.com id
	2C/EA-24124-9DB0A645; Mon, 17 Nov 2014 14:53:13 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-206.messagelabs.com!1416235993!11786393!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9130 invoked from network); 17 Nov 2014 14:53:13 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:53:13 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905053"
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: [PATCH 08/10] Stear transmitter packets to queues
Thread-Index: AQHP/pczOKX1lgCitkqMVIcNfYlh7Jxk7mwg
Date: Mon, 17 Nov 2014 14:53:12 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537B1@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-9-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-9-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 08/10] Stear transmitter packets to 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

s/Stear/Steer

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 08/10] Stear transmitter packets to queues
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/transmitter.c | 109
> +++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 92 insertions(+), 17 deletions(-)
> 
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index f1a3e9e..38e9c62 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3782,6 +3782,96 @@ fail1:
>      return status;
>  }
> 
> +static FORCEINLINE ULONG
> +__TransmitterGetQueue(
> +    IN  PXENVIF_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    PXENVIF_FRONTEND    Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> +
> +    // simplistic mod of hash value
> +    // this should become a lookup operation using a shared table
> +    return (ULONG)(Packet->HashValue %
> FrontendGetQueueCount(Frontend));
> +}
> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_RING
> +__TransmitterGetRing(
> +    IN  PXENVIF_TRANSMITTER             Transmitter,
> +    IN  ULONG                           Index
> +    )
> +{
> +    PLIST_ENTRY     ListEntry;
> +
> +    ASSERT3U(Index, <, FrontendGetQueueCount(Transmitter->Frontend));
> +
> +    for (ListEntry = Transmitter->List.Flink;
> +         ListEntry != &Transmitter->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_TRANSMITTER_RING    Ring;
> +
> +        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> +
> +        return Ring;
> +    }
> +
> +    // return queue-0
> +    ListEntry = Transmitter->List.Flink;
> +    return CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +}

Possibly time to change from a list of queues to an array?

  Paul

> +
> +static FORCEINLINE VOID
> +__TransmitterQueuePackets(
> +    IN  PXENVIF_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
> +    )
> +{
> +    PXENVIF_FRONTEND            Frontend;
> +    PLIST_ENTRY                 ListEntry;
> +    PXENVIF_TRANSMITTER_RING    Ring;
> +
> +    Frontend = Transmitter->Frontend;
> +
> +    if (FrontendGetQueueCount(Frontend) == 1) {
> +        ListEntry = Transmitter->List.Flink;
> +        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +
> +        __TransmitterRingQueuePackets(Ring, List);
> +    } else {
> +        while (!IsListEmpty(List)) {
> +            LIST_ENTRY                      SubList;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +            ULONG                           Queue;
> +
> +            InitializeListHead(&SubList);
> +
> +            Packet = CONTAINING_RECORD(List->Flink,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +            Queue = __TransmitterGetQueue(Transmitter, Packet);
> +
> +            ListEntry = RemoveHeadList(List);
> +            ASSERT3U(ListEntry, !=, List);
> +            InsertTailList(&SubList, ListEntry);
> +
> +            while (!IsListEmpty(List)) {
> +                Packet = CONTAINING_RECORD(List->Flink,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +                if (__TransmitterGetQueue(Transmitter, Packet) != Queue)
> +                    break;
> +
> +                ListEntry = RemoveHeadList(List);
> +                ASSERT3U(ListEntry, !=, List);
> +                InsertTailList(&SubList, ListEntry);
> +            }
> +
> +            Ring = __TransmitterGetRing(Transmitter, Queue);
> +            __TransmitterRingQueuePackets(Ring, &SubList);
> +        }
> +    }
> +}
> +
>  VOID
>  TransmitterQueuePacketsV1(
>      IN  PXENVIF_TRANSMITTER             Transmitter,
> @@ -3798,8 +3888,6 @@ TransmitterQueuePacketsV1(
>           NULL)
> 
>      LIST_ENTRY                      List;
> -    PLIST_ENTRY                     ListEntry;
> -    PXENVIF_TRANSMITTER_RING        Ring;
> 
>      InitializeListHead(&List);
>      while (HeadPacket != NULL) {
> @@ -3828,12 +3916,7 @@ TransmitterQueuePacketsV1(
>          HeadPacket = HeadPacket->Next;
>      }
> 
> -    // 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);
> -
> -    __TransmitterRingQueuePackets(Ring, &List);
> +    __TransmitterQueuePackets(Transmitter, &List);
> 
>      // if HeadPacket != NULL, errors occured and need returning
>      if (HeadPacket != NULL) {
> @@ -3861,15 +3944,7 @@ TransmitterQueuePacketsV2(
>      IN  PLIST_ENTRY         List
>      )
>  {
> -    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);
> -
> -    __TransmitterRingQueuePackets(Ring, List);
> +    __TransmitterQueuePackets(Transmitter, List);
>  }
> 
>  static BOOLEAN
> --
> 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 Mon Nov 17 14:53:15 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:53: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 1XqNg3-0006Dy-JK; Mon, 17 Nov 2014 14:53:15 +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 1XqNg2-0006Dl-Hp
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:53:14 +0000
Received: from [85.158.139.211] by server-1.bemta-5.messagelabs.com id
	2C/EA-24124-9DB0A645; Mon, 17 Nov 2014 14:53:13 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-5.tower-206.messagelabs.com!1416235993!11786393!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=0.0 required=7.0 tests=UPPERCASE_25_50,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 9130 invoked from network); 17 Nov 2014 14:53:13 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-5.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:53:13 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905053"
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: [PATCH 08/10] Stear transmitter packets to queues
Thread-Index: AQHP/pczOKX1lgCitkqMVIcNfYlh7Jxk7mwg
Date: Mon, 17 Nov 2014 14:53:12 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537B1@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-9-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-9-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 08/10] Stear transmitter packets to 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

s/Stear/Steer

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 08/10] Stear transmitter packets to queues
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenvif/transmitter.c | 109
> +++++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 92 insertions(+), 17 deletions(-)
> 
> diff --git a/src/xenvif/transmitter.c b/src/xenvif/transmitter.c
> index f1a3e9e..38e9c62 100644
> --- a/src/xenvif/transmitter.c
> +++ b/src/xenvif/transmitter.c
> @@ -3782,6 +3782,96 @@ fail1:
>      return status;
>  }
> 
> +static FORCEINLINE ULONG
> +__TransmitterGetQueue(
> +    IN  PXENVIF_TRANSMITTER             Transmitter,
> +    IN  PXENVIF_TRANSMITTER_PACKET_V2   Packet
> +    )
> +{
> +    PXENVIF_FRONTEND    Frontend;
> +
> +    Frontend = Transmitter->Frontend;
> +
> +    // simplistic mod of hash value
> +    // this should become a lookup operation using a shared table
> +    return (ULONG)(Packet->HashValue %
> FrontendGetQueueCount(Frontend));
> +}
> +
> +static FORCEINLINE PXENVIF_TRANSMITTER_RING
> +__TransmitterGetRing(
> +    IN  PXENVIF_TRANSMITTER             Transmitter,
> +    IN  ULONG                           Index
> +    )
> +{
> +    PLIST_ENTRY     ListEntry;
> +
> +    ASSERT3U(Index, <, FrontendGetQueueCount(Transmitter->Frontend));
> +
> +    for (ListEntry = Transmitter->List.Flink;
> +         ListEntry != &Transmitter->List;
> +         ListEntry = ListEntry->Flink) {
> +        PXENVIF_TRANSMITTER_RING    Ring;
> +
> +        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +        if (Ring->Index != Index)
> +            continue;
> +
> +        return Ring;
> +    }
> +
> +    // return queue-0
> +    ListEntry = Transmitter->List.Flink;
> +    return CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +}

Possibly time to change from a list of queues to an array?

  Paul

> +
> +static FORCEINLINE VOID
> +__TransmitterQueuePackets(
> +    IN  PXENVIF_TRANSMITTER     Transmitter,
> +    IN  PLIST_ENTRY             List
> +    )
> +{
> +    PXENVIF_FRONTEND            Frontend;
> +    PLIST_ENTRY                 ListEntry;
> +    PXENVIF_TRANSMITTER_RING    Ring;
> +
> +    Frontend = Transmitter->Frontend;
> +
> +    if (FrontendGetQueueCount(Frontend) == 1) {
> +        ListEntry = Transmitter->List.Flink;
> +        Ring = CONTAINING_RECORD(ListEntry, XENVIF_TRANSMITTER_RING,
> ListEntry);
> +
> +        __TransmitterRingQueuePackets(Ring, List);
> +    } else {
> +        while (!IsListEmpty(List)) {
> +            LIST_ENTRY                      SubList;
> +            PXENVIF_TRANSMITTER_PACKET_V2   Packet;
> +            ULONG                           Queue;
> +
> +            InitializeListHead(&SubList);
> +
> +            Packet = CONTAINING_RECORD(List->Flink,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +            Queue = __TransmitterGetQueue(Transmitter, Packet);
> +
> +            ListEntry = RemoveHeadList(List);
> +            ASSERT3U(ListEntry, !=, List);
> +            InsertTailList(&SubList, ListEntry);
> +
> +            while (!IsListEmpty(List)) {
> +                Packet = CONTAINING_RECORD(List->Flink,
> XENVIF_TRANSMITTER_PACKET_V2, ListEntry);
> +                if (__TransmitterGetQueue(Transmitter, Packet) != Queue)
> +                    break;
> +
> +                ListEntry = RemoveHeadList(List);
> +                ASSERT3U(ListEntry, !=, List);
> +                InsertTailList(&SubList, ListEntry);
> +            }
> +
> +            Ring = __TransmitterGetRing(Transmitter, Queue);
> +            __TransmitterRingQueuePackets(Ring, &SubList);
> +        }
> +    }
> +}
> +
>  VOID
>  TransmitterQueuePacketsV1(
>      IN  PXENVIF_TRANSMITTER             Transmitter,
> @@ -3798,8 +3888,6 @@ TransmitterQueuePacketsV1(
>           NULL)
> 
>      LIST_ENTRY                      List;
> -    PLIST_ENTRY                     ListEntry;
> -    PXENVIF_TRANSMITTER_RING        Ring;
> 
>      InitializeListHead(&List);
>      while (HeadPacket != NULL) {
> @@ -3828,12 +3916,7 @@ TransmitterQueuePacketsV1(
>          HeadPacket = HeadPacket->Next;
>      }
> 
> -    // 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);
> -
> -    __TransmitterRingQueuePackets(Ring, &List);
> +    __TransmitterQueuePackets(Transmitter, &List);
> 
>      // if HeadPacket != NULL, errors occured and need returning
>      if (HeadPacket != NULL) {
> @@ -3861,15 +3944,7 @@ TransmitterQueuePacketsV2(
>      IN  PLIST_ENTRY         List
>      )
>  {
> -    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);
> -
> -    __TransmitterRingQueuePackets(Ring, List);
> +    __TransmitterQueuePackets(Transmitter, List);
>  }
> 
>  static BOOLEAN
> --
> 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 Mon Nov 17 14:53:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:53: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 1XqNgk-0006G5-Lw; Mon, 17 Nov 2014 14:53:58 +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 1XqNgj-0006Fz-KB
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:53:57 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	D7/93-02702-40C0A645; Mon, 17 Nov 2014 14:53:56 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1416236036!9741055!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 32618 invoked from network); 17 Nov 2014 14:53:56 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:53:56 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905076"
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: [PATCH 09/10] Pin queue's DPC to appropriate vCPU when using
	multiple queues
Thread-Index: AQHP/pczwW3tgWTym0mXNlqD5/V0QZxk72BQ
Date: Mon, 17 Nov 2014 14:53:55 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537BD@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-10-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-10-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 09/10] Pin queue's DPC to appropriate
 vCPU when using 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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 09/10] Pin queue's DPC to appropriate vCPU when using
> multiple queues
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

Ok.

  Paul

> ---
>  src/xenvif/notifier.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 573ffaa..93f2395 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -295,6 +295,11 @@ NotifierQueueConnect(
>          PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
>          BOOLEAN             Pending;
> 
> +        if (FrontendGetQueueCount(Frontend) > 1) {
> +            KeSetTargetProcessorDpc(&Queue->Dpc[Index],
> +                                    (CCHAR)Queue->Index);
> +        }
> +
>          Queue->Channel[Index] = XENBUS_EVTCHN(Open,
>                                                &Notifier->EvtchnInterface,
>                                                XENBUS_EVTCHN_TYPE_UNBOUND,
> --
> 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 Mon Nov 17 14:53:58 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:53: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 1XqNgk-0006G5-Lw; Mon, 17 Nov 2014 14:53:58 +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 1XqNgj-0006Fz-KB
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:53:57 +0000
Received: from [193.109.254.147] by server-12.bemta-14.messagelabs.com id
	D7/93-02702-40C0A645; Mon, 17 Nov 2014 14:53:56 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-11.tower-27.messagelabs.com!1416236036!9741055!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 32618 invoked from network); 17 Nov 2014 14:53:56 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-11.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:53:56 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905076"
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: [PATCH 09/10] Pin queue's DPC to appropriate vCPU when using
	multiple queues
Thread-Index: AQHP/pczwW3tgWTym0mXNlqD5/V0QZxk72BQ
Date: Mon, 17 Nov 2014 14:53:55 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537BD@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-10-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-10-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 09/10] Pin queue's DPC to appropriate
 vCPU when using 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

> -----Original Message-----
> From: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 09/10] Pin queue's DPC to appropriate vCPU when using
> multiple queues
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

Ok.

  Paul

> ---
>  src/xenvif/notifier.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 573ffaa..93f2395 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -295,6 +295,11 @@ NotifierQueueConnect(
>          PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
>          BOOLEAN             Pending;
> 
> +        if (FrontendGetQueueCount(Frontend) > 1) {
> +            KeSetTargetProcessorDpc(&Queue->Dpc[Index],
> +                                    (CCHAR)Queue->Index);
> +        }
> +
>          Queue->Channel[Index] = XENBUS_EVTCHN(Open,
>                                                &Notifier->EvtchnInterface,
>                                                XENBUS_EVTCHN_TYPE_UNBOUND,
> --
> 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 Mon Nov 17 14:54:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:54:54 +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 1XqNhe-0006HJ-PU; Mon, 17 Nov 2014 14:54:54 +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 1XqNhd-0006HE-Hy
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:54:53 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	14/E8-28296-C3C0A645; Mon, 17 Nov 2014 14:54:52 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1416236092!8195555!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 28506 invoked from network); 17 Nov 2014 14:54:52 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:54:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905109"
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: [PATCH 10/10] Only call EVTCHN:Open for rx and tx or single
	event channel, based on "feature-split-event-channels"
Thread-Index: AQHP/ph4m112eqpwzkmUsNkTjsAXHZxk74vQ
Date: Mon, 17 Nov 2014 14:54:50 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537D1@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-11-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-11-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 10/10] Only call EVTCHN:Open for rx and
 tx or single event channel, based on "feature-split-event-channels"
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 10/10] Only call EVTCHN:Open for rx and tx or single event
> channel, based on "feature-split-event-channels"
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

As mentioned before, Notifier object should go.

  Paul

> ---
>  src/xenvif/notifier.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 93f2395..e9972d2 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -295,6 +295,27 @@ NotifierQueueConnect(
>          PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
>          BOOLEAN             Pending;
> 
> +        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 (FrontendGetQueueCount(Frontend) > 1) {
>              KeSetTargetProcessorDpc(&Queue->Dpc[Index],
>                                      (CCHAR)Queue->Index);
> @@ -328,6 +349,9 @@ fail1:
>      Error("fail1 (%08x)\n", status);
> 
>      while (--Index >= 0) {
> +        if (Queue->Channel[Index] == NULL)
> +            continue;
> +
>          XENBUS_EVTCHN(Close,
>                        &Notifier->EvtchnInterface,
>                        Queue->Channel[Index]);
> @@ -384,6 +408,7 @@ NotifierQueueStoreWrite(
>              break;
>          }
> 
> +        ASSERT(Queue->Channel[Index] != NULL);
>          Port = XENBUS_EVTCHN(GetPort,
>                               &Notifier->EvtchnInterface,
>                               Queue->Channel[Index]);
> --
> 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 Mon Nov 17 14:54:54 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Mon, 17 Nov 2014 14:54:54 +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 1XqNhe-0006HJ-PU; Mon, 17 Nov 2014 14:54:54 +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 1XqNhd-0006HE-Hy
	for win-pv-devel@lists.xenproject.org; Mon, 17 Nov 2014 14:54:53 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	14/E8-28296-C3C0A645; Mon, 17 Nov 2014 14:54:52 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1416236092!8195555!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 28506 invoked from network); 17 Nov 2014 14:54:52 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	17 Nov 2014 14:54:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,403,1413244800"; d="scan'208";a="26905109"
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: [PATCH 10/10] Only call EVTCHN:Open for rx and tx or single
	event channel, based on "feature-split-event-channels"
Thread-Index: AQHP/ph4m112eqpwzkmUsNkTjsAXHZxk74vQ
Date: Mon, 17 Nov 2014 14:54:50 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD0111537D1@AMSPEX01CL01.citrite.net>
References: <1415810347-7152-1-git-send-email-owen.smith@citrix.com>
	<1415810347-7152-11-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1415810347-7152-11-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 10/10] Only call EVTCHN:Open for rx and
 tx or single event channel, based on "feature-split-event-channels"
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: Owen Smith [mailto:owen.smith@citrix.com]
> Sent: 12 November 2014 16:39
> To: win-pv-devel@lists.xenproject.org
> Cc: Paul Durrant; Owen Smith
> Subject: [PATCH 10/10] Only call EVTCHN:Open for rx and tx or single event
> channel, based on "feature-split-event-channels"
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>

As mentioned before, Notifier object should go.

  Paul

> ---
>  src/xenvif/notifier.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/src/xenvif/notifier.c b/src/xenvif/notifier.c
> index 93f2395..e9972d2 100644
> --- a/src/xenvif/notifier.c
> +++ b/src/xenvif/notifier.c
> @@ -295,6 +295,27 @@ NotifierQueueConnect(
>          PKSERVICE_ROUTINE   Callback = NotifierQueueEvtchnCallback[Index];
>          BOOLEAN             Pending;
> 
> +        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 (FrontendGetQueueCount(Frontend) > 1) {
>              KeSetTargetProcessorDpc(&Queue->Dpc[Index],
>                                      (CCHAR)Queue->Index);
> @@ -328,6 +349,9 @@ fail1:
>      Error("fail1 (%08x)\n", status);
> 
>      while (--Index >= 0) {
> +        if (Queue->Channel[Index] == NULL)
> +            continue;
> +
>          XENBUS_EVTCHN(Close,
>                        &Notifier->EvtchnInterface,
>                        Queue->Channel[Index]);
> @@ -384,6 +408,7 @@ NotifierQueueStoreWrite(
>              break;
>          }
> 
> +        ASSERT(Queue->Channel[Index] != NULL);
>          Port = XENBUS_EVTCHN(GetPort,
>                               &Notifier->EvtchnInterface,
>                               Queue->Channel[Index]);
> --
> 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 Nov 20 08:58:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 08:58:49 +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 1XrNZh-0004fg-53; Thu, 20 Nov 2014 08:58:49 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrNZe-0004fb-Ku
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 08:58:47 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	0C/77-17958-54DAD645; Thu, 20 Nov 2014 08:58:45 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-6.tower-31.messagelabs.com!1416473923!8201775!1
X-Originating-IP: [209.85.212.170]
X-SpamReason: No, hits=2.0 required=7.0 tests=BIZ_TLD,HTML_60_70, HTML_MESSAGE
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15412 invoked from network); 20 Nov 2014 08:58:44 -0000
Received: from mail-wi0-f170.google.com (HELO mail-wi0-f170.google.com)
	(209.85.212.170)
	by server-6.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 08:58:44 -0000
Received: by mail-wi0-f170.google.com with SMTP id bs8so11866258wib.1
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 20 Nov 2014 00:58:43 -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:references:in-reply-to:content-type;
	bh=oh4PCZpZMRiflsNZplc2eIx8dvkWG+DC3lPrHluFRp0=;
	b=CDxjIIHWNJrYg3fcVdjOROYXJ5dWDyjFwRVorwCwEm6jSyUF8a8euPefofCUW3B5ID
	1KjZyT81NI0+sbcCgNAX69gv5Z6FNm1lKMbXOOygLiSaUyNiGuhsnBfrwvYRYiKWS67f
	fT9pUdzKCX8WLQjJhPQdQr5dz7N3NqBc1SrjFM6F8fK4+PvUs5rY8o7v4a2YhJoskOi8
	C14cvB/HMHaSvXDf/MhQn9dW0kHE9WbbhbsskRhEPBA2NEYE/j3deotPJWfv16sSMKe7
	YW/5pKSPlNhYbfROp/MBJYK9KiLVrJb48T+SUvx4KTUKxmeQp+B9xgCyb2EpBdrNMmYV
	WO/A==
X-Gm-Message-State: ALoCoQlDh3D78AWAgW3rb8BtDc8iZLmhUIrSwYQ1AgJD0laOoo/9O/zqhoKAyTftxfbaajBlkJNZ
X-Received: by 10.194.81.38 with SMTP id w6mr66153486wjx.17.1416473923743;
	Thu, 20 Nov 2014 00:58:43 -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 fv5sm2378210wjc.37.2014.11.20.00.58.35
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 20 Nov 2014 00:58:42 -0800 (PST)
Message-ID: <546DAD42.1080808@m2r.biz>
Date: Thu, 20 Nov 2014 09:58:42 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>
References: <5464BDF4.1090103@m2r.biz>	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>	<5464C25D.6070200@m2r.biz>	<5466279C.207@m2r.biz>	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
	<CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
In-Reply-To: <CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
Content-Type: multipart/mixed; boundary="------------080009070007070309030302"
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------080009070007070309030302
Content-Type: multipart/alternative;
 boundary="------------000104010701060601060306"


--------------000104010701060601060306
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

Il 14/11/2014 18:54, Fabio Fantoni ha scritto:
> 2014-11-14 17:15 GMT+01:00 Paul Durrant <Paul.Durrant@citrix.com 
> <mailto:Paul.Durrant@citrix.com>>:
>
>     > -----Original Message-----
>     > From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz
>     <mailto:fabio.fantoni@m2r.biz>]
>     > Sent: 14 November 2014 16:03
>     > To: Paul Durrant; win-pv-devel@lists.xenproject.org
>     <mailto:win-pv-devel@lists.xenproject.org>
>     > Subject: Re: Windows 7 64 bit blue screen with stop 1e after
>     restore with
>     > new build of win pv drivers
>     >
>     > Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
>     > > Il 13/11/2014 15:26, Paul Durrant ha scritto:
>     > >>> -----Original Message-----
>     > >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz
>     <mailto:fabio.fantoni@m2r.biz>]
>     > >>> Sent: 13 November 2014 14:20
>     > >>> To: win-pv-devel@lists.xenproject.org
>     <mailto:win-pv-devel@lists.xenproject.org>; Paul Durrant
>     > >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
>     > >>> with new
>     > >>> build of win pv drivers
>     > >>>
>     > >>> I did a new build of winpv drivers and tested on one windows
>     7 64 bit
>     > >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf
>     with
>     > vcpu
>     > >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and
>     qemu 2.2
>     > >>> from spice git:
>     > >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>     > >>>
>     > >>> After restore windows showed blue screen with stop 1e, I
>     open the
>     > dump
>     > >>> with "BlueScreenView" and showed that cause is xennet driver.
>     > >>> I attached the dump, if you need more informations/tests
>     tell me and
>     > >>> I'll post them.
>     > >>>
>     > >> I've been testing with win7 32-bit and seen no problems. The
>     minidump
>     > >> doesn't tell me much unfortunately do you have a full dump,
>     plus the
>     > >> QEMU log?
>     > >>
>     > >>    Paul
>     > >
>     > > Thanks for reply.
>     > > qemu log was without errors or warning related, I changed windows
>     > > option for full memory dump and enable qemu trace of xen and
>     retried
>     > > to reproduce the problem but this time after restore on same
>     domU not
>     > > had the blue screen.
>     >
>     > Blue screen re-happen, in attachment qemu logs (before and after
>     > restore) with xen trace.
>     > Also memory.dmp full this time but there is a problem, is 1,87
>     gb and my
>     > connection is max 256kbps of upload :(
>     > If is really needed tell me and I'll try to load it in my webserver
>     > tomorrow.
>     >
>
>     I'll try to repro. You're crash happened very early in resume. Is
>     your xenbus driver the built from tip?
>
>
> Yes I updated all to latest git in 
> http://xenbits.xen.org/gitweb/?o=age, all except xeniface was updated 
> if I remember good.
> Was happen 2 time on total of 5 save/restore I tried.
> Latest test was with qemu upstream updated including also the new 2 
> xen bugfix http://git.qemu.org/qemu.git (commit 
> 4e70f9271dabc58fbf14680843bfac510c193152).

I have updated xen to latest staging and qemu to tag v2.2.0-rc2 and the 
crash still happen, in attachment minidump of latest crash and below the 
link of full memory dump, hope that these will help you to found and 
solves the problem:
http://fantu.info/xen/MEMORY.DMP

>
>       Paul
>
>     > >
>     > >>
>     > >>> Thanks for any reply and sorry for my bad english.
>     > >
>     >
>
>


--------------000104010701060601060306
Content-Type: text/html; charset=utf-8
Content-Length: 7906
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    <div class=3D"moz-cite-prefix">Il 14/11/2014 18:54, Fabio Fantoni ha
      scritto:<br>
    </div>
    <blockquote
cite=3D"mid:CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com"
      type=3D"cite">
      <div dir=3D"ltr">2014-11-14 17:15 GMT+01:00 Paul Durrant <span
          dir=3D"ltr">&lt;<a moz-do-not-send=3D"true"
            href=3D"mailto:Paul.Durrant@citrix.com" target=3D"_blank">Paul.Durrant@citrix.com</a>&gt;</span>:<br>
        <div class=3D"gmail_extra">
          <div class=3D"gmail_quote">
            <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex"><span class=3D"">&gt;
                -----Original Message-----<br>
                &gt; From: Fabio Fantoni [mailto:<a
                  moz-do-not-send=3D"true"
                  href=3D"mailto:fabio.fantoni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
              </span>
              <div>
                <div class=3D"h5">&gt; Sent: 14 November 2014 16:03<br>
                  &gt; To: Paul Durrant; <a moz-do-not-send=3D"true"
                    href=3D"mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a><br>
                  &gt; Subject: Re: Windows 7 64 bit blue screen with
                  stop 1e after restore with<br>
                  &gt; new build of win pv drivers<br>
                  &gt;<br>
                  &gt; Il 13/11/2014 15:38, Fabio Fantoni ha scritto:<br>
                  &gt; &gt; Il 13/11/2014 15:26, Paul Durrant ha
                  scritto:<br>
                  &gt; &gt;&gt;&gt; -----Original Message-----<br>
                  &gt; &gt;&gt;&gt; From: Fabio Fantoni [mailto:<a
                    moz-do-not-send=3D"true"
                    href=3D"mailto:fabio.fantoni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
                  &gt; &gt;&gt;&gt; Sent: 13 November 2014 14:20<br>
                  &gt; &gt;&gt;&gt; To: <a moz-do-not-send=3D"true"
                    href=3D"mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>;
                  Paul Durrant<br>
                  &gt; &gt;&gt;&gt; Subject: Windows 7 64 bit blue
                  screen with stop 1e after restore<br>
                  &gt; &gt;&gt;&gt; with new<br>
                  &gt; &gt;&gt;&gt; build of win pv drivers<br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt;&gt; I did a new build of winpv drivers
                  and tested on one windows 7 64 bit<br>
                  &gt; &gt;&gt;&gt; domU, dom0 xen-unstable with
                  "x86/hvm: Extend HVM cpuid leaf with<br>
                  &gt; vcpu<br>
                  &gt; &gt;&gt;&gt; id" and "x86/hvm: Add per-vcpu
                  evtchn upcalls" patches, and qemu 2.2<br>
                  &gt; &gt;&gt;&gt; from spice git:<br>
                  &gt; &gt;&gt;&gt; <a moz-do-not-send=3D"true"
                    href=3D"https://github.com/Fantu/Xen/commits/rebase/m2r-staging"
                    target=3D"_blank">https://github.com/Fantu/Xen/commits/rebase/m2r-staging</a><br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt;&gt; After restore windows showed blue
                  screen with stop 1e, I open the<br>
                  &gt; dump<br>
                  &gt; &gt;&gt;&gt; with "BlueScreenView" and showed
                  that cause is xennet driver.<br>
                  &gt; &gt;&gt;&gt; I attached the dump, if you need
                  more informations/tests tell me and<br>
                  &gt; &gt;&gt;&gt; I'll post them.<br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt; I've been testing with win7 32-bit and
                  seen no problems. The minidump<br>
                  &gt; &gt;&gt; doesn't tell me much unfortunately do
                  you have a full dump, plus the<br>
                  &gt; &gt;&gt; QEMU log=3F<br>
                  &gt; &gt;&gt;<br>
                  &gt; &gt;&gt;=C2=A0 =C2=A0 Paul<br>
                  &gt; &gt;<br>
                  &gt; &gt; Thanks for reply.<br>
                  &gt; &gt; qemu log was without errors or warning
                  related, I changed windows<br>
                  &gt; &gt; option for full memory dump and enable qemu
                  trace of xen and retried<br>
                  &gt; &gt; to reproduce the problem but this time after
                  restore on same domU not<br>
                  &gt; &gt; had the blue screen.<br>
                  &gt;<br>
                  &gt; Blue screen re-happen, in attachment qemu logs
                  (before and after<br>
                  &gt; restore) with xen trace.<br>
                  &gt; Also memory.dmp full this time but there is a
                  problem, is 1,87 gb and my<br>
                  &gt; connection is max 256kbps of upload :(<br>
                  &gt; If is really needed tell me and I'll try to load
                  it in my webserver<br>
                  &gt; tomorrow.<br>
                  &gt;<br>
                  <br>
                </div>
              </div>
              I'll try to repro. You're crash happened very early in
              resume. Is your xenbus driver the built from tip=3F<br>
            </blockquote>
            <div><br>
            </div>
            <div>Yes I updated all to latest git in <a
                moz-do-not-send=3D"true"
                href=3D"http://xenbits.xen.org/gitweb/=3Fo=3Dage">http://xenbits.xen.org/gitweb/=3Fo=3Dage</a>,
              all except xeniface was updated if I remember good.<br>
            </div>
            <div>Was happen 2 time on total of 5 save/restore I tried.<br>
            </div>
            <div>Latest test was with qemu upstream updated including
              also the new 2 xen bugfix <a moz-do-not-send=3D"true"
                href=3D"http://git.qemu.org/qemu.git">http://git.qemu.org/qemu.git</a>
              (commit 4e70f9271dabc58fbf14680843bfac510c193152).<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    I have updated xen to latest staging and qemu to tag v2.2.0-rc2 and
    the crash still happen, in attachment minidump of latest crash and
    below the link of full memory dump, hope that these will help you to
    found and solves the problem:<br>
    <a class=3D"moz-txt-link-freetext" href=3D"http://fantu.info/xen/MEMORY.DMP">http://fantu.info/xen/MEMORY.DMP</a><br>
    <br>
    <blockquote
cite=3D"mid:CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com"
      type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra">
          <div class=3D"gmail_quote">
            <div>=C2=A0</div>
            <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex">
              <span class=3D""><font color=3D"#888888"><br>
                  =C2=A0 Paul<br>
                </font></span>
              <div class=3D"">
                <div class=3D"h5"><br>
                  &gt; &gt;<br>
                  &gt; &gt;&gt;<br>
                  &gt; &gt;&gt;&gt; Thanks for any reply and sorry for
                  my bad english.<br>
                  &gt; &gt;<br>
                  &gt;<br>
                  <br>
                </div>
              </div>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>

--------------000104010701060601060306--

--------------080009070007070309030302
Content-Type: application/octet-stream;
 name="111914-10467-01.dmp"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="111914-10467-01.dmp"

UEFHRURVNjQPAAAAsR0AAABwGAAAAAAAeDLQAgD4//+QmMkCAPj//5C1xwIA+P//ZIYAAAIA
AAAeAAAAUEFHRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0WgUMQCAPj//1BBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAA
AAAAAICN5gKA+P//WLPBAgD4///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC
5gKA+P//4HvmAoD4//+wjeYCgPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//
AAAAAAAAAACQu6wCAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAwAAgAEAAAAAAAAAAAAAAJC7rAIA+P//AAAAAFBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UEAAAA
UEFHRbAaBAAAAAAAsMf+VQME0AFQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRSAIbjwAAAAA/wwAAFBB
R0UBAAAAEAEAAAAAAABQAEdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UAAQAAAAAEAPz/AwBIAwAA
AA8AAIAgAADQIAAA8CEAAPBuAADAcwAAaHgAAAAQAACoiwAAigAAAEjZAAA4LgAAAAAAAP//
///oeuYCgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaIgAAEADAACABwEA
DwAAAAEAAABQAAAAAAAAAAAAAAAAAAAAAAAAAHh5BQAAAAAAuxcAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAkR0CAAAAAAB9wQIAAAAAAHT+HQAAAAAABQAAAAAAAAAYABgAAAAAAAAAAAAAAAAA
YwByAGEAcwBoAGQAbQBwAC4AcwB5AHMAAABDAYD4//8A4EMBgPj//xgAGAAAAAAAAAAAAAAA
AABkAHUAbQBwAF8AcwB0AG8AcgBwAG8AcgAA4EMBgPj//wCARAGA+P//GAAYAAAAAAAAAAAA
AAAAAGQAdQBtAHAAXwB4AGUAbgBjAHIAcwBoAAAwGwGA+P//ANAeAYD4//8YABgAAAAAAAAA
AAAAAAAAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AAIBEAYD4//8AQEcBgPj//xgAGAAAAAAA
AAAAAAAAAABkAHUAbQBwAF8AZAB1AG0AcABmAHYAZQAAQEcBgPj//wBwSAGA+P//gB8AAAEA
AABAr+QCgPj//wAAAAAAAAAAQK/kAoD4//8BAAAAAQAAALCN5gKA+P//AAAAAAAAAAAAAAAA
AAAAADEABYAAAAAAABAuAAAAAAAAcBgAAAAAAPgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADwD///AAAAAAAEAAAAAAAAAAAAAAAAfwDAtOQCgPj//wAAAAAAAP8P
QLXkAoD4//9AAAAAgB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAAAAAAAICN5gKA+P//WLPBAgD4
///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC5gKA+P//4HvmAoD4//+wjeYC
gPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//AAAAAAAAAACQu6wCAPj//wAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAABQb29M8AEAABD8vwIA+P//0PC/AgD4//+AIeQCgPj//yAh5AKA+P//
TwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABygAAAAAAAAAAAAAAAAAAAAAA
AABQb29MAAIAABD8vwIA+P//0PC/AgD4///gIeQCgPj//4Ah5AKA+P//ygAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MEAAAABD8
vwIA+P//0PC/AgD4//+gCuQCgPj//0AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MIAAAABD8vwIA+P//0PC/AgD4
//8AC+QCgPj//6AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//9gC+QCgPj//wAL
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29MQAAAABD8vwIA+P//0PC/AgD4///AC+QCgPj//2AL5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
UAAAABD8vwIA+P//0PC/AgD4//8gDOQCgPj//8AL5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MYAAAABD8vwIA+P//
0PC/AgD4//+ADOQCgPj//yAM5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29McAAAABD8vwIA+P//0PC/AgD4///gDOQC
gPj//4AM5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MgAAAABD8vwIA+P//0PC/AgD4//9ADeQCgPj//+AM5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MkAAAABD8vwIA+P//0PC/AgD4//+gDeQCgPj//0AN5AKA+P//AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MoAAAABD8
vwIA+P//0PC/AgD4//8ADuQCgPj//6AN5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MsAAAABD8vwIA+P//0PC/AgD4
//9gDuQCgPj//wAO5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MwAAAABD8vwIA+P//0PC/AgD4///ADuQCgPj//2AO
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29M0AAAABD8vwIA+P//0PC/AgD4//8gD+QCgPj//8AO5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
4AAAABD8vwIA+P//0PC/AgD4//+AD+QCgPj//yAP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M8AAAABD8vwIA+P//
0PC/AgD4///gD+QCgPj//4AP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MAAEAABD8vwIA+P//0PC/AgD4//9AEOQC
gPj//+AP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MEAEAABD8vwIA+P//0PC/AgD4//+gEOQCgPj//0AQ5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MIAEAABD8vwIA+P//0PC/AgD4//8AEeQCgPj//6AQ5AKA+P//AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MMAEAABD8
vwIA+P//0PC/AgD4//9gEeQCgPj//wAR5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MQAEAABD8vwIA+P//0PC/AgD4
///AEeQCgPj//2AR5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MUAEAABD8vwIA+P//0PC/AgD4//8gEuQCgPj//8AR
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29MYAEAABD8vwIA+P//0PC/AgD4//+AEuQCgPj//yAS5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
cAEAABD8vwIA+P//0PC/AgD4///gEuQCgPj//4AS5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MgAEAABD8vwIA+P//
0PC/AgD4//9AE+QCgPj//+AS5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MkAEAABD8vwIA+P//0PC/AgD4//+gE+QC
gPj//0AT5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MoAEAABD8vwIA+P//0PC/AgD4//8AFOQCgPj//6AT5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MsAEAABD8vwIA+P//0PC/AgD4//9gFOQCgPj//wAU5AKA+P//AAAAAAAAAAAAAAAA
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
SCfkAoD4//9IJ+QCgPj//0BNQzn/////AAAAAAAAAABoJ+QCgPj//2gn5AKA+P//oO6CNP//
//8AAAAAAAAAAIgn5AKA+P//iCfkAoD4//9ACTtY/////wAAAAAAAAAAqCfkAoD4//+oJ+QC
gPj//2DRqzv/////AAAAAAAAAADIJ+QCgPj//8gn5AKA+P//AEzFYf////8AAAAAAAAAADA8
UgOA+v//MDxSA4D6//9gDSlkAAAAAAAAAAAAAAAAMJx5A4D6//8Q70cDgPr//2DqdEAAAAAA
AAAAAAAAAAAoKOQCgPj//ygo5AKA+P//4PZTOf////8AAAAAAAAAAEgo5AKA+P//SCjkAoD4
//9AmJM0/////wAAAAAAAAAAaCjkAoD4//9oKOQCgPj//+DSWTn/////AAAAAAAAAACIKOQC
gPj//4go5AKA+P//AHu8O/////8AAAAAAAAAAKgo5AKA+P//qCjkAoD4//9gHPw2/////wAA
AAAAAAAAyCjkAoD4///IKOQCgPj//5DFOzL/////AAAAAAAAAADoKOQCgPj//+go5AKA+P//
YJi2Wv////8AAAAAAAAAAAgp5AKA+P//CCnkAoD4//+AoGQ5/////wAAAAAAAAAAKCnkAoD4
//8oKeQCgPj//8DWBDf/////AAAAAAAAAABIKeQCgPj//0gp5AKA+P//QOPjL/////8AAAAA
AAAAAGgp5AKA+P//aCnkAoD4//+gJM07/////wAAAAAAAAAAiCnkAoD4//+IKeQCgPj//6DV
DDf/////AAAAAAAAAACoKeQCgPj//6gp5AKA+P//4MtvOf////8AAAAAAAAAAMgp5AKA+P//
yCnkAoD4//8AohI3/////wAAAAAAAAAA6CnkAoD4///oKeQCgPj//yBKdTn/////AAAAAAAA
AADgmYsDgPr//+CZiwOA+v//wGQiSgAAAAAAAAAAAAAAACgq5AKA+P//KCrkAoD4//8gZs5a
/////wAAAAAAAAAAYKlpA4D6//9gqWkDgPr//4AnJ0oAAAAAAAAAAAAAAAAA/X0BgPr//zB0
iwOA+v//gCSiQAAAAAAAAAAAAAAAAEBxoAOA+v//QHGgA4D6//9AitVaAAAAAAAAAAAAAAAA
QLGGAoD6//9AsYYCgPr//6BrXWQAAAAAAAAAAAAAAADIKuQCgPj//8gq5AKA+P//wPOFOf//
//8AAAAAAAAAAEDxOQOA+v//QPE5A4D6//9gLldRAAAAAAAAAAAAAAAAIAlFA4D6//8gCUUD
gPr//8CPWVEAAAAAAAAAAAAAAAAoK+QCgPj//ygr5AKA+P//4HfuO/////8AAAAAAAAAAEgr
5AKA+P//SCvkAoD4//9AUPI7/////wAAAAAAAAAAQIePAoD6//9Ah48CgPr//4APnEwAAAAA
AAAAAAAAAACgPZoDgPr//6A9mgOA+v//4LDbRwAAAAAAAAAAAAAAAKgr5AKA+P//qCvkAoD4
//9gnZY5/////wAAAAAAAAAAyCvkAoD4///IK+QCgPj//2Dx+Tv/////AAAAAAAAAADoK+QC
gPj//+gr5AKA+P//IOAVMP////8AAAAAAAAAAAgs5AKA+P//CCzkAoD4//9QKf87/////wAA
AAAAAAAAKCzkAoD4//8oLOQCgPj//+DCPjf/////AAAAAAAAAABILOQCgPj//0gs5AKA+P//
wCIEPP////8AAAAAAAAAAGgs5AKA+P//aCzkAoD4///gp70t/////wAAAAAAAAAAiCzkAoD4
//+ILOQCgPj//4CLpjn/////AAAAAAAAAACoLOQCgPj//6gs5AKA+P//4IZIN/////8AAAAA
AAAAAMgs5AKA+P//yCzkAoD4//9Argw8/////wAAAAAAAAAA6CzkAoD4///oLOQCgPj//yDL
Dzz/////AAAAAAAAAACwxJ0DgPr//7DEnQOA+v//YKFZSgAAAAAAAAAAAAAAACgt5AKA+P//
KC3kAoD4///gDY8y/////wAAAAAAAAAASC3kAoD4//9ILeQCgPj//4AILmL/////AAAAAAAA
AAAw3G0DgPr//zDcbQOA+v//wMJdnGQAAAAAAAAAAAAAADAsjQOA+v//MFySA4D6///ANT9D
AAAAAAAAAAAAAAAAqC3kAoD4//+oLeQCgPj//6AMEVv/////AAAAAAAAAADA1Z8CgPr//8DV
nwKA+v//AO6NUQAAAAAAAAAAAAAAAOgt5AKA+P//6C3kAoD4//8gFmA3/////wAAAAAAAAAA
CC7kAoD4//8ILuQCgPj//4C3nzL/////AAAAAAAAAAAoLuQCgPj//ygu5AKA+P//IBKVUf//
//8AAAAAAAAAAEgu5AKA+P//SC7kAoD4//9Amsg5/////wAAAAAAAAAAaC7kAoD4//9oLuQC
gPj//6A7CDX/////AAAAAAAAAACILuQCgPj//4gu5AKA+P//gPipMv////8AAAAAAAAAAKgu
5AKA+P//qC7kAoD4//9gHjE8/////wAAAAAAAAAAyC7kAoD4///ILuQCgPj//4BgMzz/////
AAAAAAAAAADoLuQCgPj//+gu5AKA+P//IGGwMv////8AAAAAAAAAAAgv5AKA+P//CC/kAoD4
//+AmRU1/////wAAAAAAAAAAKC/kAoD4//8oL+QCgPj//+BD2Tn/////AAAAAAAAAABIL+QC
gPj//0gv5AKA+P//IJcYNf////8AAAAAAAAAAGgv5AKA+P//aC/kAoD4///g/7oy/////wAA
AAAAAAAAiC/kAoD4//+IL+QCgPj//wDIQTz/////AAAAAAAAAACoL+QCgPj//6gv5AKA+P//
YGmBN/////8AAAAAAAAAAMgv5AKA+P//yC/kAoD4//8ApF1i/////wAAAAAAAAAA6C/kAoD4
///oL+QCgPj//2BRhTf/////AAAAAAAAAAAIMOQCgPj//wgw5AKA+P//gO3pOf////8AAAAA
AAAAACgw5AKA+P//KDDkAoD4//+Anik1/////wAAAAAAAAAASDDkAoD4//9IMOQCgPj//8CI
jjf/////AAAAAAAAAABoMOQCgPj//2gw5AKA+P//oOhTPP////8AAAAAAAAAAIgw5AKA+P//
iDDkAoD4//8AE5I3/////wAAAAAAAAAAqDDkAoD4//+oMOQCgPj//+BYMjX/////AAAAAAAA
AADIMOQCgPj//8gw5AKA+P//oKo0Nf////8AAAAAAAAAAOgw5AKA+P//6DDkAoD4//8gl/o5
/////wAAAAAAAAAAoHSBA4D6//+gdIEDgPr//0DcjFYAAAAAAAAAAAAAAAAoMeQCgPj//ygx
5AKA+P//YD6dN/////8AAAAAAAAAAEgx5AKA+P//SDHkAoD4//9AG2M8/////wAAAAAAAAAA
4CmmA4D6//9AgWgDgPr//+AV7EUAAAAAAAAAAAAAAACgalwDgPr//0Ch+gKA+v//AMHIPgAA
AAAAAAAAAAAAAFANNwOA+v//UA03A4D6///goBNNAAAAAAAAAAAAAAAAoKh7A4D6//+gqHsD
gPr//wDanFYAAAAAAAAAAAAAAADoMeQCgPj//+gx5AKA+P//YIRKNf////8AAAAAAAAAAAgy
5AKA+P//CDLkAoD4//+Ag4ow/////wAAAAAAAAAAMAyUA4D6///ARfwCgPr//2AJczwAAAAA
AAAAAAAAAABIMuQCgPj//0gy5AKA+P//QGazN/////8AAAAAAAAAAGgy5AKA+P//aDLkAoD4
//9ga/Iy/////wAAAAAAAAAAiDLkAoD4//+IMuQCgPj//zAeMy7/////AAAAAAAAAACoMuQC
gPj//6gy5AKA+P//4KsmTf////8AAAAAAAAAADBMkQOA+v//oCmXA4D6//+Az0FBAAAAAAAA
AAAAAAAA6DLkAoD4///oMuQCgPj//2CPXTX/////AAAAAAAAAAAIM+QCgPj//wgz5AKA+P//
AO22JP////8AAAAAAAAAACgz5AKA+P//KDPkAoD4///gD8Q3/////wAAAAAAAAAASDPkAoD4
//9IM+QCgPj//8CSMk3/////AAAAAAAAAABAeJkDgPr//0B4mQOA+v//IDHtPgAAAAAAAAAA
AAAAAIgz5AKA+P//iDPkAoD4//8AlCw6/////wAAAAAAAAAAqDPkAoD4//+oM+QCgPj//+B5
azX/////AAAAAAAAAABAAYYDgPr//0ABhgOA+v//wC2UPAAAAAAAAAAAAAAAADAcmQOA+v//
MDw/A4D6//9gceldAAAAAAAAAAAAAAAACDTkAoD4//8INOQCgPj//8DS613/////AAAAAAAA
AABwq5kDgPr//0ARdAOA+v//IDTuXQAAAAAAAAAAAAAAADBIPQOA+v//MEg9A4D6//+AtQlS
AAAAAAAAAAAAAAAAEI9sA4D6//8Qj2wDgPr//yA8AD8AAAAAAAAAAAAAAAAw7AcDgPr//0Bx
pgOA+v//4KE7IgIAAAAAAAAAAAAAAKg05AKA+P//qDTkAoD4//8As2VB/////wAAAAAAAAAA
yDTkAoD4///INOQCgPj//4ClHzP/////AAAAAAAAAADoNOQCgPj//+g05AKA+P//YNxdYP//
//8AAAAAAAAAADD8mAOA+v//MGxPA4D6//9ACNlWAAAAAAAAAAAAAAAA8PkNA4D6///w+Q0D
gPr//2AqrDwAAAAAAAAAAAAAAABINeQCgPj//0g15AKA+P//QOdNOv////8AAAAAAAAAAFB4
UwOA+v//UHhTA4D6///gYWdgAAAAAAAAAAAAAAAAiDXkAoD4//+INeQCgPj//0APjzX/////
AAAAAAAAAACoNeQCgPj//6g15AKA+P//oERvLv////8AAAAAAAAAAEBxYAOA+v//gOBHA4D6
//8A5rk8AAAAAAAAAAAAAAAA6DXkAoD4///oNeQCgPj//yCuNTP/////AAAAAAAAAAAINuQC
gPj//wg25AKA+P//wJSYNf////8AAAAAAAAAALDLTwOA+v//oMZPA4D6//+g9GhNAAAAAAAA
AAAAAAAAQHFXA4D6//9AcVcDgPr//4DLL1IAAAAAAAAAAAAAAABoNuQCgPj//2g25AKA+P//
oNPdMP////8AAAAAAAAAAIg25AKA+P//iDbkAoD4//8Aj0Iz/////wAAAAAAAAAAQFGSA4D6
//9AUZIDgPr//yCai0EAAAAAAAAAAAAAAAAQvpMDgPr//0ANPgOA+v//APfLPAAAAAAAAAAA
AAAAAOg25AKA+P//6DbkAoD4//8AziMs/////wAAAAAAAAAAwGlZA4D6///AaVkDgPr//yDt
kkEAAAAAAAAAAAAAAAAwzHUDgPr//zDMdQOA+v//4DKXQQAAAAAAAAAAAAAAAEg35AKA+P//
SDfkAoD4//9Afe4w/////wAAAAAAAAAAaDfkAoD4//9oN+QCgPj//+D3B1f/////AAAAAAAA
AACIN+QCgPj//4g35AKA+P//AGAXOP////8AAAAAAAAAAKg35AKA+P//qDfkAoD4//+g2jBe
/////wAAAAAAAAAAQAGRA4D6//9AAZEDgPr///AUddAAAAAAAAAAAAAAAADgJUwDgPr//+Al
TAOA+v//4McPVwAAAAAAAAAAAAAAAAg45AKA+P//CDjkAoD4///ACiA4/////wAAAAAAAAAA
KDjkAoD4//8oOOQCgPj//+Am/zD/////AAAAAAAAAABIOOQCgPj//0g45AKA+P//4HhuOP//
//8AAAAAAAAAACBqogOA+v//IGqiA4D6//9gjVZSAAAAAAAAAAAAAAAAiDjkAoD4//+IOOQC
gPj//3DCZzP/////AAAAAAAAAACAyWMDgPr//4DJYwOA+v//oKXwPAAAAAAAAAAAAAAAAMg4
5AKA+P//yDjkAoD4///AjZA6/////wAAAAAAAAAA6DjkAoD4///oOOQCgPj//9BrzzX/////
AAAAAAAAAAAIOeQCgPj//wg55AKA+P//gNAPMf////8AAAAAAAAAACg55AKA+P//KDnkAoD4
///gyDc4/////wAAAAAAAAAAUGmkA4D6//9AR1gDgPr//wCXvUEAAAAAAAAAAAAAAABAcVUD
gPr//zB8VQOA+v//4PMedgAAAAAAAAAAAAAAAIg55AKA+P//iDnkAoD4//9A23kz/////wAA
AAAAAAAAqDnkAoD4//+oOeQCgPj//2A3oTr/////AAAAAAAAAABA8V4DgPr//7D7iwOA+v//
gPytTQAAAAAAAAAAAAAAADCYngOA+v//MJieA4D6///gNFXCAAAAAAAAAAAAAAAAMIx2A4D6
//8wjHYDgPr//8C08UgAAAAAAAAAAAAAAABw65YDgPr//zD8QgOA+v//IBb0SAAAAAAAAAAA
AAAAAEAxlAOA+v//MMyeA4D6//+Ad/ZIAAAAAAAAAAAAAAAAaDrkAoD4//9oOuQCgPj//+BE
QiX/////AAAAAAAAAACIOuQCgPj//4g65AKA+P//0OixOv////8AAAAAAAAAAFAFiAOA+v//
UAWIA4D6//8gZoFSAAAAAAAAAAAAAAAAMMyGA4D6//8wzIYDgPr//4DHg1IAAAAAAAAAAAAA
AAAw/GcDgPr//zCsQAOA+v//4GjDTQAAAAAAAAAAAAAAAAg75AKA+P//CDvkAoD4//+ABlo4
/////wAAAAAAAAAAQBFqA4D6//9AQZcDgPr//4C6Hj0AAAAAAAAAAAAAAAAwvGkDgPr//zC8
aQOA+v//gKI4YwAAAAAAAAAAAAAAAGA6TAOA+v//YDpMA4D6///gI1RXAAAAAAAAAAAAAAAA
iDvkAoD4//+IO+QCgPj//4BwATb/////AAAAAAAAAACoO+QCgPj//6g75AKA+P//YM1BMf//
//8AAAAAAAAAABDJRQOA+v//EMlFA4D6//8AKEJjAAAAAAAAAAAAAAAA6DvkAoD4///oO+QC
gPj//6Bxajj/////AAAAAAAAAABAgYwDgPr//0CBjAOA+v//wApgVwAAAAAAAAAAAAAAAJBS
cQOA+v//kFJxA4D6//9glNtNAAAAAAAAAAAAAAAAUOg8A4D6//9AQWwDgPr//8D13U0AAAAA
AAAAAAAAAABoPOQCgPj//2g85AKA+P//IBoSNv////8AAAAAAAAAAIg85AKA+P//iDzkAoD4
//+AO9c6/////wAAAAAAAAAAQCFnA4D6//9AIWcDgPr//6ARkF4AAAAAAAAAAAAAAAAQqHID
gPr//+CkngOA+v//gB3nTQAAAAAAAAAAAAAAADB8pgOA+v//MHymA4D6//9gFMdGAAAAAAAA
AAAAAAAAAPxmA4D6//8A/GYDgPr//8CV+GAAAAAAAAAAAAAAAAAoPeQCgPj//yg95AKA+P//
4N3jOv////8AAAAAAAAAADD9RQOA+v//MP1FA4D6//8gyw+5AAAAAAAAAAAAAAAAaD3kAoD4
//9oPeQCgPj//6AgYzH/////AAAAAAAAAAAwXE4DgPr//zBcTgOA+v//QHtjYwAAAAAAAAAA
AAAAAKg95AKA+P//qD3kAoD4//+gXNVG/////wAAAAAAAAAAyD3kAoD4///IPeQCgPj//8Ck
yzP/////AAAAAAAAAADoPeQCgPj//+g95AKA+P//oGrmJ/////8AAAAAAAAAAAg+5AKA+P//
CD7kAoD4//+Ah/Q6/////wAAAAAAAAAAKD7kAoD4//8oPuQCgPj//+AoNDb/////AAAAAAAA
AABIPuQCgPj//0g+5AKA+P//QMpzMf////8AAAAAAAAAAGg+5AKA+P//aD7kAoD4//+AF7Qs
/////wAAAAAAAAAAiD7kAoD4//+IPuQCgPj//wCtnDj/////AAAAAAAAAACoPuQCgPj//6g+
5AKA+P//gNmfOP////8AAAAAAAAAABCseQGA+v//kIx7AYD6//+AjWQ9AAAAAAAAAAAAAAAA
6D7kAoD4///oPuQCgPj//4BBKUL/////AAAAAAAAAABA8ZMDgPr//0ABPQOA+v//wNcqQgAA
AAAAAAAAAAAAACg/5AKA+P//KD/kAoD4///gc4Qx/////wAAAAAAAAAASD/kAoD4//9IP+QC
gPj//4C6SDb/////AAAAAAAAAABoP+QCgPj//2g/5AKA+P//oFatOP////8AAAAAAAAAAKB1
pgOA+v//oHWmA4D6///AmzRCAAAAAAAAAAAAAAAAqD/kAoD4//+oP+QCgPj//6DSZ1z/////
AAAAAAAAAADIP+QCgPj//8g/5AKA+P//AFSOY/////8AAAAAAAAAAOg/5AKA+P//6D/kAoD4
//9g9c1e/////wAAAAAAAAAACEDkAoD4//8IQOQCgPj//yCuoDb/////AAAAAAAAAAAoQOQC
gPj//yhA5AKA+P//IMS6OP////8AAAAAAAAAAEhA5AKA+P//SEDkAoD4//9AAL44/////wAA
AAAAAAAAaEDkAoD4//9oQOQCgPj//yD6Ijv/////AAAAAAAAAACIQOQCgPj//4hA5AKA+P//
QOjBOP////8AAAAAAAAAAKhA5AKA+P//qEDkAoD4//9ghCY7/////wAAAAAAAAAAyEDkAoD4
///IQOQCgPj//wCrxjj/////AAAAAAAAAADoQOQCgPj//+hA5AKA+P//oMtnNv////8AAAAA
AAAAAAhB5AKA+P//CEHkAoD4//8wJWo2/////wAAAAAAAAAAKEHkAoD4//8oQeQCgPj//+Cp
zjj/////AAAAAAAAAABIQeQCgPj//0hB5AKA+P//wOlvNv////8AAAAAAAAAAGhB5AKA+P//
aEHkAoD4///AlLAx/////wAAAAAAAAAAiEHkAoD4//+IQeQCgPj//wAuNzv/////AAAAAAAA
AACoQeQCgPj//6hB5AKA+P//MNd2Nv////8AAAAAAAAAAGAapgOA+v//YBqmA4D6//8Ais1X
AAAAAAAAAAAAAAAA6EHkAoD4///oQeQCgPj//6CWPTv/////AAAAAAAAAAAIQuQCgPj//whC
5AKA+P//YOg/O/////8AAAAAAAAAALAjTwOA+v//sCNPA4D6//9ACqBnCAAAAAAAAAAAAAAA
QEF7A4D6//9AQXsDgPr//4DvvWMAAAAAAAAAAAAAAABoQuQCgPj//2hC5AKA+P//QGpHO///
//8AAAAAAAAAAIhC5AKA+P//iELkAoD4//8AeYc2/////wAAAAAAAAAAqELkAoD4//+oQuQC
gPj//2AaxzH/////AAAAAAAAAAAwPA8DgPr//zA8DwOA+v//gB8cUwAAAAAAAAAAAAAAAOhC
5AKA+P//6ELkAoD4///A71A7/////wAAAAAAAAAACEPkAoD4//8IQ+QCgPj//4CeLzT/////
AAAAAAAAAAAoQ+QCgPj//yhD5AKA+P//YP70OP////8AAAAAAAAAAEhD5AKA+P//SEPkAoD4
//9AgVg7/////wAAAAAAAAAAaEPkAoD4//9oQ+QCgPj//6AimDb/////AAAAAAAAAACIQ+QC
gPj//4hD5AKA+P//gAjXMf////8AAAAAAAAAAKhD5AKA+P//qEPkAoD4///gKZw2/////wAA
AAAAAAAAyEPkAoD4///IQ+QCgPj//8CmADn/////AAAAAAAAAABAcZADgPr//wCthQOA+v//
wFrFPQAAAAAAAAAAAAAAADDInQOA+v//MMidA4D6//9vQG/m/PsvfgAAAAAAAAAAQBGRA4D6
//8QX1gDgPr//6BONlMAAAAAAAAAAAAAAABIROQCgPj//0hE5AKA+P//QMyoNv////8AAAAA
AAAAAGhE5AKA+P//aETkAoD4//9AQDBA/////wAAAAAAAAAAiETkAoD4//+IROQCgPj//2A8
6zH/////AAAAAAAAAABAwXUDgPr//0DBdQOA+v//oCnrYwAAAAAAAAAAAAAAAMhE5AKA+P//
yETkAoD4///A8VA0/////wAAAAAAAAAAIPdCA4D6//8g90IDgPr//8Alm0IAAAAAAAAAAAAA
AAAIReQCgPj//whF5AKA+P//gNR5O/////8AAAAAAAAAAChF5AKA+P//KEXkAoD4//8gT5Nh
/////wAAAAAAAAAASEXkAoD4//9IReQCgPj//0AX+TH/////AAAAAAAAAAAwyIgDgPr//zDI
iAOA+v//YHykQgAAAAAHAQYAAAAAAEgheAGA+v//SCF4AYD6//8AAAAAAAAAABMCAQEAAAAA
ACPkAoD4//8AI+QCgPj//zATtgIA+P//AAAAAAAAAAAAPB4DgPj//wg8HgOA+P//AAAAAAAA
AAABAAAAAGQAAAAAAAAAAAAAKEgCAAAAAAAAAAAAAAAAAPC7bQOA+v//ALGGAoD6//8AAAAA
AAAAAAAAAAABAAAAEwEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAQH6/AgD4//8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gEbkAoD4//+ARuQCgPj//5BG5AKA+P//kEbkAoD4//+gRuQCgPj//6BG5AKA+P//sEbkAoD4
//+wRuQCgPj//8BG5AKA+P//wEbkAoD4///QRuQCgPj//9BG5AKA+P//4EbkAoD4///gRuQC
gPj///BG5AKA+P//8EbkAoD4//8AR+QCgPj//wBH5AKA+P//EEfkAoD4//8QR+QCgPj//yBH
5AKA+P//IEfkAoD4//8wR+QCgPj//zBH5AKA+P//QEfkAoD4//9AR+QCgPj//1BH5AKA+P//
UEfkAoD4//9gR+QCgPj//2BH5AKA+P//cEfkAoD4//9wR+QCgPj//4BH5AKA+P//gEfkAoD4
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
AAAAAAAAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAHkAoD4//+wjeYCgPj//wAAAAAAAAAA
QK/kAoD4//9gsIYCgPr//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAJCobAGA+v//wE7kAoD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAIbm0CgPr//wEAAAAAAAAAAgAAAAAAAAAKAAAAAAAAAEhubQKA+v//
gAHkAoD4///Aaa0CAPj//yAC4///////gAHkAoD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
gPr//7lp+wCA+P//AgIAAAAAAAAqEq0BgB8AAAAAAAAAAAAA4BDGAgD4///gEMYCAPj//0tE
QkdAAwAAAGClAgD4///wOawCAPj//wAAAAAAAAAA6AHYAAAAAQAQMqwCAPj//wAAAAAAAAAA
kJjJAgD4//+QtccCAPj//8i1xwIA+P//UBTHAgD4//8wOtACAPj//3gw0AIA+P//lDDQAgD4
//8AxcwCAPj//4BjzAIA+P//8ArNAgD4///QwccCAPj//+jBxwIA+P//AAAAAAAAAAAAAAAA
AAAAAABr0AIA+P//eDLQAgD4//8AAAAAAAAAAAAAAAAAAAAA+DnQAgD4//8kL8gCAPj///gy
0AIA+P//CDHQAgD4//9gMNACAPj//+Ay0AIA+P//AAAAAAAAAAC4MNACAPj//wAAAAAAAAAA
AAAAAAAAAACgMdACAPj//9A40AIA+P//ABAAAAAAAACQNNACAPj//xgfyAIA+P//IB/IAgD4
///A0sYCAPj//yiZyQIA+P//8B7IAgD4//9gH8gCAPj//wAAAAAAAAAAAGXQAgD4///AatAC
APj//8Br0AIA+P//wGLQAgD4//9gTMQCAPj//8D7xAIA+P//APzEAgD4//9oGscCAPj//4C1
xQIA+P//EDDQAgD4//8AMdACAPj//wAw0AIA+P//cM/FAgD4//9w38UCAPj//7hPxAIA+P//
ZM/FAgD4///woMkCAPj//6CrwAIA+P//AAAAAAAAAABAPNACAPj//+gx0AIA+P//iJjJAgD4
///InMcCAPj//9Qw0AIA+P//yP7GAgD4///gnMkCAPj//xA0yAIA+P//UB/IAgD4//8oH8gC
APj//5wtzQIA+P//ODDQAgD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwA
uAA4ACgAcABkAQAAAADQBDgDkAIoAABN2iEIAPQF8AW4SyABJACoBAAAAAAAAJBQxAIA+P//
mFDEAgD4//9A1cwCAPj//4BOGAAgAIABAAAAAAAAAAAAAEAAEAAYAAAAMwArAAAAAABAACMA
UwAABs0CAPj//wACzQIA+P//AAAAAAAAAABIG8gCAPj//0QbyAIA+P//gGfAAgD4///YSwAA
AAAAAEjZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJD3AID4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAS8AAAAAAAADbyltKAAAAAKDdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGD4AID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJwBAAAAAAD8dWRU
AAAAAPjdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAGD5AID4//8AAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADaoBAAAAAADxdWRUAAAAAEjeAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD6AID4//8AAAAA
AAAAAABQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFdYCAAAAAAAcdmRUAAAAAKDeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED9AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyN8BAAAAAADBG2RP
AAAAAPjeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAJD+AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcp8BAAAAAACgkudMAAAAAFDfAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAID4//8AAAAA
AAAAAADABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAbV8GAAAAAADrkudMAAAAAKjfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAID4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqRABAAAAAAAUwVtK
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMDFAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxZwBAAAAAAAUwVtKAAAAAFjgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDGAID4//8AAAAA
AAAAAACgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAISYCAAAAAACZkudMAAAAALDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDIAID4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu2UAAAAAAAATwVtK
AAAAAAjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAGDdAID4//8AAAAAAAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVgsDAAAAAAC1+f5RAAAAAGDhAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAALjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMADAYD4//8AAAAAAAAAAABABgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlb4DAAAAAAAyRPBS
AAAAABDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAKAYD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNUAAAAAGjiAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKANAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjikBAAAAAAA+YGNUAAAAAMDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAOAYD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt5IAAAAAAADKo6NL
AAAAABjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFAPAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALUUFAAAAAACckudMAAAAAHDjAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAUAYD4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAARFYBAAAAAACBxFtKAAAAAMjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAgAYD4//8AAAAAAAAAAACQGgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXfIZAAAAAACKvuFS
AAAAABjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFAVAYD4//8AAAAAAAAAAADgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+kFAAAAAAA0k+dMAAAAAHDkAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA6AYD4//8AAAAA
AAAAAACwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAqfcBAAAAAAAOkkhTAAAAAMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJAYD4//8AAAAAAAAAAAAgBwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhV4HAAAAAAC3TxlQ
AAAAABjlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAACBQAYD4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXksBAAAAAAD/wFtKAAAAAGjlAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBRAYD4//8AAAAA
AAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAki8BAAAAAADS705PAAAAAMDlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBvAYD4//8AAAAAAAAAAAAgDwAAAAAAAAAAAAAA
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
AAAAAAAAAABAAYD4//8AAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvhgDAAAAAACbkudMAAAAAHjqAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKA8AYD4//8AAAAA
AAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAQrcCAAAAAACYkudMAAAAANDqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBIAYD4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2+kAAAAAAAAJwVtK
AAAAACDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADBfAYD4//8AAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6zYAAAAAAACNyltKAAAAAHDrAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAeAYD4//8AAAAA
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAbz4BAAAAAACHxVtKAAAAAMDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDMA4D4//8AAAAAAAAAAABQAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx48CAAAAAACLxVtK
AAAAABjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAODOA4D4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvpwBAAAAAAA/xVtKAAAAAHDsAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODPA4D4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArP8AAAAAAABizltKAAAAAMjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDQA4D4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1XQAAAAAAABizltK
AAAAACDtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAADRA4D4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzasAAAAAAABjzltKAAAAAHjtAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDRA4D4//8AAAAA
AAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAJnEAAAAAAAATwVtKAAAAAMjtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDSA4D4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ZoBAAAAAAAUwVtK
AAAAABjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFDTA4D4//8AAAAAAAAAAAAgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsogCAAAAAAAyk+dMAAAAAGjuAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDVA4D4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVWIBAAAAAAA+k+dMAAAAALjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDWA4D4//8AAAAAAAAAAACQCAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ukHAAAAAAAcKYhT
AAAAAAjvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAADAA4D4//8AAAAAAAAAAABQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBEEAAAAAACGk+dMAAAAAGDvAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFDEA4D4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAe7EAAAAAAAC2zFtKAAAAALjvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODEA4D4//8AAAAAAAAAAABgAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzw0CAAAAAABiqOdM
AAAAABDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEDHA4D4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaBYBAAAAAAC2zFtKAAAAAGjwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIA4D4//8AAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTQBAAAAAAAZRPBSAAAAAMD9AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHA1BID4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAACD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA4BID4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNU
AAAAAID+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANA7BID4//8AAAAAAAAAAAAwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6g0BAAAAAACPwVtKAAAAAOD+AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAGD5//8AAAAA
AAAAAAAgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAACj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9BID4//8AAAAAAAAAAADAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkEBAAAAAAB0xVtK
AAAAAID/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABQAGD5//8AAAAAAAAAAADgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAND/AAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCxAoD4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdQAAAAAAAAWJcdT
AAAAAHgGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAICyAoD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApR8EAAAAAAAxJcdTAAAAANAGAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC2AoD4//8AAAAA
AAAAAAAQBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFCIHAAAAAAB6XghKAAAAACgHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC9AoD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmgAAAAAAADlzFtK
AAAAACEAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABuAHQA
bwBzAGsAcgBuAGwALgBlAHgAZQAAABwAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABoAGEAbAAuAGQAbABsAAAAAAAeAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAawBkAGMAbwBtAC4AZABsAGwAAAAAAAAAAAAuAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAbQBjAHUAcABkAGEA
dABlAF8ARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwALgBkAGwAbAAAAAAAAAAAAB4AAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABQAFMASABFAEQALgBkAGwA
bAAAAAAAAAAAAB0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABDAEwARgBTAC4AUwBZAFMAAAAbAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAQwBJAC4AZABsAGwAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABXAGQAZgAwADEAMAAwADAA
LgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAVwBEAEYATABEAFIALgBTAFkAUwAAAAAAAAAlAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAEEA
QwBQAEkALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBNAEkATABJAEIALgBTAFkAUwAAAAAAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAG0AcwBpAHMAYQBkAHIAdgAuAHMAeQBzAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABwAGMAaQAuAHMAeQBzAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHYAZAByAHYAcgBvAG8AdAAuAHMAeQBzAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBmAGkA
bAB0AC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4ALgBzAHkAcwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgBiAHUAcwAuAHMAeQBzAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABhAHIAdABtAGcAcgAuAHMAeQBzAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHYAbwBsAG0AZwByAC4AcwB5AHMAAAAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXAB2AG8AbABtAGcA
cgB4AC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaQBuAHQAZQBsAGkAZABlAC4AcwB5AHMAAAAoAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAFAAQwBJAEkARABFAFgALgBTAFkAUwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABtAG8AdQBuAHQAbQBnAHIA
LgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAYQB0AGEAcABpAC4AcwB5AHMAAAAAAAAAAAAoAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGEA
dABhAHAAbwByAHQALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgB2AGIAZAAuAHMAeQBzAAAA
AAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAcwB0AG8AcgBwAG8AcgB0AC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHgAZQBuAGMA
cgBzAGgALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBkAGkAcwBrAC4AcwB5AHMAAAAAACgA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwAYQBtAGQAeABhAHQAYQAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGYAbAB0AG0AZwByAC4A
cwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAGQAcgBpAHYAZQByAHMAXABmAGkAbABlAGkAbgBmAG8ALgBzAHkAcwAAACUAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwA
TgB0AGYAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQA
ZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABtAHMAcgBwAGMALgBzAHkAcwAAAAAAAAAAACcA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAawBzAGUAYwBkAGQALgBzAHkAcwAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAGMAbgBnAC4AcwB5AHMA
AAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIA
aQB2AGUAcgBzAFwAcABjAHcALgBzAHkAcwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABGAHMAXwBSAGUAYwAuAHMA
eQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAbgBkAGkAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABOAEUAVABJAE8A
LgBTAFkAUwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBwAGsAZwAuAHMAeQBzAAAAAAAmAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHQAYwBwAGkAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABmAHcAcABrAGMAbABuAHQA
LgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAdgBtAHMAdABvAHIAZgBsAC4AcwB5AHMAAAAoAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYA
bwBsAHMAbgBhAHAALgBzAHkAcwAAAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMA
eQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAHAAbABkAHIALgBzAHkAcwAAAAAA
AAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIA
aQB2AGUAcgBzAFwAcgBkAHkAYgBvAG8AcwB0AC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAG0AdQBwAC4A
cwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAaAB3AHAAbwBsAGkAYwB5AC4AcwB5AHMAAAAnAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGYA
dgBlAHYAbwBsAC4AcwB5AHMAAAAAAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABkAGkAcwBrAC4AcwB5AHMAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAEMATABBAFMAUwBQAE4AUAAuAFMAWQBTAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABjAGQAcgBvAG0ALgBzAHkA
cwAAAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAHIAaQB2AGUAcgBzAFwATgB1AGwAbAAuAFMAWQBTAAAAJQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABCAGUAZQBwAC4A
UwBZAFMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHYAZwBhAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVgBJAEQARQBPAFAA
UgBUAC4AUwBZAFMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHcAYQB0AGMAaABkAG8AZwAuAHMAeQBzAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABSAEQAUABDAEQARAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAAZQBuAGMAZABkAC4A
cwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHIAZABwAHIAZQBmAG0AcAAuAHMAeQBzAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABNAHMA
ZgBzAC4AUwBZAFMAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwARAByAGkAdgBlAHIAcwBcAE4AcABmAHMALgBTAFkAUwAAACQAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdABkAHgA
LgBzAHkAcwAAAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABUAEQASQAuAFMAWQBTAAAAAAAkAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGEAZgBkAC4A
cwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgB0AC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHcA
ZgBwAGwAdwBmAC4AcwB5AHMAAAAAAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABwAGEAYwBlAHIALgBzAHkAcwAAAAAA
AAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAbgBlAHQAYgBpAG8AcwAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHcAYQBuAGEA
cgBwAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AGUAcgBtAGQAZAAuAHMAeQBzAAAAAAAAACYA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAcgBkAGIAcwBzAC4AcwB5AHMAAAAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAG4AcwBpAHAAcgBvAHgA
eQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABtAHMAcwBtAGIAaQBvAHMALgBzAHkAcwAAACkAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwA
ZABpAHMAYwBhAGMAaABlAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGMAcwBjAC4AcwB5AHMAAAAAACUA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAZABmAHMAYwAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAGwAYgBkAHIAaQB2AGUALgBzAHkA
cwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAdAB1AG4AbgBlAGwALgBzAHkAcwAAAAAAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGkAOAAwADQA
MgBwAHIAdAAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAG8AdQBjAGwAYQBzAHMALgBzAHkAcwAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAawBiAGQAYwBsAGEAcwBzAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGYAZABjAC4AcwB5AHMA
AAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAeABlAG4AdgBpAGYALgBzAHkAcwAAAAAAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHgAZQBuAGkA
ZgBhAGMAZQAuAHMAeQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB2AGkAbwBzAGUAcgAuAHMAeQBzAAAAAAAAACQA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAcQB4AGwALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB1AHMAYgB1AGgAYwBpAC4AcwB5AHMA
AAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAVQBTAEIAUABPAFIAVAAuAFMAWQBTAAAAAAAoAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHUAcwBiAGUA
aABjAGkALgBzAHkAcwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABpAG4AdABlAGwAcABwAG0ALgBzAHkAcwAAAC0A
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAQwBvAG0AcABvAHMAaQB0AGUAQgB1AHMALgBzAHkAcwAAACkAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAQQBnAGkA
bABlAFYAcABuAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAGwAMgB0AHAALgBzAHkAcwAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXABuAGQAaQBzAHQAYQBwAGkALgBzAHkAcwAAACgAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBkAGkAcwB3AGEA
bgAuAHMAeQBzAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAHAAcABwAG8AZQAuAHMAeQBzAAAAKAAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XAByAGEAcwBwAHAAdABwAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcgBhAHMAcwBzAHQAcAAuAHMA
eQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAHIAZABwAGIAdQBzAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHcA
ZQBuAHUAbQAuAHMAeQBzAAAAAAAAACMAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAawBzAC4AcwB5AHMAAAAAAAAAJgAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XAB1AG0AYgB1AHMALgBzAHkAcwAAAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdQBzAGIAaAB1AGIALgBzAHkA
cwAAAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
RAByAGkAdgBlAHIAcwBcAE4ARABQAHIAbwB4AHkALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgBuAGUAdAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAYwByAGEAcwBoAGQAbQBwAC4AcwB5AHMA
AAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkA
dgBlAHIAcwBcAGQAdQBtAHAAXwBkAGkAcwBrAGQAdQBtAHAALgBzAHkAcwAAAAAAAAAAACwA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AcwB5AHMAAAAAAC0AAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0A
cABfAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAC0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0AcABfAGQAdQBtAHAA
ZgB2AGUALgBzAHkAcwAAAB8AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXAB3AGkAbgAzADIAawAuAHMAeQBzAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwARAB4AGEAcABpAC4A
cwB5AHMAAAAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAGQAeABnAC4AcwB5AHMAAAAAAB4AAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABUAFMARABEAEQALgBkAGwAbAAAAAAA
AAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABxAHgA
bABkAGQALgBkAGwAbAAAAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbAB1AGEAZgB2AC4AcwB5AHMAAAAAAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAGwAbAB0AGQAaQBvAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAByAHMAcABuAGQA
cgAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABUAFQAUAAuAHMAeQBzAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAG8A
dwBzAGUAcgAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbQBwAHMAZAByAHYALgBzAHkAcwAAAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAG0AcgB4AHMAbQBiAC4AcwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAHIAeABzAG0A
YgAxADAALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAbQByAHgAcwBtAGIAMgAwAC4AcwB5AHMAAAAnAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHAAZQBhAHUAdABoAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAGUAYwBkAHIAdgAuAFMA
WQBTAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAFIASQBWAEUAUgBTAFwAcwByAHYAbgBlAHQALgBzAHkAcwAAAAAAAAApAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHQA
YwBwAGkAcAByAGUAZwAuAHMAeQBzAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHIAdgAyAC4AcwB5AHMAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAHMAcgB2AC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAAZAByAC4AcwB5AHMAAAAAAAAA
AAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHQAZAB0AGMAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AHMAcwBlAGMA
cwByAHYALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAUgBEAFAAVwBEAC4AUwBZAFMAAAAAAAAAAAAmAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHMAcABzAHkAcwAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABhAHMAeQBuAGMAbQBhAGMA
LgBzAHkAcwAAAOCcyQIA+P//cAgBAJwAAABIG8gCAPj//wwJAQAEAAAARBvIAgD4//8QCQEA
BAAAAKCrwAIA+P//FAkBAAABAAAABs0CAPj//xQKAQAEAAAAAALNAgD4//8YCgEAUAAAAHww
0AIA+P//aAoBAAQAAABoMNACAPj//2wKAQAEAAAAWOIcAoD6//9wCgEAACAAAIDSxgIA+P//
cCoBAAgAAACI0sYCAPj//3gqAQAIAAAAALDBAgD4//+AKgEAABAAAABgpQIA+P//gDoBAAAQ
AAAAgOYCgPj//4BKAQAAEAAAALCsAgD4//+AWgEAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANzYwMS4xODUyNi5hbWQ2NGZy
ZS53aW43c3AxX2dkci4xNDA3MDYtMTUwNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhMDVlNTg1NC1h
MDAxLTRjMjItODg1MS1kZDc4NWUxMAUAAAB8MNACAPj//4Aw0AIA+P//aDDQAgD4//9sMNAC
APj//1jiHAKA+v//WAIdAoD6//+A0sYCAPj//4jSxgIA+P//iNLGAgD4//+Q0sYCAPj//0cA
AAAAAAAAaAAAAAgEAACEBgAAtAkAANwIAAAgBwAAuAIAAGgJAAAkAAAAhAgAADwAAAA8BQAA
VAUAAEgFAABICwAACAAAAAgHCAgICA0EDQgMCAgICAADAAAAgF4AAOAGLwQAAABcAACQDa8G
AAAAXAAAhBFXBgAAAFwAACgRawQAAABcAAC8DecEAAAAXAAAIAtTBgAAAFwAAEAQfwYAAABc
AAB8DxsEAAAAXAAAwY8BAAaAmwFx7QMABoAAAd2YAwAGAP8AdfEDAAaA+wBppgMABgD9AE32
AwAGAP0AoXoCAAqeQhOAcwqeySYYwwYAWgFl7AMABgADAX1PAQBOjCkETA5SIq8IZHxSorsC
gDBSoi4GHCBSHlADnB5WHnke1cMQABqaXgFhejsAHogmCKnGZAEaGokBmYWgARqabAH9kKAB
Ih5YARqaBwImm0cErV4BACoAPx2plHQALgzwA0QdMh7cAMWidgA2CNoAoYGyABqacAE5hKAB
GhpsAcGHoAEammsBJhvMBM1JOwAamggBfQhlARoaaAFph6ABGhoMAu0GZQG6GpEC9WU7ABqa
DgEmG9gDtKd+EBcCRBMGgMwBhNsAAAIAAsDyAAoDvAgAALgIAACtynJhAQAAAAAAAAAAAAAA
AABAAAAAAAAAkBwAAAAAALgIAACPlhsAmHQbUgAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA
AABcAEQAZQB2AGkAYwBlAFwASABhAHIAZABkAGkAcwBrAFYAbwBsAHUAbQBlADIAXABQAHIA
bwBnAHIAYQBtACAARgBpAGwAZQBzACAAKAB4ADgANgApAFwAUwBQAEkAQwBFACAARwB1AGUA
cwB0ACAAVABvAG8AbABzAFwANgA0AFwAdgBkAGEAZwBlAG4AdAAuAGUAeABlAAAAAsBQAAoB
AgACwJYACgO8CAAAuAgAAGPNcmEBAAAAAAAAAAAAAAAAAAN3AAAAAACQGgAAAAAAuAgAAF+H
GgAkrx5SAAAAAAAAA3cAAAAAAAAAAAAAAAAAAAAAAAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAG4AdABkAGwAbAAuAGQAbABsAAAAAAACABHAmgAgBIzm
cmEBAAAAQPH5AqD4//9cAEQAZQB2AGkAYwBlAFwASABhAHIAZABkAGkAcwBrAFYAbwBsAHUA
bQBlADIAXABXAGkAbgBkAG8AdwBzAFwAUAByAGUAZgBlAHQAYwBoAFwAVgBEAEEARwBFAE4A
VAAuAEUAWABFAC0ARQA0AEQAQgAwAEEANABEAC4AcABmAAAAAAAAAAAAAgARwJIAIASVhIJh
AQAAAECh+AKg+P//XABEAGUAdgBpAGMAZQBcAEgAYQByAGQAZABpAHMAawBWAG8AbAB1AG0A
ZQAyAFwAVwBpAG4AZABvAHcAcwBcAFMAeQBzAHQAZQBtADMAMgBcAGkAdAAtAEkAVABcAHQA
egByAGUAcwAuAGQAbABsAC4AbQB1AGkAAABTAoD6//8CAALAlgAKA7wIAAC4CAAAxCmEYQEA
AAAAAAAAAAAAAAAA8XYAAAAAAPARAAAAAAC4CAAAxAcSAFmgFVMAAAAAAADxdgAAAAAAAAAA
AAAAAAAAAAAAAAAAXABXAGkAbgBkAG8AdwBzAFwAUwB5AHMAdABlAG0AMwAyAFwAawBlAHIA
bgBlAGwAMwAyAC4AZABsAGwAAAAAAAIAAsCaAAoDvAgAALgIAAC+QIRhAQAAAAAAAAAAAAAA
AADh/P4HAAAAwAYAAAAAALgIAAAw1AYAWqAVUwAAAAAAAOH8/gcAAAAAAAAAAAAAAAAAAAAA
AABcAFcAaQBuAGQAbwB3AHMAXABTAHkAcwB0AGUAbQAzADIAXABLAGUAcgBuAGUAbABCAGEA
cwBlAC4AZABsAGwAAAAAAAAAAAACAALAkAAKA7wIAAC4CAAAGmaGYQEAAAAAAAAAAAAAAAAA
Kf/+BwAAAOACAAAAAAC4CAAADVUDAEDfW0oAAAAAAAAp//4HAAAAAAAAAAAAAAAAAAAAAAAA
XABXAGkAbgBkAG8AdwBzAFwAUwB5AHMAdABlAG0AMwAyAFwAaQBtAG0AMwAyAC4AZABsAGwA
AAACAALAkAAKA7wIAAC4CAAARHqGYQEAAAAAAAAAAAAAAAAApv3+BwAAAJAQAAAAAAC4CAAA
zAARAKrfW0oAAAAAAACm/f4HAAAAAAAAAAAAAAAAAAAAAAAAXABXAGkAbgBkAG8AdwBzAFwA
UwB5AHMAdABlAG0AMwAyAFwAbQBzAGMAdABmAC4AZABsAGwAAAADAALAaAABBbwIAAC4CAAA
42qJYQEAAAAAAAAAAAAAALgIAADACAAAAODwAYD4//8AgPABgPj//wAACAIAAAAAAPAHAgAA
AAADAAAAAAAAAPDgQAAAAAAAAMD9//8HAAAAAAAADQUCAAIAAsCUAAoDvAgAALgIAAByPoph
AQAAAAAAAAAAAAAAAAB8+/4HAAAAYAUAAAAAALgIAABgbQUAk+BbSgAAAAAAAHz7/gcAAAAA
AAAAAAAAAAAAAAAAAABcAFcAaQBuAGQAbwB3AHMAXABTAHkAcwB0AGUAbQAzADIAXAB1AHgA
dABoAGUAbQBlAC4AZABsAGwAAAACzKs3AgARwKABJQXfI5FhAQAAAH5mcmEBAAAAvAgAAFwC
AAAwBAAAIAcAANwIAAC0CQAACAAAAGgAAAAIBAAAQAIAALgBAABwAgAANAgAAHAKAADABAAA
hAYAAAgNCAgICAAIBw0NCAgICAgCCgAAaLdGoC0HvJgCEukW3Vs3AAoMOgIODHANaHYSIqYK
1CJSHlcDjEFC0JtFAAZCzI9NVowgBUIS3xdaEA4CeG47BQAAB1wAABwfmwsAAAdcAAA4GN8K
AAAHXAAAOBJ/CgAAB1wAAEgSlwoAAAdcAAC8F1sHAAAHXAAA9CKzEAAAB1wAAHgaOwwAAAdc
AAD0GmMGAAAHXAAAMJQiAL4CePdCUFgB+AaCUDEGWAVCzqkXQqKSVSIAaAFPGwAAZCo0AGag
bgETAAcAZCphAGqgmAJCAKhhLszGAkI2VT8yzHEBglCjATLMKgGC0LAEMsw9AUKjoCq2TC8C
giNWxTJM0QKCo418esxnAoIj8wB6ILUBPkxGAoKj2QB6INQAPkzSAIKjMQV6oOwAPkznAXsp
GgCwOQAA/AUCAALAkgAKA7wIAAC4CAAAjLqxYQEAAAABAAAAAAAAAAAAOfv+BwAAAIABAAAA
AAC4CAAAd0gBACffW0oAAAAAAAA5+/4HAAAAAAAAAAAAAAAAAAAAAAAAXABXAGkAbgBkAG8A
dwBzAFwAUwB5AHMAdABlAG0AMwAyAFwAZAB3AG0AYQBwAGkALgBkAGwAbAAAADY/BgCVCwIA
AsCSAAoDvAgAALgIAAA0ebthAQAAAAEAAAAAAAAAAADG/P4HAAAA0AMAAAAAALgIAACccAQA
6C/HUwAAAAAAAMb8/gcAAAAAAAAAAAAAAAAAAAAAAABcAFcAaQBuAGQAbwB3AHMAXABTAHkA
cwB0AGUAbQAzADIAXAB3AGkAbgBzAHQAYQAuAGQAbABsAAAAAAAAAAAAAwACwGgAAQW8CAAA
uAgAAJg8vGEBAAAAAQAAAAAAAAC4CAAA5AEAAADAFgWA+P//AGAWBYD4//8AAE0CAAAAAADw
TAIAAAAAAwAAAAAAAADwrgR3AAAAAACg/f//BwAAAAAAAA0FAgADAALAaAABBbwIAAC4CAAA
mU+9YQEAAAABAAAAAAAAALgIAAAgCAAAAHAtA4D4//8AEC0DgPj//wAAbQIAAAAAAPBsAgAA
AAADAAAAAAAAAPD7BHcAAAAAAID9//8HAAAAAAAADQUCAAIAEcD6AyUFQpq5YgEAAAADI5Fh
AQAAANAIAACECAAAvAgAAGgJAAD0AgAAPAMAAOQBAAAsBAAA8AMAACAIAAC4AQAACAAAALgC
AABkAAAAkAYAAIwAAAAICA0ECQkNCAgNDQANCAcPQjcAAHQpBrcHAhgPSrYQBNgPQrd5AbgM
SjZFA6gMQjdxAXgOSjYeA5wMQrdbAegMSrZ0ipwFBjdeAUgOSjaZBKwNBreTAcAMSrZFA8wM
BrdLArAESrYJA/QMBjfOASgeQjeAARQRQjcnATwdQtG9AEo2ZwMGNwABSjZHAwY3JwHrRxoA
sjkAAKgFQs2oAkpQdgFCzQQBSracAnQSQjf3AlgNSlBBAwbNIAFKNmgBBk3LAUo2UwEG0TYC
SjZNATQRSjaCAZwEBs0GAUo2NAEGURsBeAQGNwICsAwGNzgBYA8GNyQBIDQGNxsB/A0GNyIB
dBIGtxwBuBFKtisBIAxKNuQABtGsAEo2EgEGN7wAIARKtlEBBrfCAEQESjZDBEgOQk0fAUpQ
BAFCzfEASrZCAUI38gBKtpgBBlH0AoQEBk2tAUq2nR4GtxwFFbUQAA6IqwrpvRsABjd+AWgr
Qjd0AQY3HgFCN5sABrd2AkXFLQBKNpsCRtE0AUo2MQFCTSsBSlBeAUJNCwFKtlwBQrfXAMQR
SrYzAdQOSjajAQwWSjaMAZgRSrYjAUwTSjZ+AfQPSjZqAbQVSlCXAYwEStC1AAZN+wBKtmgB
BrdpAUq24QHgDkq2awHADEo2swAG0SEBSrbpAxANStCWA3gFSjZGJQZNoAFKtqQDBhsgAdWC
JQBKNhsC4BRKIu0yEkzrAkoiLAQSnqEBFkwqAkqiNQMWnmwBEszQCEoiWAYSHpMBFkxvCEqi
TgQWHoMBEkwEBUoq0g0aTA4ESir2ARpMpQFKIsYEGoxqARIegwEWTAkHSqKBAxYegQESTJUH
SiJmAxKeewEWTOkESqITCBaelgESTOAGSiKVAxIehgEWzP8GSiJXAxYegAESzLMESqJbBxKe
wAEeTOYCSiIFAh4eewEizLMCSqKpASKe+QAeoiwMEp61BF5MUAVKjAINXp4wARciAABpNgIA
aiDjASaeaQEinhMD3WY9AG6QzAENHAMABtFCFbQFBregAXgVBjdSAlAVBjc7AWQWBjc5AZwR
BlE7AWwEBjeqAYwMBrdfA8gMBjczASAPBtFAArgEBrenAQQKBlESA5wEBjc+AUgPBtEoApQE
BjezAcwJBrctAUwPBlHKAYAEBjfMAigKBtHoAvwEBjeGAWgMrwKpANEkAAD9xiYBMpotAiF2
oAEymnkBfXs7ANdWAQANQAAAOoxNAz4A0QAAAAQAAAACABHA+gAlBWo8SGUBAAAAcZm5YgEA
AACQAAAAnAAAAIQAAACUAAAAiAAAACQAAAA8AAAAPAUAAMAGAAC4AgAASAoAAJALAACMCAAA
BAsAADAEAACEBgAACA8PDw8NDAgIDQgICAgICMIBAAAGgBABCgCbAA6AlwASgJgAFh6/ABoA
6DQJ9wIAFp5VAkG5cAAejOYDICIiHvMBUdHtACYaEQMVW6ABJpqsAbGBoAEmGmoBmft2ACoM
hAEunhQEnFgyHgAJTbQ6ACaaNQEV/e0AJppIAYGdoAEmGgoDxdd2ADYMVAKtfSkBJppzARmA
sgA6DCUDPgyoEKiQAAAAAAAAAwACwGgAAgWYCwAAZAYAALa0QWcBAAAAAAAAAAAAAABkBgAA
mAsAAACQ8ASA+P//ADDwBID4//8AAKwBAAAAAACAqwEAAAAAAwAAAAAAAADw+wR3AAAAAADg
+f//BwAAAAAAAAgFAgACABHAsAElBZhE4mgBAAAAaDtIZQEAAADcCAAAmAcAAPQCAAC0CQAA
IAcAAJQHAABoCQAAJAAAALgCAAA8AAAAPAUAAMAGAAA0AAAAmAsAAIAKAABIBQAACAgJCAgI
BA0NDAgIDAgECAIiAADQK0KenAOUmUaMKAdsn0aiEQ84lgoeHgfkKE4MCwF8C04MewQwLkIi
KQPUKEKinAFgJkJQc3fQBULMMgHsEkJMIAHsDUJMJAE4DUJQ6wF4BEJQhAGkBEJMCQHUDUJM
ZgGYC5MHGAAQJQAACKZCovEPkTwBAEKiBegKHqQErEQSnisR7BYSnhkGlDESns0DBBlGjCIF
UN5WjBACqZZIABoIaAgNyXYA3oBOC1U4oAEiGn8BgYagASIa/AHx8HYAHp7FAO2TAQAmgAId
8aZ0ACoM7QZYGC6eXgFFh3YAMh7vABl6OwAimvABMYKgASIahQEl+XYANlITCY1aKQEimhgD
GWI7ACaeUQE5bLIAOgzSAd2NOwAiGj0Dec92ACKakwFdfbIAPgj9AHGCsgAeHsEArXI7ACIa
VwGVjKABIhpRAk3+dgACABHAtAElBbOPKWoBAAAAyULiaAEAAABICwAAMAQAACAHAACUBwAA
sAMAANwIAAD0AgAACAAAAAgEAABoAAAAtAkAAIQGAAC4AgAAhAgAACQAAACQBgAACAgICAgI
CQAHCAgIDQgNB4IaAAARZLIABgwfA3AECp7cAPQ/TiINDbhHCh45BCAZTgyMDZwmTgzmE9xZ
Eh4+DOQlViKID6wtVqJ3CRoeCgeAGRqegwQgEBqeFQRErl4QDQQFVwIAIoC4AbQbpwUAAAlc
AABMDBMHAAAJXAAArBB3BgAACVwAAJwPYwYAAAlcAAA4EG8EAAAJXAAAxA2nBAAACVwAAJwL
YwYAAAlcAADwD2cGAAAJXAAANA8fBAAACVwAAP3SAwAigAkBMbIDACKAMwH9BQQAIgAVASmY
AwAigAcBARgEACKAGQG9qwMAIgAJAThHCp4JFKRzCp6tJo0AAwAiAG4B5ZoDACIABQHgN2oM
RATUBFYizQjQh1Yi0gIAMFaiYAbEH1YeIwPoH26eoh7pukoAMhoeATab4QNxZKABMhqJAQmE
oAEyGvcBYX2yADoe3wA+DIECAgAAAAIAEcAOASUF6/DVbAEAAADijilqAQAAAJAAAACcAAAA
hAAAAJQAAACIAAAAPAAAAHQAAAAkAAAAHAAAAGgAAAA8BQAAVAUAALgCAABIBQAAgAoAAIQI
AAAIDw8PDwwIDQ0ICAgNCAQIwgEAAAYA/QAKgJYADoCOABIAkgAWgMcvnekCABqQvwAeAOkG
Ip6QABYeigFkF4csAAAJXAAAVfFxACoMwAbcGC6e+gBhj3YAMpoeAgF8oAEyGn0BAYQpATaI
9QBF/XYAMppvAcX5ewAWTrYhTBMW0PgA5BAWHqsFvaXnADoMswK5YjsAMpqXAamDoAEyGn8B
vZGgATKafwKFdaABMpoYAT4begNMDgAAAgARwLABJQWwfP9tAQAAABbw1WwBAAAAIAcAAJQH
AADcCAAA9AIAAAgAAABoAAAACAQAALQJAACEBgAAaAkAALgCAABkAAAAJAAAAHQKAAA8AAAA
PAUAAAgICAkACAcICAQNCA0IDAgCHgAA/DtGIoMNcEYCHkoECBlGjJ4NzCVGDCMUtGFKoqMP
CC1KoncJDh4jBygaDp62BKwQDp4WBMSGUpBpAw2OAgALCQAABVwAAEQS1wYAAAVcAADID48G
AAAFXAAASA+DBgAABVwAAOgPdwQAAAVcAAA4DZ8EAAAFXAAA0AtfBgAABVwAAAgQcwYAAAVc
AABEDzsEAAAFXAAAMZABABoAhgGx7wMAGgANAX2aAwAagP8AMfEDABqAAwHFogMAGoABATH6
AwAaAH8BNUsCAAIeFhSwcwIeRSecwRqAfwGl7gMAGgAGAfknAgBejKsGIBtKIoUJzIRKotEC
lDFKImgGZB9KnhsDfB9iHlQexTVLACYIzAhNYSkBKpr3A+VZoAEqGv4BjXgpAa8qAQALQAAA
Mp7pADaMsQLwSjoAjB1BCjkAPoyeAiQbAgARwNQBJQWfF6dwAQAAAN17/20BAAAAwAYAALgC
AACECAAAJAAAAIAKAAA8AAAACAIAAEgLAAAwBAAAIAcAAJQHAADcCAAA9AIAAAgAAAAIBAAA
aAAAAAgNCA0EDAgICAgICAkABwgCHgAAGUY7AAaabgGRhKABBhoQAQqbcwNNa6ABBhp8AQF9
sgAOHrUHUc7tAAaaogGlczsAEgzMAc1zOwAGmusBNXspAQYaXgER/HYAFp4VAW16OwAagEAB
NfrtAAaacgH5jCkBnhrLAqXidgAGGqYBgf12ACIMyAJsBCYe1AAcPWqibwzoQSYePwSAGmoM
Yw0YKmoMkhNgX26iYw/YLG6igwkyHgMHGBsyHhwFABAyHhsEKKZ2kIsCvW8BADqAmwFc7jsF
AAAPXAAAWA3XBgAAD1wAALgQawYAAA9cAAAYEFsGAAAPXAAAvBBvBAAAD1wAAIQMrwQAAA9c
AACsC08GAAAPXAAABBBrBgAAD1wAAGAPDwQAAA9cAADF+QIAOgAFAaWYAwA6gAEBofEDADqA
/wAFpgMAOoD6AH3xAwA6AP4AbZ8DADoA/ACZNgEAJp7QE2xzJh72JrUqAgA6AGgBpZsDADqA
AwE9EQEAAAAAAAIAEcDuACUFX6O3cQEAAACbFqdwAQAAALQJAADcCAAAhAYAAGgJAAC4AgAA
JAAAAJAGAACQAAAAnAAAAIQAAACUAAAAiAAAADwAAAB0AAAAaAAAADwFAAAICAgEDQ0HDw8P
Dw8MCAgIQgwAANgIRiLQCOCHRiLIAuQwRiJbBswfRp4bAxggSp57HrmoSwAOCG0IUUWyABKa
gAHNgqABEpp0AQUHZQEWntwAGgyqAh4AyAAigJcAJgCeACoAkAAugJUAMoCgL9FbAgA2kLcA
Fp67ANhvMh6FATxKRwQAAA5cAAA9ozYA0w8AAG+iAwAAAAMAAsBoAAEF7AQAAOQCAACbwAp0
AQAAAAMAAAABAAAA5AIAAPwLAAAAkPAEgPj//wAw8ASA+P//AADrAQAAAAAAgOoBAAAAAAMA
AAAAAAAA8PsEdwAAAAAAYP3//wcAAAAAAAAIBQIAAgARwAYBJQUg0gp0AQAAAA2it3EBAAAA
hAgAADwFAABUBQAAuAIAAEACAADcAgAA8AMAACwEAACACgAASAMAAKAIAAAcBwAAJAAAANwJ
AAB8AgAA7AQAAAgICA0NCQgIBAgICA0ICAgCGwAABozvAlgNCh7mAGkooAEOGoABTTJlAVKg
nQFRQjsADhqmAQmGKQEWDHQCcAQaHiMEHp7TAN3AdgAOGhICNXayACKMIQJtbzsADhqGAfUW
dwAmHhwGCp6sAh6eUQL8ESoeTActwDoADpoBAQIbXwPsBC6e9AClVrIAMh7EAD2aOwA2ngsF
eT2yAA6ahAFpiSkBegyIAyATPp7eBf//AgARwHQBJQU422B1AQAAADPRCnQBAAAA/AsAALgC
AACECAAAMAQAACAHAACEBgAA3AgAAJgHAAA8AwAAtAkAAAgEAACUBwAAaAkAADwFAADABgAA
VAUAAAgNCAgICAgICQgHCAQICAgCHgAAsXN2AAaacAEKGwYF4dbtAA4MsQIoDBIeOwjABBaM
KQnUcRoiXAqQJlqeYQMUcF4MnQY4kl4iAw40iiKeFAYsJmYM7gCgDWaMPARYKloiAAOIKVqi
nwEkJFpQLHG4BVpMLAGEDlrMGwHsDVrMKAEgDVpQ8gGABFpQggGABFpMCQG0DVpMZwF8Cwei
FwAWJQAAsJ4qAGsBEh46ASxlEp5VKFFPAwAqgEABEZwDAGYMqwR0F1oiFAmYgyqAUQESUCcB
aAQSHkAGWDQSHtkDgBleDBAFkNVujAUCDQBKADII8wmNMTsABhqHAdWDoAEGGnoBAXc7ADaM
JwMUFzqeWQWwBD6ekAUZhGQBAgAAAAIAEcAgASUFcAQreAEAAABj2mB1AQAAACQAAAC4AgAA
hAgAADwAAAA0AAAAPAUAAMAGAAAUBQAABAYAAEgKAACMCAAAgAoAAAQLAAAABwAASAsAADAE
AAAIDQgMDAgICAgICAQICAgIQh8AAAYaiwEKG30EwVABAA4eTQESAL0h8eY4ABaMGQOkFxoe
YAF9PzsAHp64ABGjKQEGmt8D5WayACKAXAJ13+0ABhqDAdGJoAEmjPgB0wkAAGqiAwAKm8sD
Kp4KA50vKQEujNoBfXk7AAaaUQFlcjsABpo8AfUC7gBCnycBaX+yAAYa9wGZdjsAMozPAq1m
OwAGGioCBZGyADYe0QLJ0nYABprZAbl7OwC6mqwCIXQpAT6MgQNYDwIAEcC2ASUFuF8ZeQEA
AABqAyt4AQAAACAHAACUBwAA3AgAADwDAAAIAAAAaAAAAAgEAAC0CQAAhAYAALgCAABoCQAA
SAUAAGQAAACQBgAAjAAAAJAAAAAICAgJAAgHCAgNBAgIBw8PAh4AAAQ3RiLvDHBCAp4sBKQY
RgwtDWglRow2E5ReSiKkD8wqSiJeCQ4e3gbAGQ6ejASkEA6eSQR8qlKQbAMNXwIAOwUAAAVc
AACEDdcGAAAFXAAAOBFzBgAABVwAAAQQZwYAAAVcAAC0EJMEAAAFXAAAsAynBAAABVwAAKAL
XwYAAAVcAAD8D3MGAAAFXAAAOA8XBAAABVwAACUxAgAaAHkB5ZoDABoAAwFp8AMAGgADAbGa
AwAagPwA7fEDABqA/gCRmwMAGoD7AFX0AQACni4T9HICHqUmvVsBABoAZwG5ogMAGoAEAVnn
AQBeDDIEQBBKIgQJ/IRKItACFDJKIlUG8B9KHhsDuB9iHjgeES8QACYaTAFBezsAKggSBwXr
ZAEmmvcEaUcpAS6I3QCZ+3YAJpryANWPOwCvSwEADEAAADaMLAM6gMYAPgCkAAAAAwACwGgA
AgUcBgAAHAQAADuPVHkBAAAAAAAAAAAAAAAcBAAAHAYAAABQngOA+P//AOCdA4D4//8AABsD
AAAAAACAGgMAAAAAAwAAAAAAAACMq+L5/gcAAAAg9f//BwAAMwAAAAgFAgAAoBwCgPr//1gC
HQKA+v//HgoAAAEeAQAeCgAAAR4BAB4KAAABHgEAHgoAAAEeAQAeCgAAAR4BAB4KAAABHgEA
HgoAAAEeAQAeCgAAAR4BAB4KAAABHgEAHgoAAAEeAQAeCgAAAR4BAB4KAAABHgEAHgoAAAEe
AQAeCgAAAR4BAB4KAAABHgEAHgoAAAEeAQAeCgAAAR4BAB4KAAABHgEAHgoAAAEeAQAeCgAA
AR4BAB4KAAABHgEAHgoAAAEeAQAeCgAAAQQBAARCAAABBAEABEIAAAEZAgAZUhUCAVgYAFg0
GgBQ+AwAR+gLAD7YCgA1yAkALLgIACOoBwAdmAYAF4gFABF4BAAMaAMABwEbAAEEAQAEYgAA
AQkDAAlkBgAEYgAAAQQBAARCAAAZEwaFE1MIASoAAWAAUAAaoBQHAAAAAAAAAAAAARMHABPE
CAAOdAcACTQGAASCAAAZEwaFE1MIASoAAWAAUAAaoBQHAAAAAAAAAAAAGRMGhRNTCAEqAAFg
AFAAGqAUBwAAAAAAAAAAABkTBoUTUwgBKgABYABQABqgFAcAAAAAAAAAAAAZEwaFE1MIASoA
AWAAUAAaoBQHAAAAAAAAAAAAARMGhRNTCAEqAAFgAFAAGgECAQACMAAAAV8kAF/0JgBb5CUA
V9QkAFPEIwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4
BAAUaAMABwEnAAEJAwAJNAQABEIAAAFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAA
RPgMAD/oCwA62AoANcgJADC4CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBJwAZAAIAADIAGrDV
BgAAAAAAAAAAAAEJAwAJVAYABGIAAAEJAwAJVAYABGIAAAFmJwVm9CYAYuQlAF7UJABaxCMA
VmQiAFJ0IQBONCAAS1NIVB8ARPgMAD/oCwA62AoANcgJADC4CAArqAcAJZgGAB+IBQAZeAQA
FGgDAAcBJwAAAAEFAgAFMgFQAQ4FAA5kAgAJdAEABCIAAAEEAQAEQgAAGQ4FAA5kAgAJdAEA
BCIAALDVBgAAAAAAAAAAAAEAAgAAMgAaAQ4FAA5kAgAJdAEABCIAABkEAQAEQgAAsNUGAAAA
AAAAAAAAATMGhTNTKwErACRQIwIACgFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAA
RPgMAD/oCwA62AoANcgJADC4CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBJwABMwaFM1MrASsA
JFAjAgAKAQQBAAQCAAABFAaFFFMMASsABVAEAgAKARQGhRRTDAErAAVQBAIACgF7JAB79CYA
d+QlAHPUJABvxCMAa2QiAGd0IQBjNCAAYPgMAFvoCwBW2AoAUcgJAEy4CABHqAcAQZgGADuI
BQA1eAQAMGgDACMBJwABXyQAX/QmAFvkJQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsA
OtgKADXICQAwuAgAK6gHACWYBgAfiAUAGXgEABRoAwAHAScAAQABAABCAAABFAaFFFMMASsA
BVAEAgAKAV8kAF/0JgBb5CUAV9QkAFPEIwBPZCIAS3QhAEc0IABE+AwAP+gLADrYCgA1yAkA
MLgIACuoBwAlmAYAH4gFABl4BAAUaAMABwEnAAEBAQABcAAAAQEBAAFwAAABCAMACDQAAAQC
AAABjSYAjfgLAIToCgB72AkAcsgIAGm4BwBjqAYAXZgFAFeIBABReAMATGgCAEf0HwA/5B4A
N9QdAC/EHAAndBsAH2QaABdUGQAPNBgABwEhAAECAQACMAAAAQIBAAIwAAABAgEAAjAAAAEC
AQACMAAAAQIBAAICAAABCwUFC1MIUgRwA2ACUAAAAQAnAAD4KQAA6CgAANgnAADIJgAAuCUA
AKgkAACYIwAAiCIAAHghAABoIAAA9B4AAOQdAADUHAAAxBsAAHQWAABkFQAAVBQAADQSAAAB
mgAACgAAAQ0FAA10AQAIZAAABBIAAAEIAwAIdAAABAIAABkEAQAEQgAAIAcKAAAAAAAAAAAA
GQQBAARCAABwBwoAAAAAAAAAAAABHAsAHMQEABdkAwASdAIADTQBAAhUAAAEQgAAAQEBAAEC
AAABAQEAAQIAAAEBAQABAgAAAQEBAAECAAABAQEAAQIAAAEBAQABAgAAAQEBAAECAAABGQIA
GVIVAgEHAgAHAacAAQQBAARCAAAZBAEABEIAAHDsAQAAAAAAAAAAAAEEAQAEQgAAGQQBAARC
AADAPwIAAAAAAAAAAAABBAEABEIAABkEAQAEQgAA8EUIAAAAAAAAAAAAAQQBAARCAAAZBAEA
BEIAAEBRAgAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABg/AcAAAAAAAAAAAABBAEABEIAABkE
AQAEQgAAMBkMAAAAAAAAAAAAAQQBAARCAAAZBAEABEIAALDeAAAAAAAAAAAAAAEEAQAEQgAA
GQQBAARCAADwGQwAAAAAAAAAAAABBAEABEIAABkEAQAEQgAAsBoMAAAAAAAAAAAAAQQBAARC
AAAZBAEABEIAAHAbDAAAAAAAAAAAAAEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsABVAEAgAK
ARQGhRRTDAErAAVQBAIACgFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAARPgMAD/o
CwA62AoANcgJADC4CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBJwABFAaFFFMMASsABVAEAgAK
ARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsABVAEAgAKARQGhRRT
DAErAAVQBAIACgEQBYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKARAFhRBTCAErAAFQ
ABoAAAEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARAFhRBTCAErAAFQABoAAAEQ
BYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKARAFhRBTCAErAAFQABoAAAEUBoUUUwwB
KwAFUAQCAAoBXyQAX/QmAFvkJQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXI
CQAwuAgAK6gHACWYBgAfiAUAGXgEABRoAwAHAScAARQGhRRTDAErAAVQBAIACgEZBoUZUxEB
KwAKUAkCBQoBGAaFGFMQASsACVAIAgQKATsGhTtTMwErACxQKwInCgEEAQAEYgAAASkMhSlk
KgAidCkAGzQoABRTDAErAAVQBAIAChlQDIVQZCoASXQpAEI0KAA7UzMBKwAsUCsCJwpASgcA
AAAAAAAAAAABXyQAX/QmAFvkJQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXI
CQAwuAgAK6gHACWYBgAfiAUAGXgEABRoAwAHAScAAV8kAF/0JgBb5CUAV9QkAFPEIwBPZCIA
S3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMABwE7AAEE
AQAEQgAAAZ8kAJ80LgCXZDAAj3QvAIf0NAB/5DMAd9QyAG/EMQBn+BMAXugSAFXYEQBMyBAA
Q7gPADqoDgAxmA0AKIgMAB94CwAXaAoADwE1AAEEAQAEQgAAAX8eAH/0NAB35DMAb9QyAGfE
MQBf+BMAVugSAE3YEQBEyBAAO7gPADKoDgApmA0AIIgMABd4CwAPaAoABwE1AAEEAQAEQgAA
AQQBAATCAAABlyQAlzQuAI9kMACHdC8Af/Q0AHfkMwBv1DIAZ8QxAF/4EwBW6BIATdgRAETI
EAA7uA8AMqgOACmYDQAgiAwAF3gLAA9oCgAHATUAAQYDAAZCAlABMAAAAQUCAAUyAVABBgMA
BmICUAEwAAABBQIABVIBUAEHBAAHMgNgAlABMAEHBAAHMgNwAmABUAEFAgAFkgFQAQYDAAaC
AlABMAAAAQkFAAliBdADcAJQATAAAAEFAgAFcgFQAQgEAAhSBOACUAEwAQcDAAdiA9ABUAAA
AQcEAAcyA3ACUAEwAQcDAAdCA+ABUAAAAQgEAAhyBNACcAFQAQcDAAeCA/ABUAAAAQkEAAmS
BeADwAFQAQ4IAA5SCuAI0AbABHADYAJQATABEAkAEIIM8ArgCNAGwARwA2ACUAEwAAABBwQA
B1IDcAJQATABCAUACGIEcANgAlABMAAAIQAEAAB0AAAAZAMAoKMEAKSjBAAw2BsAIQAAAKBh
CwDwYQsAWMkbACEAAACclwQA5JcEAODSGwAhAAAALN0BAN/dAQC81BsAIQAAALzTCQAw1AkA
WMkbACEAAACA0gkATNMJACTJGwAhAAAAJFMEAAhUBADg0hsAIQAAAPRFAAApRgAATDscACEA
AADk5QQAxOYEAOwqHAAhAAAA/DEBAOwzAQAwPhwAIQAAAKRBAAAYQwAA6B8cACEAAABAPwQA
kD8EACDKGwAhAAAAAIkBAKCKAQDsKhwAIQAAAOCvAQB0sAEAfMkbACEACAAA9AMAAHQEAABU
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
UwAACgEAAApKAAAAAAAAAAAAAAAAAEAAAEBQQUdFREFUQQDdAAAAEFQAAEwAAAAUSwAAAAAA
AAAAAAAAAABAAADAUEFHRVZSRkMeKQAAAPBUAAAqAAAAYEsAAAAAAAAAAAAAAAAAQAAAQFBB
R0VWUkZEUBIAAAAgVQAAFAAAAIpLAAAAAAAAAAAAAAAAAEAAAMBJTklUAAAAAFx2BQAAQFUA
AHgFAACeSwAAAAAAAAAAAAAAAAAgAADiLnJzcmMAAAA8XwMAAMBaAABgAwAAFlEAAAAAAAAA
AAAAAAAAQAAAQC5yZWxvYwAAdCAAAAAgXgAAIgAAAHZUAAAAAAAAAAAAAAAAAEAAAEIAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABwOKwCAPj//2Yv/ACA+P//
AGD5AID4///4lPoAgPj//wDw+gCA+P//TP78AID4//8AYKUCAPj//4CjzQIA+P//AGClAgD4
//8ghc0CAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO5AKA+P//
0IjmAoD4//8fABAAAAAAAGCC5gKA+P//AAAAAAAAAACwiuYCgPj//2CH5gKA+P//CIrmAoD4
///BZLACAPj//wiK5gKA+P//YILmAoD4//8AAAAAgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/IqwIA+P//AAAAAAAAAAAAAAAAAAAAAB8A
EACAHwAAEAArACsAUwArABgAhgAAABHy+QCA+P//aPJ2A4D6//+4EncDgPr//w8AAAAAAAAA
AIBvAYD6///QgG8BgPr//wAAAAAAAAAAoAMAAAAAAAAAAAAAAAAAAAIAAAAAAAAAQIzmAoD4
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
QI3mAoD4//8AAAAAAAAAAAAw5gKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAfAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+8OD/yB1W4lFgEiJTYhIiVWQ
TIlFmEyJTaDokYT//wvAi0WASItNiEiLVZBMi0WYTItNoEiJo9gBAAAPhLH8//9IjT1YiSMA
i3cQSIs/O8ZzEEiNPLcPvgQ4C8APjvn9//+4HAAAwOnv/f//uUoAAABFM8lFDyDARQvAdRS5
AQAAAEUPtoPwAQAARYuLxAEAAEiLlegAAABMi9XoYAAAAEiD7FBIiUwkIEiJVCQoTIlEJDBM
iUwkOEyJVCRASYvK6GvIDgBIi0wkIEiLVCQoTItEJDBMi0wkOEyLVCRASIPEUEH/0kiJRbBI
i8jo38cOAEiLRbDpWf3//2YPH0QAAEiB7DgBAABIjYQkAAEAAA8pdCQwDyl8JEBEDylEJFBE
DylMJGBEDylUJHBEDylYgEQPKWCQRA8paKBEDylwsEQPKXjASIkYSIl4CEiJcBBMiWAYTIlo
IEyJcChMiXgwTIlUJCDoVwoAAJBmZmZmZmZmDx+EAAAAAAAPH4AAAAAASIHs2AEAAEiNhCQA
AQAADyl0JDAPKXwkQEQPKUQkUEQPKUwkYEQPKVQkcEQPKViARA8pYJBEDylooEQPKXCwRA8p
eMBIiRhIiXgISIlwEEyJYBhMiWggTIlwKEyJeDBlSIsEJYgBAAAPumBMC3MO9oXwAAAAAXQF
6IMHAABIjYQkOAEAAIkIM8mJSARIiUgITIlAEIlQGEyJSCBMiVAoTIlYMESKjfAAAABBgOEB
xkQkIAFMjUWASIvUSIvI6EqxAwBIjYwkAAEAAA8odCQwDyh8JEBEDyhEJFBEDyhMJGBEDyhU
JHBEDyhZgEQPKGGQRA8oaaBEDyhxsEQPKHnASIsZSIt5CEiLcRBMi2EYTItpIEyLcShMi3kw
+vaF8AAAAAEPhLsAAABlSIsMJYgBAACAeXoAdBm5AQAAAEQPIsH76Ao3///6uQAAAABEDyLB
ZUiLDCWIAQAA9wEAAAJAdCX2QQICdA7oRDAKAGVIiwwliAEAAPZBA0B0C0iNZYCxAeg6BwAA
D65VrGaDvYAAAAAAdAXo5wwAAA8oRfAPKE0ADyhVEA8oXSAPKGUwDyhtQEyLXeBMi1XYTItN
0EyLRchIi1XASItNuEiLRbBIi+VIi63YAAAASIHE6AAAAA8B+EjPD65VrA8oRfAPKE0ADyhV
EA8oXSAPKGUwDyhtQEyLXeBMi1XYTItN0EyLRchIi1XASItNuEiLRbBIi+VIi63YAAAASIHE
6AAAAEjPZmZmZmZmZg8fhAAAAAAADx8ASIPsKGVIixwliAEAAEiLi9gBAABIjamAAAAARA8g
wAqD8AEAAAuDxAEAAHQ0uUoAAABFM8lFDyDARQvAdRS5AQAAAEQPtoPwAQAARIuLxAEAAEiL
legAAABMi9Xo3/z///plSIsMJYgBAACAeXoAdFdIiUWwM8BIiUW4SIlFwEiJRchIiUXQSIlF
2EiJReBmD+/ADylF8A8pRQAPKUUQDylFIA8pRTAPKUVAuQEAAABEDyLB++hWNf//+rkAAAAA
RA8iwUiLRbBlSIsMJYgBAAD3AQAAAkB0LkiJRbD2QQICdA7oiC4KAGVIiwwliAEAAPZBA0B0
DEiNZYBIM8nofQUAAEiLRbAPrlWsTTPSZoO9gAAAAAB0PkiJRbDoHwsAAGVIiwQliAEAAEiL
QHBIi4AAAQAASAvAdBhmg73wAAAAM3UOTIuV6AAAAEiJhegAAABIi0WwTIuFAAEAAEyLjdgA
AAAz0mYP78BmD+/JZg/v0mYP79tmD+/kZg/v7UiLjegAAABMi534AAAASYvpSYvgDwH4SA8H
ZmZmZmZmZg8fhAAAAAAAZmZmZmZmZg8fhAAAAAAAZmYPH4QAAAAAAPplSIsUJYgBAABIi3oo
SI2v8P7//0iD7whIi3EgSIPuCEiL0UiLSTBIwekD/fNIpfxIjWcISIvKSItROP/iZpBIiU2A
SIlFiEiB7KgBAAAPKbQkoAAAAA8pvCSwAAAARA8phCTAAAAARA8pjCTQAAAARA8plCTgAAAA
RA8pnCTwAAAARA8ppCQAAQAARA8prCQQAQAARA8ptCQgAQAARA8pvCQwAQAATImkJIgBAABM
iawkkAEAAEyJtCSYAQAATIm8JKABAABIibwkeAEAAEiJtCSAAQAASImcJHABAABIjYUQAQAA
SIlEJCBIK8RIiUQkKEgtqAEAAEiJRCQwSI0FewAAAEiJRCQ4SI1UJHBIiVQkWEiNVYBIiVQk
UEgPumwkSABIi8zo5AwSAEyLpCSIAQAATIusJJABAABMi7QkmAEAAEiBxKgBAADp8Pz//2Zm
ZmZmZmYPH4QAAAAAAGZmZmZmZmYPH4QAAAAAAGZmZmZmZmYPH4QAAAAAAA8fAEiD7ChIi0FY
Zg9vcDBmD294QGZED29AUGZED29IYGZED29QcGZED2+YgAAAAGZED2+gkAAAAGZED2+ooAAA
AGZED2+wsAAAAGZED2+4wAAAAEyLoBgBAABMi6ggAQAATIuwKAEAAEyLuDABAABIi7gIAQAA
SIuwEAEAAEiLmAABAAD7ZQ+uFCWAAQAA6M/0CwBIi02ASItFiEiDxCjDZmZmZmZmZg8fhAAA
AAAAZmZmZmZmZg8fhAAAAAAADx9AAEiB7KgBAAAPKbQkoAAAAA8pvCSwAAAARA8phCTAAAAA
RA8pjCTQAAAARA8plCTgAAAARA8pnCTwAAAARA8ppCQAAQAARA8prCQQAQAARA8ptCQgAQAA
RA8pvCQwAQAATImkJIgBAABMiawkkAEAAEyJtCSYAQAATIm8JKABAABIjYUQAQAASIlEJCBI
K8RIiUQkKEgtqAEAAEiJRCQwSI0FWwAAAEiJRCQ4SI1UJHBIiVQkWEiNVYBIiVQkUEgPunQk
SABIi8zoBAsSAEyLpCSIAQAATIusJJABAABMi7QkmAEAAEiBxKgBAADpEPv//2ZmZmZmZmYP
H4QAAAAAAJBIg+woSItBWGYPb3AwZg9veEBmRA9vQFBmRA9vSGBmRA9vUHBmRA9vmIAAAABm
RA9voJAAAABmRA9vqKAAAABmRA9vsLAAAABmRA9vuMAAAABMi6AYAQAATIuoIAEAAEyLsCgB
AABMi7gwAQAA+2VIixwliAEAAGUPrhQlgAEAAOgb8wsASIPEKMNmZmZmZmZmDx+EAAAAAABm
ZmZmZmZmDx+EAAAAAABmZmZmZmZmDx+EAAAAAABmDx+EAAAAAABIg+xoTIlFgEyJTYhMiVWQ
TIldmEyNRCRwSYkISYlQCEiNhRABAABIiUQkIEgrxEiJRCQoSIlEJDBIjQVDAAAASIlEJDhM
iUQkWEiNVYBIiVQkUEgPumwkSABIi8zorgkSAEyLpCSIAQAATIusJJABAABMi7QkmAEAAEiD
xGjpvfn///voV/ILAGUPrhQlgAEAAEyNRCRwSYsISYtQCEyLRYBMi02ITItVkEyLXZhIg8Ro
w2ZmZmZmDx+EAAAAAABIgeyoAQAADym0JKAAAAAPKbwksAAAAEQPKYQkwAAAAEQPKYwk0AAA
AEQPKZQk4AAAAEQPKZwk8AAAAEQPKaQkAAEAAEQPKawkEAEAAEQPKbQkIAEAAEQPKbwkMAEA
AEyJpCSIAQAATImsJJABAABMibQkmAEAAEyJvCSgAQAASIm8JHgBAABIibQkgAEAAEiJnCRw
AQAA+4hMJEhIjVQkcEiJVCRYSI1VgEiJVCRQSIvM6On7EQBIjUQkcGYPb3AwZg9veEBmRA9v
QFBmRA9vSGBmRA9vUHBmRA9vmIAAAABmRA9voJAAAABmRA9vqKAAAABmRA9vsLAAAABmRA9v
uMAAAABMi6AYAQAATIuoIAEAAEyLsCgBAABMi7gwAQAASIu4CAEAAEiLsBABAABIi5gAAQAA
SIHEqAEAAMOQkMzMzMzMzGZmDx+EAAAAAABIg+wo6CcAAACQzMzMzMzMSIPsKEjHRCQgAAAA
AOgOAAAAkMzMzMzMzA8fgAAAAABIiUwkCEiJVCQQTIlEJBhMiUwkIJxIg+ww+mVIiwwlIAAA
AEiLidhLAADoYQYAAGVIiwwlIAAAAEiDwUDo7wIAAGVMixQlIAAAAE2LkthLAABIi0QkQEmJ
goAAAABIi0QkMEmJQkRIjQVs////SDtEJDh1DkyNRCRoTI0NUP///+sMTI1EJDhMjQ1y////
TYmCmAAAAE2JivgAAABEDyDAZYgEJZhIAAA8An0JuQIAAABEDyLBSItEJDBIJQACAAB0Afvw
/wXmFRoASItMJEBIx0QkKAAAAABIjQX6/v//SDtEJDh0H0iLRCRgSIlEJCBMi0wkWEyLRCRQ
SItUJEjoHBQPAJBIx0QkIAAAAABFM8lFM8Az0ugFFA8AkMzMzMzMzGZmZmZmZg8fhAAAAAAA
SIHs2AAAAA8pdCQwDyl8JEBEDylEJFBEDylMJGBEDylUJHBEDymcJIAAAABEDymkJJAAAABE
DymsJKAAAABEDym0JLAAAABEDym8JMAAAABIiZwk0AAAAEQPIMCJRCQog/gBcwm4AQAAAEQP
IsBJi9hMi5QkAAEAAEyJVCQg6L12AgCEwHQKSI2LAAEAAA+uCYN8JCgBcwiLRCQoRA8iwEiL
nCTQAAAADyh0JDAPKHwkQEQPKEQkUEQPKEwkYEQPKFQkcEQPKJwkgAAAAEQPKKQkkAAAAEQP
KKwkoAAAAEQPKLQksAAAAEQPKLwkwAAAAEiBxNgAAADDzMzMzMzMkA8gwEiJAQ8g0EiJQQgP
INhIiUEQDyDgSIlBGEQPIMBIiYGgAAAADwFBVg8BSWYPAElwDwBBcg+uWXTDzMzMzMzMZmZm
ZmZmZg8fhAAAAAAASIsBDyLASItBEA8i2EiLQRgPIuBIi4GgAAAARA8iwA8BUVYPAVlmD7dB
cEgDQViAYAX9DwBZcGaLQXIPANAPrlF0M9IPI/pIi0EgSItRKA8jwA8jykiLQTBIi1E4DyPQ
DyPaSItRSDPADyPwDyP6ZfYEJUpNAAACdCpm98IAAnQDg8gCZvfCAAF0A4PIAYXAdBJEi8C5
2QEAAA8yg+D8QQvADzDCAADMzMzMzMwPHwAPIMBIiQEPINBIiUEIDyDYSIlBEA8g4EiJQRhE
DyDASImBoAAAAA8BQVYPAUlmDwBJcA8AQXIPrll0DyHADyHKSIlBIEiJUSgPIdAPIdpIiUEw
SIlROA8h8A8h+kiJQUBIiVFIM8API/hl9gQlSk0AAAIPhIwAAABm98IAAw+EgQAAAESLDQ54
IwBMi8FFC8l0CEGLyQ8yRIvIiw2AcyMAQQPJDzJBiYCIAAAAiw0ydCMAQYmQjAAAAEEDyQ8y
QYmAgAAAAEGJkIQAAACLDVp1IwAPMkGJgJgAAABBiZCcAAAAiw1AdSMADzJBiYCQAAAAQYmQ
lAAAALnZAQAADzKD4PwPMMIAAMzMzMzMzA8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVFJHRER1bXBCbG9iEAAAALEdAPAgAAAAjwBcvDoe
10SYjYb2iExnWGEBAAAAAAAABwAAAAACBCRZAQAAABgAAAECAOgDAIAACAAAAAAAAAQEBf//
WGVuADQuNS4wLXJjADExLzE5LzIwMTQAAAEbAAEBAgMEAAAAAAAAAAAAAAAAAAAAAAYAAFhl
bgBIVk0gZG9tVQA0LjUuMC1yYwAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAAAAMNAAMBAQAAAAMDAwJYZW4AAAQaAQQBAwEC5QYBAP/7iRcAAAAAZApkCkEBQ1BVIDEA
SW50ZWwAAAQaAgQBAwEC5QYBAP/7iRcAAAAAZApkCkEBQ1BVIDIASW50ZWwAAAsFAAsBWGVu
AAAQDwAQAQMGAAAeAP7/AQAAABEVABEAEAAAQABAAIAHCQABAAcAAERJTU0gMAAAEw8AEwAA
AAD//x0AABABAAAUEwAUAAAAAP//HQAAEQATAQAAAAAgCwAgAAAAAAAAAAAAfwQAfwAAAAAA
AAAAACAAAACJw3psE0PcR580qIAKD7VsbgIAAAAAAAACAAAACgAAAH4ATQBIAHoAAAAEAAAA
BAAAAGQKAAAsAAAAQwBvAG0AcABvAG4AZQBuAHQAIABJAG4AZgBvAHIAbQBhAHQAaQBvAG4A
AAADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAmAAAAQwBvAG4AZgBpAGcAdQByAGEAdABpAG8A
bgAgAEQAYQB0AGEAAAAJAAAAEAAAAP//////////AAAAAAAAAAAWAAAASQBkAGUAbgB0AGkA
ZgBpAGUAcgAAAAEAAABKAAAASQBuAHQAZQBsADYANAAgAEYAYQBtAGkAbAB5ACAANgAgAE0A
bwBkAGUAbAAgADMAMAAgAFMAdABlAHAAcABpAG4AZwAgADUAAAAoAAAAUAByAG8AYwBlAHMA
cwBvAHIATgBhAG0AZQBTAHQAcgBpAG4AZwAAAAEAAABgAAAASQBuAHQAZQBsACgAUgApACAA
WABlAG8AbgAoAFIAKQAgAEMAUABVACAAIAAgACAAIAAgACAAIAAgACAAIABYADMANAA1ADAA
IAAgAEAAIAAyAC4ANgA3AEcASAB6AAAAIgAAAFUAcABkAGEAdABlACAAUwBpAGcAbgBhAHQA
dQByAGUAAAADAAAACAAAAAAAAAAHAAAAHAAAAFUAcABkAGEAdABlACAAUwB0AGEAdAB1AHMA
AAAEAAAABAAAAAcAAAAiAAAAVgBlAG4AZABvAHIASQBkAGUAbgB0AGkAZgBpAGUAcgAAAAEA
AAAaAAAARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwAAAAMAAAATQBTAFIAOABCAAAACwAAAAgA
AAAAAAAABwAAAAAAIAAAAG/APdCO2MVEuir64DUXLRmYAwAAAAAAAAAAAAAAAAAAAAAAAAsA
AABHZW51bnRlbGluZUkLAAAAR2VudW50ZWxpbmVJAAAAAAEAAADlBgEAAAggAgEiuIH/+4sX
5QYBAAAIIAIBIriB//uLFwAAAAACAAAAAVoDVeSy8AAAAAAALCHKCQFaA1XksvAAAAAAACwh
ygkAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAdEAAAAAAAAAAAAAAAAAAAH
RAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAEA
AAAXAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAABAAAAiwAAAAAAAAAHAAAA
AAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAIAAAMABDQAAAAAAAAAAAAAAAAAAAQ0AAAAA
AAAAAAAAAAAAAAAAAAAAAACACAAAgAAAAAAAAAAAAAAAAAgAAIAAAAAAAAAAAAAAAAAAAAAA
AQAAgAAAAAAAAAAAAQAAAAAIECgAAAAAAAAAAAEAAAAACBAoAAAAAAIAAIBJbnRlbChSKSBY
ZW9uKFIpSW50ZWwoUikgWGVvbihSKQAAAAADAACAIENQVSAgICAgICAgICAgWCBDUFUgICAg
ICAgICAgIFgAAAAABAAAgDM0NTAgIEAgMi42N0dIegAzNDUwICBAIDIuNjdHSHoAAAAAAAUA
AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAACAAAAAAAAAAABAYAAB
AAAAAAAAAAAAAAAAQGAAAQAAAAAAAAAABwAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAgAAIAkMAAAAAAAAAAAAAAAAAAAJDAAAAAAAAAAAAAAAAAAACAAAADSQDvo
oLBCSKvqccnjRj3RQAAAAAAAAAAAAAAAQVBJQ2AEAAACsFhlbgAAAEZBQ1D0AAAABEBYZW4A
AABXQUVUKAAAAAFWWGVuAAAASFBFVDgAAAAB0lhlbgAAACAAAACISMhU0QEeTL7WKCyYJBMD
ABAAAAAAAAAAAAAAnUxNVCyU1Ua/UN9c2VJKUEjwxAKA+v//uA8AAOgIrAgyAAAAY2Ryb20A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATFIcAAEAAAAAAAoAZh/S0VbuKDl3P2A3
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
TFI8ACwAAAAIBw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAAFAU1AKA
+v//AAAATFI8AC0AAABEBw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAA
APBlJAOA+v//AAAATFI8AC4AAACABw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6
//8HBAAAAOAQVQOA+v//AAAATFI8AC8AAAC8Bw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAA
cCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADAAAAD4Bw8Ad/p5j+/a3gVZfKRoubDwn9jf
NP1/BQAAcCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADEAAAA0CA8Ad/p5j+/a3gVZfKRo
ubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADIAAABwCA8Ad/p5j+/a
3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAABAAmwOA+v//AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACAAAABMSn74ocUvTb/w1d5jpeTDMAIAAAAAAAAAAAAAAAAAAAAAAAABAAAACwAAAAAA
AABXZGYwMTAwMAAAAAAAAAAA/0TKFXpNqku7pQmYlV5THgQAABBQ2k8CgPr//wEAAAAJAAAA
sB0AAG1zaXNhZHJ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgBcAED+dgGA+v//AQAAAAkA
AACwHQAAdmRydnJvb3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIMzgAsOhyAoD6//8BAAAA
BQAAAHAXAABzdG9yZmx0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAQwMQCgPr//wEA
AAAJAAAAsB0AAGNkcm9tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAECuzAKA+v//
AQAAAAkAAACwHQAAVmlydGlvU2VyaWFsAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAA8OrKAoD6
//8BAAAACQAAALAdAABpbnRlbHBwbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAErWAABAfsoC
gPr//wEAAAAJAAAAsB0AAENvbXBvc2l0ZUJ1cwAAAAAAAAAAAAAAAAAAAAAAAAAASzM4AGB2
3AKA+v//AQAAAAkAAACwHQAAdW1idXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA
8MhgA4D6//8BAAAABwAAAHEXAABQRUFVVEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA
AAA=
--------------080009070007070309030302
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Thu Nov 20 08:58:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 08:58:49 +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 1XrNZh-0004fg-53; Thu, 20 Nov 2014 08:58:49 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrNZe-0004fb-Ku
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 08:58:47 +0000
Received: from [85.158.137.68] by server-7.bemta-3.messagelabs.com id
	0C/77-17958-54DAD645; Thu, 20 Nov 2014 08:58:45 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-6.tower-31.messagelabs.com!1416473923!8201775!1
X-Originating-IP: [209.85.212.170]
X-SpamReason: No, hits=2.0 required=7.0 tests=BIZ_TLD,HTML_60_70, HTML_MESSAGE
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15412 invoked from network); 20 Nov 2014 08:58:44 -0000
Received: from mail-wi0-f170.google.com (HELO mail-wi0-f170.google.com)
	(209.85.212.170)
	by server-6.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 08:58:44 -0000
Received: by mail-wi0-f170.google.com with SMTP id bs8so11866258wib.1
	for <win-pv-devel@lists.xenproject.org>;
	Thu, 20 Nov 2014 00:58:43 -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:references:in-reply-to:content-type;
	bh=oh4PCZpZMRiflsNZplc2eIx8dvkWG+DC3lPrHluFRp0=;
	b=CDxjIIHWNJrYg3fcVdjOROYXJ5dWDyjFwRVorwCwEm6jSyUF8a8euPefofCUW3B5ID
	1KjZyT81NI0+sbcCgNAX69gv5Z6FNm1lKMbXOOygLiSaUyNiGuhsnBfrwvYRYiKWS67f
	fT9pUdzKCX8WLQjJhPQdQr5dz7N3NqBc1SrjFM6F8fK4+PvUs5rY8o7v4a2YhJoskOi8
	C14cvB/HMHaSvXDf/MhQn9dW0kHE9WbbhbsskRhEPBA2NEYE/j3deotPJWfv16sSMKe7
	YW/5pKSPlNhYbfROp/MBJYK9KiLVrJb48T+SUvx4KTUKxmeQp+B9xgCyb2EpBdrNMmYV
	WO/A==
X-Gm-Message-State: ALoCoQlDh3D78AWAgW3rb8BtDc8iZLmhUIrSwYQ1AgJD0laOoo/9O/zqhoKAyTftxfbaajBlkJNZ
X-Received: by 10.194.81.38 with SMTP id w6mr66153486wjx.17.1416473923743;
	Thu, 20 Nov 2014 00:58:43 -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 fv5sm2378210wjc.37.2014.11.20.00.58.35
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Thu, 20 Nov 2014 00:58:42 -0800 (PST)
Message-ID: <546DAD42.1080808@m2r.biz>
Date: Thu, 20 Nov 2014 09:58:42 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>
References: <5464BDF4.1090103@m2r.biz>	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>	<5464C25D.6070200@m2r.biz>	<5466279C.207@m2r.biz>	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
	<CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
In-Reply-To: <CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
Content-Type: multipart/mixed; boundary="------------080009070007070309030302"
Cc: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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>
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--------------080009070007070309030302
Content-Type: multipart/alternative;
 boundary="------------000104010701060601060306"


--------------000104010701060601060306
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

Il 14/11/2014 18:54, Fabio Fantoni ha scritto:
> 2014-11-14 17:15 GMT+01:00 Paul Durrant <Paul.Durrant@citrix.com 
> <mailto:Paul.Durrant@citrix.com>>:
>
>     > -----Original Message-----
>     > From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz
>     <mailto:fabio.fantoni@m2r.biz>]
>     > Sent: 14 November 2014 16:03
>     > To: Paul Durrant; win-pv-devel@lists.xenproject.org
>     <mailto:win-pv-devel@lists.xenproject.org>
>     > Subject: Re: Windows 7 64 bit blue screen with stop 1e after
>     restore with
>     > new build of win pv drivers
>     >
>     > Il 13/11/2014 15:38, Fabio Fantoni ha scritto:
>     > > Il 13/11/2014 15:26, Paul Durrant ha scritto:
>     > >>> -----Original Message-----
>     > >>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz
>     <mailto:fabio.fantoni@m2r.biz>]
>     > >>> Sent: 13 November 2014 14:20
>     > >>> To: win-pv-devel@lists.xenproject.org
>     <mailto:win-pv-devel@lists.xenproject.org>; Paul Durrant
>     > >>> Subject: Windows 7 64 bit blue screen with stop 1e after restore
>     > >>> with new
>     > >>> build of win pv drivers
>     > >>>
>     > >>> I did a new build of winpv drivers and tested on one windows
>     7 64 bit
>     > >>> domU, dom0 xen-unstable with "x86/hvm: Extend HVM cpuid leaf
>     with
>     > vcpu
>     > >>> id" and "x86/hvm: Add per-vcpu evtchn upcalls" patches, and
>     qemu 2.2
>     > >>> from spice git:
>     > >>> https://github.com/Fantu/Xen/commits/rebase/m2r-staging
>     > >>>
>     > >>> After restore windows showed blue screen with stop 1e, I
>     open the
>     > dump
>     > >>> with "BlueScreenView" and showed that cause is xennet driver.
>     > >>> I attached the dump, if you need more informations/tests
>     tell me and
>     > >>> I'll post them.
>     > >>>
>     > >> I've been testing with win7 32-bit and seen no problems. The
>     minidump
>     > >> doesn't tell me much unfortunately do you have a full dump,
>     plus the
>     > >> QEMU log?
>     > >>
>     > >>    Paul
>     > >
>     > > Thanks for reply.
>     > > qemu log was without errors or warning related, I changed windows
>     > > option for full memory dump and enable qemu trace of xen and
>     retried
>     > > to reproduce the problem but this time after restore on same
>     domU not
>     > > had the blue screen.
>     >
>     > Blue screen re-happen, in attachment qemu logs (before and after
>     > restore) with xen trace.
>     > Also memory.dmp full this time but there is a problem, is 1,87
>     gb and my
>     > connection is max 256kbps of upload :(
>     > If is really needed tell me and I'll try to load it in my webserver
>     > tomorrow.
>     >
>
>     I'll try to repro. You're crash happened very early in resume. Is
>     your xenbus driver the built from tip?
>
>
> Yes I updated all to latest git in 
> http://xenbits.xen.org/gitweb/?o=age, all except xeniface was updated 
> if I remember good.
> Was happen 2 time on total of 5 save/restore I tried.
> Latest test was with qemu upstream updated including also the new 2 
> xen bugfix http://git.qemu.org/qemu.git (commit 
> 4e70f9271dabc58fbf14680843bfac510c193152).

I have updated xen to latest staging and qemu to tag v2.2.0-rc2 and the 
crash still happen, in attachment minidump of latest crash and below the 
link of full memory dump, hope that these will help you to found and 
solves the problem:
http://fantu.info/xen/MEMORY.DMP

>
>       Paul
>
>     > >
>     > >>
>     > >>> Thanks for any reply and sorry for my bad english.
>     > >
>     >
>
>


--------------000104010701060601060306
Content-Type: text/html; charset=utf-8
Content-Length: 7906
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    <div class=3D"moz-cite-prefix">Il 14/11/2014 18:54, Fabio Fantoni ha
      scritto:<br>
    </div>
    <blockquote
cite=3D"mid:CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com"
      type=3D"cite">
      <div dir=3D"ltr">2014-11-14 17:15 GMT+01:00 Paul Durrant <span
          dir=3D"ltr">&lt;<a moz-do-not-send=3D"true"
            href=3D"mailto:Paul.Durrant@citrix.com" target=3D"_blank">Paul.Durrant@citrix.com</a>&gt;</span>:<br>
        <div class=3D"gmail_extra">
          <div class=3D"gmail_quote">
            <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex"><span class=3D"">&gt;
                -----Original Message-----<br>
                &gt; From: Fabio Fantoni [mailto:<a
                  moz-do-not-send=3D"true"
                  href=3D"mailto:fabio.fantoni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
              </span>
              <div>
                <div class=3D"h5">&gt; Sent: 14 November 2014 16:03<br>
                  &gt; To: Paul Durrant; <a moz-do-not-send=3D"true"
                    href=3D"mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a><br>
                  &gt; Subject: Re: Windows 7 64 bit blue screen with
                  stop 1e after restore with<br>
                  &gt; new build of win pv drivers<br>
                  &gt;<br>
                  &gt; Il 13/11/2014 15:38, Fabio Fantoni ha scritto:<br>
                  &gt; &gt; Il 13/11/2014 15:26, Paul Durrant ha
                  scritto:<br>
                  &gt; &gt;&gt;&gt; -----Original Message-----<br>
                  &gt; &gt;&gt;&gt; From: Fabio Fantoni [mailto:<a
                    moz-do-not-send=3D"true"
                    href=3D"mailto:fabio.fantoni@m2r.biz">fabio.fantoni@m2r.biz</a>]<br>
                  &gt; &gt;&gt;&gt; Sent: 13 November 2014 14:20<br>
                  &gt; &gt;&gt;&gt; To: <a moz-do-not-send=3D"true"
                    href=3D"mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>;
                  Paul Durrant<br>
                  &gt; &gt;&gt;&gt; Subject: Windows 7 64 bit blue
                  screen with stop 1e after restore<br>
                  &gt; &gt;&gt;&gt; with new<br>
                  &gt; &gt;&gt;&gt; build of win pv drivers<br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt;&gt; I did a new build of winpv drivers
                  and tested on one windows 7 64 bit<br>
                  &gt; &gt;&gt;&gt; domU, dom0 xen-unstable with
                  "x86/hvm: Extend HVM cpuid leaf with<br>
                  &gt; vcpu<br>
                  &gt; &gt;&gt;&gt; id" and "x86/hvm: Add per-vcpu
                  evtchn upcalls" patches, and qemu 2.2<br>
                  &gt; &gt;&gt;&gt; from spice git:<br>
                  &gt; &gt;&gt;&gt; <a moz-do-not-send=3D"true"
                    href=3D"https://github.com/Fantu/Xen/commits/rebase/m2r-staging"
                    target=3D"_blank">https://github.com/Fantu/Xen/commits/rebase/m2r-staging</a><br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt;&gt; After restore windows showed blue
                  screen with stop 1e, I open the<br>
                  &gt; dump<br>
                  &gt; &gt;&gt;&gt; with "BlueScreenView" and showed
                  that cause is xennet driver.<br>
                  &gt; &gt;&gt;&gt; I attached the dump, if you need
                  more informations/tests tell me and<br>
                  &gt; &gt;&gt;&gt; I'll post them.<br>
                  &gt; &gt;&gt;&gt;<br>
                  &gt; &gt;&gt; I've been testing with win7 32-bit and
                  seen no problems. The minidump<br>
                  &gt; &gt;&gt; doesn't tell me much unfortunately do
                  you have a full dump, plus the<br>
                  &gt; &gt;&gt; QEMU log=3F<br>
                  &gt; &gt;&gt;<br>
                  &gt; &gt;&gt;=C2=A0 =C2=A0 Paul<br>
                  &gt; &gt;<br>
                  &gt; &gt; Thanks for reply.<br>
                  &gt; &gt; qemu log was without errors or warning
                  related, I changed windows<br>
                  &gt; &gt; option for full memory dump and enable qemu
                  trace of xen and retried<br>
                  &gt; &gt; to reproduce the problem but this time after
                  restore on same domU not<br>
                  &gt; &gt; had the blue screen.<br>
                  &gt;<br>
                  &gt; Blue screen re-happen, in attachment qemu logs
                  (before and after<br>
                  &gt; restore) with xen trace.<br>
                  &gt; Also memory.dmp full this time but there is a
                  problem, is 1,87 gb and my<br>
                  &gt; connection is max 256kbps of upload :(<br>
                  &gt; If is really needed tell me and I'll try to load
                  it in my webserver<br>
                  &gt; tomorrow.<br>
                  &gt;<br>
                  <br>
                </div>
              </div>
              I'll try to repro. You're crash happened very early in
              resume. Is your xenbus driver the built from tip=3F<br>
            </blockquote>
            <div><br>
            </div>
            <div>Yes I updated all to latest git in <a
                moz-do-not-send=3D"true"
                href=3D"http://xenbits.xen.org/gitweb/=3Fo=3Dage">http://xenbits.xen.org/gitweb/=3Fo=3Dage</a>,
              all except xeniface was updated if I remember good.<br>
            </div>
            <div>Was happen 2 time on total of 5 save/restore I tried.<br>
            </div>
            <div>Latest test was with qemu upstream updated including
              also the new 2 xen bugfix <a moz-do-not-send=3D"true"
                href=3D"http://git.qemu.org/qemu.git">http://git.qemu.org/qemu.git</a>
              (commit 4e70f9271dabc58fbf14680843bfac510c193152).<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    I have updated xen to latest staging and qemu to tag v2.2.0-rc2 and
    the crash still happen, in attachment minidump of latest crash and
    below the link of full memory dump, hope that these will help you to
    found and solves the problem:<br>
    <a class=3D"moz-txt-link-freetext" href=3D"http://fantu.info/xen/MEMORY.DMP">http://fantu.info/xen/MEMORY.DMP</a><br>
    <br>
    <blockquote
cite=3D"mid:CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com"
      type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra">
          <div class=3D"gmail_quote">
            <div>=C2=A0</div>
            <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px
              0.8ex;border-left:1px solid
              rgb(204,204,204);padding-left:1ex">
              <span class=3D""><font color=3D"#888888"><br>
                  =C2=A0 Paul<br>
                </font></span>
              <div class=3D"">
                <div class=3D"h5"><br>
                  &gt; &gt;<br>
                  &gt; &gt;&gt;<br>
                  &gt; &gt;&gt;&gt; Thanks for any reply and sorry for
                  my bad english.<br>
                  &gt; &gt;<br>
                  &gt;<br>
                  <br>
                </div>
              </div>
            </blockquote>
          </div>
          <br>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>

--------------000104010701060601060306--

--------------080009070007070309030302
Content-Type: application/octet-stream;
 name="111914-10467-01.dmp"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="111914-10467-01.dmp"

UEFHRURVNjQPAAAAsR0AAABwGAAAAAAAeDLQAgD4//+QmMkCAPj//5C1xwIA+P//ZIYAAAIA
AAAeAAAAUEFHRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0WgUMQCAPj//1BBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAA
AAAAAICN5gKA+P//WLPBAgD4///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC
5gKA+P//4HvmAoD4//+wjeYCgPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//
AAAAAAAAAACQu6wCAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAwAAgAEAAAAAAAAAAAAAAJC7rAIA+P//AAAAAFBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UEAAAA
UEFHRbAaBAAAAAAAsMf+VQME0AFQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRSAIbjwAAAAA/wwAAFBB
R0UBAAAAEAEAAAAAAABQAEdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdF
UEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBB
R0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0VQQUdFUEFHRVBBR0UAAQAAAAAEAPz/AwBIAwAA
AA8AAIAgAADQIAAA8CEAAPBuAADAcwAAaHgAAAAQAACoiwAAigAAAEjZAAA4LgAAAAAAAP//
///oeuYCgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaIgAAEADAACABwEA
DwAAAAEAAABQAAAAAAAAAAAAAAAAAAAAAAAAAHh5BQAAAAAAuxcAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAkR0CAAAAAAB9wQIAAAAAAHT+HQAAAAAABQAAAAAAAAAYABgAAAAAAAAAAAAAAAAA
YwByAGEAcwBoAGQAbQBwAC4AcwB5AHMAAABDAYD4//8A4EMBgPj//xgAGAAAAAAAAAAAAAAA
AABkAHUAbQBwAF8AcwB0AG8AcgBwAG8AcgAA4EMBgPj//wCARAGA+P//GAAYAAAAAAAAAAAA
AAAAAGQAdQBtAHAAXwB4AGUAbgBjAHIAcwBoAAAwGwGA+P//ANAeAYD4//8YABgAAAAAAAAA
AAAAAAAAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AAIBEAYD4//8AQEcBgPj//xgAGAAAAAAA
AAAAAAAAAABkAHUAbQBwAF8AZAB1AG0AcABmAHYAZQAAQEcBgPj//wBwSAGA+P//gB8AAAEA
AABAr+QCgPj//wAAAAAAAAAAQK/kAoD4//8BAAAAAQAAALCN5gKA+P//AAAAAAAAAAAAAAAA
AAAAADEABYAAAAAAABAuAAAAAAAAcBgAAAAAAPgGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAADwD///AAAAAAAEAAAAAAAAAAAAAAAAfwDAtOQCgPj//wAAAAAAAP8P
QLXkAoD4//9AAAAAgB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAADwAQAIAfAAAQACsAKwBTACsAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIHmAoD4//8eAAAAAAAAAICN5gKA+P//WLPBAgD4
///oeuYCgPj//wAAAAAAAAAAAGClAgD4//8AAAAAAAAAAGCC5gKA+P//4HvmAoD4//+wjeYC
gPj//5h75gKA+P//yjisAgD4//8ghc0CAPj//7A1rAIA+P//AAAAAAAAAACQu6wCAPj//wAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAABQb29M8AEAABD8vwIA+P//0PC/AgD4//+AIeQCgPj//yAh5AKA+P//
TwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABygAAAAAAAAAAAAAAAAAAAAAA
AABQb29MAAIAABD8vwIA+P//0PC/AgD4///gIeQCgPj//4Ah5AKA+P//ygAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MEAAAABD8
vwIA+P//0PC/AgD4//+gCuQCgPj//0AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MIAAAABD8vwIA+P//0PC/AgD4
//8AC+QCgPj//6AK5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MMAAAABD8vwIA+P//0PC/AgD4//9gC+QCgPj//wAL
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29MQAAAABD8vwIA+P//0PC/AgD4///AC+QCgPj//2AL5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
UAAAABD8vwIA+P//0PC/AgD4//8gDOQCgPj//8AL5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MYAAAABD8vwIA+P//
0PC/AgD4//+ADOQCgPj//yAM5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29McAAAABD8vwIA+P//0PC/AgD4///gDOQC
gPj//4AM5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MgAAAABD8vwIA+P//0PC/AgD4//9ADeQCgPj//+AM5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MkAAAABD8vwIA+P//0PC/AgD4//+gDeQCgPj//0AN5AKA+P//AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MoAAAABD8
vwIA+P//0PC/AgD4//8ADuQCgPj//6AN5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MsAAAABD8vwIA+P//0PC/AgD4
//9gDuQCgPj//wAO5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MwAAAABD8vwIA+P//0PC/AgD4///ADuQCgPj//2AO
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29M0AAAABD8vwIA+P//0PC/AgD4//8gD+QCgPj//8AO5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
4AAAABD8vwIA+P//0PC/AgD4//+AD+QCgPj//yAP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M8AAAABD8vwIA+P//
0PC/AgD4///gD+QCgPj//4AP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MAAEAABD8vwIA+P//0PC/AgD4//9AEOQC
gPj//+AP5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MEAEAABD8vwIA+P//0PC/AgD4//+gEOQCgPj//0AQ5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MIAEAABD8vwIA+P//0PC/AgD4//8AEeQCgPj//6AQ5AKA+P//AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MMAEAABD8
vwIA+P//0PC/AgD4//9gEeQCgPj//wAR5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MQAEAABD8vwIA+P//0PC/AgD4
///AEeQCgPj//2AR5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAB
AAAAAAAAAAAAAAAAAAAAAAEAAABQb29MUAEAABD8vwIA+P//0PC/AgD4//8gEuQCgPj//8AR
5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAA
AAAAAAEAAABQb29MYAEAABD8vwIA+P//0PC/AgD4//+AEuQCgPj//yAS5AKA+P//AAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29M
cAEAABD8vwIA+P//0PC/AgD4///gEuQCgPj//4AS5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MgAEAABD8vwIA+P//
0PC/AgD4//9AE+QCgPj//+AS5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAEAAABAAAAAAAAAAAAAAAAAAAAAAEAAABQb29MkAEAABD8vwIA+P//0PC/AgD4//+gE+QC
gPj//0AT5AKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAA
AAAAAAAAAAAAAAEAAABQb29MoAEAABD8vwIA+P//0PC/AgD4//8AFOQCgPj//6AT5AKA+P//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAABAAAAAAAAAAAAAAAAAAAAAAEA
AABQb29MsAEAABD8vwIA+P//0PC/AgD4//9gFOQCgPj//wAU5AKA+P//AAAAAAAAAAAAAAAA
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
SCfkAoD4//9IJ+QCgPj//0BNQzn/////AAAAAAAAAABoJ+QCgPj//2gn5AKA+P//oO6CNP//
//8AAAAAAAAAAIgn5AKA+P//iCfkAoD4//9ACTtY/////wAAAAAAAAAAqCfkAoD4//+oJ+QC
gPj//2DRqzv/////AAAAAAAAAADIJ+QCgPj//8gn5AKA+P//AEzFYf////8AAAAAAAAAADA8
UgOA+v//MDxSA4D6//9gDSlkAAAAAAAAAAAAAAAAMJx5A4D6//8Q70cDgPr//2DqdEAAAAAA
AAAAAAAAAAAoKOQCgPj//ygo5AKA+P//4PZTOf////8AAAAAAAAAAEgo5AKA+P//SCjkAoD4
//9AmJM0/////wAAAAAAAAAAaCjkAoD4//9oKOQCgPj//+DSWTn/////AAAAAAAAAACIKOQC
gPj//4go5AKA+P//AHu8O/////8AAAAAAAAAAKgo5AKA+P//qCjkAoD4//9gHPw2/////wAA
AAAAAAAAyCjkAoD4///IKOQCgPj//5DFOzL/////AAAAAAAAAADoKOQCgPj//+go5AKA+P//
YJi2Wv////8AAAAAAAAAAAgp5AKA+P//CCnkAoD4//+AoGQ5/////wAAAAAAAAAAKCnkAoD4
//8oKeQCgPj//8DWBDf/////AAAAAAAAAABIKeQCgPj//0gp5AKA+P//QOPjL/////8AAAAA
AAAAAGgp5AKA+P//aCnkAoD4//+gJM07/////wAAAAAAAAAAiCnkAoD4//+IKeQCgPj//6DV
DDf/////AAAAAAAAAACoKeQCgPj//6gp5AKA+P//4MtvOf////8AAAAAAAAAAMgp5AKA+P//
yCnkAoD4//8AohI3/////wAAAAAAAAAA6CnkAoD4///oKeQCgPj//yBKdTn/////AAAAAAAA
AADgmYsDgPr//+CZiwOA+v//wGQiSgAAAAAAAAAAAAAAACgq5AKA+P//KCrkAoD4//8gZs5a
/////wAAAAAAAAAAYKlpA4D6//9gqWkDgPr//4AnJ0oAAAAAAAAAAAAAAAAA/X0BgPr//zB0
iwOA+v//gCSiQAAAAAAAAAAAAAAAAEBxoAOA+v//QHGgA4D6//9AitVaAAAAAAAAAAAAAAAA
QLGGAoD6//9AsYYCgPr//6BrXWQAAAAAAAAAAAAAAADIKuQCgPj//8gq5AKA+P//wPOFOf//
//8AAAAAAAAAAEDxOQOA+v//QPE5A4D6//9gLldRAAAAAAAAAAAAAAAAIAlFA4D6//8gCUUD
gPr//8CPWVEAAAAAAAAAAAAAAAAoK+QCgPj//ygr5AKA+P//4HfuO/////8AAAAAAAAAAEgr
5AKA+P//SCvkAoD4//9AUPI7/////wAAAAAAAAAAQIePAoD6//9Ah48CgPr//4APnEwAAAAA
AAAAAAAAAACgPZoDgPr//6A9mgOA+v//4LDbRwAAAAAAAAAAAAAAAKgr5AKA+P//qCvkAoD4
//9gnZY5/////wAAAAAAAAAAyCvkAoD4///IK+QCgPj//2Dx+Tv/////AAAAAAAAAADoK+QC
gPj//+gr5AKA+P//IOAVMP////8AAAAAAAAAAAgs5AKA+P//CCzkAoD4//9QKf87/////wAA
AAAAAAAAKCzkAoD4//8oLOQCgPj//+DCPjf/////AAAAAAAAAABILOQCgPj//0gs5AKA+P//
wCIEPP////8AAAAAAAAAAGgs5AKA+P//aCzkAoD4///gp70t/////wAAAAAAAAAAiCzkAoD4
//+ILOQCgPj//4CLpjn/////AAAAAAAAAACoLOQCgPj//6gs5AKA+P//4IZIN/////8AAAAA
AAAAAMgs5AKA+P//yCzkAoD4//9Argw8/////wAAAAAAAAAA6CzkAoD4///oLOQCgPj//yDL
Dzz/////AAAAAAAAAACwxJ0DgPr//7DEnQOA+v//YKFZSgAAAAAAAAAAAAAAACgt5AKA+P//
KC3kAoD4///gDY8y/////wAAAAAAAAAASC3kAoD4//9ILeQCgPj//4AILmL/////AAAAAAAA
AAAw3G0DgPr//zDcbQOA+v//wMJdnGQAAAAAAAAAAAAAADAsjQOA+v//MFySA4D6///ANT9D
AAAAAAAAAAAAAAAAqC3kAoD4//+oLeQCgPj//6AMEVv/////AAAAAAAAAADA1Z8CgPr//8DV
nwKA+v//AO6NUQAAAAAAAAAAAAAAAOgt5AKA+P//6C3kAoD4//8gFmA3/////wAAAAAAAAAA
CC7kAoD4//8ILuQCgPj//4C3nzL/////AAAAAAAAAAAoLuQCgPj//ygu5AKA+P//IBKVUf//
//8AAAAAAAAAAEgu5AKA+P//SC7kAoD4//9Amsg5/////wAAAAAAAAAAaC7kAoD4//9oLuQC
gPj//6A7CDX/////AAAAAAAAAACILuQCgPj//4gu5AKA+P//gPipMv////8AAAAAAAAAAKgu
5AKA+P//qC7kAoD4//9gHjE8/////wAAAAAAAAAAyC7kAoD4///ILuQCgPj//4BgMzz/////
AAAAAAAAAADoLuQCgPj//+gu5AKA+P//IGGwMv////8AAAAAAAAAAAgv5AKA+P//CC/kAoD4
//+AmRU1/////wAAAAAAAAAAKC/kAoD4//8oL+QCgPj//+BD2Tn/////AAAAAAAAAABIL+QC
gPj//0gv5AKA+P//IJcYNf////8AAAAAAAAAAGgv5AKA+P//aC/kAoD4///g/7oy/////wAA
AAAAAAAAiC/kAoD4//+IL+QCgPj//wDIQTz/////AAAAAAAAAACoL+QCgPj//6gv5AKA+P//
YGmBN/////8AAAAAAAAAAMgv5AKA+P//yC/kAoD4//8ApF1i/////wAAAAAAAAAA6C/kAoD4
///oL+QCgPj//2BRhTf/////AAAAAAAAAAAIMOQCgPj//wgw5AKA+P//gO3pOf////8AAAAA
AAAAACgw5AKA+P//KDDkAoD4//+Anik1/////wAAAAAAAAAASDDkAoD4//9IMOQCgPj//8CI
jjf/////AAAAAAAAAABoMOQCgPj//2gw5AKA+P//oOhTPP////8AAAAAAAAAAIgw5AKA+P//
iDDkAoD4//8AE5I3/////wAAAAAAAAAAqDDkAoD4//+oMOQCgPj//+BYMjX/////AAAAAAAA
AADIMOQCgPj//8gw5AKA+P//oKo0Nf////8AAAAAAAAAAOgw5AKA+P//6DDkAoD4//8gl/o5
/////wAAAAAAAAAAoHSBA4D6//+gdIEDgPr//0DcjFYAAAAAAAAAAAAAAAAoMeQCgPj//ygx
5AKA+P//YD6dN/////8AAAAAAAAAAEgx5AKA+P//SDHkAoD4//9AG2M8/////wAAAAAAAAAA
4CmmA4D6//9AgWgDgPr//+AV7EUAAAAAAAAAAAAAAACgalwDgPr//0Ch+gKA+v//AMHIPgAA
AAAAAAAAAAAAAFANNwOA+v//UA03A4D6///goBNNAAAAAAAAAAAAAAAAoKh7A4D6//+gqHsD
gPr//wDanFYAAAAAAAAAAAAAAADoMeQCgPj//+gx5AKA+P//YIRKNf////8AAAAAAAAAAAgy
5AKA+P//CDLkAoD4//+Ag4ow/////wAAAAAAAAAAMAyUA4D6///ARfwCgPr//2AJczwAAAAA
AAAAAAAAAABIMuQCgPj//0gy5AKA+P//QGazN/////8AAAAAAAAAAGgy5AKA+P//aDLkAoD4
//9ga/Iy/////wAAAAAAAAAAiDLkAoD4//+IMuQCgPj//zAeMy7/////AAAAAAAAAACoMuQC
gPj//6gy5AKA+P//4KsmTf////8AAAAAAAAAADBMkQOA+v//oCmXA4D6//+Az0FBAAAAAAAA
AAAAAAAA6DLkAoD4///oMuQCgPj//2CPXTX/////AAAAAAAAAAAIM+QCgPj//wgz5AKA+P//
AO22JP////8AAAAAAAAAACgz5AKA+P//KDPkAoD4///gD8Q3/////wAAAAAAAAAASDPkAoD4
//9IM+QCgPj//8CSMk3/////AAAAAAAAAABAeJkDgPr//0B4mQOA+v//IDHtPgAAAAAAAAAA
AAAAAIgz5AKA+P//iDPkAoD4//8AlCw6/////wAAAAAAAAAAqDPkAoD4//+oM+QCgPj//+B5
azX/////AAAAAAAAAABAAYYDgPr//0ABhgOA+v//wC2UPAAAAAAAAAAAAAAAADAcmQOA+v//
MDw/A4D6//9gceldAAAAAAAAAAAAAAAACDTkAoD4//8INOQCgPj//8DS613/////AAAAAAAA
AABwq5kDgPr//0ARdAOA+v//IDTuXQAAAAAAAAAAAAAAADBIPQOA+v//MEg9A4D6//+AtQlS
AAAAAAAAAAAAAAAAEI9sA4D6//8Qj2wDgPr//yA8AD8AAAAAAAAAAAAAAAAw7AcDgPr//0Bx
pgOA+v//4KE7IgIAAAAAAAAAAAAAAKg05AKA+P//qDTkAoD4//8As2VB/////wAAAAAAAAAA
yDTkAoD4///INOQCgPj//4ClHzP/////AAAAAAAAAADoNOQCgPj//+g05AKA+P//YNxdYP//
//8AAAAAAAAAADD8mAOA+v//MGxPA4D6//9ACNlWAAAAAAAAAAAAAAAA8PkNA4D6///w+Q0D
gPr//2AqrDwAAAAAAAAAAAAAAABINeQCgPj//0g15AKA+P//QOdNOv////8AAAAAAAAAAFB4
UwOA+v//UHhTA4D6///gYWdgAAAAAAAAAAAAAAAAiDXkAoD4//+INeQCgPj//0APjzX/////
AAAAAAAAAACoNeQCgPj//6g15AKA+P//oERvLv////8AAAAAAAAAAEBxYAOA+v//gOBHA4D6
//8A5rk8AAAAAAAAAAAAAAAA6DXkAoD4///oNeQCgPj//yCuNTP/////AAAAAAAAAAAINuQC
gPj//wg25AKA+P//wJSYNf////8AAAAAAAAAALDLTwOA+v//oMZPA4D6//+g9GhNAAAAAAAA
AAAAAAAAQHFXA4D6//9AcVcDgPr//4DLL1IAAAAAAAAAAAAAAABoNuQCgPj//2g25AKA+P//
oNPdMP////8AAAAAAAAAAIg25AKA+P//iDbkAoD4//8Aj0Iz/////wAAAAAAAAAAQFGSA4D6
//9AUZIDgPr//yCai0EAAAAAAAAAAAAAAAAQvpMDgPr//0ANPgOA+v//APfLPAAAAAAAAAAA
AAAAAOg25AKA+P//6DbkAoD4//8AziMs/////wAAAAAAAAAAwGlZA4D6///AaVkDgPr//yDt
kkEAAAAAAAAAAAAAAAAwzHUDgPr//zDMdQOA+v//4DKXQQAAAAAAAAAAAAAAAEg35AKA+P//
SDfkAoD4//9Afe4w/////wAAAAAAAAAAaDfkAoD4//9oN+QCgPj//+D3B1f/////AAAAAAAA
AACIN+QCgPj//4g35AKA+P//AGAXOP////8AAAAAAAAAAKg35AKA+P//qDfkAoD4//+g2jBe
/////wAAAAAAAAAAQAGRA4D6//9AAZEDgPr///AUddAAAAAAAAAAAAAAAADgJUwDgPr//+Al
TAOA+v//4McPVwAAAAAAAAAAAAAAAAg45AKA+P//CDjkAoD4///ACiA4/////wAAAAAAAAAA
KDjkAoD4//8oOOQCgPj//+Am/zD/////AAAAAAAAAABIOOQCgPj//0g45AKA+P//4HhuOP//
//8AAAAAAAAAACBqogOA+v//IGqiA4D6//9gjVZSAAAAAAAAAAAAAAAAiDjkAoD4//+IOOQC
gPj//3DCZzP/////AAAAAAAAAACAyWMDgPr//4DJYwOA+v//oKXwPAAAAAAAAAAAAAAAAMg4
5AKA+P//yDjkAoD4///AjZA6/////wAAAAAAAAAA6DjkAoD4///oOOQCgPj//9BrzzX/////
AAAAAAAAAAAIOeQCgPj//wg55AKA+P//gNAPMf////8AAAAAAAAAACg55AKA+P//KDnkAoD4
///gyDc4/////wAAAAAAAAAAUGmkA4D6//9AR1gDgPr//wCXvUEAAAAAAAAAAAAAAABAcVUD
gPr//zB8VQOA+v//4PMedgAAAAAAAAAAAAAAAIg55AKA+P//iDnkAoD4//9A23kz/////wAA
AAAAAAAAqDnkAoD4//+oOeQCgPj//2A3oTr/////AAAAAAAAAABA8V4DgPr//7D7iwOA+v//
gPytTQAAAAAAAAAAAAAAADCYngOA+v//MJieA4D6///gNFXCAAAAAAAAAAAAAAAAMIx2A4D6
//8wjHYDgPr//8C08UgAAAAAAAAAAAAAAABw65YDgPr//zD8QgOA+v//IBb0SAAAAAAAAAAA
AAAAAEAxlAOA+v//MMyeA4D6//+Ad/ZIAAAAAAAAAAAAAAAAaDrkAoD4//9oOuQCgPj//+BE
QiX/////AAAAAAAAAACIOuQCgPj//4g65AKA+P//0OixOv////8AAAAAAAAAAFAFiAOA+v//
UAWIA4D6//8gZoFSAAAAAAAAAAAAAAAAMMyGA4D6//8wzIYDgPr//4DHg1IAAAAAAAAAAAAA
AAAw/GcDgPr//zCsQAOA+v//4GjDTQAAAAAAAAAAAAAAAAg75AKA+P//CDvkAoD4//+ABlo4
/////wAAAAAAAAAAQBFqA4D6//9AQZcDgPr//4C6Hj0AAAAAAAAAAAAAAAAwvGkDgPr//zC8
aQOA+v//gKI4YwAAAAAAAAAAAAAAAGA6TAOA+v//YDpMA4D6///gI1RXAAAAAAAAAAAAAAAA
iDvkAoD4//+IO+QCgPj//4BwATb/////AAAAAAAAAACoO+QCgPj//6g75AKA+P//YM1BMf//
//8AAAAAAAAAABDJRQOA+v//EMlFA4D6//8AKEJjAAAAAAAAAAAAAAAA6DvkAoD4///oO+QC
gPj//6Bxajj/////AAAAAAAAAABAgYwDgPr//0CBjAOA+v//wApgVwAAAAAAAAAAAAAAAJBS
cQOA+v//kFJxA4D6//9glNtNAAAAAAAAAAAAAAAAUOg8A4D6//9AQWwDgPr//8D13U0AAAAA
AAAAAAAAAABoPOQCgPj//2g85AKA+P//IBoSNv////8AAAAAAAAAAIg85AKA+P//iDzkAoD4
//+AO9c6/////wAAAAAAAAAAQCFnA4D6//9AIWcDgPr//6ARkF4AAAAAAAAAAAAAAAAQqHID
gPr//+CkngOA+v//gB3nTQAAAAAAAAAAAAAAADB8pgOA+v//MHymA4D6//9gFMdGAAAAAAAA
AAAAAAAAAPxmA4D6//8A/GYDgPr//8CV+GAAAAAAAAAAAAAAAAAoPeQCgPj//yg95AKA+P//
4N3jOv////8AAAAAAAAAADD9RQOA+v//MP1FA4D6//8gyw+5AAAAAAAAAAAAAAAAaD3kAoD4
//9oPeQCgPj//6AgYzH/////AAAAAAAAAAAwXE4DgPr//zBcTgOA+v//QHtjYwAAAAAAAAAA
AAAAAKg95AKA+P//qD3kAoD4//+gXNVG/////wAAAAAAAAAAyD3kAoD4///IPeQCgPj//8Ck
yzP/////AAAAAAAAAADoPeQCgPj//+g95AKA+P//oGrmJ/////8AAAAAAAAAAAg+5AKA+P//
CD7kAoD4//+Ah/Q6/////wAAAAAAAAAAKD7kAoD4//8oPuQCgPj//+AoNDb/////AAAAAAAA
AABIPuQCgPj//0g+5AKA+P//QMpzMf////8AAAAAAAAAAGg+5AKA+P//aD7kAoD4//+AF7Qs
/////wAAAAAAAAAAiD7kAoD4//+IPuQCgPj//wCtnDj/////AAAAAAAAAACoPuQCgPj//6g+
5AKA+P//gNmfOP////8AAAAAAAAAABCseQGA+v//kIx7AYD6//+AjWQ9AAAAAAAAAAAAAAAA
6D7kAoD4///oPuQCgPj//4BBKUL/////AAAAAAAAAABA8ZMDgPr//0ABPQOA+v//wNcqQgAA
AAAAAAAAAAAAACg/5AKA+P//KD/kAoD4///gc4Qx/////wAAAAAAAAAASD/kAoD4//9IP+QC
gPj//4C6SDb/////AAAAAAAAAABoP+QCgPj//2g/5AKA+P//oFatOP////8AAAAAAAAAAKB1
pgOA+v//oHWmA4D6///AmzRCAAAAAAAAAAAAAAAAqD/kAoD4//+oP+QCgPj//6DSZ1z/////
AAAAAAAAAADIP+QCgPj//8g/5AKA+P//AFSOY/////8AAAAAAAAAAOg/5AKA+P//6D/kAoD4
//9g9c1e/////wAAAAAAAAAACEDkAoD4//8IQOQCgPj//yCuoDb/////AAAAAAAAAAAoQOQC
gPj//yhA5AKA+P//IMS6OP////8AAAAAAAAAAEhA5AKA+P//SEDkAoD4//9AAL44/////wAA
AAAAAAAAaEDkAoD4//9oQOQCgPj//yD6Ijv/////AAAAAAAAAACIQOQCgPj//4hA5AKA+P//
QOjBOP////8AAAAAAAAAAKhA5AKA+P//qEDkAoD4//9ghCY7/////wAAAAAAAAAAyEDkAoD4
///IQOQCgPj//wCrxjj/////AAAAAAAAAADoQOQCgPj//+hA5AKA+P//oMtnNv////8AAAAA
AAAAAAhB5AKA+P//CEHkAoD4//8wJWo2/////wAAAAAAAAAAKEHkAoD4//8oQeQCgPj//+Cp
zjj/////AAAAAAAAAABIQeQCgPj//0hB5AKA+P//wOlvNv////8AAAAAAAAAAGhB5AKA+P//
aEHkAoD4///AlLAx/////wAAAAAAAAAAiEHkAoD4//+IQeQCgPj//wAuNzv/////AAAAAAAA
AACoQeQCgPj//6hB5AKA+P//MNd2Nv////8AAAAAAAAAAGAapgOA+v//YBqmA4D6//8Ais1X
AAAAAAAAAAAAAAAA6EHkAoD4///oQeQCgPj//6CWPTv/////AAAAAAAAAAAIQuQCgPj//whC
5AKA+P//YOg/O/////8AAAAAAAAAALAjTwOA+v//sCNPA4D6//9ACqBnCAAAAAAAAAAAAAAA
QEF7A4D6//9AQXsDgPr//4DvvWMAAAAAAAAAAAAAAABoQuQCgPj//2hC5AKA+P//QGpHO///
//8AAAAAAAAAAIhC5AKA+P//iELkAoD4//8AeYc2/////wAAAAAAAAAAqELkAoD4//+oQuQC
gPj//2AaxzH/////AAAAAAAAAAAwPA8DgPr//zA8DwOA+v//gB8cUwAAAAAAAAAAAAAAAOhC
5AKA+P//6ELkAoD4///A71A7/////wAAAAAAAAAACEPkAoD4//8IQ+QCgPj//4CeLzT/////
AAAAAAAAAAAoQ+QCgPj//yhD5AKA+P//YP70OP////8AAAAAAAAAAEhD5AKA+P//SEPkAoD4
//9AgVg7/////wAAAAAAAAAAaEPkAoD4//9oQ+QCgPj//6AimDb/////AAAAAAAAAACIQ+QC
gPj//4hD5AKA+P//gAjXMf////8AAAAAAAAAAKhD5AKA+P//qEPkAoD4///gKZw2/////wAA
AAAAAAAAyEPkAoD4///IQ+QCgPj//8CmADn/////AAAAAAAAAABAcZADgPr//wCthQOA+v//
wFrFPQAAAAAAAAAAAAAAADDInQOA+v//MMidA4D6//9vQG/m/PsvfgAAAAAAAAAAQBGRA4D6
//8QX1gDgPr//6BONlMAAAAAAAAAAAAAAABIROQCgPj//0hE5AKA+P//QMyoNv////8AAAAA
AAAAAGhE5AKA+P//aETkAoD4//9AQDBA/////wAAAAAAAAAAiETkAoD4//+IROQCgPj//2A8
6zH/////AAAAAAAAAABAwXUDgPr//0DBdQOA+v//oCnrYwAAAAAAAAAAAAAAAMhE5AKA+P//
yETkAoD4///A8VA0/////wAAAAAAAAAAIPdCA4D6//8g90IDgPr//8Alm0IAAAAAAAAAAAAA
AAAIReQCgPj//whF5AKA+P//gNR5O/////8AAAAAAAAAAChF5AKA+P//KEXkAoD4//8gT5Nh
/////wAAAAAAAAAASEXkAoD4//9IReQCgPj//0AX+TH/////AAAAAAAAAAAwyIgDgPr//zDI
iAOA+v//YHykQgAAAAAHAQYAAAAAAEgheAGA+v//SCF4AYD6//8AAAAAAAAAABMCAQEAAAAA
ACPkAoD4//8AI+QCgPj//zATtgIA+P//AAAAAAAAAAAAPB4DgPj//wg8HgOA+P//AAAAAAAA
AAABAAAAAGQAAAAAAAAAAAAAKEgCAAAAAAAAAAAAAAAAAPC7bQOA+v//ALGGAoD6//8AAAAA
AAAAAAAAAAABAAAAEwEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAQH6/AgD4//8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gEbkAoD4//+ARuQCgPj//5BG5AKA+P//kEbkAoD4//+gRuQCgPj//6BG5AKA+P//sEbkAoD4
//+wRuQCgPj//8BG5AKA+P//wEbkAoD4///QRuQCgPj//9BG5AKA+P//4EbkAoD4///gRuQC
gPj///BG5AKA+P//8EbkAoD4//8AR+QCgPj//wBH5AKA+P//EEfkAoD4//8QR+QCgPj//yBH
5AKA+P//IEfkAoD4//8wR+QCgPj//zBH5AKA+P//QEfkAoD4//9AR+QCgPj//1BH5AKA+P//
UEfkAoD4//9gR+QCgPj//2BH5AKA+P//cEfkAoD4//9wR+QCgPj//4BH5AKA+P//gEfkAoD4
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
AAAAAAAAGACGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAHkAoD4//+wjeYCgPj//wAAAAAAAAAA
QK/kAoD4//9gsIYCgPr//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAJCobAGA+v//wE7kAoD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAIbm0CgPr//wEAAAAAAAAAAgAAAAAAAAAKAAAAAAAAAEhubQKA+v//
gAHkAoD4///Aaa0CAPj//yAC4///////gAHkAoD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
gPr//7lp+wCA+P//AgIAAAAAAAAqEq0BgB8AAAAAAAAAAAAA4BDGAgD4///gEMYCAPj//0tE
QkdAAwAAAGClAgD4///wOawCAPj//wAAAAAAAAAA6AHYAAAAAQAQMqwCAPj//wAAAAAAAAAA
kJjJAgD4//+QtccCAPj//8i1xwIA+P//UBTHAgD4//8wOtACAPj//3gw0AIA+P//lDDQAgD4
//8AxcwCAPj//4BjzAIA+P//8ArNAgD4///QwccCAPj//+jBxwIA+P//AAAAAAAAAAAAAAAA
AAAAAABr0AIA+P//eDLQAgD4//8AAAAAAAAAAAAAAAAAAAAA+DnQAgD4//8kL8gCAPj///gy
0AIA+P//CDHQAgD4//9gMNACAPj//+Ay0AIA+P//AAAAAAAAAAC4MNACAPj//wAAAAAAAAAA
AAAAAAAAAACgMdACAPj//9A40AIA+P//ABAAAAAAAACQNNACAPj//xgfyAIA+P//IB/IAgD4
///A0sYCAPj//yiZyQIA+P//8B7IAgD4//9gH8gCAPj//wAAAAAAAAAAAGXQAgD4///AatAC
APj//8Br0AIA+P//wGLQAgD4//9gTMQCAPj//8D7xAIA+P//APzEAgD4//9oGscCAPj//4C1
xQIA+P//EDDQAgD4//8AMdACAPj//wAw0AIA+P//cM/FAgD4//9w38UCAPj//7hPxAIA+P//
ZM/FAgD4///woMkCAPj//6CrwAIA+P//AAAAAAAAAABAPNACAPj//+gx0AIA+P//iJjJAgD4
///InMcCAPj//9Qw0AIA+P//yP7GAgD4///gnMkCAPj//xA0yAIA+P//UB/IAgD4//8oH8gC
APj//5wtzQIA+P//ODDQAgD4//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwA
uAA4ACgAcABkAQAAAADQBDgDkAIoAABN2iEIAPQF8AW4SyABJACoBAAAAAAAAJBQxAIA+P//
mFDEAgD4//9A1cwCAPj//4BOGAAgAIABAAAAAAAAAAAAAEAAEAAYAAAAMwArAAAAAABAACMA
UwAABs0CAPj//wACzQIA+P//AAAAAAAAAABIG8gCAPj//0QbyAIA+P//gGfAAgD4///YSwAA
AAAAAEjZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJD3AID4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAS8AAAAAAAADbyltKAAAAAKDdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGD4AID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPJwBAAAAAAD8dWRU
AAAAAPjdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAGD5AID4//8AAAAAAAAAAACQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADaoBAAAAAADxdWRUAAAAAEjeAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPD6AID4//8AAAAA
AAAAAABQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFdYCAAAAAAAcdmRUAAAAAKDeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED9AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyN8BAAAAAADBG2RP
AAAAAPjeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAJD+AID4//8AAAAAAAAAAABQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcp8BAAAAAACgkudMAAAAAFDfAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAID4//8AAAAA
AAAAAADABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAbV8GAAAAAADrkudMAAAAAKjfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAID4//8AAAAAAAAAAACAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqRABAAAAAAAUwVtK
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAMDFAID4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxZwBAAAAAAAUwVtKAAAAAFjgAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDGAID4//8AAAAA
AAAAAACgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAISYCAAAAAACZkudMAAAAALDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDIAID4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu2UAAAAAAAATwVtK
AAAAAAjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAGDdAID4//8AAAAAAAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVgsDAAAAAAC1+f5RAAAAAGDhAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAYD4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAALjhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMADAYD4//8AAAAAAAAAAABABgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlb4DAAAAAAAyRPBS
AAAAABDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAKAYD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNUAAAAAGjiAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKANAYD4//8AAAAA
AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAjikBAAAAAAA+YGNUAAAAAMDiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAOAYD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAt5IAAAAAAADKo6NL
AAAAABjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFAPAYD4//8AAAAAAAAAAADABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALUUFAAAAAACckudMAAAAAHDjAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAUAYD4//8AAAAA
AAAAAABAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAARFYBAAAAAACBxFtKAAAAAMjjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAgAYD4//8AAAAAAAAAAACQGgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXfIZAAAAAACKvuFS
AAAAABjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFAVAYD4//8AAAAAAAAAAADgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+kFAAAAAAA0k+dMAAAAAHDkAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA6AYD4//8AAAAA
AAAAAACwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAqfcBAAAAAAAOkkhTAAAAAMjkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJAYD4//8AAAAAAAAAAAAgBwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhV4HAAAAAAC3TxlQ
AAAAABjlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAACBQAYD4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXksBAAAAAAD/wFtKAAAAAGjlAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBRAYD4//8AAAAA
AAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAki8BAAAAAADS705PAAAAAMDlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBvAYD4//8AAAAAAAAAAAAgDwAAAAAAAAAAAAAA
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
AAAAAAAAAABAAYD4//8AAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvhgDAAAAAACbkudMAAAAAHjqAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKA8AYD4//8AAAAA
AAAAAACgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAQrcCAAAAAACYkudMAAAAANDqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBIAYD4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2+kAAAAAAAAJwVtK
AAAAACDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAADBfAYD4//8AAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6zYAAAAAAACNyltKAAAAAHDrAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANAeAYD4//8AAAAA
AAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAbz4BAAAAAACHxVtKAAAAAMDrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDMA4D4//8AAAAAAAAAAABQAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx48CAAAAAACLxVtK
AAAAABjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAODOA4D4//8AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvpwBAAAAAAA/xVtKAAAAAHDsAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODPA4D4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAArP8AAAAAAABizltKAAAAAMjsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDQA4D4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1XQAAAAAAABizltK
AAAAACDtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAADRA4D4//8AAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzasAAAAAAABjzltKAAAAAHjtAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJDRA4D4//8AAAAA
AAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAJnEAAAAAAAATwVtKAAAAAMjtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDSA4D4//8AAAAAAAAAAAAQAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7ZoBAAAAAAAUwVtK
AAAAABjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAFDTA4D4//8AAAAAAAAAAAAgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsogCAAAAAAAyk+dMAAAAAGjuAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHDVA4D4//8AAAAA
AAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAVWIBAAAAAAA+k+dMAAAAALjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDWA4D4//8AAAAAAAAAAACQCAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ukHAAAAAAAcKYhT
AAAAAAjvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAADAA4D4//8AAAAAAAAAAABQBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANBEEAAAAAACGk+dMAAAAAGDvAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFDEA4D4//8AAAAA
AAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAe7EAAAAAAAC2zFtKAAAAALjvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODEA4D4//8AAAAAAAAAAABgAgAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzw0CAAAAAABiqOdM
AAAAABDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAEDHA4D4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaBYBAAAAAAC2zFtKAAAAAGjwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIA4D4//8AAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTQBAAAAAAAZRPBSAAAAAMD9AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHA1BID4//8AAAAA
AAAAAADAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAoH8CAAAAAABUYGNUAAAAACD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA4BID4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsEDAAAAAAAzYGNU
AAAAAID+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAANA7BID4//8AAAAAAAAAAAAwAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6g0BAAAAAACPwVtKAAAAAOD+AAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAGD5//8AAAAA
AAAAAAAgMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAACj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9BID4//8AAAAAAAAAAADAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjkEBAAAAAAB0xVtK
AAAAAID/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAABQAGD5//8AAAAAAAAAAADgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAND/AAAAAAAAAAAAAAAA
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
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCxAoD4//8AAAAAAAAAAADwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABdQAAAAAAAAWJcdT
AAAAAHgGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAICyAoD4//8AAAAAAAAAAACgAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApR8EAAAAAAAxJcdTAAAAANAGAQAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC2AoD4//8AAAAA
AAAAAAAQBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAFCIHAAAAAAB6XghKAAAAACgHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC9AoD4//8AAAAAAAAAAACwAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmgAAAAAAADlzFtK
AAAAACEAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABuAHQA
bwBzAGsAcgBuAGwALgBlAHgAZQAAABwAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABoAGEAbAAuAGQAbABsAAAAAAAeAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAawBkAGMAbwBtAC4AZABsAGwAAAAAAAAAAAAuAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAbQBjAHUAcABkAGEA
dABlAF8ARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwALgBkAGwAbAAAAAAAAAAAAB4AAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABQAFMASABFAEQALgBkAGwA
bAAAAAAAAAAAAB0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABDAEwARgBTAC4AUwBZAFMAAAAbAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwAQwBJAC4AZABsAGwAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABXAGQAZgAwADEAMAAwADAA
LgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAVwBEAEYATABEAFIALgBTAFkAUwAAAAAAAAAlAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAEEA
QwBQAEkALgBzAHkAcwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVwBNAEkATABJAEIALgBTAFkAUwAAAAAAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAG0AcwBpAHMAYQBkAHIAdgAuAHMAeQBzAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABwAGMAaQAuAHMAeQBzAAAA
AAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHYAZAByAHYAcgBvAG8AdAAuAHMAeQBzAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBmAGkA
bAB0AC4AcwB5AHMAAAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAeABlAG4ALgBzAHkAcwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgBiAHUAcwAuAHMAeQBzAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcABhAHIAdABtAGcAcgAuAHMAeQBzAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHYAbwBsAG0AZwByAC4AcwB5AHMAAAAAAAAAKAAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXAB2AG8AbABtAGcA
cgB4AC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwAaQBuAHQAZQBsAGkAZABlAC4AcwB5AHMAAAAoAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAFAAQwBJAEkARABFAFgALgBTAFkAUwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABtAG8AdQBuAHQAbQBnAHIA
LgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAYQB0AGEAcABpAC4AcwB5AHMAAAAAAAAAAAAoAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGEA
dABhAHAAbwByAHQALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgB2AGIAZAAuAHMAeQBzAAAA
AAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAcwB0AG8AcgBwAG8AcgB0AC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHgAZQBuAGMA
cgBzAGgALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUAbgBkAGkAcwBrAC4AcwB5AHMAAAAAACgA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUA
cgBzAFwAYQBtAGQAeABhAHQAYQAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGYAbAB0AG0AZwByAC4A
cwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAGQAcgBpAHYAZQByAHMAXABmAGkAbABlAGkAbgBmAG8ALgBzAHkAcwAAACUAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwA
TgB0AGYAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQA
ZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABtAHMAcgBwAGMALgBzAHkAcwAAAAAAAAAAACcA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAawBzAGUAYwBkAGQALgBzAHkAcwAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAGMAbgBnAC4AcwB5AHMA
AAAAACQAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIA
aQB2AGUAcgBzAFwAcABjAHcALgBzAHkAcwAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABGAHMAXwBSAGUAYwAuAHMA
eQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAbgBkAGkAcwAuAHMAeQBzAAAAJgAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABOAEUAVABJAE8A
LgBTAFkAUwAAAAAAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAawBzAGUAYwBwAGsAZwAuAHMAeQBzAAAAAAAmAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHQAYwBwAGkAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABmAHcAcABrAGMAbABuAHQA
LgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAdgBtAHMAdABvAHIAZgBsAC4AcwB5AHMAAAAoAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHYA
bwBsAHMAbgBhAHAALgBzAHkAcwAAAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMA
eQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAHAAbABkAHIALgBzAHkAcwAAAAAA
AAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIA
aQB2AGUAcgBzAFwAcgBkAHkAYgBvAG8AcwB0AC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkAdgBlAHIAcwBcAG0AdQBwAC4A
cwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABkAHIAaQB2AGUAcgBzAFwAaAB3AHAAbwBsAGkAYwB5AC4AcwB5AHMAAAAnAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGYA
dgBlAHYAbwBsAC4AcwB5AHMAAAAAAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAGQAcgBpAHYAZQByAHMAXABkAGkAcwBrAC4AcwB5AHMAAAApAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAEMATABBAFMAUwBQAE4AUAAuAFMAWQBTAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABjAGQAcgBvAG0ALgBzAHkA
cwAAAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAHIAaQB2AGUAcgBzAFwATgB1AGwAbAAuAFMAWQBTAAAAJQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABCAGUAZQBwAC4A
UwBZAFMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHYAZwBhAC4AcwB5AHMAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAVgBJAEQARQBPAFAA
UgBUAC4AUwBZAFMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAHcAYQB0AGMAaABkAG8AZwAuAHMAeQBzAAAAJwAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XABSAEQAUABDAEQARAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAAZQBuAGMAZABkAC4A
cwB5AHMAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
ZAByAGkAdgBlAHIAcwBcAHIAZABwAHIAZQBmAG0AcAAuAHMAeQBzAAAAJQAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABNAHMA
ZgBzAC4AUwBZAFMAAAAlAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwARAByAGkAdgBlAHIAcwBcAE4AcABmAHMALgBTAFkAUwAAACQAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdABkAHgA
LgBzAHkAcwAAAAAAJAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABUAEQASQAuAFMAWQBTAAAAAAAkAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGEAZgBkAC4A
cwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAFIASQBWAEUAUgBTAFwAbgBlAHQAYgB0AC4AcwB5AHMAAAAAAAAAAAAnAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHcA
ZgBwAGwAdwBmAC4AcwB5AHMAAAAAAAAAJgAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABwAGEAYwBlAHIALgBzAHkAcwAAAAAA
AAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAbgBlAHQAYgBpAG8AcwAuAHMAeQBzAAAAAAAnAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHcAYQBuAGEA
cgBwAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AGUAcgBtAGQAZAAuAHMAeQBzAAAAAAAAACYA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAcgBkAGIAcwBzAC4AcwB5AHMAAAAAAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAG4AcwBpAHAAcgBvAHgA
eQAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMA
MgBcAEQAUgBJAFYARQBSAFMAXABtAHMAcwBtAGIAaQBvAHMALgBzAHkAcwAAACkAAABcAFMA
eQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwA
ZABpAHMAYwBhAGMAaABlAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwA
cwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAGMAcwBjAC4AcwB5AHMAAAAAACUA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAZABmAHMAYwAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAGwAYgBkAHIAaQB2AGUALgBzAHkA
cwAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAdAB1AG4AbgBlAGwALgBzAHkAcwAAAAAAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGkAOAAwADQA
MgBwAHIAdAAuAHMAeQBzAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAG8AdQBjAGwAYQBzAHMALgBzAHkAcwAAACkA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAawBiAGQAYwBsAGEAcwBzAC4AcwB5AHMAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8A
bwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAGYAZABjAC4AcwB5AHMA
AAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAeABlAG4AdgBpAGYALgBzAHkAcwAAAAAAAAApAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHgAZQBuAGkA
ZgBhAGMAZQAuAHMAeQBzAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB2AGkAbwBzAGUAcgAuAHMAeQBzAAAAAAAAACQA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAcQB4AGwALgBzAHkAcwAAAAAAKAAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB1AHMAYgB1AGgAYwBpAC4AcwB5AHMA
AAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIA
SQBWAEUAUgBTAFwAVQBTAEIAUABPAFIAVAAuAFMAWQBTAAAAAAAoAAAAXABTAHkAcwB0AGUA
bQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHUAcwBiAGUA
aABjAGkALgBzAHkAcwAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQA
ZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABpAG4AdABlAGwAcABwAG0ALgBzAHkAcwAAAC0A
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUA
UgBTAFwAQwBvAG0AcABvAHMAaQB0AGUAQgB1AHMALgBzAHkAcwAAACkAAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAQQBnAGkA
bABlAFYAcABuAC4AcwB5AHMAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMA
dABlAG0AMwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAGwAMgB0AHAALgBzAHkAcwAAAAAA
KQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYA
RQBSAFMAXABuAGQAaQBzAHQAYQBwAGkALgBzAHkAcwAAACgAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAbgBkAGkAcwB3AGEA
bgAuAHMAeQBzAAAAAAApAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0A
MwAyAFwARABSAEkAVgBFAFIAUwBcAHIAYQBzAHAAcABwAG8AZQAuAHMAeQBzAAAAKAAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XAByAGEAcwBwAHAAdABwAC4AcwB5AHMAAAAAACgAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAcgBhAHMAcwBzAHQAcAAuAHMA
eQBzAAAAAAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwA
RABSAEkAVgBFAFIAUwBcAHIAZABwAGIAdQBzAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHcA
ZQBuAHUAbQAuAHMAeQBzAAAAAAAAACMAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAawBzAC4AcwB5AHMAAAAAAAAAJgAAAFwA
UwB5AHMAdABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMA
XAB1AG0AYgB1AHMALgBzAHkAcwAAAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABzAHkAcwB0AGUAbQAzADIAXABEAFIASQBWAEUAUgBTAFwAdQBzAGIAaAB1AGIALgBzAHkA
cwAAAAAAAAAoAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwA
RAByAGkAdgBlAHIAcwBcAE4ARABQAHIAbwB4AHkALgBTAFkAUwAAAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB4AGUA
bgBuAGUAdAAuAHMAeQBzAAAAAAAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAYwByAGEAcwBoAGQAbQBwAC4AcwB5AHMA
AAAuAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARAByAGkA
dgBlAHIAcwBcAGQAdQBtAHAAXwBkAGkAcwBrAGQAdQBtAHAALgBzAHkAcwAAAAAAAAAAACwA
AABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUA
cgBzAFwAZAB1AG0AcABfAHgAZQBuAHYAYgBkAC4AcwB5AHMAAAAAAC0AAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0A
cABfAHgAZQBuAGMAcgBzAGgALgBzAHkAcwAAAC0AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQA
XABTAHkAcwB0AGUAbQAzADIAXABEAHIAaQB2AGUAcgBzAFwAZAB1AG0AcABfAGQAdQBtAHAA
ZgB2AGUALgBzAHkAcwAAAB8AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXAB3AGkAbgAzADIAawAuAHMAeQBzAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIA
bwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwARAB4AGEAcABpAC4A
cwB5AHMAAAAAAAAAAAAkAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0A
MwAyAFwAZAByAGkAdgBlAHIAcwBcAGQAeABnAC4AcwB5AHMAAAAAAB4AAABcAFMAeQBzAHQA
ZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABUAFMARABEAEQALgBkAGwAbAAAAAAA
AAAAAB4AAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIAXABxAHgA
bABkAGQALgBkAGwAbAAAAAAAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbAB1AGEAZgB2AC4AcwB5AHMAAAAAAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAGwAbAB0AGQAaQBvAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAByAHMAcABuAGQA
cgAuAHMAeQBzAAAAAAAAACUAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABkAHIAaQB2AGUAcgBzAFwASABUAFQAUAAuAHMAeQBzAAAAJwAAAFwAUwB5AHMA
dABlAG0AUgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABiAG8A
dwBzAGUAcgAuAHMAeQBzAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAbQBwAHMAZAByAHYALgBzAHkAcwAAAAAA
AAAnAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwARABSAEkA
VgBFAFIAUwBcAG0AcgB4AHMAbQBiAC4AcwB5AHMAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABtAHIAeABzAG0A
YgAxADAALgBzAHkAcwAAACkAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABzAHkAcwB0AGUA
bQAzADIAXABEAFIASQBWAEUAUgBTAFwAbQByAHgAcwBtAGIAMgAwAC4AcwB5AHMAAAAnAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHAAZQBhAHUAdABoAC4AcwB5AHMAAAAAAAAAJwAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAEQAcgBpAHYAZQByAHMAXABzAGUAYwBkAHIAdgAuAFMA
WQBTAAAAAAAAACcAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUAbQAzADIA
XABEAFIASQBWAEUAUgBTAFwAcwByAHYAbgBlAHQALgBzAHkAcwAAAAAAAAApAAAAXABTAHkA
cwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIAcwBcAHQA
YwBwAGkAcAByAGUAZwAuAHMAeQBzAAAAJQAAAFwAUwB5AHMAdABlAG0AUgBvAG8AdABcAFMA
eQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABzAHIAdgAyAC4AcwB5AHMAAAAkAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAUwB5AHMAdABlAG0AMwAyAFwARABSAEkAVgBFAFIA
UwBcAHMAcgB2AC4AcwB5AHMAAAAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkA
cwB0AGUAbQAzADIAXABkAHIAaQB2AGUAcgBzAFwAcgBkAHAAZAByAC4AcwB5AHMAAAAAAAAA
AAAmAAAAXABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkA
dgBlAHIAcwBcAHQAZAB0AGMAcAAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0A
UgBvAG8AdABcAFMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXAB0AHMAcwBlAGMA
cwByAHYALgBzAHkAcwAAACYAAABcAFMAeQBzAHQAZQBtAFIAbwBvAHQAXABTAHkAcwB0AGUA
bQAzADIAXABEAHIAaQB2AGUAcgBzAFwAUgBEAFAAVwBEAC4AUwBZAFMAAAAAAAAAAAAmAAAA
XABTAHkAcwB0AGUAbQBSAG8AbwB0AFwAcwB5AHMAdABlAG0AMwAyAFwAZAByAGkAdgBlAHIA
cwBcAHMAcABzAHkAcwAuAHMAeQBzAAAAAAAAAAAAKQAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAHMAeQBzAHQAZQBtADMAMgBcAEQAUgBJAFYARQBSAFMAXABhAHMAeQBuAGMAbQBhAGMA
LgBzAHkAcwAAAOCcyQIA+P//cAgBAJwAAABIG8gCAPj//wwJAQAEAAAARBvIAgD4//8QCQEA
BAAAAKCrwAIA+P//FAkBAAABAAAABs0CAPj//xQKAQAEAAAAAALNAgD4//8YCgEAUAAAAHww
0AIA+P//aAoBAAQAAABoMNACAPj//2wKAQAEAAAAWOIcAoD6//9wCgEAACAAAIDSxgIA+P//
cCoBAAgAAACI0sYCAPj//3gqAQAIAAAAALDBAgD4//+AKgEAABAAAABgpQIA+P//gDoBAAAQ
AAAAgOYCgPj//4BKAQAAEAAAALCsAgD4//+AWgEAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANzYwMS4xODUyNi5hbWQ2NGZy
ZS53aW43c3AxX2dkci4xNDA3MDYtMTUwNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhMDVlNTg1NC1h
MDAxLTRjMjItODg1MS1kZDc4NWUxMAUAAAB8MNACAPj//4Aw0AIA+P//aDDQAgD4//9sMNAC
APj//1jiHAKA+v//WAIdAoD6//+A0sYCAPj//4jSxgIA+P//iNLGAgD4//+Q0sYCAPj//0cA
AAAAAAAAaAAAAAgEAACEBgAAtAkAANwIAAAgBwAAuAIAAGgJAAAkAAAAhAgAADwAAAA8BQAA
VAUAAEgFAABICwAACAAAAAgHCAgICA0EDQgMCAgICAADAAAAgF4AAOAGLwQAAABcAACQDa8G
AAAAXAAAhBFXBgAAAFwAACgRawQAAABcAAC8DecEAAAAXAAAIAtTBgAAAFwAAEAQfwYAAABc
AAB8DxsEAAAAXAAAwY8BAAaAmwFx7QMABoAAAd2YAwAGAP8AdfEDAAaA+wBppgMABgD9AE32
AwAGAP0AoXoCAAqeQhOAcwqeySYYwwYAWgFl7AMABgADAX1PAQBOjCkETA5SIq8IZHxSorsC
gDBSoi4GHCBSHlADnB5WHnke1cMQABqaXgFhejsAHogmCKnGZAEaGokBmYWgARqabAH9kKAB
Ih5YARqaBwImm0cErV4BACoAPx2plHQALgzwA0QdMh7cAMWidgA2CNoAoYGyABqacAE5hKAB
GhpsAcGHoAEammsBJhvMBM1JOwAamggBfQhlARoaaAFph6ABGhoMAu0GZQG6GpEC9WU7ABqa
DgEmG9gDtKd+EBcCRBMGgMwBhNsAAAIAAsDyAAoDvAgAALgIAACtynJhAQAAAAAAAAAAAAAA
AABAAAAAAAAAkBwAAAAAALgIAACPlhsAmHQbUgAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA
AABcAEQAZQB2AGkAYwBlAFwASABhAHIAZABkAGkAcwBrAFYAbwBsAHUAbQBlADIAXABQAHIA
bwBnAHIAYQBtACAARgBpAGwAZQBzACAAKAB4ADgANgApAFwAUwBQAEkAQwBFACAARwB1AGUA
cwB0ACAAVABvAG8AbABzAFwANgA0AFwAdgBkAGEAZwBlAG4AdAAuAGUAeABlAAAAAsBQAAoB
AgACwJYACgO8CAAAuAgAAGPNcmEBAAAAAAAAAAAAAAAAAAN3AAAAAACQGgAAAAAAuAgAAF+H
GgAkrx5SAAAAAAAAA3cAAAAAAAAAAAAAAAAAAAAAAAAAAFwAUwB5AHMAdABlAG0AUgBvAG8A
dABcAFMAeQBzAHQAZQBtADMAMgBcAG4AdABkAGwAbAAuAGQAbABsAAAAAAACABHAmgAgBIzm
cmEBAAAAQPH5AqD4//9cAEQAZQB2AGkAYwBlAFwASABhAHIAZABkAGkAcwBrAFYAbwBsAHUA
bQBlADIAXABXAGkAbgBkAG8AdwBzAFwAUAByAGUAZgBlAHQAYwBoAFwAVgBEAEEARwBFAE4A
VAAuAEUAWABFAC0ARQA0AEQAQgAwAEEANABEAC4AcABmAAAAAAAAAAAAAgARwJIAIASVhIJh
AQAAAECh+AKg+P//XABEAGUAdgBpAGMAZQBcAEgAYQByAGQAZABpAHMAawBWAG8AbAB1AG0A
ZQAyAFwAVwBpAG4AZABvAHcAcwBcAFMAeQBzAHQAZQBtADMAMgBcAGkAdAAtAEkAVABcAHQA
egByAGUAcwAuAGQAbABsAC4AbQB1AGkAAABTAoD6//8CAALAlgAKA7wIAAC4CAAAxCmEYQEA
AAAAAAAAAAAAAAAA8XYAAAAAAPARAAAAAAC4CAAAxAcSAFmgFVMAAAAAAADxdgAAAAAAAAAA
AAAAAAAAAAAAAAAAXABXAGkAbgBkAG8AdwBzAFwAUwB5AHMAdABlAG0AMwAyAFwAawBlAHIA
bgBlAGwAMwAyAC4AZABsAGwAAAAAAAIAAsCaAAoDvAgAALgIAAC+QIRhAQAAAAAAAAAAAAAA
AADh/P4HAAAAwAYAAAAAALgIAAAw1AYAWqAVUwAAAAAAAOH8/gcAAAAAAAAAAAAAAAAAAAAA
AABcAFcAaQBuAGQAbwB3AHMAXABTAHkAcwB0AGUAbQAzADIAXABLAGUAcgBuAGUAbABCAGEA
cwBlAC4AZABsAGwAAAAAAAAAAAACAALAkAAKA7wIAAC4CAAAGmaGYQEAAAAAAAAAAAAAAAAA
Kf/+BwAAAOACAAAAAAC4CAAADVUDAEDfW0oAAAAAAAAp//4HAAAAAAAAAAAAAAAAAAAAAAAA
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
AAABAQEAAQIAAAEBAQABAgAAAQEBAAECAAABAQEAAQIAAAEBAQABAgAAAQEBAAECAAABGQIA
GVIVAgEHAgAHAacAAQQBAARCAAAZBAEABEIAAHDsAQAAAAAAAAAAAAEEAQAEQgAAGQQBAARC
AADAPwIAAAAAAAAAAAABBAEABEIAABkEAQAEQgAA8EUIAAAAAAAAAAAAAQQBAARCAAAZBAEA
BEIAAEBRAgAAAAAAAAAAAAEEAQAEQgAAGQQBAARCAABg/AcAAAAAAAAAAAABBAEABEIAABkE
AQAEQgAAMBkMAAAAAAAAAAAAAQQBAARCAAAZBAEABEIAALDeAAAAAAAAAAAAAAEEAQAEQgAA
GQQBAARCAADwGQwAAAAAAAAAAAABBAEABEIAABkEAQAEQgAAsBoMAAAAAAAAAAAAAQQBAARC
AAAZBAEABEIAAHAbDAAAAAAAAAAAAAEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsABVAEAgAK
ARQGhRRTDAErAAVQBAIACgFfJABf9CYAW+QlAFfUJABTxCMAT2QiAEt0IQBHNCAARPgMAD/o
CwA62AoANcgJADC4CAArqAcAJZgGAB+IBQAZeAQAFGgDAAcBJwABFAaFFFMMASsABVAEAgAK
ARQGhRRTDAErAAVQBAIACgEUBoUUUwwBKwAFUAQCAAoBFAaFFFMMASsABVAEAgAKARQGhRRT
DAErAAVQBAIACgEQBYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKARAFhRBTCAErAAFQ
ABoAAAEQBYUQUwgBKwABUAAaAAABEAWFEFMIASsAAVAAGgAAARAFhRBTCAErAAFQABoAAAEQ
BYUQUwgBKwABUAAaAAABFAaFFFMMASsABVAEAgAKARAFhRBTCAErAAFQABoAAAEUBoUUUwwB
KwAFUAQCAAoBXyQAX/QmAFvkJQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXI
CQAwuAgAK6gHACWYBgAfiAUAGXgEABRoAwAHAScAARQGhRRTDAErAAVQBAIACgEZBoUZUxEB
KwAKUAkCBQoBGAaFGFMQASsACVAIAgQKATsGhTtTMwErACxQKwInCgEEAQAEYgAAASkMhSlk
KgAidCkAGzQoABRTDAErAAVQBAIAChlQDIVQZCoASXQpAEI0KAA7UzMBKwAsUCsCJwpASgcA
AAAAAAAAAAABXyQAX/QmAFvkJQBX1CQAU8QjAE9kIgBLdCEARzQgAET4DAA/6AsAOtgKADXI
CQAwuAgAK6gHACWYBgAfiAUAGXgEABRoAwAHAScAAV8kAF/0JgBb5CUAV9QkAFPEIwBPZCIA
S3QhAEc0IABE+AwAP+gLADrYCgA1yAkAMLgIACuoBwAlmAYAH4gFABl4BAAUaAMABwE7AAEE
AQAEQgAAAZ8kAJ80LgCXZDAAj3QvAIf0NAB/5DMAd9QyAG/EMQBn+BMAXugSAFXYEQBMyBAA
Q7gPADqoDgAxmA0AKIgMAB94CwAXaAoADwE1AAEEAQAEQgAAAX8eAH/0NAB35DMAb9QyAGfE
MQBf+BMAVugSAE3YEQBEyBAAO7gPADKoDgApmA0AIIgMABd4CwAPaAoABwE1AAEEAQAEQgAA
AQQBAATCAAABlyQAlzQuAI9kMACHdC8Af/Q0AHfkMwBv1DIAZ8QxAF/4EwBW6BIATdgRAETI
EAA7uA8AMqgOACmYDQAgiAwAF3gLAA9oCgAHATUAAQYDAAZCAlABMAAAAQUCAAUyAVABBgMA
BmICUAEwAAABBQIABVIBUAEHBAAHMgNgAlABMAEHBAAHMgNwAmABUAEFAgAFkgFQAQYDAAaC
AlABMAAAAQkFAAliBdADcAJQATAAAAEFAgAFcgFQAQgEAAhSBOACUAEwAQcDAAdiA9ABUAAA
AQcEAAcyA3ACUAEwAQcDAAdCA+ABUAAAAQgEAAhyBNACcAFQAQcDAAeCA/ABUAAAAQkEAAmS
BeADwAFQAQ4IAA5SCuAI0AbABHADYAJQATABEAkAEIIM8ArgCNAGwARwA2ACUAEwAAABBwQA
B1IDcAJQATABCAUACGIEcANgAlABMAAAIQAEAAB0AAAAZAMAoKMEAKSjBAAw2BsAIQAAAKBh
CwDwYQsAWMkbACEAAACclwQA5JcEAODSGwAhAAAALN0BAN/dAQC81BsAIQAAALzTCQAw1AkA
WMkbACEAAACA0gkATNMJACTJGwAhAAAAJFMEAAhUBADg0hsAIQAAAPRFAAApRgAATDscACEA
AADk5QQAxOYEAOwqHAAhAAAA/DEBAOwzAQAwPhwAIQAAAKRBAAAYQwAA6B8cACEAAABAPwQA
kD8EACDKGwAhAAAAAIkBAKCKAQDsKhwAIQAAAOCvAQB0sAEAfMkbACEACAAA9AMAAHQEAABU
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
UwAACgEAAApKAAAAAAAAAAAAAAAAAEAAAEBQQUdFREFUQQDdAAAAEFQAAEwAAAAUSwAAAAAA
AAAAAAAAAABAAADAUEFHRVZSRkMeKQAAAPBUAAAqAAAAYEsAAAAAAAAAAAAAAAAAQAAAQFBB
R0VWUkZEUBIAAAAgVQAAFAAAAIpLAAAAAAAAAAAAAAAAAEAAAMBJTklUAAAAAFx2BQAAQFUA
AHgFAACeSwAAAAAAAAAAAAAAAAAgAADiLnJzcmMAAAA8XwMAAMBaAABgAwAAFlEAAAAAAAAA
AAAAAAAAQAAAQC5yZWxvYwAAdCAAAAAgXgAAIgAAAHZUAAAAAAAAAAAAAAAAAEAAAEIAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAABwOKwCAPj//2Yv/ACA+P//
AGD5AID4///4lPoAgPj//wDw+gCA+P//TP78AID4//8AYKUCAPj//4CjzQIA+P//AGClAgD4
//8ghc0CAPj//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABO5AKA+P//
0IjmAoD4//8fABAAAAAAAGCC5gKA+P//AAAAAAAAAACwiuYCgPj//2CH5gKA+P//CIrmAoD4
///BZLACAPj//wiK5gKA+P//YILmAoD4//8AAAAAgPj//wAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI/IqwIA+P//AAAAAAAAAAAAAAAAAAAAAB8A
EACAHwAAEAArACsAUwArABgAhgAAABHy+QCA+P//aPJ2A4D6//+4EncDgPr//w8AAAAAAAAA
AIBvAYD6///QgG8BgPr//wAAAAAAAAAAoAMAAAAAAAAAAAAAAAAAAAIAAAAAAAAAQIzmAoD4
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
QI3mAoD4//8AAAAAAAAAAAAw5gKA+P//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAfAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+8OD/yB1W4lFgEiJTYhIiVWQ
TIlFmEyJTaDokYT//wvAi0WASItNiEiLVZBMi0WYTItNoEiJo9gBAAAPhLH8//9IjT1YiSMA
i3cQSIs/O8ZzEEiNPLcPvgQ4C8APjvn9//+4HAAAwOnv/f//uUoAAABFM8lFDyDARQvAdRS5
AQAAAEUPtoPwAQAARYuLxAEAAEiLlegAAABMi9XoYAAAAEiD7FBIiUwkIEiJVCQoTIlEJDBM
iUwkOEyJVCRASYvK6GvIDgBIi0wkIEiLVCQoTItEJDBMi0wkOEyLVCRASIPEUEH/0kiJRbBI
i8jo38cOAEiLRbDpWf3//2YPH0QAAEiB7DgBAABIjYQkAAEAAA8pdCQwDyl8JEBEDylEJFBE
DylMJGBEDylUJHBEDylYgEQPKWCQRA8paKBEDylwsEQPKXjASIkYSIl4CEiJcBBMiWAYTIlo
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
QYmAgAAAAEGJkIQAAACLDVp1IwAPMkGJgJgAAABBiZCcAAAAiw1AdSMADzJBiYCQAAAAQYmQ
lAAAALnZAQAADzKD4PwPMMIAAMzMzMzMzA8fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVFJHRER1bXBCbG9iEAAAALEdAPAgAAAAjwBcvDoe
10SYjYb2iExnWGEBAAAAAAAABwAAAAACBCRZAQAAABgAAAECAOgDAIAACAAAAAAAAAQEBf//
WGVuADQuNS4wLXJjADExLzE5LzIwMTQAAAEbAAEBAgMEAAAAAAAAAAAAAAAAAAAAAAYAAFhl
bgBIVk0gZG9tVQA0LjUuMC1yYwAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAAAAMNAAMBAQAAAAMDAwJYZW4AAAQaAQQBAwEC5QYBAP/7iRcAAAAAZApkCkEBQ1BVIDEA
SW50ZWwAAAQaAgQBAwEC5QYBAP/7iRcAAAAAZApkCkEBQ1BVIDIASW50ZWwAAAsFAAsBWGVu
AAAQDwAQAQMGAAAeAP7/AQAAABEVABEAEAAAQABAAIAHCQABAAcAAERJTU0gMAAAEw8AEwAA
AAD//x0AABABAAAUEwAUAAAAAP//HQAAEQATAQAAAAAgCwAgAAAAAAAAAAAAfwQAfwAAAAAA
AAAAACAAAACJw3psE0PcR580qIAKD7VsbgIAAAAAAAACAAAACgAAAH4ATQBIAHoAAAAEAAAA
BAAAAGQKAAAsAAAAQwBvAG0AcABvAG4AZQBuAHQAIABJAG4AZgBvAHIAbQBhAHQAaQBvAG4A
AAADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAmAAAAQwBvAG4AZgBpAGcAdQByAGEAdABpAG8A
bgAgAEQAYQB0AGEAAAAJAAAAEAAAAP//////////AAAAAAAAAAAWAAAASQBkAGUAbgB0AGkA
ZgBpAGUAcgAAAAEAAABKAAAASQBuAHQAZQBsADYANAAgAEYAYQBtAGkAbAB5ACAANgAgAE0A
bwBkAGUAbAAgADMAMAAgAFMAdABlAHAAcABpAG4AZwAgADUAAAAoAAAAUAByAG8AYwBlAHMA
cwBvAHIATgBhAG0AZQBTAHQAcgBpAG4AZwAAAAEAAABgAAAASQBuAHQAZQBsACgAUgApACAA
WABlAG8AbgAoAFIAKQAgAEMAUABVACAAIAAgACAAIAAgACAAIAAgACAAIABYADMANAA1ADAA
IAAgAEAAIAAyAC4ANgA3AEcASAB6AAAAIgAAAFUAcABkAGEAdABlACAAUwBpAGcAbgBhAHQA
dQByAGUAAAADAAAACAAAAAAAAAAHAAAAHAAAAFUAcABkAGEAdABlACAAUwB0AGEAdAB1AHMA
AAAEAAAABAAAAAcAAAAiAAAAVgBlAG4AZABvAHIASQBkAGUAbgB0AGkAZgBpAGUAcgAAAAEA
AAAaAAAARwBlAG4AdQBpAG4AZQBJAG4AdABlAGwAAAAMAAAATQBTAFIAOABCAAAACwAAAAgA
AAAAAAAABwAAAAAAIAAAAG/APdCO2MVEuir64DUXLRmYAwAAAAAAAAAAAAAAAAAAAAAAAAsA
AABHZW51bnRlbGluZUkLAAAAR2VudW50ZWxpbmVJAAAAAAEAAADlBgEAAAggAgEiuIH/+4sX
5QYBAAAIIAIBIriB//uLFwAAAAACAAAAAVoDVeSy8AAAAAAALCHKCQFaA1XksvAAAAAAACwh
ygkAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAdEAAAAAAAAAAAAAAAAAAAH
RAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAEA
AAAXAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAABAAAAiwAAAAAAAAAHAAAA
AAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAQAAAIAAAMABDQAAAAAAAAAAAAAAAAAAAQ0AAAAA
AAAAAAAAAAAAAAAAAAAAAACACAAAgAAAAAAAAAAAAAAAAAgAAIAAAAAAAAAAAAAAAAAAAAAA
AQAAgAAAAAAAAAAAAQAAAAAIECgAAAAAAAAAAAEAAAAACBAoAAAAAAIAAIBJbnRlbChSKSBY
ZW9uKFIpSW50ZWwoUikgWGVvbihSKQAAAAADAACAIENQVSAgICAgICAgICAgWCBDUFUgICAg
ICAgICAgIFgAAAAABAAAgDM0NTAgIEAgMi42N0dIegAzNDUwICBAIDIuNjdHSHoAAAAAAAUA
AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAACAAAAAAAAAAABAYAAB
AAAAAAAAAAAAAAAAQGAAAQAAAAAAAAAABwAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAgAAIAkMAAAAAAAAAAAAAAAAAAAJDAAAAAAAAAAAAAAAAAAACAAAADSQDvo
oLBCSKvqccnjRj3RQAAAAAAAAAAAAAAAQVBJQ2AEAAACsFhlbgAAAEZBQ1D0AAAABEBYZW4A
AABXQUVUKAAAAAFWWGVuAAAASFBFVDgAAAAB0lhlbgAAACAAAACISMhU0QEeTL7WKCyYJBMD
ABAAAAAAAAAAAAAAnUxNVCyU1Ua/UN9c2VJKUEjwxAKA+v//uA8AAOgIrAgyAAAAY2Ryb20A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATFIcAAEAAAAAAAoAZh/S0VbuKDl3P2A3
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
TFI8ACwAAAAIBw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAAFAU1AKA
+v//AAAATFI8AC0AAABEBw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAA
APBlJAOA+v//AAAATFI8AC4AAACABw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6
//8HBAAAAOAQVQOA+v//AAAATFI8AC8AAAC8Bw8Ad/p5j+/a3gVZfKRoubDwn9jfNP1/BQAA
cCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADAAAAD4Bw8Ad/p5j+/a3gVZfKRoubDwn9jf
NP1/BQAAcCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADEAAAA0CA8Ad/p5j+/a3gVZfKRo
ubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAAOAQVQOA+v//AAAATFI8ADIAAABwCA8Ad/p5j+/a
3gVZfKRoubDwn9jfNP1/BQAAcCzLAoD6//8HBAAAABAAmwOA+v//AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACAAAABMSn74ocUvTb/w1d5jpeTDMAIAAAAAAAAAAAAAAAAAAAAAAAABAAAACwAAAAAA
AABXZGYwMTAwMAAAAAAAAAAA/0TKFXpNqku7pQmYlV5THgQAABBQ2k8CgPr//wEAAAAJAAAA
sB0AAG1zaXNhZHJ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgBcAED+dgGA+v//AQAAAAkA
AACwHQAAdmRydnJvb3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIMzgAsOhyAoD6//8BAAAA
BQAAAHAXAABzdG9yZmx0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAQwMQCgPr//wEA
AAAJAAAAsB0AAGNkcm9tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAECuzAKA+v//
AQAAAAkAAACwHQAAVmlydGlvU2VyaWFsAAAAAAAAAAAAAAAAAAAAAAAAAAANAAAA8OrKAoD6
//8BAAAACQAAALAdAABpbnRlbHBwbQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAErWAABAfsoC
gPr//wEAAAAJAAAAsB0AAENvbXBvc2l0ZUJ1cwAAAAAAAAAAAAAAAAAAAAAAAAAASzM4AGB2
3AKA+v//AQAAAAkAAACwHQAAdW1idXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA
8MhgA4D6//8BAAAABwAAAHEXAABQRUFVVEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA
AAA=
--------------080009070007070309030302
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Thu Nov 20 14:38:46 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 14:38:46 +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 1XrSsg-0000a9-LA; Thu, 20 Nov 2014 14:38:46 +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 1XrSsf-0000Zy-2F
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 14:38:45 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	7D/78-28296-4FCFD645; Thu, 20 Nov 2014 14:38:44 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1416494323!12715737!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31743 invoked from network); 20 Nov 2014 14:38:43 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 14:38:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,424,1413244800"; d="scan'208";a="27002284"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Fabio Fantoni <fabio.fantoni@m2r.biz>
Thread-Topic: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ///y4ICAAanfAIAAE64ggAALr4CACNgwAIAAaEgQ
Date: Thu, 20 Nov 2014 14:38:41 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02574FF93@AMSPEX01CL02.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz>	<5466279C.207@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
	<CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
	<546DAD42.1080808@m2r.biz>
In-Reply-To: <546DAD42.1080808@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: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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

RnJvbTogRmFiaW8gRmFudG9uaSBbbWFpbHRvOmZhYmlvLmZhbnRvbmlAbTJyLmJpel0gDQpTZW50
OiAyMCBOb3ZlbWJlciAyMDE0IDA4OjU5DQpUbzogUGF1bCBEdXJyYW50DQpDYzogd2luLXB2LWRl
dmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQpTdWJqZWN0OiBSZTogV2luZG93cyA3IDY0IGJpdCBi
bHVlIHNjcmVlbiB3aXRoIHN0b3AgMWUgYWZ0ZXIgcmVzdG9yZSB3aXRoIG5ldyBidWlsZCBvZiB3
aW4gcHYgZHJpdmVycw0KDQpJbCAxNC8xMS8yMDE0IDE4OjU0LCBGYWJpbyBGYW50b25pIGhhIHNj
cml0dG86DQoyMDE0LTExLTE0IDE3OjE1IEdNVCswMTowMCBQYXVsIER1cnJhbnQgPFBhdWwuRHVy
cmFudEBjaXRyaXguY29tPjoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTog
RmFiaW8gRmFudG9uaSBbbWFpbHRvOmZhYmlvLmZhbnRvbmlAbTJyLmJpel0NCj4gU2VudDogMTQg
Tm92ZW1iZXIgMjAxNCAxNjowMw0KPiBUbzogUGF1bCBEdXJyYW50OyB3aW4tcHYtZGV2ZWxAbGlz
dHMueGVucHJvamVjdC5vcmcNCj4gU3ViamVjdDogUmU6IFdpbmRvd3MgNyA2NCBiaXQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlIGFmdGVyIHJlc3RvcmUgd2l0aA0KPiBuZXcgYnVpbGQgb2Ygd2lu
IHB2IGRyaXZlcnMNCj4NCj4gSWwgMTMvMTEvMjAxNCAxNTozOCwgRmFiaW8gRmFudG9uaSBoYSBz
Y3JpdHRvOg0KPiA+IElsIDEzLzExLzIwMTQgMTU6MjYsIFBhdWwgRHVycmFudCBoYSBzY3JpdHRv
Og0KPiA+Pj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPj4+IEZyb206IEZhYmlvIEZh
bnRvbmkgW21haWx0bzpmYWJpby5mYW50b25pQG0yci5iaXpdDQo+ID4+PiBTZW50OiAxMyBOb3Zl
bWJlciAyMDE0IDE0OjIwDQo+ID4+PiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qu
b3JnOyBQYXVsIER1cnJhbnQNCj4gPj4+IFN1YmplY3Q6IFdpbmRvd3MgNyA2NCBiaXQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlIGFmdGVyIHJlc3RvcmUNCj4gPj4+IHdpdGggbmV3DQo+ID4+PiBi
dWlsZCBvZiB3aW4gcHYgZHJpdmVycw0KPiA+Pj4NCj4gPj4+IEkgZGlkIGEgbmV3IGJ1aWxkIG9m
IHdpbnB2IGRyaXZlcnMgYW5kIHRlc3RlZCBvbiBvbmUgd2luZG93cyA3IDY0IGJpdA0KPiA+Pj4g
ZG9tVSwgZG9tMCB4ZW4tdW5zdGFibGUgd2l0aCAieDg2L2h2bTogRXh0ZW5kIEhWTSBjcHVpZCBs
ZWFmIHdpdGgNCj4gdmNwdQ0KPiA+Pj4gaWQiIGFuZCAieDg2L2h2bTogQWRkIHBlci12Y3B1IGV2
dGNobiB1cGNhbGxzIiBwYXRjaGVzLCBhbmQgcWVtdSAyLjINCj4gPj4+IGZyb20gc3BpY2UgZ2l0
Og0KPiA+Pj4gaHR0cHM6Ly9naXRodWIuY29tL0ZhbnR1L1hlbi9jb21taXRzL3JlYmFzZS9tMnIt
c3RhZ2luZw0KPiA+Pj4NCj4gPj4+IEFmdGVyIHJlc3RvcmUgd2luZG93cyBzaG93ZWQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlLCBJIG9wZW4gdGhlDQo+IGR1bXANCj4gPj4+IHdpdGggIkJsdWVT
Y3JlZW5WaWV3IiBhbmQgc2hvd2VkIHRoYXQgY2F1c2UgaXMgeGVubmV0IGRyaXZlci4NCj4gPj4+
IEkgYXR0YWNoZWQgdGhlIGR1bXAsIGlmIHlvdSBuZWVkIG1vcmUgaW5mb3JtYXRpb25zL3Rlc3Rz
IHRlbGwgbWUgYW5kDQo+ID4+PiBJJ2xsIHBvc3QgdGhlbS4NCj4gPj4+DQo+ID4+IEkndmUgYmVl
biB0ZXN0aW5nIHdpdGggd2luNyAzMi1iaXQgYW5kIHNlZW4gbm8gcHJvYmxlbXMuIFRoZSBtaW5p
ZHVtcA0KPiA+PiBkb2Vzbid0IHRlbGwgbWUgbXVjaCB1bmZvcnR1bmF0ZWx5IGRvIHlvdSBoYXZl
IGEgZnVsbCBkdW1wLCBwbHVzIHRoZQ0KPiA+PiBRRU1VIGxvZz8NCj4gPj4NCj4gPj7CoCDCoCBQ
YXVsDQo+ID4NCj4gPiBUaGFua3MgZm9yIHJlcGx5Lg0KPiA+IHFlbXUgbG9nIHdhcyB3aXRob3V0
IGVycm9ycyBvciB3YXJuaW5nIHJlbGF0ZWQsIEkgY2hhbmdlZCB3aW5kb3dzDQo+ID4gb3B0aW9u
IGZvciBmdWxsIG1lbW9yeSBkdW1wIGFuZCBlbmFibGUgcWVtdSB0cmFjZSBvZiB4ZW4gYW5kIHJl
dHJpZWQNCj4gPiB0byByZXByb2R1Y2UgdGhlIHByb2JsZW0gYnV0IHRoaXMgdGltZSBhZnRlciBy
ZXN0b3JlIG9uIHNhbWUgZG9tVSBub3QNCj4gPiBoYWQgdGhlIGJsdWUgc2NyZWVuLg0KPg0KPiBC
bHVlIHNjcmVlbiByZS1oYXBwZW4sIGluIGF0dGFjaG1lbnQgcWVtdSBsb2dzIChiZWZvcmUgYW5k
IGFmdGVyDQo+IHJlc3RvcmUpIHdpdGggeGVuIHRyYWNlLg0KPiBBbHNvIG1lbW9yeS5kbXAgZnVs
bCB0aGlzIHRpbWUgYnV0IHRoZXJlIGlzIGEgcHJvYmxlbSwgaXMgMSw4NyBnYiBhbmQgbXkNCj4g
Y29ubmVjdGlvbiBpcyBtYXggMjU2a2JwcyBvZiB1cGxvYWQgOigNCj4gSWYgaXMgcmVhbGx5IG5l
ZWRlZCB0ZWxsIG1lIGFuZCBJJ2xsIHRyeSB0byBsb2FkIGl0IGluIG15IHdlYnNlcnZlcg0KPiB0
b21vcnJvdy4NCj4NCkknbGwgdHJ5IHRvIHJlcHJvLiBZb3UncmUgY3Jhc2ggaGFwcGVuZWQgdmVy
eSBlYXJseSBpbiByZXN1bWUuIElzIHlvdXIgeGVuYnVzIGRyaXZlciB0aGUgYnVpbHQgZnJvbSB0
aXA/DQoNClllcyBJIHVwZGF0ZWQgYWxsIHRvIGxhdGVzdCBnaXQgaW4gaHR0cDovL3hlbmJpdHMu
eGVuLm9yZy9naXR3ZWIvP289YWdlLCBhbGwgZXhjZXB0IHhlbmlmYWNlIHdhcyB1cGRhdGVkIGlm
IEkgcmVtZW1iZXIgZ29vZC4NCldhcyBoYXBwZW4gMiB0aW1lIG9uIHRvdGFsIG9mIDUgc2F2ZS9y
ZXN0b3JlIEkgdHJpZWQuDQpMYXRlc3QgdGVzdCB3YXMgd2l0aCBxZW11IHVwc3RyZWFtIHVwZGF0
ZWQgaW5jbHVkaW5nIGFsc28gdGhlIG5ldyAyIHhlbiBidWdmaXggaHR0cDovL3NlY3VyZS13ZWIu
Y2lzY28uY29tLzFpTkRGc2p3RjdYUEVfejBVby1VYjRyLS12aDRWaG1sQ3kxM3FKeTVTTEVWOUNW
dFRyVWt6b0RlTWtOQUxPOU56dlg4a1NiVExJZzgxdmIzaWxsLUI1RVZTQWlLYjZTMmNFWGJqa2I2
ZlJLTE9RUXhUX1pxVFkwRUpOSG1JaENScFpadzlQQ1d1b1FseHdzMFNBVldmM2lSSmNYbmZ0RFot
NExOaHN2RVkwMlUvaHR0cCUzQSUyRiUyRmdpdC5xZW11Lm9yZyUyRnFlbXUuZ2l0IChjb21taXQg
NGU3MGY5MjcxZGFiYzU4ZmJmMTQ2ODA4NDNiZmFjNTEwYzE5MzE1MikuDQoNCkkgaGF2ZSB1cGRh
dGVkIHhlbiB0byBsYXRlc3Qgc3RhZ2luZyBhbmQgcWVtdSB0byB0YWcgdjIuMi4wLXJjMiBhbmQg
dGhlIGNyYXNoIHN0aWxsIGhhcHBlbiwgaW4gYXR0YWNobWVudCBtaW5pZHVtcCBvZiBsYXRlc3Qg
Y3Jhc2ggYW5kIGJlbG93IHRoZSBsaW5rIG9mIGZ1bGwgbWVtb3J5IGR1bXAsIGhvcGUgdGhhdCB0
aGVzZSB3aWxsIGhlbHAgeW91IHRvIGZvdW5kIGFuZCBzb2x2ZXMgdGhlIHByb2JsZW06DQpodHRw
Oi8vZmFudHUuaW5mby94ZW4vTUVNT1JZLkRNUA0KDQotLS0tLS0NCg0KVGhhbmtzIGZvciB0aGUg
ZnVsbCBkdW1wLiBUaGUgY3Jhc2ggaXMgdmVyeSBvZGQuIFRoZSBzdGFjayBJIHNlZSBpczoNCg0K
MToga2Q+IGtiDQpSZXRBZGRyICAgICAgICAgICA6IEFyZ3MgdG8gQ2hpbGQgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogQ2FsbCBTaXRl
DQpmZmZmZjgwMGAwMmFjMzViZSA6IDAwMDAwMDAwYDAwMDAwMDAwIDAwMDAwMDAwYDAwMDAwMDAw
IGZmZmZmODgwYDAyZTY4MjYwIGZmZmZmODAwYDAyYWY2YTkwIDogbnQhS2VCdWdDaGVjaw0KZmZm
ZmY4MDBgMDJhZjY3NWQgOiBmZmZmZjgwMGAwMmNkYTM4MCBmZmZmZjgwMGAwMmMxNzU4MCBmZmZm
ZjgwMGAwMmE1NjAwMCBmZmZmZjg4MGAwMmU2OGEwOCA6IG50IUtpS2VybmVsQ2FsbG91dEV4Y2Vw
dGlvbkhhbmRsZXIrMHhlDQpmZmZmZjgwMGAwMmFmNTUzNSA6IGZmZmZmODAwYDAyYzFiMzU4IGZm
ZmZmODgwYDAyZTY3Yjk4IGZmZmZmODgwYDAyZTY4YTA4IGZmZmZmODAwYDAyYTU2MDAwIDogbnQh
UnRscEV4ZWN1dGVIYW5kbGVyRm9yRXhjZXB0aW9uKzB4ZA0KZmZmZmY4MDBgMDJiMDY0YzEgOiBm
ZmZmZjg4MGAwMmU2OGEwOCBmZmZmZjg4MGAwMmU2ODI2MCBmZmZmZjg4MGAwMDAwMDAwMCAwMDAw
MDAwMGAwMDAwMDAwMCA6IG50IVJ0bERpc3BhdGNoRXhjZXB0aW9uKzB4NDE1DQpmZmZmZjgwMGAw
MmFjYjI0MiA6IGZmZmZmODgwYDAyZTY4YTA4IDAwMDAwMDAwYDAwMDAwMDAyIGZmZmZmODgwYDAy
ZTY4YWIwIDAwMDAwMDAwYDAwMDAwMDAwIDogbnQhS2lEaXNwYXRjaEV4Y2VwdGlvbisweDEzNQ0K
ZmZmZmY4MDBgMDJhYzkwNzQgOiAwMDAwMDAwMGAwMDAwMDAwMSAwMDAwMDAwMGAwMDAwMDAwMSBm
ZmZmZmE4MGAwMTZmNzcxMCBmZmZmZjg4MGAwMGZiNjliOSA6IG50IUtpRXhjZXB0aW9uRGlzcGF0
Y2grMHhjMg0KZmZmZmY4ODBgMDBmYTAzYTkgOiBmZmZmZjg4MGAwMGY5Nzk3OCAwMDAwMDAwMGAw
MDAwMDAwMiAwMDAwMDAwMGAwMDAwMDAwMCBmZmZmZjg4MGAwMGY5ZjIxMSA6IG50IUtpQnJlYWtw
b2ludFRyYXArMHhmNA0KZmZmZmY4ODBgMDBmOTc5NzggOiAwMDAwMDAwMGAwMDAwMDAwMiAwMDAw
MDAwMGAwMDAwMDAwMCBmZmZmZjg4MGAwMGY5ZjIxMSBmZmZmZmE4MGAwMTc5YzAxMCA6IHhlbiFI
eXBlcmNhbGxQb3B1bGF0ZSsweDEyNjkNCjAwMDAwMDAwYDAwMDAwMDAyIDogMDAwMDAwMDBgMDAw
MDAwMDAgZmZmZmY4ODBgMDBmOWYyMTEgZmZmZmZhODBgMDE3OWMwMTAgMDAwMDAwMDBgMDAwMDAw
MDEgOiB4ZW4rMHgxOTc4DQowMDAwMDAwMGAwMDAwMDAwMCA6IGZmZmZmODgwYDAwZjlmMjExIGZm
ZmZmYTgwYDAxNzljMDEwIDAwMDAwMDAwYDAwMDAwMDAxIDAwMDAwMDAwYDAwMDAwMDEwIDogMHgy
DQoNCkFuZCBpZiBJIGR1bXAgdGhlIGNvZGUgYXQgeGVuIUh5cGVyY2FsbFBvcHVsYXRlKzB4MTI2
OSwgSSBzZWUgMToga2Q+IHUgeGVuIUh5cGVyY2FsbFBvcHVsYXRlKzB4MTI2OQ0KeGVuIUh5cGVy
Y2FsbFBvcHVsYXRlKzB4MTI2OToNCmZmZmZmODgwYDAwZmEwM2E5IGNjICAgICAgICAgICAgICBp
bnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FhIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZm
ZmZmODgwYDAwZmEwM2FiIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEw
M2FjIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FkIGNjICAgICAg
ICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FlIGNjICAgICAgICAgICAgICBpbnQg
ICAgIDMNCmZmZmZmODgwYDAwZmEwM2FmIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZm
ODgwYDAwZmEwM2IwIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCg0KU28sIGV2ZW4gaWYgdGhl
IHN5bWJvbHMgYXJlIHdyb25nIHRoZW4gaXQgc3RpbGwgbWVhbnMgdGhlIGNvZGUgYXBwZWFycyB0
byBoYXZlIGp1bXBlZCBpbnRvIHRoZSBtaWRkbGUgb2YgYSBsb2FkIDB4Y2MgYnl0ZXMsIHdoaWNo
IGlzIHdoYXQgaHlwZXJjYWxsX3BhZ2VfaW5pdGlhbGlzZSBmaWxscyB0aGUgaHlwZXJjYWxsIHBh
Z2Ugd2l0aCBiZWZvcmUgY2FsbGluZyB0aGUgc3ZtL3ZteCBzcGVjaWZpYyBjb2RlIHRvIHNldCBp
dCB1cC4gQWxzbywgSSBub3RlIHRoYXQgdGhpcyBzdGFjayBpcyBvbiBDUFUgMSB3aGljaCBzaG91
bGQgYmUgc3R1Y2sgc3Bpbm5pbmcgd2l0aCBpbnRlcnJ1cHRzIGRpc2FibGVkIGF0IHRoaXMgc3Rh
Z2UuIFRoZSBwcm9ibGVtIGlzIHRoYXQgdGhlIGxvb3AgdGhlcmUgaXMgYWN0dWFsbHkgbWFraW5n
IHlpZWxkIGh5cGVyY2FsbHMgYW5kIGRvZXNuJ3QgdGFrZSBraW5kbHkgdG8gdGhlIGh5cGVyY2Fs
bCBwYWdlIGJlaW5nIHJlLXdyaXR0ZW4gdW5kZXIgaXRzIGZlZXQgOi0oIEknZCBtaXNzZWQgdGhl
IDB4Y2MgZmlsbCB3aGVuIEknZCBhZGRlZCB0aGUgY29kZSB0byByZS1wb3B1bGF0ZSB0aGUgaHlw
ZXJjYWxsIHBhZ2UgYW5kIHRodXMgYmVsaWV2ZWQgdGhlIGNvbnRlbnRzIHdvdWxkIHNpbXBseSBi
ZSByZS13cml0dGVuIHdpdGggdGhlIHNhbWUgYnl0ZXMgdGhhdCB3ZXJlIGFscmVhZHkgdGhlcmUs
IG1lYW5pbmcgdGhhdCB0aGVyZSdzIGJlIG5vIHByb2JsZW0gd2l0aCB0aGUgc3BpbiBjb2RlIGlu
IENQVSAxKy4gSSBzaG91bGQgaG9wZWZ1bGx5IGJlIGFibGUgdG8gZml4IHRoZSBwcm9ibGVtIGJ5
IHJlbW92aW5nIHRoZSB5aWVsZCBoeXBlcmNhbGxzIGFuZCByZXBsYWNpbmcgdGhlbSB3aXRoIG1t
X3BhdXNlIGludHJpbnNpY3MuDQoNCiAgUGF1bA0KX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1haWxpbmcgbGlzdAp3aW4tcHYtZGV2
ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3RzLnhlbnByb2plY3Qub3JnL2NnaS1i
aW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 20 14:38:46 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 14:38:46 +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 1XrSsg-0000a9-LA; Thu, 20 Nov 2014 14:38:46 +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 1XrSsf-0000Zy-2F
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 14:38:45 +0000
Received: from [85.158.137.68] by server-8.bemta-3.messagelabs.com id
	7D/78-28296-4FCFD645; Thu, 20 Nov 2014 14:38:44 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-2.tower-31.messagelabs.com!1416494323!12715737!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=1.7 required=7.0 tests=BIZ_TLD,received_headers: 
	No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 31743 invoked from network); 20 Nov 2014 14:38:43 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 14:38:43 -0000
X-IronPort-AV: E=Sophos;i="5.07,424,1413244800"; d="scan'208";a="27002284"
From: Paul Durrant <Paul.Durrant@citrix.com>
To: Fabio Fantoni <fabio.fantoni@m2r.biz>
Thread-Topic: Windows 7 64 bit blue screen with stop 1e after restore with
	new build of win pv drivers
Thread-Index: AQHP/00RmB3jtmoHEUKEz+zGC4lwtpxenLPQ///y4ICAAanfAIAAE64ggAALr4CACNgwAIAAaEgQ
Date: Thu, 20 Nov 2014 14:38:41 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02574FF93@AMSPEX01CL02.citrite.net>
References: <5464BDF4.1090103@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD01114ED29@AMSPEX01CL01.citrite.net>
	<5464C25D.6070200@m2r.biz>	<5466279C.207@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD011151F67@AMSPEX01CL01.citrite.net>
	<CABMPFzimdvuK65dQH2y7Qi0_t9ypBRaOOWS8MhkFw1MyBw+KGg@mail.gmail.com>
	<546DAD42.1080808@m2r.biz>
In-Reply-To: <546DAD42.1080808@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: "win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
Subject: Re: [win-pv-devel] Windows 7 64 bit blue screen with stop 1e after
 restore with new build of win pv drivers
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

RnJvbTogRmFiaW8gRmFudG9uaSBbbWFpbHRvOmZhYmlvLmZhbnRvbmlAbTJyLmJpel0gDQpTZW50
OiAyMCBOb3ZlbWJlciAyMDE0IDA4OjU5DQpUbzogUGF1bCBEdXJyYW50DQpDYzogd2luLXB2LWRl
dmVsQGxpc3RzLnhlbnByb2plY3Qub3JnDQpTdWJqZWN0OiBSZTogV2luZG93cyA3IDY0IGJpdCBi
bHVlIHNjcmVlbiB3aXRoIHN0b3AgMWUgYWZ0ZXIgcmVzdG9yZSB3aXRoIG5ldyBidWlsZCBvZiB3
aW4gcHYgZHJpdmVycw0KDQpJbCAxNC8xMS8yMDE0IDE4OjU0LCBGYWJpbyBGYW50b25pIGhhIHNj
cml0dG86DQoyMDE0LTExLTE0IDE3OjE1IEdNVCswMTowMCBQYXVsIER1cnJhbnQgPFBhdWwuRHVy
cmFudEBjaXRyaXguY29tPjoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTog
RmFiaW8gRmFudG9uaSBbbWFpbHRvOmZhYmlvLmZhbnRvbmlAbTJyLmJpel0NCj4gU2VudDogMTQg
Tm92ZW1iZXIgMjAxNCAxNjowMw0KPiBUbzogUGF1bCBEdXJyYW50OyB3aW4tcHYtZGV2ZWxAbGlz
dHMueGVucHJvamVjdC5vcmcNCj4gU3ViamVjdDogUmU6IFdpbmRvd3MgNyA2NCBiaXQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlIGFmdGVyIHJlc3RvcmUgd2l0aA0KPiBuZXcgYnVpbGQgb2Ygd2lu
IHB2IGRyaXZlcnMNCj4NCj4gSWwgMTMvMTEvMjAxNCAxNTozOCwgRmFiaW8gRmFudG9uaSBoYSBz
Y3JpdHRvOg0KPiA+IElsIDEzLzExLzIwMTQgMTU6MjYsIFBhdWwgRHVycmFudCBoYSBzY3JpdHRv
Og0KPiA+Pj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPj4+IEZyb206IEZhYmlvIEZh
bnRvbmkgW21haWx0bzpmYWJpby5mYW50b25pQG0yci5iaXpdDQo+ID4+PiBTZW50OiAxMyBOb3Zl
bWJlciAyMDE0IDE0OjIwDQo+ID4+PiBUbzogd2luLXB2LWRldmVsQGxpc3RzLnhlbnByb2plY3Qu
b3JnOyBQYXVsIER1cnJhbnQNCj4gPj4+IFN1YmplY3Q6IFdpbmRvd3MgNyA2NCBiaXQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlIGFmdGVyIHJlc3RvcmUNCj4gPj4+IHdpdGggbmV3DQo+ID4+PiBi
dWlsZCBvZiB3aW4gcHYgZHJpdmVycw0KPiA+Pj4NCj4gPj4+IEkgZGlkIGEgbmV3IGJ1aWxkIG9m
IHdpbnB2IGRyaXZlcnMgYW5kIHRlc3RlZCBvbiBvbmUgd2luZG93cyA3IDY0IGJpdA0KPiA+Pj4g
ZG9tVSwgZG9tMCB4ZW4tdW5zdGFibGUgd2l0aCAieDg2L2h2bTogRXh0ZW5kIEhWTSBjcHVpZCBs
ZWFmIHdpdGgNCj4gdmNwdQ0KPiA+Pj4gaWQiIGFuZCAieDg2L2h2bTogQWRkIHBlci12Y3B1IGV2
dGNobiB1cGNhbGxzIiBwYXRjaGVzLCBhbmQgcWVtdSAyLjINCj4gPj4+IGZyb20gc3BpY2UgZ2l0
Og0KPiA+Pj4gaHR0cHM6Ly9naXRodWIuY29tL0ZhbnR1L1hlbi9jb21taXRzL3JlYmFzZS9tMnIt
c3RhZ2luZw0KPiA+Pj4NCj4gPj4+IEFmdGVyIHJlc3RvcmUgd2luZG93cyBzaG93ZWQgYmx1ZSBz
Y3JlZW4gd2l0aCBzdG9wIDFlLCBJIG9wZW4gdGhlDQo+IGR1bXANCj4gPj4+IHdpdGggIkJsdWVT
Y3JlZW5WaWV3IiBhbmQgc2hvd2VkIHRoYXQgY2F1c2UgaXMgeGVubmV0IGRyaXZlci4NCj4gPj4+
IEkgYXR0YWNoZWQgdGhlIGR1bXAsIGlmIHlvdSBuZWVkIG1vcmUgaW5mb3JtYXRpb25zL3Rlc3Rz
IHRlbGwgbWUgYW5kDQo+ID4+PiBJJ2xsIHBvc3QgdGhlbS4NCj4gPj4+DQo+ID4+IEkndmUgYmVl
biB0ZXN0aW5nIHdpdGggd2luNyAzMi1iaXQgYW5kIHNlZW4gbm8gcHJvYmxlbXMuIFRoZSBtaW5p
ZHVtcA0KPiA+PiBkb2Vzbid0IHRlbGwgbWUgbXVjaCB1bmZvcnR1bmF0ZWx5IGRvIHlvdSBoYXZl
IGEgZnVsbCBkdW1wLCBwbHVzIHRoZQ0KPiA+PiBRRU1VIGxvZz8NCj4gPj4NCj4gPj7CoCDCoCBQ
YXVsDQo+ID4NCj4gPiBUaGFua3MgZm9yIHJlcGx5Lg0KPiA+IHFlbXUgbG9nIHdhcyB3aXRob3V0
IGVycm9ycyBvciB3YXJuaW5nIHJlbGF0ZWQsIEkgY2hhbmdlZCB3aW5kb3dzDQo+ID4gb3B0aW9u
IGZvciBmdWxsIG1lbW9yeSBkdW1wIGFuZCBlbmFibGUgcWVtdSB0cmFjZSBvZiB4ZW4gYW5kIHJl
dHJpZWQNCj4gPiB0byByZXByb2R1Y2UgdGhlIHByb2JsZW0gYnV0IHRoaXMgdGltZSBhZnRlciBy
ZXN0b3JlIG9uIHNhbWUgZG9tVSBub3QNCj4gPiBoYWQgdGhlIGJsdWUgc2NyZWVuLg0KPg0KPiBC
bHVlIHNjcmVlbiByZS1oYXBwZW4sIGluIGF0dGFjaG1lbnQgcWVtdSBsb2dzIChiZWZvcmUgYW5k
IGFmdGVyDQo+IHJlc3RvcmUpIHdpdGggeGVuIHRyYWNlLg0KPiBBbHNvIG1lbW9yeS5kbXAgZnVs
bCB0aGlzIHRpbWUgYnV0IHRoZXJlIGlzIGEgcHJvYmxlbSwgaXMgMSw4NyBnYiBhbmQgbXkNCj4g
Y29ubmVjdGlvbiBpcyBtYXggMjU2a2JwcyBvZiB1cGxvYWQgOigNCj4gSWYgaXMgcmVhbGx5IG5l
ZWRlZCB0ZWxsIG1lIGFuZCBJJ2xsIHRyeSB0byBsb2FkIGl0IGluIG15IHdlYnNlcnZlcg0KPiB0
b21vcnJvdy4NCj4NCkknbGwgdHJ5IHRvIHJlcHJvLiBZb3UncmUgY3Jhc2ggaGFwcGVuZWQgdmVy
eSBlYXJseSBpbiByZXN1bWUuIElzIHlvdXIgeGVuYnVzIGRyaXZlciB0aGUgYnVpbHQgZnJvbSB0
aXA/DQoNClllcyBJIHVwZGF0ZWQgYWxsIHRvIGxhdGVzdCBnaXQgaW4gaHR0cDovL3hlbmJpdHMu
eGVuLm9yZy9naXR3ZWIvP289YWdlLCBhbGwgZXhjZXB0IHhlbmlmYWNlIHdhcyB1cGRhdGVkIGlm
IEkgcmVtZW1iZXIgZ29vZC4NCldhcyBoYXBwZW4gMiB0aW1lIG9uIHRvdGFsIG9mIDUgc2F2ZS9y
ZXN0b3JlIEkgdHJpZWQuDQpMYXRlc3QgdGVzdCB3YXMgd2l0aCBxZW11IHVwc3RyZWFtIHVwZGF0
ZWQgaW5jbHVkaW5nIGFsc28gdGhlIG5ldyAyIHhlbiBidWdmaXggaHR0cDovL3NlY3VyZS13ZWIu
Y2lzY28uY29tLzFpTkRGc2p3RjdYUEVfejBVby1VYjRyLS12aDRWaG1sQ3kxM3FKeTVTTEVWOUNW
dFRyVWt6b0RlTWtOQUxPOU56dlg4a1NiVExJZzgxdmIzaWxsLUI1RVZTQWlLYjZTMmNFWGJqa2I2
ZlJLTE9RUXhUX1pxVFkwRUpOSG1JaENScFpadzlQQ1d1b1FseHdzMFNBVldmM2lSSmNYbmZ0RFot
NExOaHN2RVkwMlUvaHR0cCUzQSUyRiUyRmdpdC5xZW11Lm9yZyUyRnFlbXUuZ2l0IChjb21taXQg
NGU3MGY5MjcxZGFiYzU4ZmJmMTQ2ODA4NDNiZmFjNTEwYzE5MzE1MikuDQoNCkkgaGF2ZSB1cGRh
dGVkIHhlbiB0byBsYXRlc3Qgc3RhZ2luZyBhbmQgcWVtdSB0byB0YWcgdjIuMi4wLXJjMiBhbmQg
dGhlIGNyYXNoIHN0aWxsIGhhcHBlbiwgaW4gYXR0YWNobWVudCBtaW5pZHVtcCBvZiBsYXRlc3Qg
Y3Jhc2ggYW5kIGJlbG93IHRoZSBsaW5rIG9mIGZ1bGwgbWVtb3J5IGR1bXAsIGhvcGUgdGhhdCB0
aGVzZSB3aWxsIGhlbHAgeW91IHRvIGZvdW5kIGFuZCBzb2x2ZXMgdGhlIHByb2JsZW06DQpodHRw
Oi8vZmFudHUuaW5mby94ZW4vTUVNT1JZLkRNUA0KDQotLS0tLS0NCg0KVGhhbmtzIGZvciB0aGUg
ZnVsbCBkdW1wLiBUaGUgY3Jhc2ggaXMgdmVyeSBvZGQuIFRoZSBzdGFjayBJIHNlZSBpczoNCg0K
MToga2Q+IGtiDQpSZXRBZGRyICAgICAgICAgICA6IEFyZ3MgdG8gQ2hpbGQgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogQ2FsbCBTaXRl
DQpmZmZmZjgwMGAwMmFjMzViZSA6IDAwMDAwMDAwYDAwMDAwMDAwIDAwMDAwMDAwYDAwMDAwMDAw
IGZmZmZmODgwYDAyZTY4MjYwIGZmZmZmODAwYDAyYWY2YTkwIDogbnQhS2VCdWdDaGVjaw0KZmZm
ZmY4MDBgMDJhZjY3NWQgOiBmZmZmZjgwMGAwMmNkYTM4MCBmZmZmZjgwMGAwMmMxNzU4MCBmZmZm
ZjgwMGAwMmE1NjAwMCBmZmZmZjg4MGAwMmU2OGEwOCA6IG50IUtpS2VybmVsQ2FsbG91dEV4Y2Vw
dGlvbkhhbmRsZXIrMHhlDQpmZmZmZjgwMGAwMmFmNTUzNSA6IGZmZmZmODAwYDAyYzFiMzU4IGZm
ZmZmODgwYDAyZTY3Yjk4IGZmZmZmODgwYDAyZTY4YTA4IGZmZmZmODAwYDAyYTU2MDAwIDogbnQh
UnRscEV4ZWN1dGVIYW5kbGVyRm9yRXhjZXB0aW9uKzB4ZA0KZmZmZmY4MDBgMDJiMDY0YzEgOiBm
ZmZmZjg4MGAwMmU2OGEwOCBmZmZmZjg4MGAwMmU2ODI2MCBmZmZmZjg4MGAwMDAwMDAwMCAwMDAw
MDAwMGAwMDAwMDAwMCA6IG50IVJ0bERpc3BhdGNoRXhjZXB0aW9uKzB4NDE1DQpmZmZmZjgwMGAw
MmFjYjI0MiA6IGZmZmZmODgwYDAyZTY4YTA4IDAwMDAwMDAwYDAwMDAwMDAyIGZmZmZmODgwYDAy
ZTY4YWIwIDAwMDAwMDAwYDAwMDAwMDAwIDogbnQhS2lEaXNwYXRjaEV4Y2VwdGlvbisweDEzNQ0K
ZmZmZmY4MDBgMDJhYzkwNzQgOiAwMDAwMDAwMGAwMDAwMDAwMSAwMDAwMDAwMGAwMDAwMDAwMSBm
ZmZmZmE4MGAwMTZmNzcxMCBmZmZmZjg4MGAwMGZiNjliOSA6IG50IUtpRXhjZXB0aW9uRGlzcGF0
Y2grMHhjMg0KZmZmZmY4ODBgMDBmYTAzYTkgOiBmZmZmZjg4MGAwMGY5Nzk3OCAwMDAwMDAwMGAw
MDAwMDAwMiAwMDAwMDAwMGAwMDAwMDAwMCBmZmZmZjg4MGAwMGY5ZjIxMSA6IG50IUtpQnJlYWtw
b2ludFRyYXArMHhmNA0KZmZmZmY4ODBgMDBmOTc5NzggOiAwMDAwMDAwMGAwMDAwMDAwMiAwMDAw
MDAwMGAwMDAwMDAwMCBmZmZmZjg4MGAwMGY5ZjIxMSBmZmZmZmE4MGAwMTc5YzAxMCA6IHhlbiFI
eXBlcmNhbGxQb3B1bGF0ZSsweDEyNjkNCjAwMDAwMDAwYDAwMDAwMDAyIDogMDAwMDAwMDBgMDAw
MDAwMDAgZmZmZmY4ODBgMDBmOWYyMTEgZmZmZmZhODBgMDE3OWMwMTAgMDAwMDAwMDBgMDAwMDAw
MDEgOiB4ZW4rMHgxOTc4DQowMDAwMDAwMGAwMDAwMDAwMCA6IGZmZmZmODgwYDAwZjlmMjExIGZm
ZmZmYTgwYDAxNzljMDEwIDAwMDAwMDAwYDAwMDAwMDAxIDAwMDAwMDAwYDAwMDAwMDEwIDogMHgy
DQoNCkFuZCBpZiBJIGR1bXAgdGhlIGNvZGUgYXQgeGVuIUh5cGVyY2FsbFBvcHVsYXRlKzB4MTI2
OSwgSSBzZWUgMToga2Q+IHUgeGVuIUh5cGVyY2FsbFBvcHVsYXRlKzB4MTI2OQ0KeGVuIUh5cGVy
Y2FsbFBvcHVsYXRlKzB4MTI2OToNCmZmZmZmODgwYDAwZmEwM2E5IGNjICAgICAgICAgICAgICBp
bnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FhIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZm
ZmZmODgwYDAwZmEwM2FiIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEw
M2FjIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FkIGNjICAgICAg
ICAgICAgICBpbnQgICAgIDMNCmZmZmZmODgwYDAwZmEwM2FlIGNjICAgICAgICAgICAgICBpbnQg
ICAgIDMNCmZmZmZmODgwYDAwZmEwM2FmIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCmZmZmZm
ODgwYDAwZmEwM2IwIGNjICAgICAgICAgICAgICBpbnQgICAgIDMNCg0KU28sIGV2ZW4gaWYgdGhl
IHN5bWJvbHMgYXJlIHdyb25nIHRoZW4gaXQgc3RpbGwgbWVhbnMgdGhlIGNvZGUgYXBwZWFycyB0
byBoYXZlIGp1bXBlZCBpbnRvIHRoZSBtaWRkbGUgb2YgYSBsb2FkIDB4Y2MgYnl0ZXMsIHdoaWNo
IGlzIHdoYXQgaHlwZXJjYWxsX3BhZ2VfaW5pdGlhbGlzZSBmaWxscyB0aGUgaHlwZXJjYWxsIHBh
Z2Ugd2l0aCBiZWZvcmUgY2FsbGluZyB0aGUgc3ZtL3ZteCBzcGVjaWZpYyBjb2RlIHRvIHNldCBp
dCB1cC4gQWxzbywgSSBub3RlIHRoYXQgdGhpcyBzdGFjayBpcyBvbiBDUFUgMSB3aGljaCBzaG91
bGQgYmUgc3R1Y2sgc3Bpbm5pbmcgd2l0aCBpbnRlcnJ1cHRzIGRpc2FibGVkIGF0IHRoaXMgc3Rh
Z2UuIFRoZSBwcm9ibGVtIGlzIHRoYXQgdGhlIGxvb3AgdGhlcmUgaXMgYWN0dWFsbHkgbWFraW5n
IHlpZWxkIGh5cGVyY2FsbHMgYW5kIGRvZXNuJ3QgdGFrZSBraW5kbHkgdG8gdGhlIGh5cGVyY2Fs
bCBwYWdlIGJlaW5nIHJlLXdyaXR0ZW4gdW5kZXIgaXRzIGZlZXQgOi0oIEknZCBtaXNzZWQgdGhl
IDB4Y2MgZmlsbCB3aGVuIEknZCBhZGRlZCB0aGUgY29kZSB0byByZS1wb3B1bGF0ZSB0aGUgaHlw
ZXJjYWxsIHBhZ2UgYW5kIHRodXMgYmVsaWV2ZWQgdGhlIGNvbnRlbnRzIHdvdWxkIHNpbXBseSBi
ZSByZS13cml0dGVuIHdpdGggdGhlIHNhbWUgYnl0ZXMgdGhhdCB3ZXJlIGFscmVhZHkgdGhlcmUs
IG1lYW5pbmcgdGhhdCB0aGVyZSdzIGJlIG5vIHByb2JsZW0gd2l0aCB0aGUgc3BpbiBjb2RlIGlu
IENQVSAxKy4gSSBzaG91bGQgaG9wZWZ1bGx5IGJlIGFibGUgdG8gZml4IHRoZSBwcm9ibGVtIGJ5
IHJlbW92aW5nIHRoZSB5aWVsZCBoeXBlcmNhbGxzIGFuZCByZXBsYWNpbmcgdGhlbSB3aXRoIG1t
X3BhdXNlIGludHJpbnNpY3MuDQoNCiAgUGF1bA0KX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX18Kd2luLXB2LWRldmVsIG1haWxpbmcgbGlzdAp3aW4tcHYtZGV2
ZWxAbGlzdHMueGVucHJvamVjdC5vcmcKaHR0cDovL2xpc3RzLnhlbnByb2plY3Qub3JnL2NnaS1i
aW4vbWFpbG1hbi9saXN0aW5mby93aW4tcHYtZGV2ZWw=

From win-pv-devel-bounces@lists.xenproject.org Thu Nov 20 16:27:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 16:27:05 +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 1XrUZV-0000uU-Di; Thu, 20 Nov 2014 16:27:05 +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 1XrUZT-0000uE-Sh
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 16:27:04 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	DC/00-22819-7561E645; Thu, 20 Nov 2014 16:27:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-206.messagelabs.com!1416500819!12491405!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17526 invoked from network); 20 Nov 2014 16:27:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-12.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 16:27:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,424,1413244800"; d="scan'208";a="193333925"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Thu, 20 Nov 2014 11:25: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 1XrUYE-0006JF-Gs;
	Thu, 20 Nov 2014 16:25:46 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 20 Nov 2014 16:25:39 +0000
Message-ID: <1416500739-5716-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] Avoid making hypercalls in the SyncWorker DPC
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 code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within that
code is thus incompatible with re-populating the hypercall table on resume
since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that the
code was actually making was a SCHEDOP_yield and this is trivially replaced
by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/sync.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
index 41ecbf9..78b5bef 100644
--- a/src/xenbus/sync.c
+++ b/src/xenbus/sync.c
@@ -151,7 +151,7 @@ SyncWorker(
             break;
 
         if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
-            SchedYield();
+            _mm_pause();
             KeMemoryBarrier();
 
             continue;
@@ -171,7 +171,7 @@ SyncWorker(
             Attempts = 0;
             while (SyncContext.Sequence == Sequence &&
                    SyncContext.CompletionCount < CpuCount) {
-                SchedYield();
+                _mm_pause();
                 KeMemoryBarrier();
 
                 if (++Attempts > 1000) {
@@ -213,7 +213,7 @@ SyncWorker(
 
             while (SyncContext.Sequence == Sequence &&
                    SyncContext.CompletionCount < CpuCount) {
-                SchedYield();
+                _mm_pause();
                 KeMemoryBarrier();
             }
 
@@ -268,7 +268,7 @@ SyncCapture(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
@@ -305,7 +305,7 @@ again:
 
     Attempts = 0;
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
 
         if (++Attempts > 1000) {
@@ -366,7 +366,7 @@ SyncEnableInterrupts(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
@@ -400,7 +400,7 @@ SyncRelease(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
-- 
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 Nov 20 16:27:05 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Thu, 20 Nov 2014 16:27:05 +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 1XrUZV-0000uU-Di; Thu, 20 Nov 2014 16:27:05 +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 1XrUZT-0000uE-Sh
	for win-pv-devel@lists.xenproject.org; Thu, 20 Nov 2014 16:27:04 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	DC/00-22819-7561E645; Thu, 20 Nov 2014 16:27:03 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-12.tower-206.messagelabs.com!1416500819!12491405!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17526 invoked from network); 20 Nov 2014 16:27:02 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-12.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	20 Nov 2014 16:27:02 -0000
X-IronPort-AV: E=Sophos;i="5.07,424,1413244800"; d="scan'208";a="193333925"
Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com
	(10.13.107.80) with Microsoft SMTP Server id 14.3.181.6;
	Thu, 20 Nov 2014 11:25: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 1XrUYE-0006JF-Gs;
	Thu, 20 Nov 2014 16:25:46 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Thu, 20 Nov 2014 16:25:39 +0000
Message-ID: <1416500739-5716-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] Avoid making hypercalls in the SyncWorker DPC
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 code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within that
code is thus incompatible with re-populating the hypercall table on resume
since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that the
code was actually making was a SCHEDOP_yield and this is trivially replaced
by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/sync.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
index 41ecbf9..78b5bef 100644
--- a/src/xenbus/sync.c
+++ b/src/xenbus/sync.c
@@ -151,7 +151,7 @@ SyncWorker(
             break;
 
         if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
-            SchedYield();
+            _mm_pause();
             KeMemoryBarrier();
 
             continue;
@@ -171,7 +171,7 @@ SyncWorker(
             Attempts = 0;
             while (SyncContext.Sequence == Sequence &&
                    SyncContext.CompletionCount < CpuCount) {
-                SchedYield();
+                _mm_pause();
                 KeMemoryBarrier();
 
                 if (++Attempts > 1000) {
@@ -213,7 +213,7 @@ SyncWorker(
 
             while (SyncContext.Sequence == Sequence &&
                    SyncContext.CompletionCount < CpuCount) {
-                SchedYield();
+                _mm_pause();
                 KeMemoryBarrier();
             }
 
@@ -268,7 +268,7 @@ SyncCapture(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
@@ -305,7 +305,7 @@ again:
 
     Attempts = 0;
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
 
         if (++Attempts > 1000) {
@@ -366,7 +366,7 @@ SyncEnableInterrupts(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
@@ -400,7 +400,7 @@ SyncRelease(
     InterlockedIncrement(&SyncContext.CompletionCount);
 
     while (SyncContext.CompletionCount < CpuCount) {
-        SchedYield();
+        _mm_pause();
         KeMemoryBarrier();
     }
 
-- 
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 Nov 21 10:29:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 10:29:44 +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 1XrlTE-0001N9-IN; Fri, 21 Nov 2014 10:29:44 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrlTD-0001N2-EH
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 10:29:43 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	28/5E-09936-6141F645; Fri, 21 Nov 2014 10:29:42 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-7.tower-21.messagelabs.com!1416565781!14389437!1
X-Originating-IP: [74.125.82.53]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17408 invoked from network); 21 Nov 2014 10:29:41 -0000
Received: from mail-wg0-f53.google.com (HELO mail-wg0-f53.google.com)
	(74.125.82.53)
	by server-7.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 10:29:41 -0000
Received: by mail-wg0-f53.google.com with SMTP id l18so6070081wgh.40
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 21 Nov 2014 02:29:39 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=h7ErbxRkOt3CeEzSXLVEl24CAV8FqTuXw9hsP+Nox3U=;
	b=IyAgPKVSEd8P4iTlttIoz6xGtCRuMkB6Y5UwqwR1/2PsorO+y+JMuDUh9qhcEUOpHz
	q7oqysWVKRlQvmiBkIeU0XE4l340tpHKSh4npygWdvAUzXcS9dlg1tNie2Wrhi0mGtki
	+7PoTlNp6RmEIc6enURX2V1vQONWPumY5hd6fhveR5pzWybhH/nLI7RT0T+eAEn8h88Z
	CV68yPPw0pfNGkOR2kku9AN8ZaR0A3emrOm9wth6kQy33Bdxcr4WFAUIuNDuNYRgBJTl
	NPKucyq7K6Eu13+nyIdzxb+aF5HfroxosLOua6eYhbcrgGZmi7VJkkTiD+sxJZ1N4C0l
	nCtg==
X-Gm-Message-State: ALoCoQkrMDf243kiVxGrbV5XvLA8JwQh1TrXF/mWfYr4MqIKn5DeO2j4doDdmEPFpAVkj3bruKAy
X-Received: by 10.180.78.9 with SMTP id x9mr2457886wiw.39.1416565779460;
	Fri, 21 Nov 2014 02:29:39 -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 t9sm7425121wjf.41.2014.11.21.02.29.37
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 21 Nov 2014 02:29:38 -0800 (PST)
Message-ID: <546F141C.9010900@m2r.biz>
Date: Fri, 21 Nov 2014 11:29:48 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <paul.durrant@citrix.com>, win-pv-devel@lists.xenproject.org
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

Il 20/11/2014 17:25, Paul Durrant ha scritto:
> The code has to run with interrupts disabled on all CPUs apart from 0 to
> corale them across a suspend/resume. Making hypercalls from within that
> code is thus incompatible with re-populating the hypercall table on resume
> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> before actually setting up the hypercall thunks. The only hypercall that the
> code was actually making was a SCHEDOP_yield and this is trivially replaced
> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> VMEXIT handler.
Thanks for the patch, I tested it, 3 save/restore without crash for now 
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is 
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU 
"freeze" for 2-3 minutes on spice connect (always first time and 
occasional the others), on windows shutdown/reboot and probably other 
operations.
I'm unable to found the exactly cause of that, is there a way to know if 
is caused by something unexpected in windows pv drivers or other xen 
particular things in xen save/restore? (for example "interrupts disabled 
on all CPUs apart from 0 to corale them across a suspend/resume" if I 
understand good).

Thanks for any reply and sorry for my bad english.

>
> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> ---
>   src/xenbus/sync.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> index 41ecbf9..78b5bef 100644
> --- a/src/xenbus/sync.c
> +++ b/src/xenbus/sync.c
> @@ -151,7 +151,7 @@ SyncWorker(
>               break;
>   
>           if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> -            SchedYield();
> +            _mm_pause();
>               KeMemoryBarrier();
>   
>               continue;
> @@ -171,7 +171,7 @@ SyncWorker(
>               Attempts = 0;
>               while (SyncContext.Sequence == Sequence &&
>                      SyncContext.CompletionCount < CpuCount) {
> -                SchedYield();
> +                _mm_pause();
>                   KeMemoryBarrier();
>   
>                   if (++Attempts > 1000) {
> @@ -213,7 +213,7 @@ SyncWorker(
>   
>               while (SyncContext.Sequence == Sequence &&
>                      SyncContext.CompletionCount < CpuCount) {
> -                SchedYield();
> +                _mm_pause();
>                   KeMemoryBarrier();
>               }
>   
> @@ -268,7 +268,7 @@ SyncCapture(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> @@ -305,7 +305,7 @@ again:
>   
>       Attempts = 0;
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>   
>           if (++Attempts > 1000) {
> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> @@ -400,7 +400,7 @@ SyncRelease(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> -- 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 Nov 21 10:29:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 10:29:44 +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 1XrlTE-0001N9-IN; Fri, 21 Nov 2014 10:29:44 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrlTD-0001N2-EH
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 10:29:43 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	28/5E-09936-6141F645; Fri, 21 Nov 2014 10:29:42 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-7.tower-21.messagelabs.com!1416565781!14389437!1
X-Originating-IP: [74.125.82.53]
X-SpamReason: No, hits=0.5 required=7.0 tests=BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 17408 invoked from network); 21 Nov 2014 10:29:41 -0000
Received: from mail-wg0-f53.google.com (HELO mail-wg0-f53.google.com)
	(74.125.82.53)
	by server-7.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 10:29:41 -0000
Received: by mail-wg0-f53.google.com with SMTP id l18so6070081wgh.40
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 21 Nov 2014 02:29:39 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=h7ErbxRkOt3CeEzSXLVEl24CAV8FqTuXw9hsP+Nox3U=;
	b=IyAgPKVSEd8P4iTlttIoz6xGtCRuMkB6Y5UwqwR1/2PsorO+y+JMuDUh9qhcEUOpHz
	q7oqysWVKRlQvmiBkIeU0XE4l340tpHKSh4npygWdvAUzXcS9dlg1tNie2Wrhi0mGtki
	+7PoTlNp6RmEIc6enURX2V1vQONWPumY5hd6fhveR5pzWybhH/nLI7RT0T+eAEn8h88Z
	CV68yPPw0pfNGkOR2kku9AN8ZaR0A3emrOm9wth6kQy33Bdxcr4WFAUIuNDuNYRgBJTl
	NPKucyq7K6Eu13+nyIdzxb+aF5HfroxosLOua6eYhbcrgGZmi7VJkkTiD+sxJZ1N4C0l
	nCtg==
X-Gm-Message-State: ALoCoQkrMDf243kiVxGrbV5XvLA8JwQh1TrXF/mWfYr4MqIKn5DeO2j4doDdmEPFpAVkj3bruKAy
X-Received: by 10.180.78.9 with SMTP id x9mr2457886wiw.39.1416565779460;
	Fri, 21 Nov 2014 02:29:39 -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 t9sm7425121wjf.41.2014.11.21.02.29.37
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 21 Nov 2014 02:29:38 -0800 (PST)
Message-ID: <546F141C.9010900@m2r.biz>
Date: Fri, 21 Nov 2014 11:29:48 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <paul.durrant@citrix.com>, win-pv-devel@lists.xenproject.org
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
In-Reply-To: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

Il 20/11/2014 17:25, Paul Durrant ha scritto:
> The code has to run with interrupts disabled on all CPUs apart from 0 to
> corale them across a suspend/resume. Making hypercalls from within that
> code is thus incompatible with re-populating the hypercall table on resume
> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> before actually setting up the hypercall thunks. The only hypercall that the
> code was actually making was a SCHEDOP_yield and this is trivially replaced
> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> VMEXIT handler.
Thanks for the patch, I tested it, 3 save/restore without crash for now 
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is 
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU 
"freeze" for 2-3 minutes on spice connect (always first time and 
occasional the others), on windows shutdown/reboot and probably other 
operations.
I'm unable to found the exactly cause of that, is there a way to know if 
is caused by something unexpected in windows pv drivers or other xen 
particular things in xen save/restore? (for example "interrupts disabled 
on all CPUs apart from 0 to corale them across a suspend/resume" if I 
understand good).

Thanks for any reply and sorry for my bad english.

>
> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> ---
>   src/xenbus/sync.c | 14 +++++++-------
>   1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> index 41ecbf9..78b5bef 100644
> --- a/src/xenbus/sync.c
> +++ b/src/xenbus/sync.c
> @@ -151,7 +151,7 @@ SyncWorker(
>               break;
>   
>           if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> -            SchedYield();
> +            _mm_pause();
>               KeMemoryBarrier();
>   
>               continue;
> @@ -171,7 +171,7 @@ SyncWorker(
>               Attempts = 0;
>               while (SyncContext.Sequence == Sequence &&
>                      SyncContext.CompletionCount < CpuCount) {
> -                SchedYield();
> +                _mm_pause();
>                   KeMemoryBarrier();
>   
>                   if (++Attempts > 1000) {
> @@ -213,7 +213,7 @@ SyncWorker(
>   
>               while (SyncContext.Sequence == Sequence &&
>                      SyncContext.CompletionCount < CpuCount) {
> -                SchedYield();
> +                _mm_pause();
>                   KeMemoryBarrier();
>               }
>   
> @@ -268,7 +268,7 @@ SyncCapture(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> @@ -305,7 +305,7 @@ again:
>   
>       Attempts = 0;
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>   
>           if (++Attempts > 1000) {
> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> @@ -400,7 +400,7 @@ SyncRelease(
>       InterlockedIncrement(&SyncContext.CompletionCount);
>   
>       while (SyncContext.CompletionCount < CpuCount) {
> -        SchedYield();
> +        _mm_pause();
>           KeMemoryBarrier();
>       }
>   
> -- 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 Nov 21 13:24:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 13:24: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 1XroCP-0000xh-Kq; Fri, 21 Nov 2014 13:24:33 +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 1XroCO-0000xc-N4
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 13:24:32 +0000
Received: from [193.109.254.147] by server-15.bemta-14.messagelabs.com id
	73/02-02699-F0D3F645; Fri, 21 Nov 2014 13:24:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1416576270!14014168!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30739 invoked from network); 21 Nov 2014 13:24:30 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 13:24:30 -0000
X-IronPort-AV: E=Sophos;i="5.07,431,1413244800"; d="scan'208";a="27038632"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MA=
Date: Fri, 21 Nov 2014 13:24:28 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
In-Reply-To: <546F141C.9010900@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 21 November 2014 10:30
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> SyncWorker DPC
> 
> Il 20/11/2014 17:25, Paul Durrant ha scritto:
> > The code has to run with interrupts disabled on all CPUs apart from 0 to
> > corale them across a suspend/resume. Making hypercalls from within that
> > code is thus incompatible with re-populating the hypercall table on resume
> > since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> > before actually setting up the hypercall thunks. The only hypercall that the
> > code was actually making was a SCHEDOP_yield and this is trivially replaced
> > by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> > VMEXIT handler.
> Thanks for the patch, I tested it, 3 save/restore without crash for now
> and I not saw any regression, I'll report you if I'll see other crash.
> 
> There is another problem with the save/restore on windows that is
> driving me crazy for months:
> with qxl vga all works good except after save/restore that make domU
> "freeze" for 2-3 minutes on spice connect (always first time and
> occasional the others), on windows shutdown/reboot and probably other
> operations.
> I'm unable to found the exactly cause of that, is there a way to know if
> is caused by something unexpected in windows pv drivers or other xen
> particular things in xen save/restore? (for example "interrupts disabled
> on all CPUs apart from 0 to corale them across a suspend/resume" if I
> understand good).
> 

Is it a network issue? The PV drivers should re-generate gratuitous ARPs and IPv6 neighbour solicitations on resume so things should be ok but it would be worth un-firewalling ICMP so you can check whether the VM is actually pingable.
If the VM is really wedged though you can always use xen-hvmcrash from dom0 to try to forcibly crash the domain such that Windows will create a MEMORY.DMP that you can have a look at after reboot.

  Paul

> Thanks for any reply and sorry for my bad english.
> 
> >
> > Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> > ---
> >   src/xenbus/sync.c | 14 +++++++-------
> >   1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> > index 41ecbf9..78b5bef 100644
> > --- a/src/xenbus/sync.c
> > +++ b/src/xenbus/sync.c
> > @@ -151,7 +151,7 @@ SyncWorker(
> >               break;
> >
> >           if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> > -            SchedYield();
> > +            _mm_pause();
> >               KeMemoryBarrier();
> >
> >               continue;
> > @@ -171,7 +171,7 @@ SyncWorker(
> >               Attempts = 0;
> >               while (SyncContext.Sequence == Sequence &&
> >                      SyncContext.CompletionCount < CpuCount) {
> > -                SchedYield();
> > +                _mm_pause();
> >                   KeMemoryBarrier();
> >
> >                   if (++Attempts > 1000) {
> > @@ -213,7 +213,7 @@ SyncWorker(
> >
> >               while (SyncContext.Sequence == Sequence &&
> >                      SyncContext.CompletionCount < CpuCount) {
> > -                SchedYield();
> > +                _mm_pause();
> >                   KeMemoryBarrier();
> >               }
> >
> > @@ -268,7 +268,7 @@ SyncCapture(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > @@ -305,7 +305,7 @@ again:
> >
> >       Attempts = 0;
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >
> >           if (++Attempts > 1000) {
> > @@ -366,7 +366,7 @@ SyncEnableInterrupts(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > @@ -400,7 +400,7 @@ SyncRelease(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > -- 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 Nov 21 13:24:33 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 13:24: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 1XroCP-0000xh-Kq; Fri, 21 Nov 2014 13:24:33 +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 1XroCO-0000xc-N4
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 13:24:32 +0000
Received: from [193.109.254.147] by server-15.bemta-14.messagelabs.com id
	73/02-02699-F0D3F645; Fri, 21 Nov 2014 13:24:31 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-15.tower-27.messagelabs.com!1416576270!14014168!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 30739 invoked from network); 21 Nov 2014 13:24:30 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-15.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 13:24:30 -0000
X-IronPort-AV: E=Sophos;i="5.07,431,1413244800"; d="scan'208";a="27038632"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MA=
Date: Fri, 21 Nov 2014 13:24:28 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
In-Reply-To: <546F141C.9010900@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 21 November 2014 10:30
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> SyncWorker DPC
> 
> Il 20/11/2014 17:25, Paul Durrant ha scritto:
> > The code has to run with interrupts disabled on all CPUs apart from 0 to
> > corale them across a suspend/resume. Making hypercalls from within that
> > code is thus incompatible with re-populating the hypercall table on resume
> > since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> > before actually setting up the hypercall thunks. The only hypercall that the
> > code was actually making was a SCHEDOP_yield and this is trivially replaced
> > by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> > VMEXIT handler.
> Thanks for the patch, I tested it, 3 save/restore without crash for now
> and I not saw any regression, I'll report you if I'll see other crash.
> 
> There is another problem with the save/restore on windows that is
> driving me crazy for months:
> with qxl vga all works good except after save/restore that make domU
> "freeze" for 2-3 minutes on spice connect (always first time and
> occasional the others), on windows shutdown/reboot and probably other
> operations.
> I'm unable to found the exactly cause of that, is there a way to know if
> is caused by something unexpected in windows pv drivers or other xen
> particular things in xen save/restore? (for example "interrupts disabled
> on all CPUs apart from 0 to corale them across a suspend/resume" if I
> understand good).
> 

Is it a network issue? The PV drivers should re-generate gratuitous ARPs and IPv6 neighbour solicitations on resume so things should be ok but it would be worth un-firewalling ICMP so you can check whether the VM is actually pingable.
If the VM is really wedged though you can always use xen-hvmcrash from dom0 to try to forcibly crash the domain such that Windows will create a MEMORY.DMP that you can have a look at after reboot.

  Paul

> Thanks for any reply and sorry for my bad english.
> 
> >
> > Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> > ---
> >   src/xenbus/sync.c | 14 +++++++-------
> >   1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> > index 41ecbf9..78b5bef 100644
> > --- a/src/xenbus/sync.c
> > +++ b/src/xenbus/sync.c
> > @@ -151,7 +151,7 @@ SyncWorker(
> >               break;
> >
> >           if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> > -            SchedYield();
> > +            _mm_pause();
> >               KeMemoryBarrier();
> >
> >               continue;
> > @@ -171,7 +171,7 @@ SyncWorker(
> >               Attempts = 0;
> >               while (SyncContext.Sequence == Sequence &&
> >                      SyncContext.CompletionCount < CpuCount) {
> > -                SchedYield();
> > +                _mm_pause();
> >                   KeMemoryBarrier();
> >
> >                   if (++Attempts > 1000) {
> > @@ -213,7 +213,7 @@ SyncWorker(
> >
> >               while (SyncContext.Sequence == Sequence &&
> >                      SyncContext.CompletionCount < CpuCount) {
> > -                SchedYield();
> > +                _mm_pause();
> >                   KeMemoryBarrier();
> >               }
> >
> > @@ -268,7 +268,7 @@ SyncCapture(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > @@ -305,7 +305,7 @@ again:
> >
> >       Attempts = 0;
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >
> >           if (++Attempts > 1000) {
> > @@ -366,7 +366,7 @@ SyncEnableInterrupts(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > @@ -400,7 +400,7 @@ SyncRelease(
> >       InterlockedIncrement(&SyncContext.CompletionCount);
> >
> >       while (SyncContext.CompletionCount < CpuCount) {
> > -        SchedYield();
> > +        _mm_pause();
> >           KeMemoryBarrier();
> >       }
> >
> > -- 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 Nov 21 16:17:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 16:17: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 1XrquD-0002mY-5s; Fri, 21 Nov 2014 16:17:57 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrquB-0002mT-Pa
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 16:17:55 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	F6/98-15461-3B56F645; Fri, 21 Nov 2014 16:17:55 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-21.messagelabs.com!1416586674!14445014!1
X-Originating-IP: [209.85.212.181]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15554 invoked from network); 21 Nov 2014 16:17:54 -0000
Received: from mail-wi0-f181.google.com (HELO mail-wi0-f181.google.com)
	(209.85.212.181)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 16:17:54 -0000
Received: by mail-wi0-f181.google.com with SMTP id r20so9383610wiv.2
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 21 Nov 2014 08:17:52 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=7cd4lnTg6dZBpIPMK4lz6lkQSl/BUbLM3jQ+2bLE3/A=;
	b=CbpnKc6Vt2e/Yfyg5ArHzWsyHMYBOOC8V9tSHXvmEM4UpChz3/FTyGj6noVmb8ULPZ
	OCoFSXPikJxRzFclIGf/H1FrfwrNHrQIyDMCjgsXm3J4bdZ72ANeizTnlHQaH1m9OZ7P
	rw5VaYOQ3JQMuu9uTBAkOVComzVJUNAd8nA3TKDd9P+p697PpO+d2xHWwh2eD/umRcW5
	3tLYz25osLZAgD8oUTXYsvDug/ohplDdjgc8qxcIW9lsNybyzFUS+TjFepL1B7nbKRy2
	IzsvhcAavsxXCW1b1fzP5wXj45k8UMPZTsrINToOxWCS2Do2I0uBzeHxuDXoPU/pF7mp
	Aqmg==
X-Gm-Message-State: ALoCoQk9+5+LwYSwTiLck1V+26FyuYSZffVKA2V6IKi370hOoMECubFpHrwPxsmURaBauJrsSaap
X-Received: by 10.194.158.193 with SMTP id ww1mr9102947wjb.65.1416586671924;
	Fri, 21 Nov 2014 08:17:51 -0800 (PST)
Received: from [192.168.1.15] ([83.211.73.126])
	by mx.google.com with ESMTPSA id 4sm5253867wjs.24.2014.11.21.08.17.50
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 21 Nov 2014 08:17:51 -0800 (PST)
Message-ID: <546F65B6.6040504@m2r.biz>
Date: Fri, 21 Nov 2014 17:17:58 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

Il 21/11/2014 14:24, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 21 November 2014 10:30
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>> SyncWorker DPC
>>
>> Il 20/11/2014 17:25, Paul Durrant ha scritto:
>>> The code has to run with interrupts disabled on all CPUs apart from 0 to
>>> corale them across a suspend/resume. Making hypercalls from within that
>>> code is thus incompatible with re-populating the hypercall table on resume
>>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
>>> before actually setting up the hypercall thunks. The only hypercall that the
>>> code was actually making was a SCHEDOP_yield and this is trivially replaced
>>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
>>> VMEXIT handler.
>> Thanks for the patch, I tested it, 3 save/restore without crash for now
>> and I not saw any regression, I'll report you if I'll see other crash.
>>
>> There is another problem with the save/restore on windows that is
>> driving me crazy for months:
>> with qxl vga all works good except after save/restore that make domU
>> "freeze" for 2-3 minutes on spice connect (always first time and
>> occasional the others), on windows shutdown/reboot and probably other
>> operations.
>> I'm unable to found the exactly cause of that, is there a way to know if
>> is caused by something unexpected in windows pv drivers or other xen
>> particular things in xen save/restore? (for example "interrupts disabled
>> on all CPUs apart from 0 to corale them across a suspend/resume" if I
>> understand good).
>>
> Is it a network issue? The PV drivers should re-generate gratuitous ARPs and IPv6 neighbour solicitations on resume so things should be ok but it would be worth un-firewalling ICMP so you can check whether the VM is actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm 
instead vnc (and is better) and I use it also from thin client as it 
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore 
when on spice connect, windows screen resolution change, windows 
shutdown and probably other things the domU "freeze" for 2-3 minutes and 
I'm unable to debug it.

> If the VM is really wedged though you can always use xen-hvmcrash from dom0 to try to forcibly crash the domain such that Windows will create a MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to 
take a memory dump and see what happen during freeze?

>
>    Paul
>
>> Thanks for any reply and sorry for my bad english.
>>
>>> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
>>> ---
>>>    src/xenbus/sync.c | 14 +++++++-------
>>>    1 file changed, 7 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
>>> index 41ecbf9..78b5bef 100644
>>> --- a/src/xenbus/sync.c
>>> +++ b/src/xenbus/sync.c
>>> @@ -151,7 +151,7 @@ SyncWorker(
>>>                break;
>>>
>>>            if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
>>> -            SchedYield();
>>> +            _mm_pause();
>>>                KeMemoryBarrier();
>>>
>>>                continue;
>>> @@ -171,7 +171,7 @@ SyncWorker(
>>>                Attempts = 0;
>>>                while (SyncContext.Sequence == Sequence &&
>>>                       SyncContext.CompletionCount < CpuCount) {
>>> -                SchedYield();
>>> +                _mm_pause();
>>>                    KeMemoryBarrier();
>>>
>>>                    if (++Attempts > 1000) {
>>> @@ -213,7 +213,7 @@ SyncWorker(
>>>
>>>                while (SyncContext.Sequence == Sequence &&
>>>                       SyncContext.CompletionCount < CpuCount) {
>>> -                SchedYield();
>>> +                _mm_pause();
>>>                    KeMemoryBarrier();
>>>                }
>>>
>>> @@ -268,7 +268,7 @@ SyncCapture(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> @@ -305,7 +305,7 @@ again:
>>>
>>>        Attempts = 0;
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>
>>>            if (++Attempts > 1000) {
>>> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> @@ -400,7 +400,7 @@ SyncRelease(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> -- 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 Nov 21 16:17:57 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 16:17: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 1XrquD-0002mY-5s; Fri, 21 Nov 2014 16:17:57 +0000
Received: from mail6.bemta4.messagelabs.com ([85.158.143.247])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XrquB-0002mT-Pa
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 16:17:55 +0000
Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id
	F6/98-15461-3B56F645; Fri, 21 Nov 2014 16:17:55 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-5.tower-21.messagelabs.com!1416586674!14445014!1
X-Originating-IP: [209.85.212.181]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 15554 invoked from network); 21 Nov 2014 16:17:54 -0000
Received: from mail-wi0-f181.google.com (HELO mail-wi0-f181.google.com)
	(209.85.212.181)
	by server-5.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 16:17:54 -0000
Received: by mail-wi0-f181.google.com with SMTP id r20so9383610wiv.2
	for <win-pv-devel@lists.xenproject.org>;
	Fri, 21 Nov 2014 08:17:52 -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
	:subject:references:in-reply-to:content-type
	:content-transfer-encoding;
	bh=7cd4lnTg6dZBpIPMK4lz6lkQSl/BUbLM3jQ+2bLE3/A=;
	b=CbpnKc6Vt2e/Yfyg5ArHzWsyHMYBOOC8V9tSHXvmEM4UpChz3/FTyGj6noVmb8ULPZ
	OCoFSXPikJxRzFclIGf/H1FrfwrNHrQIyDMCjgsXm3J4bdZ72ANeizTnlHQaH1m9OZ7P
	rw5VaYOQ3JQMuu9uTBAkOVComzVJUNAd8nA3TKDd9P+p697PpO+d2xHWwh2eD/umRcW5
	3tLYz25osLZAgD8oUTXYsvDug/ohplDdjgc8qxcIW9lsNybyzFUS+TjFepL1B7nbKRy2
	IzsvhcAavsxXCW1b1fzP5wXj45k8UMPZTsrINToOxWCS2Do2I0uBzeHxuDXoPU/pF7mp
	Aqmg==
X-Gm-Message-State: ALoCoQk9+5+LwYSwTiLck1V+26FyuYSZffVKA2V6IKi370hOoMECubFpHrwPxsmURaBauJrsSaap
X-Received: by 10.194.158.193 with SMTP id ww1mr9102947wjb.65.1416586671924;
	Fri, 21 Nov 2014 08:17:51 -0800 (PST)
Received: from [192.168.1.15] ([83.211.73.126])
	by mx.google.com with ESMTPSA id 4sm5253867wjs.24.2014.11.21.08.17.50
	for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Fri, 21 Nov 2014 08:17:51 -0800 (PST)
Message-ID: <546F65B6.6040504@m2r.biz>
Date: Fri, 21 Nov 2014 17:17:58 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

Il 21/11/2014 14:24, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 21 November 2014 10:30
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>> SyncWorker DPC
>>
>> Il 20/11/2014 17:25, Paul Durrant ha scritto:
>>> The code has to run with interrupts disabled on all CPUs apart from 0 to
>>> corale them across a suspend/resume. Making hypercalls from within that
>>> code is thus incompatible with re-populating the hypercall table on resume
>>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
>>> before actually setting up the hypercall thunks. The only hypercall that the
>>> code was actually making was a SCHEDOP_yield and this is trivially replaced
>>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
>>> VMEXIT handler.
>> Thanks for the patch, I tested it, 3 save/restore without crash for now
>> and I not saw any regression, I'll report you if I'll see other crash.
>>
>> There is another problem with the save/restore on windows that is
>> driving me crazy for months:
>> with qxl vga all works good except after save/restore that make domU
>> "freeze" for 2-3 minutes on spice connect (always first time and
>> occasional the others), on windows shutdown/reboot and probably other
>> operations.
>> I'm unable to found the exactly cause of that, is there a way to know if
>> is caused by something unexpected in windows pv drivers or other xen
>> particular things in xen save/restore? (for example "interrupts disabled
>> on all CPUs apart from 0 to corale them across a suspend/resume" if I
>> understand good).
>>
> Is it a network issue? The PV drivers should re-generate gratuitous ARPs and IPv6 neighbour solicitations on resume so things should be ok but it would be worth un-firewalling ICMP so you can check whether the VM is actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm 
instead vnc (and is better) and I use it also from thin client as it 
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore 
when on spice connect, windows screen resolution change, windows 
shutdown and probably other things the domU "freeze" for 2-3 minutes and 
I'm unable to debug it.

> If the VM is really wedged though you can always use xen-hvmcrash from dom0 to try to forcibly crash the domain such that Windows will create a MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to 
take a memory dump and see what happen during freeze?

>
>    Paul
>
>> Thanks for any reply and sorry for my bad english.
>>
>>> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
>>> ---
>>>    src/xenbus/sync.c | 14 +++++++-------
>>>    1 file changed, 7 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
>>> index 41ecbf9..78b5bef 100644
>>> --- a/src/xenbus/sync.c
>>> +++ b/src/xenbus/sync.c
>>> @@ -151,7 +151,7 @@ SyncWorker(
>>>                break;
>>>
>>>            if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
>>> -            SchedYield();
>>> +            _mm_pause();
>>>                KeMemoryBarrier();
>>>
>>>                continue;
>>> @@ -171,7 +171,7 @@ SyncWorker(
>>>                Attempts = 0;
>>>                while (SyncContext.Sequence == Sequence &&
>>>                       SyncContext.CompletionCount < CpuCount) {
>>> -                SchedYield();
>>> +                _mm_pause();
>>>                    KeMemoryBarrier();
>>>
>>>                    if (++Attempts > 1000) {
>>> @@ -213,7 +213,7 @@ SyncWorker(
>>>
>>>                while (SyncContext.Sequence == Sequence &&
>>>                       SyncContext.CompletionCount < CpuCount) {
>>> -                SchedYield();
>>> +                _mm_pause();
>>>                    KeMemoryBarrier();
>>>                }
>>>
>>> @@ -268,7 +268,7 @@ SyncCapture(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> @@ -305,7 +305,7 @@ again:
>>>
>>>        Attempts = 0;
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>
>>>            if (++Attempts > 1000) {
>>> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> @@ -400,7 +400,7 @@ SyncRelease(
>>>        InterlockedIncrement(&SyncContext.CompletionCount);
>>>
>>>        while (SyncContext.CompletionCount < CpuCount) {
>>> -        SchedYield();
>>> +        _mm_pause();
>>>            KeMemoryBarrier();
>>>        }
>>>
>>> -- 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 Nov 21 16:22:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 16:22: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 1Xrqyj-0002pY-MW; Fri, 21 Nov 2014 16:22:37 +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 1Xrqyh-0002pT-P5
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 16:22:35 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	B1/7B-09842-BC66F645; Fri, 21 Nov 2014 16:22:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-6.tower-21.messagelabs.com!1416586954!14403684!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26545 invoked from network); 21 Nov 2014 16:22:34 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-6.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 16:22:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,432,1413244800"; d="scan'208";a="27043779"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MCAACB3AIAAEQsg
Date: Fri, 21 Nov 2014 16:22:32 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
In-Reply-To: <546F65B6.6040504@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 21 November 2014 16:18
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> SyncWorker DPC
> 
> Il 21/11/2014 14:24, Paul Durrant ha scritto:
> >> -----Original Message-----
> >> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> >> Sent: 21 November 2014 10:30
> >> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> >> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> >> SyncWorker DPC
> >>
> >> Il 20/11/2014 17:25, Paul Durrant ha scritto:
> >>> The code has to run with interrupts disabled on all CPUs apart from 0 to
> >>> corale them across a suspend/resume. Making hypercalls from within
> that
> >>> code is thus incompatible with re-populating the hypercall table on
> resume
> >>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> >>> before actually setting up the hypercall thunks. The only hypercall that
> the
> >>> code was actually making was a SCHEDOP_yield and this is trivially
> replaced
> >>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> >>> VMEXIT handler.
> >> Thanks for the patch, I tested it, 3 save/restore without crash for now
> >> and I not saw any regression, I'll report you if I'll see other crash.
> >>
> >> There is another problem with the save/restore on windows that is
> >> driving me crazy for months:
> >> with qxl vga all works good except after save/restore that make domU
> >> "freeze" for 2-3 minutes on spice connect (always first time and
> >> occasional the others), on windows shutdown/reboot and probably other
> >> operations.
> >> I'm unable to found the exactly cause of that, is there a way to know if
> >> is caused by something unexpected in windows pv drivers or other xen
> >> particular things in xen save/restore? (for example "interrupts disabled
> >> on all CPUs apart from 0 to corale them across a suspend/resume" if I
> >> understand good).
> >>
> > Is it a network issue? The PV drivers should re-generate gratuitous ARPs
> and IPv6 neighbour solicitations on resume so things should be ok but it
> would be worth un-firewalling ICMP so you can check whether the VM is
> actually pingable.
> 
> Sorry if I not explain good, spice connect to dom0 as domU's vkvm
> instead vnc (and is better) and I use it also from thin client as it
> full features is better that rdp.
> On windows domUs seems qxl works good as kvm except after xl restore
> when on spice connect, windows screen resolution change, windows
> shutdown and probably other things the domU "freeze" for 2-3 minutes and
> I'm unable to debug it.

Ah ok. That's almost certainly a qemu problem then.

> 
> > If the VM is really wedged though you can always use xen-hvmcrash from
> dom0 to try to forcibly crash the domain such that Windows will create a
> MEMORY.DMP that you can have a look at after reboot.
> 
> So if I understand good I can simulate a domU crash during the freeze to
> take a memory dump and see what happen during freeze?
> 

Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul

> >
> >    Paul
> >
> >> Thanks for any reply and sorry for my bad english.
> >>
> >>> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> >>> ---
> >>>    src/xenbus/sync.c | 14 +++++++-------
> >>>    1 file changed, 7 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> >>> index 41ecbf9..78b5bef 100644
> >>> --- a/src/xenbus/sync.c
> >>> +++ b/src/xenbus/sync.c
> >>> @@ -151,7 +151,7 @@ SyncWorker(
> >>>                break;
> >>>
> >>>            if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> >>> -            SchedYield();
> >>> +            _mm_pause();
> >>>                KeMemoryBarrier();
> >>>
> >>>                continue;
> >>> @@ -171,7 +171,7 @@ SyncWorker(
> >>>                Attempts = 0;
> >>>                while (SyncContext.Sequence == Sequence &&
> >>>                       SyncContext.CompletionCount < CpuCount) {
> >>> -                SchedYield();
> >>> +                _mm_pause();
> >>>                    KeMemoryBarrier();
> >>>
> >>>                    if (++Attempts > 1000) {
> >>> @@ -213,7 +213,7 @@ SyncWorker(
> >>>
> >>>                while (SyncContext.Sequence == Sequence &&
> >>>                       SyncContext.CompletionCount < CpuCount) {
> >>> -                SchedYield();
> >>> +                _mm_pause();
> >>>                    KeMemoryBarrier();
> >>>                }
> >>>
> >>> @@ -268,7 +268,7 @@ SyncCapture(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> @@ -305,7 +305,7 @@ again:
> >>>
> >>>        Attempts = 0;
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>
> >>>            if (++Attempts > 1000) {
> >>> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> @@ -400,7 +400,7 @@ SyncRelease(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> -- 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 Nov 21 16:22:37 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 21 Nov 2014 16:22: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 1Xrqyj-0002pY-MW; Fri, 21 Nov 2014 16:22:37 +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 1Xrqyh-0002pT-P5
	for win-pv-devel@lists.xenproject.org; Fri, 21 Nov 2014 16:22:35 +0000
Received: from [85.158.143.35] by server-1.bemta-4.messagelabs.com id
	B1/7B-09842-BC66F645; Fri, 21 Nov 2014 16:22:35 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-6.tower-21.messagelabs.com!1416586954!14403684!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 26545 invoked from network); 21 Nov 2014 16:22:34 -0000
Received: from smtp.eu.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-6.tower-21.messagelabs.com with RC4-SHA encrypted SMTP;
	21 Nov 2014 16:22:34 -0000
X-IronPort-AV: E=Sophos;i="5.07,432,1413244800"; d="scan'208";a="27043779"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MCAACB3AIAAEQsg
Date: Fri, 21 Nov 2014 16:22:32 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
In-Reply-To: <546F65B6.6040504@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> Sent: 21 November 2014 16:18
> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> SyncWorker DPC
> 
> Il 21/11/2014 14:24, Paul Durrant ha scritto:
> >> -----Original Message-----
> >> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
> >> Sent: 21 November 2014 10:30
> >> To: Paul Durrant; win-pv-devel@lists.xenproject.org
> >> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
> >> SyncWorker DPC
> >>
> >> Il 20/11/2014 17:25, Paul Durrant ha scritto:
> >>> The code has to run with interrupts disabled on all CPUs apart from 0 to
> >>> corale them across a suspend/resume. Making hypercalls from within
> that
> >>> code is thus incompatible with re-populating the hypercall table on
> resume
> >>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
> >>> before actually setting up the hypercall thunks. The only hypercall that
> the
> >>> code was actually making was a SCHEDOP_yield and this is trivially
> replaced
> >>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
> >>> VMEXIT handler.
> >> Thanks for the patch, I tested it, 3 save/restore without crash for now
> >> and I not saw any regression, I'll report you if I'll see other crash.
> >>
> >> There is another problem with the save/restore on windows that is
> >> driving me crazy for months:
> >> with qxl vga all works good except after save/restore that make domU
> >> "freeze" for 2-3 minutes on spice connect (always first time and
> >> occasional the others), on windows shutdown/reboot and probably other
> >> operations.
> >> I'm unable to found the exactly cause of that, is there a way to know if
> >> is caused by something unexpected in windows pv drivers or other xen
> >> particular things in xen save/restore? (for example "interrupts disabled
> >> on all CPUs apart from 0 to corale them across a suspend/resume" if I
> >> understand good).
> >>
> > Is it a network issue? The PV drivers should re-generate gratuitous ARPs
> and IPv6 neighbour solicitations on resume so things should be ok but it
> would be worth un-firewalling ICMP so you can check whether the VM is
> actually pingable.
> 
> Sorry if I not explain good, spice connect to dom0 as domU's vkvm
> instead vnc (and is better) and I use it also from thin client as it
> full features is better that rdp.
> On windows domUs seems qxl works good as kvm except after xl restore
> when on spice connect, windows screen resolution change, windows
> shutdown and probably other things the domU "freeze" for 2-3 minutes and
> I'm unable to debug it.

Ah ok. That's almost certainly a qemu problem then.

> 
> > If the VM is really wedged though you can always use xen-hvmcrash from
> dom0 to try to forcibly crash the domain such that Windows will create a
> MEMORY.DMP that you can have a look at after reboot.
> 
> So if I understand good I can simulate a domU crash during the freeze to
> take a memory dump and see what happen during freeze?
> 

Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul

> >
> >    Paul
> >
> >> Thanks for any reply and sorry for my bad english.
> >>
> >>> Signed-off-by: Paul Durrant<paul.durrant@citrix.com>
> >>> ---
> >>>    src/xenbus/sync.c | 14 +++++++-------
> >>>    1 file changed, 7 insertions(+), 7 deletions(-)
> >>>
> >>> diff --git a/src/xenbus/sync.c b/src/xenbus/sync.c
> >>> index 41ecbf9..78b5bef 100644
> >>> --- a/src/xenbus/sync.c
> >>> +++ b/src/xenbus/sync.c
> >>> @@ -151,7 +151,7 @@ SyncWorker(
> >>>                break;
> >>>
> >>>            if (SyncContext.DisableInterrupts[Cpu] == InterruptsDisabled) {
> >>> -            SchedYield();
> >>> +            _mm_pause();
> >>>                KeMemoryBarrier();
> >>>
> >>>                continue;
> >>> @@ -171,7 +171,7 @@ SyncWorker(
> >>>                Attempts = 0;
> >>>                while (SyncContext.Sequence == Sequence &&
> >>>                       SyncContext.CompletionCount < CpuCount) {
> >>> -                SchedYield();
> >>> +                _mm_pause();
> >>>                    KeMemoryBarrier();
> >>>
> >>>                    if (++Attempts > 1000) {
> >>> @@ -213,7 +213,7 @@ SyncWorker(
> >>>
> >>>                while (SyncContext.Sequence == Sequence &&
> >>>                       SyncContext.CompletionCount < CpuCount) {
> >>> -                SchedYield();
> >>> +                _mm_pause();
> >>>                    KeMemoryBarrier();
> >>>                }
> >>>
> >>> @@ -268,7 +268,7 @@ SyncCapture(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> @@ -305,7 +305,7 @@ again:
> >>>
> >>>        Attempts = 0;
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>
> >>>            if (++Attempts > 1000) {
> >>> @@ -366,7 +366,7 @@ SyncEnableInterrupts(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> @@ -400,7 +400,7 @@ SyncRelease(
> >>>        InterlockedIncrement(&SyncContext.CompletionCount);
> >>>
> >>>        while (SyncContext.CompletionCount < CpuCount) {
> >>> -        SchedYield();
> >>> +        _mm_pause();
> >>>            KeMemoryBarrier();
> >>>        }
> >>>
> >>> -- 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 Nov 25 09:14:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 25 Nov 2014 09:14: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 1XtCD2-0006SI-7s; Tue, 25 Nov 2014 09:14:56 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XtCCz-0006SD-DI
	for win-pv-devel@lists.xenproject.org; Tue, 25 Nov 2014 09:14:54 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	F7/36-02954-C8844745; Tue, 25 Nov 2014 09:14:52 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-7.tower-27.messagelabs.com!1416906891!14610003!1
X-Originating-IP: [74.125.82.54]
X-SpamReason: No, hits=2.4 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	HTML_30_40,HTML_MESSAGE
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8632 invoked from network); 25 Nov 2014 09:14:51 -0000
Received: from mail-wg0-f54.google.com (HELO mail-wg0-f54.google.com)
	(74.125.82.54)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	25 Nov 2014 09:14:51 -0000
Received: by mail-wg0-f54.google.com with SMTP id l2so232801wgh.41
	for <win-pv-devel@lists.xenproject.org>;
	Tue, 25 Nov 2014 01:14:51 -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
	:subject:references:in-reply-to:content-type;
	bh=hWD4E4d4ijdl5i6BNsbq1S0oE0p4s/FJ0xS4+agRQpY=;
	b=cTYSMkQnAPMaFtmhEGkTU6fkHB50b9sizet9MLRW/Idgp7QkQqtxwU/ol0hzwrYBpt
	LsWEAjHOgal2iS6nese/M1Q/O3dpHdVmFCQjuOpe5Eu6n78T7LwA4QFl5ECsAM2goLDC
	PO4X3ZyU+mhkc/VI1Q+cdWfv/RAC2kZNu0OE/jAtdnlRNfsQUhHYRet2VpNe0FAI0tLq
	v3rDtHYCFX4Ax051r5Kq0X6jEn/kFO01rdJ4p6MmDxLAtD6HDOY1SrgjtDrvO1zVT7PO
	qT9AIlwSP7kMVN986IWuxbd/Vcq5CNNTkCDC/BsjuVIDjoVQMgb2DUz29ZM7k4AMvvyO
	BiLw==
X-Gm-Message-State: ALoCoQnB4KgxBavNGxn6oyD3owiRdorlobaF179zhNdHMFbdaMROU1T0XW6l8YRQrEWTnRf5urvH
X-Received: by 10.180.91.201 with SMTP id cg9mr30156068wib.63.1416906889738;
	Tue, 25 Nov 2014 01:14:49 -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
	lp14sm1923497wic.20.2014.11.25.01.14.47 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Tue, 25 Nov 2014 01:14:49 -0800 (PST)
Message-ID: <5474489F.6020002@m2r.biz>
Date: Tue, 25 Nov 2014 10:15:11 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: multipart/mixed; boundary="===============7468767215425251350=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--===============7468767215425251350==
Content-Type: multipart/alternative;
 boundary="------------050706070707080307050405"

This is a multi-part message in MIME format.
--------------050706070707080307050405
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit

Il 21/11/2014 17:22, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 21 November 2014 16:18
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>> SyncWorker DPC
>>
>> Il 21/11/2014 14:24, Paul Durrant ha scritto:
>>>> -----Original Message-----
>>>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>>>> Sent: 21 November 2014 10:30
>>>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>>>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>>>> SyncWorker DPC
>>>>
>>>> Il 20/11/2014 17:25, Paul Durrant ha scritto:
>>>>> The code has to run with interrupts disabled on all CPUs apart from 0 to
>>>>> corale them across a suspend/resume. Making hypercalls from within
>> that
>>>>> code is thus incompatible with re-populating the hypercall table on
>> resume
>>>>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
>>>>> before actually setting up the hypercall thunks. The only hypercall that
>> the
>>>>> code was actually making was a SCHEDOP_yield and this is trivially
>> replaced
>>>>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
>>>>> VMEXIT handler.
>>>> Thanks for the patch, I tested it, 3 save/restore without crash for now
>>>> and I not saw any regression, I'll report you if I'll see other crash.
>>>>
>>>> There is another problem with the save/restore on windows that is
>>>> driving me crazy for months:
>>>> with qxl vga all works good except after save/restore that make domU
>>>> "freeze" for 2-3 minutes on spice connect (always first time and
>>>> occasional the others), on windows shutdown/reboot and probably other
>>>> operations.
>>>> I'm unable to found the exactly cause of that, is there a way to know if
>>>> is caused by something unexpected in windows pv drivers or other xen
>>>> particular things in xen save/restore? (for example "interrupts disabled
>>>> on all CPUs apart from 0 to corale them across a suspend/resume" if I
>>>> understand good).
>>>>
>>> Is it a network issue? The PV drivers should re-generate gratuitous ARPs
>> and IPv6 neighbour solicitations on resume so things should be ok but it
>> would be worth un-firewalling ICMP so you can check whether the VM is
>> actually pingable.
>>
>> Sorry if I not explain good, spice connect to dom0 as domU's vkvm
>> instead vnc (and is better) and I use it also from thin client as it
>> full features is better that rdp.
>> On windows domUs seems qxl works good as kvm except after xl restore
>> when on spice connect, windows screen resolution change, windows
>> shutdown and probably other things the domU "freeze" for 2-3 minutes and
>> I'm unable to debug it.
> Ah ok. That's almost certainly a qemu problem then.
>
>>> If the VM is really wedged though you can always use xen-hvmcrash from
>> dom0 to try to forcibly crash the domain such that Windows will create a
>> MEMORY.DMP that you can have a look at after reboot.
>>
>> So if I understand good I can simulate a domU crash during the freeze to
>> take a memory dump and see what happen during freeze?
>>
> Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.
>
>    Paul

Thanks for reply.
I tried xen-hvmcrash during "freezee" and did blue screen immediately, 
then if I understand what you wrote above during freeze don't stuck 
waiting for emulation.
I have uploaded the full memory dump generated, can you take a fast look 
to see if you find something strange about pv drivers, or other things 
please?
http://fantu.info/xen/MEMORY.DMP

I tried other 4 save/restore without crash then seems confirmed that 
this patch (Avoid making hypercalls in the SyncWorker DPC) solves 
previous problem.

Thanks for any reply and sorry for my bad english.


--------------050706070707080307050405
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: 7bit

<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Il 21/11/2014 17:22, Paul Durrant ha
      scritto:<br>
    </div>
    <blockquote
cite="mid:9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net"
      type="cite">
      <blockquote type="cite">
        <pre wrap="">-----Original Message-----
From: Fabio Fantoni [<a class="moz-txt-link-freetext" href="mailto:fabio.fantoni@m2r.biz">mailto:fabio.fantoni@m2r.biz</a>]
Sent: 21 November 2014 16:18
To: Paul Durrant; <a class="moz-txt-link-abbreviated" href="mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 21/11/2014 14:24, Paul Durrant ha scritto:
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">-----Original Message-----
From: Fabio Fantoni [<a class="moz-txt-link-freetext" href="mailto:fabio.fantoni@m2r.biz">mailto:fabio.fantoni@m2r.biz</a>]
Sent: 21 November 2014 10:30
To: Paul Durrant; <a class="moz-txt-link-abbreviated" href="mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 20/11/2014 17:25, Paul Durrant ha scritto:
</pre>
            <blockquote type="cite">
              <pre wrap="">The code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">that
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">code is thus incompatible with re-populating the hypercall table on
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">resume
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">the
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">code was actually making was a SCHEDOP_yield and this is trivially
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">replaced
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.
</pre>
            </blockquote>
            <pre wrap="">Thanks for the patch, I tested it, 3 save/restore without crash for now
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU
"freeze" for 2-3 minutes on spice connect (always first time and
occasional the others), on windows shutdown/reboot and probably other
operations.
I'm unable to found the exactly cause of that, is there a way to know if
is caused by something unexpected in windows pv drivers or other xen
particular things in xen save/restore? (for example "interrupts disabled
on all CPUs apart from 0 to corale them across a suspend/resume" if I
understand good).

</pre>
          </blockquote>
          <pre wrap="">Is it a network issue? The PV drivers should re-generate gratuitous ARPs
</pre>
        </blockquote>
        <pre wrap="">and IPv6 neighbour solicitations on resume so things should be ok but it
would be worth un-firewalling ICMP so you can check whether the VM is
actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm
instead vnc (and is better) and I use it also from thin client as it
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore
when on spice connect, windows screen resolution change, windows
shutdown and probably other things the domU "freeze" for 2-3 minutes and
I'm unable to debug it.
</pre>
      </blockquote>
      <pre wrap="">
Ah ok. That's almost certainly a qemu problem then.

</pre>
      <blockquote type="cite">
        <pre wrap="">
</pre>
        <blockquote type="cite">
          <pre wrap="">If the VM is really wedged though you can always use xen-hvmcrash from
</pre>
        </blockquote>
        <pre wrap="">dom0 to try to forcibly crash the domain such that Windows will create a
MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to
take a memory dump and see what happen during freeze?

</pre>
      </blockquote>
      <pre wrap="">
Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul</pre>
    </blockquote>
    <br>
    Thanks for reply.<br>
    I tried xen-hvmcrash during "freezee" and did blue screen <span
      style="direction: ltr;" class="gt-card-ttl-txt">immediately</span>,
    then if I understand what you wrote above during freeze don't stuck
    waiting for emulation.<br>
    I have uploaded the full memory dump generated, can you take a fast
    look to see if you find something strange about pv drivers, or other
    things please?<br>
    <a class="moz-txt-link-freetext" href="http://fantu.info/xen/MEMORY.DMP">http://fantu.info/xen/MEMORY.DMP</a><br>
    <br>
    I tried other 4 save/restore without crash then seems confirmed that
    this patch (Avoid making hypercalls in the SyncWorker DPC) solves
    previous problem.<br>
    <br>
    Thanks for any reply and sorry for my bad english.<br>
    <br>
  </body>
</html>

--------------050706070707080307050405--


--===============7468767215425251350==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Tue Nov 25 09:14:56 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Tue, 25 Nov 2014 09:14: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 1XtCD2-0006SI-7s; Tue, 25 Nov 2014 09:14:56 +0000
Received: from mail6.bemta14.messagelabs.com ([193.109.254.103])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <fabio.fantoni@m2r.biz>) id 1XtCCz-0006SD-DI
	for win-pv-devel@lists.xenproject.org; Tue, 25 Nov 2014 09:14:54 +0000
Received: from [193.109.254.147] by server-4.bemta-14.messagelabs.com id
	F7/36-02954-C8844745; Tue, 25 Nov 2014 09:14:52 +0000
X-Env-Sender: fabio.fantoni@m2r.biz
X-Msg-Ref: server-7.tower-27.messagelabs.com!1416906891!14610003!1
X-Originating-IP: [74.125.82.54]
X-SpamReason: No, hits=2.4 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	HTML_30_40,HTML_MESSAGE
X-StarScan-Received: 
X-StarScan-Version: 6.12.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 8632 invoked from network); 25 Nov 2014 09:14:51 -0000
Received: from mail-wg0-f54.google.com (HELO mail-wg0-f54.google.com)
	(74.125.82.54)
	by server-7.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	25 Nov 2014 09:14:51 -0000
Received: by mail-wg0-f54.google.com with SMTP id l2so232801wgh.41
	for <win-pv-devel@lists.xenproject.org>;
	Tue, 25 Nov 2014 01:14:51 -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
	:subject:references:in-reply-to:content-type;
	bh=hWD4E4d4ijdl5i6BNsbq1S0oE0p4s/FJ0xS4+agRQpY=;
	b=cTYSMkQnAPMaFtmhEGkTU6fkHB50b9sizet9MLRW/Idgp7QkQqtxwU/ol0hzwrYBpt
	LsWEAjHOgal2iS6nese/M1Q/O3dpHdVmFCQjuOpe5Eu6n78T7LwA4QFl5ECsAM2goLDC
	PO4X3ZyU+mhkc/VI1Q+cdWfv/RAC2kZNu0OE/jAtdnlRNfsQUhHYRet2VpNe0FAI0tLq
	v3rDtHYCFX4Ax051r5Kq0X6jEn/kFO01rdJ4p6MmDxLAtD6HDOY1SrgjtDrvO1zVT7PO
	qT9AIlwSP7kMVN986IWuxbd/Vcq5CNNTkCDC/BsjuVIDjoVQMgb2DUz29ZM7k4AMvvyO
	BiLw==
X-Gm-Message-State: ALoCoQnB4KgxBavNGxn6oyD3owiRdorlobaF179zhNdHMFbdaMROU1T0XW6l8YRQrEWTnRf5urvH
X-Received: by 10.180.91.201 with SMTP id cg9mr30156068wib.63.1416906889738;
	Tue, 25 Nov 2014 01:14:49 -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
	lp14sm1923497wic.20.2014.11.25.01.14.47 for <multiple recipients>
	(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
	Tue, 25 Nov 2014 01:14:49 -0800 (PST)
Message-ID: <5474489F.6020002@m2r.biz>
Date: Tue, 25 Nov 2014 10:15:11 +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.2.0
MIME-Version: 1.0
To: Paul Durrant <Paul.Durrant@citrix.com>, 
	"win-pv-devel@lists.xenproject.org" <win-pv-devel@lists.xenproject.org>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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: multipart/mixed; boundary="===============7468767215425251350=="
Sender: win-pv-devel-bounces@lists.xenproject.org
Errors-To: win-pv-devel-bounces@lists.xenproject.org

This is a multi-part message in MIME format.
--===============7468767215425251350==
Content-Type: multipart/alternative;
 boundary="------------050706070707080307050405"

This is a multi-part message in MIME format.
--------------050706070707080307050405
Content-Type: text/plain; charset=windows-1252; format=flowed
Content-Transfer-Encoding: 7bit

Il 21/11/2014 17:22, Paul Durrant ha scritto:
>> -----Original Message-----
>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>> Sent: 21 November 2014 16:18
>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>> SyncWorker DPC
>>
>> Il 21/11/2014 14:24, Paul Durrant ha scritto:
>>>> -----Original Message-----
>>>> From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
>>>> Sent: 21 November 2014 10:30
>>>> To: Paul Durrant; win-pv-devel@lists.xenproject.org
>>>> Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
>>>> SyncWorker DPC
>>>>
>>>> Il 20/11/2014 17:25, Paul Durrant ha scritto:
>>>>> The code has to run with interrupts disabled on all CPUs apart from 0 to
>>>>> corale them across a suspend/resume. Making hypercalls from within
>> that
>>>>> code is thus incompatible with re-populating the hypercall table on
>> resume
>>>>> since it transpites then Xen writes each byte in the page to 0xcc (int 3)
>>>>> before actually setting up the hypercall thunks. The only hypercall that
>> the
>>>>> code was actually making was a SCHEDOP_yield and this is trivially
>> replaced
>>>>> by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
>>>>> VMEXIT handler.
>>>> Thanks for the patch, I tested it, 3 save/restore without crash for now
>>>> and I not saw any regression, I'll report you if I'll see other crash.
>>>>
>>>> There is another problem with the save/restore on windows that is
>>>> driving me crazy for months:
>>>> with qxl vga all works good except after save/restore that make domU
>>>> "freeze" for 2-3 minutes on spice connect (always first time and
>>>> occasional the others), on windows shutdown/reboot and probably other
>>>> operations.
>>>> I'm unable to found the exactly cause of that, is there a way to know if
>>>> is caused by something unexpected in windows pv drivers or other xen
>>>> particular things in xen save/restore? (for example "interrupts disabled
>>>> on all CPUs apart from 0 to corale them across a suspend/resume" if I
>>>> understand good).
>>>>
>>> Is it a network issue? The PV drivers should re-generate gratuitous ARPs
>> and IPv6 neighbour solicitations on resume so things should be ok but it
>> would be worth un-firewalling ICMP so you can check whether the VM is
>> actually pingable.
>>
>> Sorry if I not explain good, spice connect to dom0 as domU's vkvm
>> instead vnc (and is better) and I use it also from thin client as it
>> full features is better that rdp.
>> On windows domUs seems qxl works good as kvm except after xl restore
>> when on spice connect, windows screen resolution change, windows
>> shutdown and probably other things the domU "freeze" for 2-3 minutes and
>> I'm unable to debug it.
> Ah ok. That's almost certainly a qemu problem then.
>
>>> If the VM is really wedged though you can always use xen-hvmcrash from
>> dom0 to try to forcibly crash the domain such that Windows will create a
>> MEMORY.DMP that you can have a look at after reboot.
>>
>> So if I understand good I can simulate a domU crash during the freeze to
>> take a memory dump and see what happen during freeze?
>>
> Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.
>
>    Paul

Thanks for reply.
I tried xen-hvmcrash during "freezee" and did blue screen immediately, 
then if I understand what you wrote above during freeze don't stuck 
waiting for emulation.
I have uploaded the full memory dump generated, can you take a fast look 
to see if you find something strange about pv drivers, or other things 
please?
http://fantu.info/xen/MEMORY.DMP

I tried other 4 save/restore without crash then seems confirmed that 
this patch (Avoid making hypercalls in the SyncWorker DPC) solves 
previous problem.

Thanks for any reply and sorry for my bad english.


--------------050706070707080307050405
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: 7bit

<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Il 21/11/2014 17:22, Paul Durrant ha
      scritto:<br>
    </div>
    <blockquote
cite="mid:9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net"
      type="cite">
      <blockquote type="cite">
        <pre wrap="">-----Original Message-----
From: Fabio Fantoni [<a class="moz-txt-link-freetext" href="mailto:fabio.fantoni@m2r.biz">mailto:fabio.fantoni@m2r.biz</a>]
Sent: 21 November 2014 16:18
To: Paul Durrant; <a class="moz-txt-link-abbreviated" href="mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 21/11/2014 14:24, Paul Durrant ha scritto:
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">-----Original Message-----
From: Fabio Fantoni [<a class="moz-txt-link-freetext" href="mailto:fabio.fantoni@m2r.biz">mailto:fabio.fantoni@m2r.biz</a>]
Sent: 21 November 2014 10:30
To: Paul Durrant; <a class="moz-txt-link-abbreviated" href="mailto:win-pv-devel@lists.xenproject.org">win-pv-devel@lists.xenproject.org</a>
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 20/11/2014 17:25, Paul Durrant ha scritto:
</pre>
            <blockquote type="cite">
              <pre wrap="">The code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">that
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">code is thus incompatible with re-populating the hypercall table on
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">resume
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">the
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">code was actually making was a SCHEDOP_yield and this is trivially
</pre>
            </blockquote>
          </blockquote>
        </blockquote>
        <pre wrap="">replaced
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <blockquote type="cite">
              <pre wrap="">by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.
</pre>
            </blockquote>
            <pre wrap="">Thanks for the patch, I tested it, 3 save/restore without crash for now
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU
"freeze" for 2-3 minutes on spice connect (always first time and
occasional the others), on windows shutdown/reboot and probably other
operations.
I'm unable to found the exactly cause of that, is there a way to know if
is caused by something unexpected in windows pv drivers or other xen
particular things in xen save/restore? (for example "interrupts disabled
on all CPUs apart from 0 to corale them across a suspend/resume" if I
understand good).

</pre>
          </blockquote>
          <pre wrap="">Is it a network issue? The PV drivers should re-generate gratuitous ARPs
</pre>
        </blockquote>
        <pre wrap="">and IPv6 neighbour solicitations on resume so things should be ok but it
would be worth un-firewalling ICMP so you can check whether the VM is
actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm
instead vnc (and is better) and I use it also from thin client as it
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore
when on spice connect, windows screen resolution change, windows
shutdown and probably other things the domU "freeze" for 2-3 minutes and
I'm unable to debug it.
</pre>
      </blockquote>
      <pre wrap="">
Ah ok. That's almost certainly a qemu problem then.

</pre>
      <blockquote type="cite">
        <pre wrap="">
</pre>
        <blockquote type="cite">
          <pre wrap="">If the VM is really wedged though you can always use xen-hvmcrash from
</pre>
        </blockquote>
        <pre wrap="">dom0 to try to forcibly crash the domain such that Windows will create a
MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to
take a memory dump and see what happen during freeze?

</pre>
      </blockquote>
      <pre wrap="">
Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul</pre>
    </blockquote>
    <br>
    Thanks for reply.<br>
    I tried xen-hvmcrash during "freezee" and did blue screen <span
      style="direction: ltr;" class="gt-card-ttl-txt">immediately</span>,
    then if I understand what you wrote above during freeze don't stuck
    waiting for emulation.<br>
    I have uploaded the full memory dump generated, can you take a fast
    look to see if you find something strange about pv drivers, or other
    things please?<br>
    <a class="moz-txt-link-freetext" href="http://fantu.info/xen/MEMORY.DMP">http://fantu.info/xen/MEMORY.DMP</a><br>
    <br>
    I tried other 4 save/restore without crash then seems confirmed that
    this patch (Avoid making hypercalls in the SyncWorker DPC) solves
    previous problem.<br>
    <br>
    Thanks for any reply and sorry for my bad english.<br>
    <br>
  </body>
</html>

--------------050706070707080307050405--


--===============7468767215425251350==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

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


From win-pv-devel-bounces@lists.xenproject.org Fri Nov 28 13:36:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 13:36:49 +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 1XuLj7-0000HZ-6x; Fri, 28 Nov 2014 13:36:49 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1XuLj5-0000HU-5c
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 13:36:47 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	BD/6B-25547-E6A78745; Fri, 28 Nov 2014 13:36:46 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1417181804!14527719!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 27761 invoked from network); 28 Nov 2014 13:36:45 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 13:36:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="197730801"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 13:36:34 +0000
Message-ID: <1417181795-4740-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [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

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);
 
     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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 28 13:36:49 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 13:36:49 +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 1XuLj7-0000HZ-6x; Fri, 28 Nov 2014 13:36:49 +0000
Received: from mail6.bemta3.messagelabs.com ([195.245.230.39])
	by lists.xen.org with esmtp (Exim 4.72)
	(envelope-from <owen.smith@citrix.com>) id 1XuLj5-0000HU-5c
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 13:36:47 +0000
Received: from [85.158.137.68] by server-11.bemta-3.messagelabs.com id
	BD/6B-25547-E6A78745; Fri, 28 Nov 2014 13:36:46 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-16.tower-31.messagelabs.com!1417181804!14527719!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 27761 invoked from network); 28 Nov 2014 13:36:45 -0000
Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63)
	by server-16.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 13:36:45 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="197730801"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 13:36:34 +0000
Message-ID: <1417181795-4740-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: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [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

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);
 
     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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 28 13:36:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 13:36: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 1XuLjA-0000I1-83; Fri, 28 Nov 2014 13:36:52 +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 1XuLj8-0000Hw-Og
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 13:36:50 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	35/7D-22819-27A78745; Fri, 28 Nov 2014 13:36:50 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1417181808!13902677!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 25158 invoked from network); 28 Nov 2014 13:36:49 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 13:36:49 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="197452255"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 13:36:35 +0000
Message-ID: <1417181795-4740-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Fix some SDV issues
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

Fix issues where variables were redefined inside a code block.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenbus/balloon.c | 12 ++++++------
 src/xenbus/fdo.c     |  2 --
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
index dab4d81..1909ef7 100644
--- a/src/xenbus/balloon.c
+++ b/src/xenbus/balloon.c
@@ -466,8 +466,8 @@ BalloonReleasePfnArray(
     Index = 0;
     while (Index < Requested) {
         ULONG       Next = Index;
-        LONGLONG    Start;
-        LONGLONG    End;
+        LONGLONG    StartLL;
+        LONGLONG    EndLL;
         NTSTATUS    status;
 
         while (Next + 1 < Requested) {
@@ -479,14 +479,14 @@ BalloonReleasePfnArray(
             Next++;
         }
 
-        Start = (LONGLONG)Context->PfnArray[Index];
-        End = (LONGLONG)Context->PfnArray[Next];
+        StartLL = (LONGLONG)Context->PfnArray[Index];
+        EndLL = (LONGLONG)Context->PfnArray[Next];
 
         status = XENBUS_RANGE_SET(Put,
                                   &Context->RangeSetInterface,
                                   Context->RangeSet,
-                                  Start,
-                                  End + 1 - Start);
+                                  StartLL,
+                                  EndLL + 1 - StartLL);
         if (!NT_SUCCESS(status))
             break;
 
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index cc0c775..8dd5c20 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -741,8 +741,6 @@ FdoEnumerate(
         PANSI_STRING Class = &Classes[Index];
 
         if (Class->Length != 0) {
-            NTSTATUS    status;
-
             status = PdoCreate(Fdo, Class);
             if (NT_SUCCESS(status))
                 NeedInvalidate = TRUE;
-- 
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 Fri Nov 28 13:36:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 13:36: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 1XuLjA-0000I1-83; Fri, 28 Nov 2014 13:36:52 +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 1XuLj8-0000Hw-Og
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 13:36:50 +0000
Received: from [85.158.139.211] by server-9.bemta-5.messagelabs.com id
	35/7D-22819-27A78745; Fri, 28 Nov 2014 13:36:50 +0000
X-Env-Sender: owen.smith@citrix.com
X-Msg-Ref: server-13.tower-206.messagelabs.com!1417181808!13902677!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 25158 invoked from network); 28 Nov 2014 13:36:49 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 13:36:49 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="197452255"
From: Owen Smith <owen.smith@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 13:36:35 +0000
Message-ID: <1417181795-4740-2-git-send-email-owen.smith@citrix.com>
X-Mailer: git-send-email 1.9.4.msysgit.1
In-Reply-To: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
MIME-Version: 1.0
X-DLP: MIA2
Cc: paul.durrant@citrix.com, Owen Smith <owen.smith@citrix.com>
Subject: [win-pv-devel] [PATCH 2/2] Fix some SDV issues
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

Fix issues where variables were redefined inside a code block.

Signed-off-by: Owen Smith <owen.smith@citrix.com>
---
 src/xenbus/balloon.c | 12 ++++++------
 src/xenbus/fdo.c     |  2 --
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
index dab4d81..1909ef7 100644
--- a/src/xenbus/balloon.c
+++ b/src/xenbus/balloon.c
@@ -466,8 +466,8 @@ BalloonReleasePfnArray(
     Index = 0;
     while (Index < Requested) {
         ULONG       Next = Index;
-        LONGLONG    Start;
-        LONGLONG    End;
+        LONGLONG    StartLL;
+        LONGLONG    EndLL;
         NTSTATUS    status;
 
         while (Next + 1 < Requested) {
@@ -479,14 +479,14 @@ BalloonReleasePfnArray(
             Next++;
         }
 
-        Start = (LONGLONG)Context->PfnArray[Index];
-        End = (LONGLONG)Context->PfnArray[Next];
+        StartLL = (LONGLONG)Context->PfnArray[Index];
+        EndLL = (LONGLONG)Context->PfnArray[Next];
 
         status = XENBUS_RANGE_SET(Put,
                                   &Context->RangeSetInterface,
                                   Context->RangeSet,
-                                  Start,
-                                  End + 1 - Start);
+                                  StartLL,
+                                  EndLL + 1 - StartLL);
         if (!NT_SUCCESS(status))
             break;
 
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index cc0c775..8dd5c20 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -741,8 +741,6 @@ FdoEnumerate(
         PANSI_STRING Class = &Classes[Index];
 
         if (Class->Length != 0) {
-            NTSTATUS    status;
-
             status = PdoCreate(Fdo, Class);
             if (NT_SUCCESS(status))
                 NeedInvalidate = TRUE;
-- 
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 Fri Nov 28 14:08:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:08:44 +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 1XuMDz-0001Uj-1A; Fri, 28 Nov 2014 14:08:43 +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 1XuMDy-0001Ue-9A
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:08:42 +0000
Received: from [193.109.254.147] by server-13.bemta-14.messagelabs.com id
	81/83-02699-9E188745; Fri, 28 Nov 2014 14:08:41 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1417183719!11768382!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 631 invoked from network); 28 Nov 2014 14:08:40 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:08:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27265499"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MCAACB3AIAAEQsggAXCKICABRkA8A==
Date: Fri, 28 Nov 2014 14:08:37 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AD8E@AMSPEX01CL01.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
	<5474489F.6020002@m2r.biz>
In-Reply-To: <5474489F.6020002@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

De-HTMLing...

From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-bounces@lists.xenproject.org] On Behalf Of Fabio Fantoni
Sent: 25 November 2014 09:15
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the SyncWorker DPC

Il 21/11/2014 17:22, Paul Durrant ha scritto:
-----Original Message-----
From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
Sent: 21 November 2014 16:18
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 21/11/2014 14:24, Paul Durrant ha scritto:
-----Original Message-----
From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
Sent: 21 November 2014 10:30
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 20/11/2014 17:25, Paul Durrant ha scritto:
The code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within
that
code is thus incompatible with re-populating the hypercall table on
resume
since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that
the
code was actually making was a SCHEDOP_yield and this is trivially
replaced
by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.
Thanks for the patch, I tested it, 3 save/restore without crash for now
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU
"freeze" for 2-3 minutes on spice connect (always first time and
occasional the others), on windows shutdown/reboot and probably other
operations.
I'm unable to found the exactly cause of that, is there a way to know if
is caused by something unexpected in windows pv drivers or other xen
particular things in xen save/restore? (for example "interrupts disabled
on all CPUs apart from 0 to corale them across a suspend/resume" if I
understand good).

Is it a network issue? The PV drivers should re-generate gratuitous ARPs
and IPv6 neighbour solicitations on resume so things should be ok but it
would be worth un-firewalling ICMP so you can check whether the VM is
actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm
instead vnc (and is better) and I use it also from thin client as it
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore
when on spice connect, windows screen resolution change, windows
shutdown and probably other things the domU "freeze" for 2-3 minutes and
I'm unable to debug it.

Ah ok. That's almost certainly a qemu problem then.


If the VM is really wedged though you can always use xen-hvmcrash from
dom0 to try to forcibly crash the domain such that Windows will create a
MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to
take a memory dump and see what happen during freeze?


Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul

Thanks for reply.
I tried xen-hvmcrash during "freezee" and did blue screen immediately, then if I understand what you wrote above during freeze don't stuck waiting for emulation.
I have uploaded the full memory dump generated, can you take a fast look to see if you find something strange about pv drivers, or other things please?
http://fantu.info/xen/MEMORY.DMP

I tried other 4 save/restore without crash then seems confirmed that this patch (Avoid making hypercalls in the SyncWorker DPC) solves previous problem.

Thanks for any reply and sorry for my bad english.

-----

I grabbed the dump but it seems to be corrupt to the point where WinDBG won't even show me a stack. (I tried downloading twice but got the same result both times). So, unfortunately there's nothing I can do to shed any further light.

  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 Nov 28 14:08:44 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:08:44 +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 1XuMDz-0001Uj-1A; Fri, 28 Nov 2014 14:08:43 +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 1XuMDy-0001Ue-9A
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:08:42 +0000
Received: from [193.109.254.147] by server-13.bemta-14.messagelabs.com id
	81/83-02699-9E188745; Fri, 28 Nov 2014 14:08:41 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-27.messagelabs.com!1417183719!11768382!1
X-Originating-IP: [185.25.65.24]
X-SpamReason: No, hits=2.2 required=7.0 tests=BIZ_TLD,BODY_RANDOM_LONG,
	received_headers: No Received headers
X-StarScan-Received: 
X-StarScan-Version: 6.12.5; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 631 invoked from network); 28 Nov 2014 14:08:40 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:08:40 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27265499"
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] [PATCH] Avoid making hypercalls in the
	SyncWorker DPC
Thread-Index: AQHQBN6vu99DRdYJskumTeB8vdQC4pxq0aUAgABA0MCAACB3AIAAEQsggAXCKICABRkA8A==
Date: Fri, 28 Nov 2014 14:08:37 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AD8E@AMSPEX01CL01.citrite.net>
References: <1416500739-5716-1-git-send-email-paul.durrant@citrix.com>
	<546F141C.9010900@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751422@AMSPEX01CL02.citrite.net>
	<546F65B6.6040504@m2r.biz>
	<9AAE0902D5BC7E449B7C8E4E778ABCD025751809@AMSPEX01CL02.citrite.net>
	<5474489F.6020002@m2r.biz>
In-Reply-To: <5474489F.6020002@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
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
 SyncWorker DPC
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

De-HTMLing...

From: win-pv-devel-bounces@lists.xenproject.org [mailto:win-pv-devel-bounces@lists.xenproject.org] On Behalf Of Fabio Fantoni
Sent: 25 November 2014 09:15
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the SyncWorker DPC

Il 21/11/2014 17:22, Paul Durrant ha scritto:
-----Original Message-----
From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
Sent: 21 November 2014 16:18
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 21/11/2014 14:24, Paul Durrant ha scritto:
-----Original Message-----
From: Fabio Fantoni [mailto:fabio.fantoni@m2r.biz]
Sent: 21 November 2014 10:30
To: Paul Durrant; win-pv-devel@lists.xenproject.org
Subject: Re: [win-pv-devel] [PATCH] Avoid making hypercalls in the
SyncWorker DPC

Il 20/11/2014 17:25, Paul Durrant ha scritto:
The code has to run with interrupts disabled on all CPUs apart from 0 to
corale them across a suspend/resume. Making hypercalls from within
that
code is thus incompatible with re-populating the hypercall table on
resume
since it transpites then Xen writes each byte in the page to 0xcc (int 3)
before actually setting up the hypercall thunks. The only hypercall that
the
code was actually making was a SCHEDOP_yield and this is trivially
replaced
by an _mm_pause intrinsic which calls through to SCHEDOP_yield in the
VMEXIT handler.
Thanks for the patch, I tested it, 3 save/restore without crash for now
and I not saw any regression, I'll report you if I'll see other crash.

There is another problem with the save/restore on windows that is
driving me crazy for months:
with qxl vga all works good except after save/restore that make domU
"freeze" for 2-3 minutes on spice connect (always first time and
occasional the others), on windows shutdown/reboot and probably other
operations.
I'm unable to found the exactly cause of that, is there a way to know if
is caused by something unexpected in windows pv drivers or other xen
particular things in xen save/restore? (for example "interrupts disabled
on all CPUs apart from 0 to corale them across a suspend/resume" if I
understand good).

Is it a network issue? The PV drivers should re-generate gratuitous ARPs
and IPv6 neighbour solicitations on resume so things should be ok but it
would be worth un-firewalling ICMP so you can check whether the VM is
actually pingable.

Sorry if I not explain good, spice connect to dom0 as domU's vkvm
instead vnc (and is better) and I use it also from thin client as it
full features is better that rdp.
On windows domUs seems qxl works good as kvm except after xl restore
when on spice connect, windows screen resolution change, windows
shutdown and probably other things the domU "freeze" for 2-3 minutes and
I'm unable to debug it.

Ah ok. That's almost certainly a qemu problem then.


If the VM is really wedged though you can always use xen-hvmcrash from
dom0 to try to forcibly crash the domain such that Windows will create a
MEMORY.DMP that you can have a look at after reboot.

So if I understand good I can simulate a domU crash during the freeze to
take a memory dump and see what happen during freeze?


Yes. xen-hvmcrash will replace the RIP of each vcpu with 0xf001 thus causing a VM crash if the vcpu is at cpl0. If you are stuck waiting for emulation though you should see the vcpus remain in the blocked state for a long time and even rewriting RIP won't have any effect until the emulation completes.

  Paul

Thanks for reply.
I tried xen-hvmcrash during "freezee" and did blue screen immediately, then if I understand what you wrote above during freeze don't stuck waiting for emulation.
I have uploaded the full memory dump generated, can you take a fast look to see if you find something strange about pv drivers, or other things please?
http://fantu.info/xen/MEMORY.DMP

I tried other 4 save/restore without crash then seems confirmed that this patch (Avoid making hypercalls in the SyncWorker DPC) solves previous problem.

Thanks for any reply and sorry for my bad english.

-----

I grabbed the dump but it seems to be corrupt to the point where WinDBG won't even show me a stack. (I tried downloading twice but got the same result both times). So, unfortunately there's nothing I can do to shed any further light.

  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 Nov 28 14:25:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:25: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 1XuMUa-0001ra-8x; Fri, 28 Nov 2014 14:25: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 1XuMUZ-0001rV-Oc
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:25:51 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	35/F1-27623-FE588745; Fri, 28 Nov 2014 14:25:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1417184750!10800077!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 27859 invoked from network); 28 Nov 2014 14:25:50 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:25:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27266045"
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: [PATCH 2/2] Fix some SDV issues
Thread-Index: AQHQCxBc+NN727BFq0WaIMNR144jdpx2GAhg
Date: Fri, 28 Nov 2014 14:25:49 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE29@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
	<1417181795-4740-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1417181795-4740-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 2/2] Fix some SDV issues
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: 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 2/2] Fix some SDV issues
> 
> Fix issues where variables were redefined inside a code block.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenbus/balloon.c | 12 ++++++------
>  src/xenbus/fdo.c     |  2 --
>  2 files changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
> index dab4d81..1909ef7 100644
> --- a/src/xenbus/balloon.c
> +++ b/src/xenbus/balloon.c
> @@ -466,8 +466,8 @@ BalloonReleasePfnArray(
>      Index = 0;
>      while (Index < Requested) {
>          ULONG       Next = Index;
> -        LONGLONG    Start;
> -        LONGLONG    End;
> +        LONGLONG    StartLL;
> +        LONGLONG    EndLL;
>          NTSTATUS    status;
> 
>          while (Next + 1 < Requested) {
> @@ -479,14 +479,14 @@ BalloonReleasePfnArray(
>              Next++;
>          }
> 
> -        Start = (LONGLONG)Context->PfnArray[Index];
> -        End = (LONGLONG)Context->PfnArray[Next];
> +        StartLL = (LONGLONG)Context->PfnArray[Index];
> +        EndLL = (LONGLONG)Context->PfnArray[Next];
> 

TBH I think we can just lose these variables. I'll re-work the patch to do that.

  Paul

>          status = XENBUS_RANGE_SET(Put,
>                                    &Context->RangeSetInterface,
>                                    Context->RangeSet,
> -                                  Start,
> -                                  End + 1 - Start);
> +                                  StartLL,
> +                                  EndLL + 1 - StartLL);
>          if (!NT_SUCCESS(status))
>              break;
> 
> diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
> index cc0c775..8dd5c20 100644
> --- a/src/xenbus/fdo.c
> +++ b/src/xenbus/fdo.c
> @@ -741,8 +741,6 @@ FdoEnumerate(
>          PANSI_STRING Class = &Classes[Index];
> 
>          if (Class->Length != 0) {
> -            NTSTATUS    status;
> -
>              status = PdoCreate(Fdo, Class);
>              if (NT_SUCCESS(status))
>                  NeedInvalidate = TRUE;
> --
> 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 Fri Nov 28 14:25:52 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:25: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 1XuMUa-0001ra-8x; Fri, 28 Nov 2014 14:25: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 1XuMUZ-0001rV-Oc
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:25:51 +0000
Received: from [85.158.137.68] by server-13.bemta-3.messagelabs.com id
	35/F1-27623-FE588745; Fri, 28 Nov 2014 14:25:51 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-9.tower-31.messagelabs.com!1417184750!10800077!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 27859 invoked from network); 28 Nov 2014 14:25:50 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-9.tower-31.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:25:50 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27266045"
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: [PATCH 2/2] Fix some SDV issues
Thread-Index: AQHQCxBc+NN727BFq0WaIMNR144jdpx2GAhg
Date: Fri, 28 Nov 2014 14:25:49 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE29@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
	<1417181795-4740-2-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1417181795-4740-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 2/2] Fix some SDV issues
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: 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 2/2] Fix some SDV issues
> 
> Fix issues where variables were redefined inside a code block.
> 
> Signed-off-by: Owen Smith <owen.smith@citrix.com>
> ---
>  src/xenbus/balloon.c | 12 ++++++------
>  src/xenbus/fdo.c     |  2 --
>  2 files changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
> index dab4d81..1909ef7 100644
> --- a/src/xenbus/balloon.c
> +++ b/src/xenbus/balloon.c
> @@ -466,8 +466,8 @@ BalloonReleasePfnArray(
>      Index = 0;
>      while (Index < Requested) {
>          ULONG       Next = Index;
> -        LONGLONG    Start;
> -        LONGLONG    End;
> +        LONGLONG    StartLL;
> +        LONGLONG    EndLL;
>          NTSTATUS    status;
> 
>          while (Next + 1 < Requested) {
> @@ -479,14 +479,14 @@ BalloonReleasePfnArray(
>              Next++;
>          }
> 
> -        Start = (LONGLONG)Context->PfnArray[Index];
> -        End = (LONGLONG)Context->PfnArray[Next];
> +        StartLL = (LONGLONG)Context->PfnArray[Index];
> +        EndLL = (LONGLONG)Context->PfnArray[Next];
> 

TBH I think we can just lose these variables. I'll re-work the patch to do that.

  Paul

>          status = XENBUS_RANGE_SET(Put,
>                                    &Context->RangeSetInterface,
>                                    Context->RangeSet,
> -                                  Start,
> -                                  End + 1 - Start);
> +                                  StartLL,
> +                                  EndLL + 1 - StartLL);
>          if (!NT_SUCCESS(status))
>              break;
> 
> diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
> index cc0c775..8dd5c20 100644
> --- a/src/xenbus/fdo.c
> +++ b/src/xenbus/fdo.c
> @@ -741,8 +741,6 @@ FdoEnumerate(
>          PANSI_STRING Class = &Classes[Index];
> 
>          if (Class->Length != 0) {
> -            NTSTATUS    status;
> -
>              status = PdoCreate(Fdo, Class);
>              if (NT_SUCCESS(status))
>                  NeedInvalidate = TRUE;
> --
> 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 Fri Nov 28 14:28:55 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:28: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 1XuMXX-0001sG-Gi; Fri, 28 Nov 2014 14:28: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 1XuMXW-0001sB-Nc
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:28:54 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	D4/9F-19763-5A688745; Fri, 28 Nov 2014 14:28:53 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1417184932!8486575!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7145 invoked from network); 28 Nov 2014 14:28:52 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:28:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27266137"
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: [PATCH 1/2] Add registry setting for removable capability of PDOs
Thread-Index: AQHQCxBbbiDmM16F+UimTo3IMPSEMJx2GJXg
Date: Fri, 28 Nov 2014 14:28:51 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1417181795-4740-1-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/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: 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.

  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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 28 14:28:55 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 14:28: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 1XuMXX-0001sG-Gi; Fri, 28 Nov 2014 14:28: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 1XuMXW-0001sB-Nc
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 14:28:54 +0000
Received: from [85.158.139.211] by server-14.bemta-5.messagelabs.com id
	D4/9F-19763-5A688745; Fri, 28 Nov 2014 14:28:53 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-14.tower-206.messagelabs.com!1417184932!8486575!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.4; banners=-,-,-
X-VirusChecked: Checked
Received: (qmail 7145 invoked from network); 28 Nov 2014 14:28:52 -0000
Received: from smtp.ctxuk.citrix.com (HELO SMTP.EU.CITRIX.COM) (185.25.65.24)
	by server-14.tower-206.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 14:28:52 -0000
X-IronPort-AV: E=Sophos;i="5.07,477,1413244800"; d="scan'208";a="27266137"
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: [PATCH 1/2] Add registry setting for removable capability of PDOs
Thread-Index: AQHQCxBbbiDmM16F+UimTo3IMPSEMJx2GJXg
Date: Fri, 28 Nov 2014 14:28:51 +0000
Message-ID: <9AAE0902D5BC7E449B7C8E4E778ABCD02576AE4E@AMSPEX01CL01.citrite.net>
References: <1417181795-4740-1-git-send-email-owen.smith@citrix.com>
In-Reply-To: <1417181795-4740-1-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/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: 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.

  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

From win-pv-devel-bounces@lists.xenproject.org Fri Nov 28 17:41:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 17:41:31 +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 1XuPXv-0000xy-Ec; Fri, 28 Nov 2014 17:41:31 +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 1XuPXu-0000xt-Am
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 17:41:30 +0000
Received: from [193.109.254.147] by server-2.bemta-14.messagelabs.com id
	B2/AF-02957-9C3B8745; Fri, 28 Nov 2014 17:41:29 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-27.messagelabs.com!1417196487!11817675!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 5649 invoked from network); 28 Nov 2014 17:41:28 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 17:41:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,478,1413244800"; d="scan'208";a="197509573"
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.181.6;
	Fri, 28 Nov 2014 12:41:26 -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 1XuPXq-0001tZ-EY;
	Fri, 28 Nov 2014 17:41:26 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 17:41:15 +0000
Message-ID: <1417196475-1496-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 v2] Fix some SDV issues
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

Fix issues where variables were redefined inside a code block (by getting
rid of those variables)

Suggested-by: Owen Smith <owen.smith@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/balloon.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
index dab4d81..7c1754c 100644
--- a/src/xenbus/balloon.c
+++ b/src/xenbus/balloon.c
@@ -465,32 +465,17 @@ BalloonReleasePfnArray(
 
     Index = 0;
     while (Index < Requested) {
-        ULONG       Next = Index;
-        LONGLONG    Start;
-        LONGLONG    End;
         NTSTATUS    status;
 
-        while (Next + 1 < Requested) {
-            ASSERT3U((ULONGLONG)Context->PfnArray[Next], <, (ULONGLONG)Context->PfnArray[Next + 1]);
-
-            if ((ULONGLONG)Context->PfnArray[Next + 1] != (ULONGLONG)Context->PfnArray[Next] + 1)
-                break;
-
-            Next++;
-        }
-
-        Start = (LONGLONG)Context->PfnArray[Index];
-        End = (LONGLONG)Context->PfnArray[Next];
-
         status = XENBUS_RANGE_SET(Put,
                                   &Context->RangeSetInterface,
                                   Context->RangeSet,
-                                  Start,
-                                  End + 1 - Start);
+                                  (LONGLONG)Context->PfnArray[Index],
+                                  1);
         if (!NT_SUCCESS(status))
             break;
 
-        Index = Next + 1;
+        Index++;
     }
     Requested = Index;
 
-- 
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 Nov 28 17:41:31 2014
Return-path: <win-pv-devel-bounces@lists.xenproject.org>
Envelope-to: archives@lists.xenproject.org
Delivery-date: Fri, 28 Nov 2014 17:41:31 +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 1XuPXv-0000xy-Ec; Fri, 28 Nov 2014 17:41:31 +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 1XuPXu-0000xt-Am
	for win-pv-devel@lists.xenproject.org; Fri, 28 Nov 2014 17:41:30 +0000
Received: from [193.109.254.147] by server-2.bemta-14.messagelabs.com id
	B2/AF-02957-9C3B8745; Fri, 28 Nov 2014 17:41:29 +0000
X-Env-Sender: Paul.Durrant@citrix.com
X-Msg-Ref: server-13.tower-27.messagelabs.com!1417196487!11817675!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 5649 invoked from network); 28 Nov 2014 17:41:28 -0000
Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89)
	by server-13.tower-27.messagelabs.com with RC4-SHA encrypted SMTP;
	28 Nov 2014 17:41:28 -0000
X-IronPort-AV: E=Sophos;i="5.07,478,1413244800"; d="scan'208";a="197509573"
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.181.6;
	Fri, 28 Nov 2014 12:41:26 -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 1XuPXq-0001tZ-EY;
	Fri, 28 Nov 2014 17:41:26 +0000
From: Paul Durrant <paul.durrant@citrix.com>
To: <win-pv-devel@lists.xenproject.org>
Date: Fri, 28 Nov 2014 17:41:15 +0000
Message-ID: <1417196475-1496-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 v2] Fix some SDV issues
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

Fix issues where variables were redefined inside a code block (by getting
rid of those variables)

Suggested-by: Owen Smith <owen.smith@citrix.com>
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
---
 src/xenbus/balloon.c | 21 +++------------------
 1 file changed, 3 insertions(+), 18 deletions(-)

diff --git a/src/xenbus/balloon.c b/src/xenbus/balloon.c
index dab4d81..7c1754c 100644
--- a/src/xenbus/balloon.c
+++ b/src/xenbus/balloon.c
@@ -465,32 +465,17 @@ BalloonReleasePfnArray(
 
     Index = 0;
     while (Index < Requested) {
-        ULONG       Next = Index;
-        LONGLONG    Start;
-        LONGLONG    End;
         NTSTATUS    status;
 
-        while (Next + 1 < Requested) {
-            ASSERT3U((ULONGLONG)Context->PfnArray[Next], <, (ULONGLONG)Context->PfnArray[Next + 1]);
-
-            if ((ULONGLONG)Context->PfnArray[Next + 1] != (ULONGLONG)Context->PfnArray[Next] + 1)
-                break;
-
-            Next++;
-        }
-
-        Start = (LONGLONG)Context->PfnArray[Index];
-        End = (LONGLONG)Context->PfnArray[Next];
-
         status = XENBUS_RANGE_SET(Put,
                                   &Context->RangeSetInterface,
                                   Context->RangeSet,
-                                  Start,
-                                  End + 1 - Start);
+                                  (LONGLONG)Context->PfnArray[Index],
+                                  1);
         if (!NT_SUCCESS(status))
             break;
 
-        Index = Next + 1;
+        Index++;
     }
     Requested = Index;
 
-- 
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

