|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [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>
---
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |