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

Re: [win-pv-devel] [PATCH 12/14 v2] Implement ring protocol



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of owen.smith@xxxxxxxxxx
> Sent: 23 February 2018 14:22
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Owen Smith <owen.smith@xxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH 12/14 v2] Implement ring protocol
> 
> From: Owen Smith <owen.smith@xxxxxxxxxx>
> 
> Adds ring.h/.c which implements the console ring protocol and
> handles the cancel safe queues for the outstanding read/write IRPs.
> Connect the ring with the state protocol in the frontend.
> Also fixes frontend state transitions to get allow the ring to
> connect and operate correctly.
> 
> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
>  src/xencons/frontend.c         |  227 +++++----
>  src/xencons/ring.c             | 1064
> ++++++++++++++++++++++++++++++++++++++++
>  src/xencons/ring.h             |   96 ++++
>  vs2015/xencons/xencons.vcxproj |    1 +
>  vs2017/xencons/xencons.vcxproj |    1 +
>  5 files changed, 1306 insertions(+), 83 deletions(-)
>  create mode 100755 src/xencons/ring.c
>  create mode 100755 src/xencons/ring.h
> 
> diff --git a/src/xencons/frontend.c b/src/xencons/frontend.c
> index a6e57d1..f7d3b23 100755
> --- a/src/xencons/frontend.c
> +++ b/src/xencons/frontend.c
> @@ -44,6 +44,7 @@
> 
>  #include "driver.h"
>  #include "frontend.h"
> +#include "ring.h"
>  #include "thread.h"
>  #include "dbg_print.h"
>  #include "assert.h"
> @@ -82,6 +83,8 @@ struct _XENCONS_FRONTEND {
>      PXENBUS_SUSPEND_CALLBACK    SuspendCallback;
>      PXENBUS_DEBUG_CALLBACK      DebugCallback;
>      PXENBUS_STORE_WATCH         Watch;
> +
> +    PXENCONS_RING               Ring;
>  };
> 
>  static const PCHAR
> @@ -592,11 +595,21 @@ FrontendClose(
>          if (!FrontendIsOnline(Frontend))
>              break;
> 
> -        FrontendSetXenbusState(Frontend,
> -                               XenbusStateClosed);
> -
>          FrontendWaitForBackendXenbusStateChange(Frontend,
>                                                  &State);
> +
> +        switch (State) {
> +        case XenbusStateClosing:
> +            FrontendSetXenbusState(Frontend,
> +                                    XenbusStateClosed);
> +            break;
> +        case XenbusStateClosed:
> +            break;
> +        default:
> +            FrontendSetXenbusState(Frontend,
> +                                   XenbusStateClosing);
> +            break;
> +        }
>      }
> 
>      FrontendReleaseBackend(Frontend);
> @@ -631,11 +644,20 @@ FrontendPrepare(
>          if (!FrontendIsOnline(Frontend))
>              break;
> 
> -        FrontendSetXenbusState(Frontend,
> -                               XenbusStateInitialising);
> -
>          FrontendWaitForBackendXenbusStateChange(Frontend,
>                                                  &State);
> +        switch (State) {
> +        case XenbusStateInitWait:
> +            break;
> +        case XenbusStateClosed:
> +            FrontendSetXenbusState(Frontend,
> +                                   XenbusStateClosed);
> +            break;
> +        default:
> +            FrontendSetXenbusState(Frontend,
> +                                    XenbusStateInitialising);
> +            break;
> +        }
>      }
> 
>      status = STATUS_UNSUCCESSFUL;
> @@ -725,7 +747,9 @@ FrontendConnect(
>      if (!NT_SUCCESS(status))
>          goto fail2;
> 
> -    // TODO: Connect Ring
> +    status = RingConnect(Frontend->Ring);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> 
>      Attempt = 0;
>      do {
> @@ -737,7 +761,10 @@ FrontendConnect(
>          if (!NT_SUCCESS(status))
>              break;
> 
> -        // TODO: StoreWrite Ring
> +        status = RingStoreWrite(Frontend->Ring,
> +                                Transaction);
> +        if (!NT_SUCCESS(status))
> +            goto abort;
> 
>          status = XENBUS_STORE(TransactionEnd,
>                                &Frontend->StoreInterface,
> @@ -748,12 +775,12 @@ FrontendConnect(
> 
>          continue;
> 
> -    //abort:
> -    //    (VOID)XENBUS_STORE(TransactionEnd,
> -    //                       &Frontend->StoreInterface,
> -    //                       Transaction,
> -    //                       FALSE);
> -    //    break;
> +    abort:
> +        (VOID)XENBUS_STORE(TransactionEnd,
> +                           &Frontend->StoreInterface,
> +                           Transaction,
> +                           FALSE);
> +        break;
>      } while (status == STATUS_RETRY);
> 
>      if (!NT_SUCCESS(status))
> @@ -764,11 +791,24 @@ FrontendConnect(
>          if (!FrontendIsOnline(Frontend))
>              break;
> 
> -        FrontendSetXenbusState(Frontend,
> -                               XenbusStateConnected);
> -
>          FrontendWaitForBackendXenbusStateChange(Frontend,
>                                                  &State);
> +
> +        switch (State) {
> +        case XenbusStateInitWait:
> +            FrontendSetXenbusState(Frontend,
> +                                   XenbusStateConnected);
> +            break;
> +        case XenbusStateConnected:
> +            break;
> +        case XenbusStateUnknown:
> +        case XenbusStateClosing:
> +        case XenbusStateClosed:
> +            FrontendSetOffline(Frontend);
> +            break;
> +        default:
> +            break;
> +        }
>      }
> 
>      status = STATUS_UNSUCCESSFUL;
> @@ -784,7 +824,7 @@ FrontendConnect(
>      if (NT_SUCCESS(status)) {
>          Length = (ULONG)strlen(Buffer);
> 
> -        Frontend->Name = __FrontendAllocate(Length);
> +        Frontend->Name = __FrontendAllocate(Length + 1);
>          if (Frontend->Name)
>              RtlCopyMemory(Frontend->Name, Buffer, Length);
> 
> @@ -802,7 +842,7 @@ FrontendConnect(
>      if (NT_SUCCESS(status)) {
>          Length = (ULONG)strlen(Buffer);
> 
> -        Frontend->Protocol = __FrontendAllocate(Length);
> +        Frontend->Protocol = __FrontendAllocate(Length + 1);
>          if (Frontend->Protocol)
>              RtlCopyMemory(Frontend->Protocol, Buffer, Length);
> 
> @@ -820,12 +860,21 @@ fail5:
>  fail4:
>      Error("fail4\n");
> 
> -//fail3:
> +    RingDisconnect(Frontend->Ring);
> +
> +fail3:
>      Error("fail3\n");
> 
> +    XENBUS_DEBUG(Deregister,
> +                 &Frontend->DebugInterface,
> +                 Frontend->DebugCallback);
> +    Frontend->DebugCallback = NULL;
> +
>  fail2:
>      Error("fail2\n");
> 
> +    XENBUS_DEBUG(Release, &Frontend->DebugInterface);
> +
>  fail1:
>      Error("fail1 (%08x)\n", status);
> 
> @@ -845,7 +894,7 @@ FrontendDisconnect(
>      __FrontendFree(Frontend->Name);
>      Frontend->Name = NULL;
> 
> -    // TODO: Disconnect Ring
> +    RingDisconnect(Frontend->Ring);
> 
>      XENBUS_DEBUG(Deregister,
>                   &Frontend->DebugInterface,
> @@ -862,14 +911,22 @@ FrontendEnable(
>      IN  PXENCONS_FRONTEND    Frontend
>      )
>  {
> +    NTSTATUS                status;
> +
>      Trace("====>\n");
> 
> -    UNREFERENCED_PARAMETER(Frontend);
> -    // TODO: Enable Ring
> +    status = RingEnable(Frontend->Ring);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> 
>      Trace("<====\n");
> 
>      return STATUS_SUCCESS;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
>  }
> 
>  static VOID
> @@ -879,8 +936,7 @@ FrontendDisable(
>  {
>      Trace("====>\n");
> 
> -    UNREFERENCED_PARAMETER(Frontend);
> -    // TODO: Disable Ring
> +    RingDisable(Frontend->Ring);
> 
>      Trace("<====\n");
>  }
> @@ -1048,6 +1104,7 @@ __FrontendResume(
> 
>      ASSERT3U(Frontend->State, == , FRONTEND_UNKNOWN);
>      UNREFERENCED_PARAMETER(Frontend);
> +    // Current backends dont like re-opening after being closed
>      //(VOID)FrontendSetState(Frontend, FRONTEND_CLOSED);
>  }
> 
> @@ -1059,7 +1116,7 @@ __FrontendSuspend(
>      ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
> 
>      UNREFERENCED_PARAMETER(Frontend);
> -    //(VOID)FrontendSetState(Frontend, FRONTEND_UNKNOWN);
> +    (VOID)FrontendSetState(Frontend, FRONTEND_UNKNOWN);
>  }
> 
>  static DECLSPEC_NOINLINE VOID
> @@ -1186,7 +1243,8 @@ FrontendDestroy(
> 
>      RtlZeroMemory(&Frontend->EjectEvent, sizeof(KEVENT));
> 
> -    // TODO: Teardown Ring
> +    RingDestroy(Frontend->Ring);
> +    Frontend->Ring = NULL;
> 
>      RtlZeroMemory(&Frontend->StoreInterface,
>                    sizeof(XENBUS_STORE_INTERFACE));
> @@ -1294,40 +1352,42 @@ FrontendAbiAcquire(
>      )
>  {
>      PXENCONS_FRONTEND               Frontend =
> (PXENCONS_FRONTEND)Context;
> +    LONG                            Count;
>      KIRQL                           Irql;
>      NTSTATUS                        status;
> 
> -    InterlockedIncrement(&Frontend->RefCount);
> +    Count = InterlockedIncrement(&Frontend->RefCount);
> +    if (Count == 2) {
> +        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
> -    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> +        status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface);
> +        if (!NT_SUCCESS(status))
> +            goto fail1;
> 
> -    status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface);
> -    if (!NT_SUCCESS(status))
> -        goto fail1;
> +        __FrontendResume(Frontend);
> 
> -    __FrontendResume(Frontend);
> +        status = XENBUS_SUSPEND(Register,
> +                                &Frontend->SuspendInterface,
> +                                SUSPEND_CALLBACK_LATE,
> +                                FrontendSuspendCallback,
> +                                Frontend,
> +                                &Frontend->SuspendCallback);
> +        if (!NT_SUCCESS(status))
> +            goto fail2;
> 
> -    status = XENBUS_SUSPEND(Register,
> -                            &Frontend->SuspendInterface,
> -                            SUSPEND_CALLBACK_LATE,
> -                            FrontendSuspendCallback,
> -                            Frontend,
> -                            &Frontend->SuspendCallback);
> -    if (!NT_SUCCESS(status))
> -        goto fail2;
> +        KeLowerIrql(Irql);
> 
> -    KeLowerIrql(Irql);
> +        KeClearEvent(&Frontend->EjectEvent);
> +        ThreadWake(Frontend->EjectThread);
> 
> -    KeClearEvent(&Frontend->EjectEvent);
> -    ThreadWake(Frontend->EjectThread);
> -
> -    Trace("waiting for eject thread\n");
> +        Trace("waiting for eject thread\n");
> 
> -    (VOID)KeWaitForSingleObject(&Frontend->EjectEvent,
> -                                Executive,
> -                                KernelMode,
> -                                FALSE,
> -                                NULL);
> +        (VOID)KeWaitForSingleObject(&Frontend->EjectEvent,
> +                                    Executive,
> +                                    KernelMode,
> +                                    FALSE,
> +                                    NULL);
> +    }
> 
>      return STATUS_SUCCESS;
> 
> @@ -1358,31 +1418,31 @@ FrontendAbiRelease(
>      KIRQL                           Irql;
> 
>      Count = InterlockedDecrement(&Frontend->RefCount);
> +    if (Count == 1) {
> +        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> 
> -    KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> -
> -    XENBUS_SUSPEND(Deregister,
> -                   &Frontend->SuspendInterface,
> -                   Frontend->SuspendCallback);
> -    Frontend->SuspendCallback = NULL;
> -
> -    __FrontendSuspend(Frontend);
> +        XENBUS_SUSPEND(Deregister,
> +                       &Frontend->SuspendInterface,
> +                       Frontend->SuspendCallback);
> +        Frontend->SuspendCallback = NULL;
> 
> -    XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
> +        __FrontendSuspend(Frontend);
> 
> -    KeLowerIrql(Irql);
> +        XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
> 
> -    KeClearEvent(&Frontend->EjectEvent);
> -    ThreadWake(Frontend->EjectThread);
> +        KeLowerIrql(Irql);
> 
> -    Trace("waiting for eject thread\n");
> +        KeClearEvent(&Frontend->EjectEvent);
> +        ThreadWake(Frontend->EjectThread);
> 
> -    (VOID)KeWaitForSingleObject(&Frontend->EjectEvent,
> -                                Executive,
> -                                KernelMode,
> -                                FALSE,
> -                                NULL);
> +        Trace("waiting for eject thread\n");
> 
> +        (VOID)KeWaitForSingleObject(&Frontend->EjectEvent,
> +                                    Executive,
> +                                    KernelMode,
> +                                    FALSE,
> +                                    NULL);
> +    }
>      if (Count == 0)
>          FrontendDestroy(Frontend);
>  }
> @@ -1403,9 +1463,7 @@ FrontendAbiD3ToD0(
>  {
>      PXENCONS_FRONTEND               Frontend =
> (PXENCONS_FRONTEND)Context;
> 
> -    UNREFERENCED_PARAMETER(Frontend);
> -    //return FrontendSetState(Frontend, FRONTEND_ENABLED);
> -    return STATUS_SUCCESS;
> +    return FrontendSetState(Frontend, FRONTEND_ENABLED);
>  }
> 
>  static VOID
> @@ -1416,7 +1474,7 @@ FrontendAbiD0ToD3(
>      PXENCONS_FRONTEND               Frontend =
> (PXENCONS_FRONTEND)Context;
> 
>      UNREFERENCED_PARAMETER(Frontend);
> -    //(VOID) FrontendSetState(Frontend, FRONTEND_CLOSED);
> +    (VOID) FrontendSetState(Frontend, FRONTEND_CLOSED);
>  }
> 
>  static NTSTATUS
> @@ -1425,9 +1483,9 @@ FrontendAbiOpen(
>      IN  PFILE_OBJECT                FileObject
>      )
>  {
> -    UNREFERENCED_PARAMETER(Context);
> -    UNREFERENCED_PARAMETER(FileObject);
> -    return STATUS_SUCCESS;
> +    PXENCONS_FRONTEND               Frontend =
> (PXENCONS_FRONTEND)Context;
> +
> +    return RingOpen(Frontend->Ring, FileObject);
>  }
> 
>  static NTSTATUS
> @@ -1436,9 +1494,9 @@ FrontendAbiClose(
>      IN  PFILE_OBJECT                FileObject
>      )
>  {
> -    UNREFERENCED_PARAMETER(Context);
> -    UNREFERENCED_PARAMETER(FileObject);
> -    return STATUS_SUCCESS;
> +    PXENCONS_FRONTEND               Frontend =
> (PXENCONS_FRONTEND)Context;
> +
> +    return RingClose(Frontend->Ring, FileObject);
>  }
> 
>  static NTSTATUS
> @@ -1455,7 +1513,7 @@ FrontendAbiPutQueue(
>      switch (StackLocation->MajorFunction) {
>      case IRP_MJ_READ:
>      case IRP_MJ_WRITE:
> -        return STATUS_DEVICE_NOT_READY;
> +        return RingPutQueue(Frontend->Ring, Irp);
> 
>      case IRP_MJ_DEVICE_CONTROL:
>          return FrontendGetProperty(Frontend, Irp);
> @@ -1526,7 +1584,9 @@ FrontendCreate(
>      FdoGetSuspendInterface(PdoGetFdo(Pdo), &Frontend-
> >SuspendInterface);
>      FdoGetStoreInterface(PdoGetFdo(Pdo), &Frontend->StoreInterface);
> 
> -    // TODO: Initialize Ring
> +    status = RingCreate(Frontend, &Frontend->Ring);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> 
>      KeInitializeEvent(&Frontend->EjectEvent, NotificationEvent, FALSE);
> 
> @@ -1546,9 +1606,10 @@ fail5:
> 
>      RtlZeroMemory(&Frontend->EjectEvent, sizeof(KEVENT));
> 
> -    // TODO: Teardown Ring
> +    RingDestroy(Frontend->Ring);
> +    Frontend->Ring = NULL;
> 
> -//fail4:
> +fail4:
>      Error("fail4\n");
> 
>      RtlZeroMemory(&Frontend->StoreInterface,
> diff --git a/src/xencons/ring.c b/src/xencons/ring.c
> new file mode 100755
> index 0000000..20c4520
> --- /dev/null
> +++ b/src/xencons/ring.c
> @@ -0,0 +1,1064 @@
> +/* Copyright (c) Citrix Systems Inc.
> +* All rights reserved.
> +*
> +* Redistribution and use in source and binary forms,
> +* with or without modification, are permitted provided
> +* that the following conditions are met:
> +*
> +* *   Redistributions of source code must retain the above
> +*     copyright notice, this list of conditions and the
> +*     following disclaimer.
> +* *   Redistributions in binary form must reproduce the above
> +*     copyright notice, this list of conditions and the
> +*     following disclaimer in the documentation and/or other
> +*     materials provided with the distribution.
> +*
> +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
> +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> +* SUCH DAMAGE.
> +*/
> +
> +#include <ntddk.h>
> +#include <ntstrsafe.h>
> +#include <stdlib.h>
> +
> +#include <xen.h>
> +#include <debug_interface.h>
> +#include <store_interface.h>
> +#include <gnttab_interface.h>
> +#include <evtchn_interface.h>
> +
> +#include "frontend.h"
> +#include "ring.h"
> +#include "names.h"
> +#include "dbg_print.h"
> +#include "assert.h"
> +#include "util.h"
> +
> +typedef struct _XENCONS_QUEUE {
> +    IO_CSQ                  Csq;
> +    LIST_ENTRY              List;
> +    KSPIN_LOCK               Lock;
> +} XENCONS_QUEUE, *PXENCONS_QUEUE;
> +
> +struct _XENCONS_RING {
> +    PXENCONS_FRONTEND           Frontend;
> +    BOOLEAN                     Connected;
> +    BOOLEAN                     Enabled;
> +    KSPIN_LOCK                  Lock;
> +    PXENBUS_GNTTAB_CACHE        GnttabCache;
> +    struct xencons_interface    *Shared;
> +    PMDL                        Mdl;
> +    PXENBUS_GNTTAB_ENTRY        Entry;
> +    KDPC                        Dpc;
> +    ULONG                       Dpcs;
> +    ULONG                       Events;
> +    PXENBUS_EVTCHN_CHANNEL      Channel;
> +    XENBUS_GNTTAB_INTERFACE     GnttabInterface;
> +    XENBUS_STORE_INTERFACE      StoreInterface;
> +    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
> +    XENBUS_DEBUG_INTERFACE      DebugInterface;
> +    PXENBUS_DEBUG_CALLBACK      DebugCallback;
> +    XENCONS_QUEUE               Read;
> +    XENCONS_QUEUE               Write;
> +    ULONG                       BytesRead;
> +    ULONG                       BytesWritten;
> +};
> +
> +#define MAXNAMELEN          128
> +#define XENCONS_RING_TAG  'GNIR'
> +
> +static FORCEINLINE PVOID
> +__RingAllocate(
> +    IN  ULONG   Length
> +    )
> +{
> +    return __AllocatePoolWithTag(NonPagedPool, Length,
> XENCONS_RING_TAG);
> +}
> +
> +static FORCEINLINE VOID
> +__RingFree(
> +    IN  PVOID   Buffer
> +    )
> +{
> +    __FreePoolWithTag(Buffer, XENCONS_RING_TAG);
> +}
> +
> +IO_CSQ_INSERT_IRP_EX RingCsqInsertIrpEx;
> +
> +NTSTATUS
> +RingCsqInsertIrpEx(
> +    IN  PIO_CSQ         Csq,
> +    IN  PIRP            Irp,
> +    IN  PVOID           InsertContext OPTIONAL
> +    )
> +{
> +    BOOLEAN             ReInsert = (BOOLEAN)(ULONG_PTR)InsertContext;
> +    PXENCONS_QUEUE      Queue;
> +
> +    Queue = CONTAINING_RECORD(Csq, XENCONS_QUEUE, Csq);
> +
> +    if (ReInsert) {
> +        // This only occurs if the DPC de-queued the IRP but
> +        // then found the console to be blocked.
> +        InsertHeadList(&Queue->List, &Irp->Tail.Overlay.ListEntry);
> +    } else {
> +        InsertTailList(&Queue->List, &Irp->Tail.Overlay.ListEntry);
> +    }
> +
> +    return STATUS_PENDING;
> +}
> +
> +IO_CSQ_REMOVE_IRP RingCsqRemoveIrp;
> +
> +VOID
> +RingCsqRemoveIrp(
> +    IN  PIO_CSQ     Csq,
> +    IN  PIRP        Irp
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Csq);
> +
> +    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
> +}
> +
> +IO_CSQ_PEEK_NEXT_IRP RingCsqPeekNextIrp;
> +
> +PIRP
> +RingCsqPeekNextIrp(
> +    IN  PIO_CSQ     Csq,
> +    IN  PIRP        Irp,
> +    IN  PVOID       PeekContext OPTIONAL
> +    )
> +{
> +    PXENCONS_QUEUE  Queue;
> +    PLIST_ENTRY     ListEntry;
> +    PIRP            NextIrp;
> +
> +    Queue = CONTAINING_RECORD(Csq, XENCONS_QUEUE, Csq);
> +
> +    ListEntry = (Irp == NULL) ?
> +        Queue->List.Flink :
> +        Irp->Tail.Overlay.ListEntry.Flink;
> +
> +    while (ListEntry != &Queue->List) {
> +        PIO_STACK_LOCATION  StackLocation;
> +
> +        NextIrp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
> +        if (PeekContext == NULL)
> +            return NextIrp;
> +
> +        StackLocation = IoGetCurrentIrpStackLocation(NextIrp);
> +        if (StackLocation->FileObject == (PFILE_OBJECT)PeekContext)
> +            return NextIrp;
> +
> +        ListEntry = ListEntry->Flink;
> +    }
> +
> +    return NULL;
> +}
> +
> +#pragma warning(push)
> +#pragma warning(disable:28167) // function changes IRQL
> +
> +IO_CSQ_ACQUIRE_LOCK RingCsqAcquireLock;
> +
> +VOID
> +RingCsqAcquireLock(
> +    IN  PIO_CSQ     Csq,
> +    OUT PKIRQL      Irql
> +    )
> +{
> +    PXENCONS_QUEUE  Queue;
> +
> +    Queue = CONTAINING_RECORD(Csq, XENCONS_QUEUE, Csq);
> +
> +    KeAcquireSpinLock(&Queue->Lock, Irql);
> +}
> +
> +IO_CSQ_RELEASE_LOCK RingCsqReleaseLock;
> +
> +VOID
> +RingCsqReleaseLock(
> +    IN  PIO_CSQ     Csq,
> +    IN  KIRQL       Irql
> +    )
> +{
> +    PXENCONS_QUEUE  Queue;
> +
> +    Queue = CONTAINING_RECORD(Csq, XENCONS_QUEUE, Csq);
> +
> +    KeReleaseSpinLock(&Queue->Lock, Irql);
> +}
> +
> +#pragma warning(pop)
> +
> +IO_CSQ_COMPLETE_CANCELED_IRP RingCsqCompleteCanceledIrp;
> +
> +VOID
> +RingCsqCompleteCanceledIrp(
> +    IN  PIO_CSQ         Csq,
> +    IN  PIRP            Irp
> +    )
> +{
> +    PIO_STACK_LOCATION  StackLocation;
> +    UCHAR               MajorFunction;
> +
> +    UNREFERENCED_PARAMETER(Csq);
> +
> +    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +    MajorFunction = StackLocation->MajorFunction;
> +
> +    Irp->IoStatus.Information = 0;
> +    Irp->IoStatus.Status = STATUS_CANCELLED;
> +
> +    Trace("CANCELLED (%02x:%s)\n",
> +          MajorFunction,
> +          MajorFunctionName(MajorFunction));
> +
> +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +}
> +
> +static FORCEINLINE VOID
> +__RingCancelRequests(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PFILE_OBJECT    FileObject
> +    )
> +{
> +    for (;;) {
> +        PIRP    Irp;
> +
> +        Irp = IoCsqRemoveNextIrp(&Ring->Read.Csq, FileObject);
> +        if (Irp == NULL)
> +            break;
> +
> +        RingCsqCompleteCanceledIrp(&Ring->Read.Csq, Irp);
> +    }
> +    for (;;) {
> +        PIRP    Irp;
> +
> +        Irp = IoCsqRemoveNextIrp(&Ring->Write.Csq, FileObject);
> +        if (Irp == NULL)
> +            break;
> +
> +        RingCsqCompleteCanceledIrp(&Ring->Write.Csq, Irp);
> +    }
> +}
> +
> +static VOID
> +RingAcquireLock(
> +    IN  PVOID       Argument
> +    )
> +{
> +    PXENCONS_RING   Ring = Argument;
> +
> +    KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
> +}
> +
> +static VOID
> +RingReleaseLock(
> +    IN  PVOID       Argument
> +    )
> +{
> +    PXENCONS_RING   Ring = Argument;
> +
> +#pragma prefast(suppress:26110)
> +    KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
> +}
> +
> +NTSTATUS
> +RingOpen(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PFILE_OBJECT    FileObject
> +    )
> +{
> +    UNREFERENCED_PARAMETER(Ring);
> +    UNREFERENCED_PARAMETER(FileObject);
> +    return STATUS_SUCCESS;
> +}
> +
> +NTSTATUS
> +RingClose(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PFILE_OBJECT    FileObject
> +    )
> +{
> +    __RingCancelRequests(Ring, FileObject);
> +    return STATUS_SUCCESS;
> +}
> +
> +NTSTATUS
> +RingPutQueue(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PIRP            Irp
> +    )
> +{
> +    PIO_STACK_LOCATION  StackLocation;
> +    NTSTATUS            status;
> +
> +    StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +
> +    switch (StackLocation->MajorFunction) {
> +    case IRP_MJ_READ:
> +        status = IoCsqInsertIrpEx(&Ring->Read.Csq,
> +                                  Irp,
> +                                  NULL,
> +                                  (PVOID)FALSE);
> +        break;
> +
> +    case IRP_MJ_WRITE:
> +        status = IoCsqInsertIrpEx(&Ring->Write.Csq,
> +                                  Irp,
> +                                  NULL,
> +                                  (PVOID)FALSE);
> +        break;
> +
> +    default:
> +        ASSERT(FALSE);
> +        status = STATUS_NOT_SUPPORTED; // Keep SDV happy
> +        break;
> +    }
> +    if (status != STATUS_PENDING)
> +        goto fail1;
> +
> +    KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
> +    return STATUS_PENDING;
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +static ULONG
> +RingCopyFromRead(
> +    IN  PXENCONS_RING           Ring,
> +    IN  PCHAR                   Data,
> +    IN  ULONG                   Length
> +    )
> +{
> +    struct xencons_interface    *Shared;
> +    XENCONS_RING_IDX            cons;
> +    XENCONS_RING_IDX            prod;
> +    ULONG                       Offset;
> +
> +    Shared = Ring->Shared;
> +
> +    KeMemoryBarrier();
> +
> +    cons = Shared->in_cons;
> +    prod = Shared->in_prod;
> +
> +    KeMemoryBarrier();
> +
> +    Offset = 0;
> +    while (Length != 0) {
> +        ULONG   Available;
> +        ULONG   Index;
> +        ULONG   CopyLength;
> +
> +        Available = prod - cons;
> +
> +        if (Available == 0)
> +            break;
> +
> +        Index = MASK_XENCONS_IDX(cons, Shared->in);
> +
> +        CopyLength = __min(Length, Available);
> +        CopyLength = __min(CopyLength, sizeof(Shared->in) - Index);
> +
> +        RtlCopyMemory(Data + Offset, &Shared->in[Index], CopyLength);
> +
> +        Offset += CopyLength;
> +        Length -= CopyLength;
> +
> +        cons += CopyLength;
> +    }
> +
> +    KeMemoryBarrier();
> +
> +    Shared->in_cons = cons;
> +
> +    KeMemoryBarrier();
> +
> +    return Offset;
> +}
> +
> +static ULONG
> +RingCopyToWrite(
> +    IN  PXENCONS_RING           Ring,
> +    IN  PCHAR                   Data,
> +    IN  ULONG                   Length
> +    )
> +{
> +    struct xencons_interface    *Shared;
> +    XENCONS_RING_IDX            cons;
> +    XENCONS_RING_IDX            prod;
> +    ULONG                       Offset;
> +
> +    Shared = Ring->Shared;
> +
> +    KeMemoryBarrier();
> +
> +    prod = Shared->out_prod;
> +    cons = Shared->out_cons;
> +
> +    KeMemoryBarrier();
> +
> +    Offset = 0;
> +    while (Length != 0) {
> +        ULONG   Available;
> +        ULONG   Index;
> +        ULONG   CopyLength;
> +
> +        Available = cons + sizeof(Shared->out) - prod;
> +
> +        if (Available == 0)
> +            break;
> +
> +        Index = MASK_XENCONS_IDX(prod, Shared->out);
> +
> +        CopyLength = __min(Length, Available);
> +        CopyLength = __min(CopyLength, sizeof(Shared->out) - Index);
> +
> +        RtlCopyMemory(&Shared->out[Index], Data + Offset, CopyLength);
> +
> +        Offset += CopyLength;
> +        Length -= CopyLength;
> +
> +        prod += CopyLength;
> +    }
> +
> +    KeMemoryBarrier();
> +
> +    Shared->out_prod = prod;
> +
> +    KeMemoryBarrier();
> +
> +    return Offset;
> +}
> +
> +static BOOLEAN
> +RingPoll(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    PIRP                Irp;
> +    PIO_STACK_LOCATION  StackLocation;
> +    ULONG               Length;
> +    PCHAR               Buffer;
> +    NTSTATUS            status;
> +
> +    for (;;) {
> +        ULONG           Read;
> +
> +        Irp = IoCsqRemoveNextIrp(&Ring->Read.Csq, NULL);
> +        if (Irp == NULL)
> +            break;
> +
> +        StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +        ASSERT(StackLocation->MajorFunction == IRP_MJ_READ);
> +
> +        Length = StackLocation->Parameters.Read.Length;
> +        Buffer = Irp->AssociatedIrp.SystemBuffer;
> +
> +        Read = RingCopyFromRead(Ring,
> +                                Buffer,
> +                                Length);
> +        if (Read == 0) {
> +            status = IoCsqInsertIrpEx(&Ring->Read.Csq,
> +                                      Irp,
> +                                      NULL,
> +                                      (PVOID)TRUE);
> +            ASSERT(status == STATUS_PENDING);
> +            break;
> +        }
> +
> +        Ring->BytesRead += Read;
> +
> +        Irp->IoStatus.Information = Read;
> +        Irp->IoStatus.Status = STATUS_SUCCESS;
> +
> +        Trace("COMPLETE (READ) (%u bytes)\n",
> +              Irp->IoStatus.Information);
> +
> +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +    }
> +
> +    for (;;) {
> +        ULONG           Written;
> +
> +        Irp = IoCsqRemoveNextIrp(&Ring->Write.Csq, NULL);
> +        if (Irp == NULL)
> +            break;
> +
> +        StackLocation = IoGetCurrentIrpStackLocation(Irp);
> +        ASSERT(StackLocation->MajorFunction == IRP_MJ_WRITE);
> +
> +        Length = StackLocation->Parameters.Write.Length;
> +        Buffer = Irp->AssociatedIrp.SystemBuffer;
> +
> +        Written = RingCopyToWrite(Ring,
> +                                  Buffer,
> +                                  Length);
> +        if (Written == 0) {
> +            status = IoCsqInsertIrpEx(&Ring->Write.Csq,
> +                                      Irp,
> +                                      NULL,
> +                                      (PVOID)TRUE);
> +            ASSERT(status == STATUS_PENDING);
> +            break;
> +        }
> +
> +        Ring->BytesWritten += Written;
> +
> +        Irp->IoStatus.Information = Written;
> +        Irp->IoStatus.Status = STATUS_SUCCESS;
> +
> +        Trace("COMPLETE (WRITE) (%u bytes)\n",
> +              Irp->IoStatus.Information);
> +
> +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
> +    }
> +
> +    return FALSE;
> +}
> +
> +__drv_functionClass(KDEFERRED_ROUTINE)
> +__drv_maxIRQL(DISPATCH_LEVEL)
> +__drv_minIRQL(PASSIVE_LEVEL)
> +__drv_sameIRQL
> +static VOID
> +RingDpc(
> +    IN  PKDPC               Dpc,
> +    IN  PVOID               Context,
> +    IN  PVOID               Argument1,
> +    IN  PVOID               Argument2
> +    )
> +{
> +    PXENCONS_RING       Ring = Context;
> +
> +    UNREFERENCED_PARAMETER(Dpc);
> +    UNREFERENCED_PARAMETER(Argument1);
> +    UNREFERENCED_PARAMETER(Argument2);
> +
> +    ASSERT(Ring != NULL);
> +
> +    for (;;) {
> +        BOOLEAN Enabled;
> +        BOOLEAN Retry;
> +        KIRQL   Irql;
> +
> +        KeAcquireSpinLock(&Ring->Lock, &Irql);
> +        Enabled = Ring->Enabled;
> +        KeReleaseSpinLock(&Ring->Lock, Irql);
> +
> +        if (!Enabled)
> +            break;
> +
> +        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
> +        Retry = RingPoll(Ring);
> +        KeLowerIrql(Irql);
> +
> +        if (!Retry)
> +            break;
> +    }
> +
> +    (VOID) XENBUS_EVTCHN(Unmask,
> +                         &Ring->EvtchnInterface,
> +                         Ring->Channel,
> +                         FALSE,
> +                         FALSE);
> +}
> +
> +KSERVICE_ROUTINE    RingEvtchnCallback;
> +
> +BOOLEAN
> +RingEvtchnCallback(
> +    IN  PKINTERRUPT InterruptObject,
> +    IN  PVOID       Argument
> +    )
> +{
> +    PXENCONS_RING   Ring = Argument;
> +
> +    UNREFERENCED_PARAMETER(InterruptObject);
> +
> +    ASSERT(Ring != NULL);
> +
> +    Ring->Events++;
> +
> +    if (KeInsertQueueDpc(&Ring->Dpc, NULL, NULL))
> +        Ring->Dpcs++;
> +
> +    return TRUE;
> +}
> +
> +static VOID
> +RingDebugCallback(
> +    IN  PVOID       Argument,
> +    IN  BOOLEAN     Crashing
> +    )
> +{
> +    PXENCONS_RING   Ring = Argument;
> +
> +    UNREFERENCED_PARAMETER(Crashing);
> +
> +    XENBUS_DEBUG(Printf,
> +                 &Ring->DebugInterface,
> +                 "0x%p [%s]\n",
> +                 Ring,
> +                 (Ring->Enabled) ? "ENABLED" : "DISABLED");
> +
> +    // Dump shared ring
> +    XENBUS_DEBUG(Printf,
> +                 &Ring->DebugInterface,
> +                 "SHARED: in_cons = %u in_prod = %u out_cons = %u out_prod =
> %u\n",
> +                 Ring->Shared->in_cons,
> +                 Ring->Shared->in_prod,
> +                 Ring->Shared->out_cons,
> +                 Ring->Shared->out_prod);
> +
> +    XENBUS_DEBUG(Printf,
> +                 &Ring->DebugInterface,
> +                 "BYTES: read = %u written = %u\n",
> +                 Ring->BytesRead,
> +                 Ring->BytesWritten);
> +}
> +
> +NTSTATUS
> +RingEnable(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    Trace("====>\n");
> +
> +    KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
> +    Ring->Enabled = TRUE;
> +    KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
> +
> +    (VOID)KeInsertQueueDpc(&Ring->Dpc, NULL, NULL);
> +
> +    Trace("<====\n");
> +
> +    return STATUS_SUCCESS;
> +}
> +
> +VOID
> +RingDisable(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    Trace("====>\n");
> +
> +    ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL);
> +
> +    KeAcquireSpinLockAtDpcLevel(&Ring->Lock);
> +    Ring->Enabled = FALSE;
> +    KeReleaseSpinLockFromDpcLevel(&Ring->Lock);
> +
> +    Trace("<====\n");
> +}
> +
> +NTSTATUS
> +RingConnect(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    CHAR                Name[MAXNAMELEN];
> +    NTSTATUS            status;
> +
> +    Trace("====>\n");
> +
> +    ASSERT(!Ring->Connected);
> +
> +    status = XENBUS_DEBUG(Acquire, &Ring->DebugInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    status = XENBUS_EVTCHN(Acquire, &Ring->EvtchnInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    status = XENBUS_GNTTAB(Acquire, &Ring->GnttabInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
> +    status = XENBUS_STORE(Acquire, &Ring->StoreInterface);
> +    if (!NT_SUCCESS(status))
> +        goto fail4;
> +
> +    status = RtlStringCbPrintfA(Name,
> +                                sizeof(Name),
> +                                "console_%s_gnttab",
> +                                PdoGetName(FrontendGetPdo(Ring->Frontend)));
> +    if (!NT_SUCCESS(status))
> +        goto fail5;
> +
> +    status = XENBUS_GNTTAB(CreateCache,
> +                           &Ring->GnttabInterface,
> +                           Name,
> +                           0,
> +                           RingAcquireLock,
> +                           RingReleaseLock,
> +                           Ring,
> +                           &Ring->GnttabCache);
> +    if (!NT_SUCCESS(status))
> +        goto fail6;
> +
> +    Ring->Mdl = __AllocatePage();
> +
> +    status = STATUS_NO_MEMORY;
> +    if (Ring->Mdl == NULL)
> +        goto fail7;
> +
> +    ASSERT(Ring->Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
> +    Ring->Shared = Ring->Mdl->MappedSystemVa;
> +    ASSERT(Ring->Shared != NULL);
> +
> +    status = XENBUS_GNTTAB(PermitForeignAccess,
> +                           &Ring->GnttabInterface,
> +                           Ring->GnttabCache,
> +                           TRUE,
> +                           FrontendGetBackendDomain(Ring->Frontend),
> +                           MmGetMdlPfnArray(Ring->Mdl)[0],
> +                           FALSE,
> +                           &Ring->Entry);
> +    if (!NT_SUCCESS(status))
> +        goto fail8;
> +
> +    Ring->Channel = XENBUS_EVTCHN(Open,
> +                                  &Ring->EvtchnInterface,
> +                                  XENBUS_EVTCHN_TYPE_UNBOUND,
> +                                  RingEvtchnCallback,
> +                                  Ring,
> +                                  FrontendGetBackendDomain(Ring->Frontend),
> +                                  TRUE);
> +
> +    status = STATUS_UNSUCCESSFUL;
> +    if (Ring->Channel == NULL)
> +        goto fail9;
> +
> +    (VOID)XENBUS_EVTCHN(Unmask,
> +                        &Ring->EvtchnInterface,
> +                        Ring->Channel,
> +                        FALSE,
> +                        TRUE);
> +
> +    status = XENBUS_DEBUG(Register,
> +                          &Ring->DebugInterface,
> +                          __MODULE__ "|POLLER",
> +                          RingDebugCallback,
> +                          Ring,
> +                          &Ring->DebugCallback);
> +    if (!NT_SUCCESS(status))
> +        goto fail10;
> +
> +    Ring->Connected = TRUE;
> +
> +    Trace("<====\n");
> +    return STATUS_SUCCESS;
> +
> +fail10:
> +    Error("fail10\n");
> +
> +    Ring->Events = 0;
> +
> +    XENBUS_EVTCHN(Close,
> +                  &Ring->EvtchnInterface,
> +                  Ring->Channel);
> +    Ring->Channel = NULL;
> +
> +fail9:
> +    Error("fail9\n");
> +
> +    (VOID)XENBUS_GNTTAB(RevokeForeignAccess,
> +                        &Ring->GnttabInterface,
> +                        Ring->GnttabCache,
> +                        TRUE,
> +                        Ring->Entry);
> +    Ring->Entry = NULL;
> +
> +fail8:
> +    Error("fail8\n");
> +
> +    RtlZeroMemory(Ring->Shared, PAGE_SIZE);
> +
> +    Ring->Shared = NULL;
> +    __FreePage(Ring->Mdl);
> +    Ring->Mdl = NULL;
> +
> +fail7:
> +    Error("fail7\n");
> +
> +    XENBUS_GNTTAB(DestroyCache,
> +                  &Ring->GnttabInterface,
> +                  Ring->GnttabCache);
> +    Ring->GnttabCache = NULL;
> +
> +fail6:
> +    Error("fail6\n");
> +
> +fail5:
> +    Error("fail5\n");
> +
> +    XENBUS_STORE(Release, &Ring->StoreInterface);
> +
> +fail4:
> +    Error("fail4\n");
> +
> +    XENBUS_GNTTAB(Release, &Ring->GnttabInterface);
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    XENBUS_EVTCHN(Release, &Ring->EvtchnInterface);
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    XENBUS_DEBUG(Release, &Ring->DebugInterface);
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +NTSTATUS
> +RingStoreWrite(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PVOID           Transaction
> +    )
> +{
> +    ULONG               Port;
> +    ULONG               GrantRef;
> +    NTSTATUS            status;
> +
> +    Port = XENBUS_EVTCHN(GetPort,
> +                         &Ring->EvtchnInterface,
> +                         Ring->Channel);
> +
> +    status = XENBUS_STORE(Printf,
> +                          &Ring->StoreInterface,
> +                          Transaction,
> +                          FrontendGetPath(Ring->Frontend),
> +                          "port",
> +                          "%u",
> +                          Port);
> +    if (!NT_SUCCESS(status))
> +        goto fail1;
> +
> +    GrantRef = XENBUS_GNTTAB(GetReference,
> +                             &Ring->GnttabInterface,
> +                             Ring->Entry);
> +
> +    status = XENBUS_STORE(Printf,
> +                          &Ring->StoreInterface,
> +                          Transaction,
> +                          FrontendGetPath(Ring->Frontend),
> +                          "ring-ref",
> +                          "%u",
> +                          GrantRef);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    return STATUS_SUCCESS;
> +
> +fail2:
> +    Error("fail2\n");
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +VOID
> +RingDisconnect(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    Trace("====>\n");
> +
> +    ASSERT(Ring->Connected);
> +    Ring->Connected = FALSE;
> +
> +    XENBUS_DEBUG(Deregister,
> +                 &Ring->DebugInterface,
> +                 Ring->DebugCallback);
> +    Ring->DebugCallback = NULL;
> +
> +    Ring->Dpcs = 0;
> +    Ring->Events = 0;
> +    Ring->BytesRead = 0;
> +    Ring->BytesWritten = 0;
> +
> +    XENBUS_EVTCHN(Close,
> +                  &Ring->EvtchnInterface,
> +                  Ring->Channel);
> +    Ring->Channel = NULL;
> +
> +    (VOID)XENBUS_GNTTAB(RevokeForeignAccess,
> +                        &Ring->GnttabInterface,
> +                        Ring->GnttabCache,
> +                        TRUE,
> +                        Ring->Entry);
> +    Ring->Entry = NULL;
> +
> +    RtlZeroMemory(Ring->Shared, PAGE_SIZE);
> +
> +    Ring->Shared = NULL;
> +    __FreePage(Ring->Mdl);
> +    Ring->Mdl = NULL;
> +
> +    XENBUS_GNTTAB(DestroyCache,
> +                  &Ring->GnttabInterface,
> +                  Ring->GnttabCache);
> +    Ring->GnttabCache = NULL;
> +
> +    XENBUS_STORE(Release, &Ring->StoreInterface);
> +
> +    XENBUS_GNTTAB(Release, &Ring->GnttabInterface);
> +
> +    XENBUS_EVTCHN(Release, &Ring->EvtchnInterface);
> +
> +    XENBUS_DEBUG(Release, &Ring->DebugInterface);
> +
> +    Trace("<====\n");
> +}
> +
> +NTSTATUS
> +RingCreate(
> +    IN  PXENCONS_FRONTEND   Frontend,
> +    OUT PXENCONS_RING       *Ring
> +    )
> +{
> +    NTSTATUS                status;
> +
> +    *Ring = __RingAllocate(sizeof(XENCONS_RING));
> +
> +    status = STATUS_NO_MEMORY;
> +    if (*Ring == NULL)
> +        goto fail1;
> +
> +    (*Ring)->Frontend = Frontend;
> +
> +    FdoGetDebugInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
> +                         &(*Ring)->DebugInterface);
> +
> +    FdoGetEvtchnInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
> +                          &(*Ring)->EvtchnInterface);
> +
> +    FdoGetGnttabInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
> +                         &(*Ring)->GnttabInterface);
> +
> +    FdoGetStoreInterface(PdoGetFdo(FrontendGetPdo(Frontend)),
> +                         &(*Ring)->StoreInterface);
> +
> +    KeInitializeSpinLock(&(*Ring)->Lock);
> +
> +    KeInitializeThreadedDpc(&(*Ring)->Dpc, RingDpc, *Ring);
> +
> +    KeInitializeSpinLock(&(*Ring)->Read.Lock);
> +    InitializeListHead(&(*Ring)->Read.List);
> +
> +    status = IoCsqInitializeEx(&(*Ring)->Read.Csq,
> +                               RingCsqInsertIrpEx,
> +                               RingCsqRemoveIrp,
> +                               RingCsqPeekNextIrp,
> +                               RingCsqAcquireLock,
> +                               RingCsqReleaseLock,
> +                               RingCsqCompleteCanceledIrp);
> +    if (!NT_SUCCESS(status))
> +        goto fail2;
> +
> +    KeInitializeSpinLock(&(*Ring)->Write.Lock);
> +    InitializeListHead(&(*Ring)->Write.List);
> +
> +    status = IoCsqInitializeEx(&(*Ring)->Write.Csq,
> +                               RingCsqInsertIrpEx,
> +                               RingCsqRemoveIrp,
> +                               RingCsqPeekNextIrp,
> +                               RingCsqAcquireLock,
> +                               RingCsqReleaseLock,
> +                               RingCsqCompleteCanceledIrp);
> +    if (!NT_SUCCESS(status))
> +        goto fail3;
> +
> +    return STATUS_SUCCESS;
> +
> +fail3:
> +    Error("fail3\n");
> +
> +    RtlZeroMemory(&(*Ring)->Write.List, sizeof(LIST_ENTRY));
> +    RtlZeroMemory(&(*Ring)->Write.Lock, sizeof(KSPIN_LOCK));
> +
> +    RtlZeroMemory(&(*Ring)->Read.Csq, sizeof(IO_CSQ));
> +
> +fail2:
> +    Error("fail2\n");
> +
> +    RtlZeroMemory(&(*Ring)->Read.List, sizeof(LIST_ENTRY));
> +    RtlZeroMemory(&(*Ring)->Read.Lock, sizeof(KSPIN_LOCK));
> +
> +fail1:
> +    Error("fail1 (%08x)\n", status);
> +
> +    return status;
> +}
> +
> +VOID
> +RingDestroy(
> +    IN  PXENCONS_RING   Ring
> +    )
> +{
> +    ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL);
> +
> +    // Cancel all outstanding IRPs
> +    __RingCancelRequests(Ring, NULL);
> +
> +    ASSERT(IsListEmpty(&Ring->Read.List));
> +    ASSERT(IsListEmpty(&Ring->Write.List));
> +
> +    RtlZeroMemory(&Ring->Write.Csq, sizeof(IO_CSQ));
> +
> +    RtlZeroMemory(&Ring->Write.List, sizeof(LIST_ENTRY));
> +    RtlZeroMemory(&Ring->Write.Lock, sizeof(KSPIN_LOCK));
> +
> +    RtlZeroMemory(&Ring->Read.Csq, sizeof(IO_CSQ));
> +
> +    RtlZeroMemory(&Ring->Read.List, sizeof(LIST_ENTRY));
> +    RtlZeroMemory(&Ring->Read.Lock, sizeof(KSPIN_LOCK));
> +
> +    RtlZeroMemory(&Ring->Dpc, sizeof(KDPC));
> +
> +    RtlZeroMemory(&Ring->Lock, sizeof(KSPIN_LOCK));
> +
> +    RtlZeroMemory(&Ring->StoreInterface,
> +                  sizeof(XENBUS_STORE_INTERFACE));
> +
> +    RtlZeroMemory(&Ring->GnttabInterface,
> +                  sizeof(XENBUS_GNTTAB_INTERFACE));
> +
> +    RtlZeroMemory(&Ring->EvtchnInterface,
> +                  sizeof(XENBUS_EVTCHN_INTERFACE));
> +
> +    RtlZeroMemory(&Ring->DebugInterface,
> +                  sizeof(XENBUS_DEBUG_INTERFACE));
> +
> +    Ring->Frontend = NULL;
> +
> +    ASSERT(IsZeroMemory(Ring, sizeof(XENCONS_RING)));
> +    __RingFree(Ring);
> +}
> diff --git a/src/xencons/ring.h b/src/xencons/ring.h
> new file mode 100755
> index 0000000..aca32a2
> --- /dev/null
> +++ b/src/xencons/ring.h
> @@ -0,0 +1,96 @@
> +/* 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 _XENCONS_RING_H
> +#define _XENCONS_RING_H
> +
> +#include <ntddk.h>
> +
> +#include "frontend.h"
> +
> +typedef struct _XENCONS_RING XENCONS_RING, *PXENCONS_RING;
> +
> +extern NTSTATUS
> +RingCreate(
> +    IN  PXENCONS_FRONTEND   Frontend,
> +    OUT PXENCONS_RING       *Ring
> +    );
> +
> +extern VOID
> +RingDestroy(
> +    IN  PXENCONS_RING   Ring
> +    );
> +
> +extern NTSTATUS
> +RingConnect(
> +    IN  PXENCONS_RING   Ring
> +    );
> +
> +extern NTSTATUS
> +RingStoreWrite(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PVOID           Transaction
> +    );
> +
> +extern VOID
> +RingDisconnect(
> +    IN  PXENCONS_RING   Ring
> +    );
> +
> +extern NTSTATUS
> +RingEnable(
> +    IN  PXENCONS_RING   Ring
> +    );
> +
> +extern VOID
> +RingDisable(
> +    IN  PXENCONS_RING   Ring
> +    );
> +
> +extern NTSTATUS
> +RingOpen(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PFILE_OBJECT    FileObject
> +    );
> +
> +extern NTSTATUS
> +RingClose(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PFILE_OBJECT    FileObject
> +    );
> +
> +extern NTSTATUS
> +RingPutQueue(
> +    IN  PXENCONS_RING   Ring,
> +    IN  PIRP            Irp
> +    );
> +
> +#endif  // _XENCONS_RING_H
> diff --git a/vs2015/xencons/xencons.vcxproj
> b/vs2015/xencons/xencons.vcxproj
> index 8846b8e..435ef21 100644
> --- a/vs2015/xencons/xencons.vcxproj
> +++ b/vs2015/xencons/xencons.vcxproj
> @@ -71,6 +71,7 @@
>      <ClCompile Include="../../src/xencons/console.c" />
>      <ClCompile Include="../../src/xencons/stream.c" />
>      <ClCompile Include="../../src/xencons/frontend.c" />
> +    <ClCompile Include="../../src/xencons/ring.c" />
>      <ClCompile Include="../../src/xencons/thread.c" />
>    </ItemGroup>
>    <ItemGroup>
> diff --git a/vs2017/xencons/xencons.vcxproj
> b/vs2017/xencons/xencons.vcxproj
> index 9811da0..defb11e 100644
> --- a/vs2017/xencons/xencons.vcxproj
> +++ b/vs2017/xencons/xencons.vcxproj
> @@ -79,6 +79,7 @@
>      <ClCompile Include="../../src/xencons/console.c" />
>      <ClCompile Include="../../src/xencons/stream.c" />
>      <ClCompile Include="../../src/xencons/frontend.c" />
> +    <ClCompile Include="../../src/xencons/ring.c" />
>      <ClCompile Include="../../src/xencons/thread.c" />
>    </ItemGroup>
>    <ItemGroup>
> --
> 2.8.3
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.