[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |