[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 03/14 v2] Add boilerplate Pdo
> -----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 03/14 v2] Add boilerplate Pdo > > From: Owen Smith <owen.smith@xxxxxxxxxx> > > Enumerates a single static RawPdo. > > Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > src/xencons/driver.c | 8 + > src/xencons/driver.h | 12 +- > src/xencons/fdo.c | 426 ++++++++- > src/xencons/fdo.h | 43 + > src/xencons/mutex.h | 82 ++ > src/xencons/pdo.c | 1865 > ++++++++++++++++++++++++++++++++++++++++ > src/xencons/pdo.h | 113 +++ > vs2015/xencons/xencons.vcxproj | 1 + > vs2017/xencons/xencons.vcxproj | 1 + > 9 files changed, 2541 insertions(+), 10 deletions(-) > create mode 100755 src/xencons/mutex.h > create mode 100755 src/xencons/pdo.c > create mode 100755 src/xencons/pdo.h > > diff --git a/src/xencons/driver.c b/src/xencons/driver.c > index 3121b99..5a4d1d3 100644 > --- a/src/xencons/driver.c > +++ b/src/xencons/driver.c > @@ -36,6 +36,7 @@ > > #include "registry.h" > #include "fdo.h" > +#include "pdo.h" > #include "driver.h" > #include "dbg_print.h" > #include "assert.h" > @@ -208,6 +209,13 @@ Dispatch( > status = FdoDispatch(Fdo, Irp); > break; > } > + case PHYSICAL_DEVICE_OBJECT: > + { > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + status = PdoDispatch(Pdo, Irp); > + break; > + } > default: > ASSERT(FALSE); > break; > diff --git a/src/xencons/driver.h b/src/xencons/driver.h > index 4a2eb61..fb5ece0 100644 > --- a/src/xencons/driver.h > +++ b/src/xencons/driver.h > @@ -50,12 +50,17 @@ DriverGetParametersKey( > ); > > typedef struct _XENCONS_FDO XENCONS_FDO, *PXENCONS_FDO; > +typedef struct _XENCONS_PDO XENCONS_PDO, *PXENCONS_PDO; > > #include "fdo.h" > +#include "pdo.h" > > #define MAX_DEVICE_ID_LEN 200 > #define MAX_GUID_STRING_LEN 39 > > +#pragma warning(push) > +#pragma warning(disable:4201) // nonstandard extension used : nameless > struct/union > + > typedef struct _XENCONS_DX { > PDEVICE_OBJECT DeviceObject; > DEVICE_OBJECT_TYPE Type; > @@ -72,7 +77,12 @@ typedef struct _XENCONS_DX { > > LIST_ENTRY ListEntry; > > - PXENCONS_FDO Fdo; > + union { > + PXENCONS_FDO Fdo; > + PXENCONS_PDO Pdo; > + }; > } XENCONS_DX, *PXENCONS_DX; > > +#pragma warning(pop) > + > #endif // _XENCONS_DRIVER_H > diff --git a/src/xencons/fdo.c b/src/xencons/fdo.c > index 0170ef6..1c5323c 100644 > --- a/src/xencons/fdo.c > +++ b/src/xencons/fdo.c > @@ -47,6 +47,8 @@ > #include "driver.h" > #include "registry.h" > #include "fdo.h" > +#include "pdo.h" > +#include "mutex.h" > #include "console.h" > #include "thread.h" > #include "names.h" > @@ -85,6 +87,9 @@ struct _XENCONS_FDO { > > CHAR VendorName[MAXNAMELEN]; > > + MUTEX Mutex; > + ULONG References; > + > FDO_RESOURCE Resource[RESOURCE_COUNT]; > > PXENCONS_CONSOLE Console; > @@ -210,6 +215,14 @@ __FdoGetPhysicalDeviceObject( > return Fdo->PhysicalDeviceObject; > } > > +PDEVICE_OBJECT > +FdoGetPhysicalDeviceObject( > + IN PXENCONS_FDO Fdo > + ) > +{ > + return __FdoGetPhysicalDeviceObject(Fdo); > +} > + > __drv_requiresIRQL(PASSIVE_LEVEL) > static FORCEINLINE NTSTATUS > __FdoAcquireLowerBusInterface( > @@ -358,6 +371,14 @@ __FdoGetVendorName( > return Fdo->VendorName; > } > > +PCHAR > +FdoGetVendorName( > + IN PXENCONS_FDO Fdo > + ) > +{ > + return __FdoGetVendorName(Fdo); > +} > + > static FORCEINLINE VOID > __FdoSetName( > IN PXENCONS_FDO Fdo > @@ -383,6 +404,99 @@ __FdoGetName( > return Dx->Name; > } > > +PCHAR > +FdoGetName( > + IN PXENCONS_FDO Fdo > + ) > +{ > + return __FdoGetName(Fdo); > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoDelegateIrp( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PKEVENT Event = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + UNREFERENCED_PARAMETER(Irp); > + > + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); > + > + return STATUS_MORE_PROCESSING_REQUIRED; > +} > + > +NTSTATUS > +FdoDelegateIrp( > + IN PXENCONS_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PDEVICE_OBJECT DeviceObject; > + PIO_STACK_LOCATION StackLocation; > + PIRP SubIrp; > + KEVENT Event; > + PIO_STACK_LOCATION SubStackLocation; > + NTSTATUS status; > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + // Find the top of the FDO stack and hold a reference > + DeviceObject = IoGetAttachedDeviceReference(Fdo->Dx- > >DeviceObject); > + > + // Get a new IRP for the FDO stack > + SubIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE); > + > + status = STATUS_NO_MEMORY; > + if (SubIrp == NULL) > + goto done; > + > + // Copy in the information from the original IRP > + SubStackLocation = IoGetNextIrpStackLocation(SubIrp); > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + RtlCopyMemory(SubStackLocation, StackLocation, > + FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); > + SubStackLocation->Control = 0; > + > + IoSetCompletionRoutine(SubIrp, > + __FdoDelegateIrp, > + &Event, > + TRUE, > + TRUE, > + TRUE); > + > + // Default completion status > + SubIrp->IoStatus.Status = Irp->IoStatus.Status; > + > + status = IoCallDriver(DeviceObject, SubIrp); > + if (status == STATUS_PENDING) { > + (VOID)KeWaitForSingleObject(&Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + status = SubIrp->IoStatus.Status; > + } else { > + ASSERT3U(status, == , SubIrp->IoStatus.Status); > + } > + > + IoFreeIrp(SubIrp); > + > +done: > + ObDereferenceObject(DeviceObject); > + > + return status; > +} > + > __drv_functionClass(IO_COMPLETION_ROUTINE) > __drv_sameIRQL > static NTSTATUS > @@ -487,6 +601,99 @@ FdoParseResources( > } > } > > +NTSTATUS > +FdoAddPhysicalDeviceObject( > + IN PXENCONS_FDO Fdo, > + IN PXENCONS_PDO Pdo > + ) > +{ > + PDEVICE_OBJECT DeviceObject; > + PXENCONS_DX Dx; > + NTSTATUS status; > + > + DeviceObject = PdoGetDeviceObject(Pdo); > + Dx = (PXENCONS_DX)DeviceObject->DeviceExtension; > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD3) > + goto done; > + > + status = PdoResume(Pdo); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > +done: > + InsertTailList(&Fdo->Dx->ListEntry, &Dx->ListEntry); > + ASSERT3U(Fdo->References, != , 0); > + Fdo->References++; > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +VOID > +FdoRemovePhysicalDeviceObject( > + IN PXENCONS_FDO Fdo, > + IN PXENCONS_PDO Pdo > + ) > +{ > + PDEVICE_OBJECT DeviceObject; > + PXENCONS_DX Dx; > + > + DeviceObject = PdoGetDeviceObject(Pdo); > + Dx = (PXENCONS_DX)DeviceObject->DeviceExtension; > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD3) > + goto done; > + > + PdoSuspend(Pdo); > + > +done: > + RemoveEntryList(&Dx->ListEntry); > + ASSERT3U(Fdo->References, != , 0); > + --Fdo->References; > +} > + > +static FORCEINLINE VOID > +__FdoAcquireMutex( > + IN PXENCONS_FDO Fdo > + ) > +{ > + AcquireMutex(&Fdo->Mutex); > +} > + > +VOID > +FdoAcquireMutex( > + IN PXENCONS_FDO Fdo > + ) > +{ > + __FdoAcquireMutex(Fdo); > +} > + > +static FORCEINLINE VOID > +__FdoReleaseMutex( > + IN PXENCONS_FDO Fdo > + ) > +{ > + ReleaseMutex(&Fdo->Mutex); > +} > + > +VOID > +FdoReleaseMutex( > + IN PXENCONS_FDO Fdo > + ) > +{ > + __FdoReleaseMutex(Fdo); > + > + if (Fdo->References == 0) > + FdoDestroy(Fdo); > +} > + > static FORCEINLINE PANSI_STRING > __FdoMultiSzToUpcaseAnsi( > IN PCHAR Buffer > @@ -831,9 +1038,9 @@ FdoD3ToD0( > IN PXENCONS_FDO Fdo > ) > { > - PXENCONS_DX Dx = Fdo->Dx; > POWER_STATE PowerState; > KIRQL Irql; > + PLIST_ENTRY ListEntry; > NTSTATUS status; > > ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > @@ -873,11 +1080,27 @@ FdoD3ToD0( > DevicePowerState, > PowerState); > > + __FdoAcquireMutex(Fdo); > + > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) { > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + status = PdoResume(Pdo); > + ASSERT(NT_SUCCESS(status)); > + } > + > + __FdoReleaseMutex(Fdo); > + > status = ConsoleD3ToD0(Fdo->Console); > ASSERT(NT_SUCCESS(status)); > > #pragma prefast(suppress:28123) > - (VOID) IoSetDeviceInterfaceState(&Dx->Link, TRUE); > + (VOID) IoSetDeviceInterfaceState(&Fdo->Dx->Link, TRUE); > > Trace("<====\n"); > > @@ -912,8 +1135,8 @@ FdoD0ToD3( > IN PXENCONS_FDO Fdo > ) > { > - PXENCONS_DX Dx = Fdo->Dx; > POWER_STATE PowerState; > + PLIST_ENTRY ListEntry; > KIRQL Irql; > > ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > @@ -922,10 +1145,29 @@ FdoD0ToD3( > Trace("====>\n"); > > #pragma prefast(suppress:28123) > - (VOID) IoSetDeviceInterfaceState(&Dx->Link, FALSE); > + (VOID) IoSetDeviceInterfaceState(&Fdo->Dx->Link, FALSE); > > ConsoleD0ToD3(Fdo->Console); > > + __FdoAcquireMutex(Fdo); > + > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) { > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (PdoGetDevicePnpState(Pdo) == Deleted || > + PdoIsMissing(Pdo)) > + continue; > + > + PdoSuspend(Pdo); > + } > + > + __FdoReleaseMutex(Fdo); > + > PowerState.DeviceState = PowerDeviceD3; > PoSetPowerState(Fdo->Dx->DeviceObject, > DevicePowerState, > @@ -1117,10 +1359,27 @@ FdoSurpriseRemoval( > IN PIRP Irp > ) > { > + PLIST_ENTRY ListEntry; > NTSTATUS status; > > __FdoSetDevicePnpState(Fdo, SurpriseRemovePending); > > + __FdoAcquireMutex(Fdo); > + > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) { > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (!PdoIsMissing(Pdo)) > + PdoSetMissing(Pdo, "FDO surprise removed"); > + } > + > + __FdoReleaseMutex(Fdo); > + > Irp->IoStatus.Status = STATUS_SUCCESS; > > IoSkipCurrentIrpStackLocation(Irp); > @@ -1135,6 +1394,7 @@ FdoRemoveDevice( > IN PIRP Irp > ) > { > + PLIST_ENTRY ListEntry; > NTSTATUS status; > > ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > @@ -1142,6 +1402,30 @@ FdoRemoveDevice( > if (__FdoGetPreviousDevicePnpState(Fdo) != Started) > goto done; > > + __FdoAcquireMutex(Fdo); > + > + ListEntry = Fdo->Dx->ListEntry.Flink; > + while (ListEntry != &Fdo->Dx->ListEntry) { > + PLIST_ENTRY Flink = ListEntry->Flink; > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (!PdoIsMissing(Pdo)) > + PdoSetMissing(Pdo, "FDO removed"); > + > + if (PdoGetDevicePnpState(Pdo) != SurpriseRemovePending) > + PdoSetDevicePnpState(Pdo, Deleted); > + > + if (PdoGetDevicePnpState(Pdo) == Deleted) > + PdoDestroy(Pdo); > + > + ListEntry = Flink; > + } > + > + __FdoReleaseMutex(Fdo); > + > if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) > FdoD0ToD3(Fdo); > > @@ -1157,7 +1441,13 @@ done: > IoSkipCurrentIrpStackLocation(Irp); > status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > > - FdoDestroy(Fdo); > + __FdoAcquireMutex(Fdo); > + ASSERT3U(Fdo->References, != , 0); > + --Fdo->References; > + __FdoReleaseMutex(Fdo); > + > + if (Fdo->References == 0) > + FdoDestroy(Fdo); > > return status; > } > @@ -1169,16 +1459,110 @@ FdoQueryDeviceRelations( > ) > { > PIO_STACK_LOCATION StackLocation; > + ULONG Size; > + PDEVICE_RELATIONS Relations; > + ULONG Count; > + PLIST_ENTRY ListEntry; > NTSTATUS status; > > - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > > StackLocation = IoGetCurrentIrpStackLocation(Irp); > > status = Irp->IoStatus.Status; > > - IoSkipCurrentIrpStackLocation(Irp); > - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + if (StackLocation->Parameters.QueryDeviceRelations.Type != > BusRelations) { > + IoSkipCurrentIrpStackLocation(Irp); > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + goto done; > + } > + > + __FdoAcquireMutex(Fdo); > + > + Count = 0; > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) > + Count++; > + > + Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + > (sizeof(PDEVICE_OBJECT) * __max(Count, 1)); > + > + Relations = ExAllocatePoolWithTag(PagedPool, Size, FDO_POOL); > + > + status = STATUS_NO_MEMORY; > + if (Relations == NULL) > + goto fail1; > + > + RtlZeroMemory(Relations, Size); > + > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) { > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (PdoIsMissing(Pdo)) > + continue; > + > + if (PdoGetDevicePnpState(Pdo) == Present) > + PdoSetDevicePnpState(Pdo, Enumerated); > + > + ObReferenceObject(Dx->DeviceObject); > + Relations->Objects[Relations->Count++] = Dx->DeviceObject; > + } > + > + ASSERT3U(Relations->Count, <= , Count); > + > + Trace("%d PDO(s)\n", Relations->Count); > + > + __FdoReleaseMutex(Fdo); > + > + Irp->IoStatus.Information = (ULONG_PTR)Relations; > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + __FdoAcquireMutex(Fdo); > + > + ListEntry = Fdo->Dx->ListEntry.Flink; > + while (ListEntry != &Fdo->Dx->ListEntry) { > + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, > ListEntry); > + PXENCONS_PDO Pdo = Dx->Pdo; > + PLIST_ENTRY Next = ListEntry->Flink; > + > + ASSERT3U(Dx->Type, == , PHYSICAL_DEVICE_OBJECT); > + > + if (PdoGetDevicePnpState(Pdo) == Deleted && > + PdoIsMissing(Pdo)) > + PdoDestroy(Pdo); > + > + ListEntry = Next; > + } > + > + __FdoReleaseMutex(Fdo); > + > +done: > + return status; > + > +fail2: > + Error("fail2\n"); > + > + __FdoAcquireMutex(Fdo); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + __FdoReleaseMutex(Fdo); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > > return status; > } > @@ -2469,13 +2853,33 @@ FdoCreate( > > Dx->Fdo = Fdo; > > + InitializeMutex(&Fdo->Mutex); > + InitializeListHead(&Dx->ListEntry); > + Fdo->References = 1; > + > Info("%p (%s)\n", > FunctionDeviceObject, > __FdoGetName(Fdo)); > > + status = PdoCreate(Fdo, NULL); > + if (!NT_SUCCESS(status)) > + goto fail13; > + > FunctionDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; > return STATUS_SUCCESS; > > +fail13: > + Error("fail13\n"); > + > + Dx->Fdo = Fdo; > + > + RtlZeroMemory(&Fdo->Mutex, sizeof(MUTEX)); > + RtlZeroMemory(&Dx->ListEntry, sizeof(LIST_ENTRY)); > + Fdo->References = 0; > + > + ConsoleDestroy(Fdo->Console); > + Fdo->Console = NULL; > + > fail12: > Error("fail12\n"); > > @@ -2561,7 +2965,9 @@ FdoDestroy( > PXENCONS_DX Dx = Fdo->Dx; > PDEVICE_OBJECT FunctionDeviceObject = Dx->DeviceObject; > > - ASSERT3U(__FdoGetDevicePnpState(Fdo), ==, Deleted); > + ASSERT(IsListEmpty(&Dx->ListEntry)); > + ASSERT3U(Fdo->References, == , 0); > + ASSERT3U(__FdoGetDevicePnpState(Fdo), == , Deleted); > > Fdo->NotDisableable = FALSE; > > @@ -2569,6 +2975,8 @@ FdoDestroy( > FunctionDeviceObject, > __FdoGetName(Fdo)); > > + RtlZeroMemory(&Fdo->Mutex, sizeof(MUTEX)); > + > Dx->Fdo = NULL; > > ConsoleDestroy(Fdo->Console); > diff --git a/src/xencons/fdo.h b/src/xencons/fdo.h > index 19eaa42..f8ebaf3 100644 > --- a/src/xencons/fdo.h > +++ b/src/xencons/fdo.h > @@ -40,6 +40,49 @@ > > #include "driver.h" > > +extern PCHAR > +FdoGetVendorName( > + IN PXENCONS_FDO Fdo > + ); > + > +extern PCHAR > +FdoGetName( > + IN PXENCONS_FDO Fdo > + ); > + > +extern NTSTATUS > +FdoAddPhysicalDeviceObject( > + IN PXENCONS_FDO Fdo, > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +FdoRemovePhysicalDeviceObject( > + IN PXENCONS_FDO Fdo, > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +FdoAcquireMutex( > + IN PXENCONS_FDO Fdo > + ); > + > +extern VOID > +FdoReleaseMutex( > + IN PXENCONS_FDO Fdo > + ); > + > +extern PDEVICE_OBJECT > +FdoGetPhysicalDeviceObject( > + IN PXENCONS_FDO Fdo > + ); > + > +extern NTSTATUS > +FdoDelegateIrp( > + IN PXENCONS_FDO Fdo, > + IN PIRP Irp > + ); > + > extern NTSTATUS > FdoDispatch( > IN PXENCONS_FDO Fdo, > diff --git a/src/xencons/mutex.h b/src/xencons/mutex.h > new file mode 100755 > index 0000000..904b21d > --- /dev/null > +++ b/src/xencons/mutex.h > @@ -0,0 +1,82 @@ > +/* 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_MUTEX_H > +#define _XENCONS_MUTEX_H > + > +#include <ntddk.h> > + > +#include "assert.h" > + > +typedef struct _MUTEX { > + PKTHREAD Owner; > + KEVENT Event; > +} MUTEX, *PMUTEX; > + > +static FORCEINLINE VOID > +InitializeMutex( > + IN PMUTEX Mutex > +) > +{ > + RtlZeroMemory(Mutex, sizeof(MUTEX)); > + > + KeInitializeEvent(&Mutex->Event, SynchronizationEvent, TRUE); > +} > + > +static FORCEINLINE VOID > +__drv_maxIRQL(PASSIVE_LEVEL) > +AcquireMutex( > + IN PMUTEX Mutex > +) > +{ > + (VOID)KeWaitForSingleObject(&Mutex->Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + ASSERT3P(Mutex->Owner, == , NULL); > + Mutex->Owner = KeGetCurrentThread(); > +} > + > +static FORCEINLINE VOID > +__drv_maxIRQL(PASSIVE_LEVEL) > +ReleaseMutex( > + IN PMUTEX Mutex > +) > +{ > + ASSERT3P(Mutex->Owner, == , KeGetCurrentThread()); > + Mutex->Owner = NULL; > + > + KeSetEvent(&Mutex->Event, IO_NO_INCREMENT, FALSE); > +} > + > +#endif // _XENCONS_MUTEX_H > diff --git a/src/xencons/pdo.c b/src/xencons/pdo.c > new file mode 100755 > index 0000000..5e90844 > --- /dev/null > +++ b/src/xencons/pdo.c > @@ -0,0 +1,1865 @@ > +/* Copyright (c) Citrix Systems Inc. > +* All rights reserved. > +* > +* Redistribution and use in source and binary forms, > +* with or without modification, are permitted provided > +* that the following conditions are met: > +* > +* * Redistributions of source code must retain the above > +* copyright notice, this list of conditions and the > +* following disclaimer. > +* * Redistributions in binary form must reproduce the above > +* copyright notice, this list of conditions and the > +* following disclaimer in the documentation and/or other > +* materials provided with the distribution. > +* > +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > +* SUCH DAMAGE. > +*/ > + > +#define INITGUID 1 > + > +#include <ntddk.h> > +#include <wdmguid.h> > +#include <ntstrsafe.h> > +#include <stdlib.h> > + > +#include <suspend_interface.h> > +#include <version.h> > + > +#include "driver.h" > +#include "names.h" > +#include "fdo.h" > +#include "pdo.h" > +#include "thread.h" > +#include "dbg_print.h" > +#include "assert.h" > +#include "util.h" > + > +#define PDO_POOL 'ODP' > + > +#define MAXNAMELEN 128 > +#define MAXTEXTLEN 1024 > + > +struct _XENCONS_PDO { > + PXENCONS_DX Dx; > + > + PXENCONS_THREAD SystemPowerThread; > + PIRP SystemPowerIrp; > + PXENCONS_THREAD DevicePowerThread; > + PIRP DevicePowerIrp; > + > + PXENCONS_FDO Fdo; > + BOOLEAN Missing; > + const CHAR *Reason; > + LONG Eject; > + > + XENBUS_SUSPEND_INTERFACE SuspendInterface; > + PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; > +}; > + > +static FORCEINLINE PVOID > +__PdoAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocatePoolWithTag(NonPagedPool, Length, PDO_POOL); > +} > + > +static FORCEINLINE VOID > +__PdoFree( > + IN PVOID Buffer > + ) > +{ > + __FreePoolWithTag(Buffer, PDO_POOL); > +} > + > +static FORCEINLINE VOID > +__PdoSetDevicePnpState( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + // We can never transition out of the deleted state > + ASSERT(Dx->DevicePnpState != Deleted || State == Deleted); > + > + Dx->PreviousDevicePnpState = Dx->DevicePnpState; > + Dx->DevicePnpState = State; > +} > + > +VOID > +PdoSetDevicePnpState( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + __PdoSetDevicePnpState(Pdo, State); > +} > + > +static FORCEINLINE VOID > +__PdoRestoreDevicePnpState( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + if (Dx->DevicePnpState == State) > + Dx->DevicePnpState = Dx->PreviousDevicePnpState; > +} > + > +static FORCEINLINE DEVICE_PNP_STATE > +__PdoGetDevicePnpState( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + return Dx->DevicePnpState; > +} > + > +DEVICE_PNP_STATE > +PdoGetDevicePnpState( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return __PdoGetDevicePnpState(Pdo); > +} > + > +static FORCEINLINE VOID > +__PdoSetSystemPowerState( > + IN PXENCONS_PDO Pdo, > + IN SYSTEM_POWER_STATE State > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + Dx->SystemPowerState = State; > +} > + > +static FORCEINLINE SYSTEM_POWER_STATE > +__PdoGetSystemPowerState( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + return Dx->SystemPowerState; > +} > + > +static FORCEINLINE VOID > +__PdoSetDevicePowerState( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_POWER_STATE State > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + Dx->DevicePowerState = State; > +} > + > +static FORCEINLINE DEVICE_POWER_STATE > +__PdoGetDevicePowerState( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + return Dx->DevicePowerState; > +} > + > +static FORCEINLINE VOID > +__PdoSetMissing( > + IN PXENCONS_PDO Pdo, > + IN const CHAR *Reason > + ) > +{ > + Pdo->Reason = Reason; > + Pdo->Missing = TRUE; > +} > + > +VOID > +PdoSetMissing( > + IN PXENCONS_PDO Pdo, > + IN const CHAR *Reason > + ) > +{ > + __PdoSetMissing(Pdo, Reason); > +} > + > +static FORCEINLINE BOOLEAN > +__PdoIsMissing( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return Pdo->Missing; > +} > + > +BOOLEAN > +PdoIsMissing( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return __PdoIsMissing(Pdo); > +} > + > +static FORCEINLINE PDEVICE_OBJECT > +__PdoGetDeviceObject( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + return (Dx->DeviceObject); > +} > + > +PDEVICE_OBJECT > +PdoGetDeviceObject( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return __PdoGetDeviceObject(Pdo); > +} > + > +static FORCEINLINE PXENCONS_FDO > +__PdoGetFdo( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return Pdo->Fdo; > +} > + > +PXENCONS_FDO > +PdoGetFdo( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return __PdoGetFdo(Pdo); > +} > + > +static FORCEINLINE VOID > +__PdoSetName( > + IN PXENCONS_PDO Pdo, > + IN PANSI_STRING Device > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + NTSTATUS status; > + > + if (Device == NULL) > + status = RtlStringCbPrintfA(Dx->Name, > + MAX_DEVICE_ID_LEN, > + "0"); > + else > + status = RtlStringCbPrintfA(Dx->Name, > + MAX_DEVICE_ID_LEN, > + "%Z", > + Device); > + ASSERT(NT_SUCCESS(status)); > +} > + > +static FORCEINLINE PCHAR > +__PdoGetName( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + > + return Dx->Name; > +} > + > +static FORCEINLINE PCHAR > +__PdoGetVendorName( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return FdoGetVendorName(__PdoGetFdo(Pdo)); > +} > + > +static FORCEINLINE BOOLEAN > +__PdoSetEjectRequested( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return (InterlockedBitTestAndSet(&Pdo->Eject, 0) == 0) ? TRUE : FALSE; > +} > + > +VOID > +PdoRequestEject( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + PDEVICE_OBJECT PhysicalDeviceObject = Dx->DeviceObject; > + PXENCONS_FDO Fdo = __PdoGetFdo(Pdo); > + > + if (!__PdoSetEjectRequested(Pdo)) > + return; > + > + Info("%p (%s)\n", > + PhysicalDeviceObject, > + __PdoGetName(Pdo)); > + > + IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo), > + BusRelations); > +} > + > +static FORCEINLINE BOOLEAN > +__PdoClearEjectRequested( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return (InterlockedBitTestAndReset(&Pdo->Eject, 0) != 0) ? TRUE : FALSE; > +} > + > +static FORCEINLINE BOOLEAN > +__PdoIsEjectRequested( > + IN PXENCONS_PDO Pdo > + ) > +{ > + KeMemoryBarrier(); > + return (Pdo->Eject & 1) ? TRUE : FALSE; > +} > + > +BOOLEAN > +PdoIsEjectRequested( > + IN PXENCONS_PDO Pdo > + ) > +{ > + return __PdoIsEjectRequested(Pdo); > +} > + > +static FORCEINLINE NTSTATUS > +__PdoD3ToD0( > + IN PXENCONS_PDO Pdo > + ) > +{ > + POWER_STATE PowerState; > + > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); > + ASSERT3U(__PdoGetDevicePowerState(Pdo), == , PowerDeviceD3); > + > + __PdoSetDevicePowerState(Pdo, PowerDeviceD0); > + > + PowerState.DeviceState = PowerDeviceD0; > + PoSetPowerState(__PdoGetDeviceObject(Pdo), > + DevicePowerState, > + PowerState); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > + > + return STATUS_SUCCESS; > +} > + > +static FORCEINLINE VOID > +__PdoD0ToD3( > + IN PXENCONS_PDO Pdo > + ) > +{ > + POWER_STATE PowerState; > + > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , DISPATCH_LEVEL); > + ASSERT3U(__PdoGetDevicePowerState(Pdo), == , PowerDeviceD0); > + > + PowerState.DeviceState = PowerDeviceD3; > + PoSetPowerState(__PdoGetDeviceObject(Pdo), > + DevicePowerState, > + PowerState); > + > + __PdoSetDevicePowerState(Pdo, PowerDeviceD3); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > +} > + > +static DECLSPEC_NOINLINE VOID > +PdoSuspendCallbackLate( > + IN PVOID Argument > + ) > +{ > + PXENCONS_PDO Pdo = Argument; > + NTSTATUS status; > + > + __PdoD0ToD3(Pdo); > + > + status = __PdoD3ToD0(Pdo); > + ASSERT(NT_SUCCESS(status)); > +} > + > +// This function must not touch pageable code or data > +static DECLSPEC_NOINLINE NTSTATUS > +PdoD3ToD0( > + IN PXENCONS_PDO Pdo > + ) > +{ > + KIRQL Irql; > + NTSTATUS status; > + > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + status = XENBUS_SUSPEND(Acquire, &Pdo->SuspendInterface); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + status = __PdoD3ToD0(Pdo); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + status = XENBUS_SUSPEND(Register, > + &Pdo->SuspendInterface, > + SUSPEND_CALLBACK_LATE, > + PdoSuspendCallbackLate, > + Pdo, > + &Pdo->SuspendCallbackLate); > + if (!NT_SUCCESS(status)) > + goto fail3; > + > + KeLowerIrql(Irql); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > + > + return STATUS_SUCCESS; > + > +fail3: > + Error("fail3\n"); > + > + __PdoD0ToD3(Pdo); > + > +fail2: > + Error("fail2\n"); > + > + XENBUS_SUSPEND(Release, &Pdo->SuspendInterface); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + KeLowerIrql(Irql); > + > + return status; > +} > + > +// This function must not touch pageable code or data > +static DECLSPEC_NOINLINE VOID > +PdoD0ToD3( > + IN PXENCONS_PDO Pdo > + ) > +{ > + KIRQL Irql; > + > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + KeRaiseIrql(DISPATCH_LEVEL, &Irql); > + > + XENBUS_SUSPEND(Deregister, > + &Pdo->SuspendInterface, > + Pdo->SuspendCallbackLate); > + Pdo->SuspendCallbackLate = NULL; > + > + __PdoD0ToD3(Pdo); > + > + XENBUS_SUSPEND(Release, &Pdo->SuspendInterface); > + > + KeLowerIrql(Irql); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > +} > + > +// This function must not touch pageable code or data > +static DECLSPEC_NOINLINE VOID > +PdoS4ToS3( > + IN PXENCONS_PDO Pdo > + ) > +{ > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + ASSERT3U(__PdoGetSystemPowerState(Pdo), == , > PowerSystemHibernate); > + > + __PdoSetSystemPowerState(Pdo, PowerSystemSleeping3); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > +} > + > +// This function must not touch pageable code or data > +static DECLSPEC_NOINLINE VOID > +PdoS3ToS4( > + IN PXENCONS_PDO Pdo > + ) > +{ > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + ASSERT3U(__PdoGetSystemPowerState(Pdo), == , > PowerSystemSleeping3); > + > + __PdoSetSystemPowerState(Pdo, PowerSystemHibernate); > + > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoStartDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = PdoD3ToD0(Pdo); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __PdoSetDevicePnpState(Pdo, Started); > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryStopDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + __PdoSetDevicePnpState(Pdo, StopPending); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoCancelStopDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + __PdoRestoreDevicePnpState(Pdo, StopPending); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoStopDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) > + goto done; > + > + PdoD0ToD3(Pdo); > + > +done: > + __PdoSetDevicePnpState(Pdo, Stopped); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryRemoveDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + __PdoSetDevicePnpState(Pdo, RemovePending); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoCancelRemoveDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + if (__PdoClearEjectRequested(Pdo)) > + Trace("(%s) Eject Failed\n", __PdoGetName(Pdo)); > + > + __PdoRestoreDevicePnpState(Pdo, RemovePending); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoSurpriseRemoval( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + Warning("%s\n", __PdoGetName(Pdo)); > + > + __PdoSetDevicePnpState(Pdo, SurpriseRemovePending); > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoRemoveDevice( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PXENCONS_FDO Fdo = __PdoGetFdo(Pdo); > + BOOLEAN NeedInvalidate; > + NTSTATUS status; > + > + if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) > + goto done; > + > + PdoD0ToD3(Pdo); > + > +done: > + NeedInvalidate = FALSE; > + > + FdoAcquireMutex(Fdo); > + > + if (__PdoIsMissing(Pdo)) { > + DEVICE_PNP_STATE State = __PdoGetDevicePnpState(Pdo); > + > + __PdoSetDevicePnpState(Pdo, Deleted); > + > + if (State == SurpriseRemovePending) > + PdoDestroy(Pdo); > + else > + NeedInvalidate = TRUE; > + } else { > + __PdoSetDevicePnpState(Pdo, Enumerated); > + } > + > + FdoReleaseMutex(Fdo); > + > + if (NeedInvalidate) > + IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo), > + BusRelations); > + > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryDeviceRelations( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + PDEVICE_RELATIONS Relations; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + status = Irp->IoStatus.Status; > + > + if (StackLocation->Parameters.QueryDeviceRelations.Type != > TargetDeviceRelation) > + goto done; > + > + Relations = ExAllocatePoolWithTag(PagedPool, > sizeof(DEVICE_RELATIONS), PDO_POOL); > + > + status = STATUS_NO_MEMORY; > + if (Relations == NULL) > + goto done; > + > + RtlZeroMemory(Relations, sizeof(DEVICE_RELATIONS)); > + > + Relations->Count = 1; > + ObReferenceObject(__PdoGetDeviceObject(Pdo)); > + Relations->Objects[0] = __PdoGetDeviceObject(Pdo); > + > + Irp->IoStatus.Information = (ULONG_PTR)Relations; > + status = STATUS_SUCCESS; > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryCapabilities( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + PDEVICE_CAPABILITIES Capabilities; > + SYSTEM_POWER_STATE SystemPowerState; > + NTSTATUS status; > + > + UNREFERENCED_PARAMETER(Pdo); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities; > + > + status = STATUS_INVALID_PARAMETER; > + if (Capabilities->Version != 1) > + goto done; > + > + Capabilities->DeviceD1 = 0; > + Capabilities->DeviceD2 = 0; > + Capabilities->LockSupported = 0; > + Capabilities->EjectSupported = 1; > + Capabilities->Removable = 1; > + Capabilities->DockDevice = 0; > + Capabilities->UniqueID = 1; > + Capabilities->SilentInstall = 1; > + Capabilities->RawDeviceOK = 1; > + Capabilities->SurpriseRemovalOK = 1; > + Capabilities->HardwareDisabled = 0; > + Capabilities->NoDisplayInUI = 0; > + > + Capabilities->Address = 0xffffffff; > + Capabilities->UINumber = 0xffffffff; > + > + for (SystemPowerState = 0; SystemPowerState < > PowerSystemMaximum; SystemPowerState++) { > + switch (SystemPowerState) { > + case PowerSystemUnspecified: > + case PowerSystemSleeping1: > + case PowerSystemSleeping2: > + break; > + > + case PowerSystemWorking: > + Capabilities->DeviceState[SystemPowerState] = PowerDeviceD0; > + break; > + > + default: > + Capabilities->DeviceState[SystemPowerState] = PowerDeviceD3; > + break; > + } > + } > + > + Capabilities->SystemWake = PowerSystemUnspecified; > + Capabilities->DeviceWake = PowerDeviceUnspecified; > + Capabilities->D1Latency = 0; > + Capabilities->D2Latency = 0; > + Capabilities->D3Latency = 0; > + > + status = STATUS_SUCCESS; > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryDeviceText( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + PWCHAR Buffer; > + UNICODE_STRING Text; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + switch (StackLocation->Parameters.QueryDeviceText.DeviceTextType) { > + case DeviceTextDescription: > + Trace("DeviceTextDescription\n"); > + break; > + > + case DeviceTextLocationInformation: > + Trace("DeviceTextLocationInformation\n"); > + break; > + > + default: > + Irp->IoStatus.Information = 0; > + status = STATUS_NOT_SUPPORTED; > + goto done; > + } > + > + Buffer = ExAllocatePoolWithTag(PagedPool, MAXTEXTLEN, PDO_POOL); > + > + status = STATUS_NO_MEMORY; > + if (Buffer == NULL) > + goto done; > + > + RtlZeroMemory(Buffer, MAXTEXTLEN); > + > + Text.Buffer = Buffer; > + Text.MaximumLength = MAXTEXTLEN; > + Text.Length = 0; > + > + switch (StackLocation->Parameters.QueryDeviceText.DeviceTextType) { > + case DeviceTextDescription: > + status = RtlStringCbPrintfW(Buffer, > + MAXTEXTLEN, > + L"%hs PV Console #%hs", > + PRODUCT_NAME_STR, > + __PdoGetName(Pdo)); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + > + break; > + > + case DeviceTextLocationInformation: > + status = RtlStringCbPrintfW(Buffer, > + MAXTEXTLEN, > + L"%hs", > + __PdoGetName(Pdo)); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + Text.Length = (USHORT)((ULONG_PTR)Buffer - > (ULONG_PTR)Text.Buffer); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + Trace("%s: %wZ\n", __PdoGetName(Pdo), &Text); > + > + Irp->IoStatus.Information = (ULONG_PTR)Text.Buffer; > + status = STATUS_SUCCESS; > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoReadConfig( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + UNREFERENCED_PARAMETER(Pdo); > + > + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return STATUS_NOT_SUPPORTED; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoWriteConfig( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + UNREFERENCED_PARAMETER(Pdo); > + > + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return STATUS_NOT_SUPPORTED; > +} > + > +#define REGSTR_VAL_MAX_HCID_LEN 1024 > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryId( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + PWCHAR Buffer; > + UNICODE_STRING Id; > + ULONG Type; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + switch (StackLocation->Parameters.QueryId.IdType) { > + case BusQueryInstanceID: > + Trace("BusQueryInstanceID\n"); > + Id.MaximumLength = (USHORT)(strlen(__PdoGetName(Pdo)) + 1) * > sizeof(WCHAR); > + break; > + > + case BusQueryDeviceID: > + Trace("BusQueryDeviceID\n"); > + Id.MaximumLength = (MAX_DEVICE_ID_LEN - 2) * sizeof(WCHAR); > + break; > + > + case BusQueryHardwareIDs: > + Trace("BusQueryHardwareIDs\n"); > + Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * > sizeof(WCHAR)); > + break; > + > + case BusQueryCompatibleIDs: > + Trace("BusQueryCompatibleIDs\n"); > + Id.MaximumLength = (USHORT)(MAX_DEVICE_ID_LEN * > sizeof(WCHAR)); > + break; > + > + default: > + Irp->IoStatus.Information = 0; > + status = STATUS_NOT_SUPPORTED; > + goto done; > + } > + > + Buffer = ExAllocatePoolWithTag(PagedPool, Id.MaximumLength, > PDO_POOL); > + > + status = STATUS_NO_MEMORY; > + if (Buffer == NULL) > + goto done; > + > + RtlZeroMemory(Buffer, Id.MaximumLength); > + > + Id.Buffer = Buffer; > + Id.Length = 0; > + > + switch (StackLocation->Parameters.QueryId.IdType) { > + case BusQueryInstanceID: > + Type = REG_SZ; > + > + status = RtlStringCbPrintfW(Buffer, > + Id.MaximumLength, > + L"%hs", > + __PdoGetName(Pdo)); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + > + break; > + > + case BusQueryDeviceID: > + Type = REG_SZ; > + > + status = RtlStringCbPrintfW(Buffer, > + Id.MaximumLength, > + L"XENCONS\\VEN_%hs&DEV_CONSOLE", > + __PdoGetVendorName(Pdo)); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + > + break; > + > + case BusQueryHardwareIDs: > + case BusQueryCompatibleIDs: > + { > + ULONG Length; > + > + Type = REG_MULTI_SZ; > + > + Length = Id.MaximumLength; > + > + status = RtlStringCbPrintfW(Buffer, > + Length, > + L"XENCONS\\VEN_%hs&DEV_CONSOLE", > + __PdoGetVendorName(Pdo)); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + Length -= (ULONG)(wcslen(Buffer) * sizeof(WCHAR)); > + > + Buffer++; > + Length -= sizeof(WCHAR); > + > + status = RtlStringCbPrintfW(Buffer, > + Length, > + L"XENDEVICE"); > + ASSERT(NT_SUCCESS(status)); > + > + Buffer += wcslen(Buffer); > + Buffer++; > + > + ASSERT3U((ULONG_PTR)Buffer - (ULONG_PTR)Id.Buffer, <, > + REGSTR_VAL_MAX_HCID_LEN); > + break; > + } > + default: > + Type = REG_NONE; > + > + ASSERT(FALSE); > + break; > + } > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + Id.Length = (USHORT)((ULONG_PTR)Buffer - (ULONG_PTR)Id.Buffer); > + Buffer = Id.Buffer; > + > + switch (Type) { > + case REG_SZ: > + Trace("- %ws\n", Buffer); > + break; > + > + case REG_MULTI_SZ: > + do { > + Trace("- %ws\n", Buffer); > + Buffer += wcslen(Buffer); > + Buffer++; > + } while (*Buffer != L'\0'); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + Irp->IoStatus.Information = (ULONG_PTR)Id.Buffer; > + status = STATUS_SUCCESS; > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryBusInformation( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PPNP_BUS_INFORMATION Info; > + NTSTATUS status; > + > + UNREFERENCED_PARAMETER(Pdo); > + > + Info = ExAllocatePoolWithTag(PagedPool, > sizeof(PNP_BUS_INFORMATION), PDO_POOL); > + > + status = STATUS_NO_MEMORY; > + if (Info == NULL) > + goto done; > + > + RtlZeroMemory(Info, sizeof(PNP_BUS_INFORMATION)); > + > + Info->BusTypeGuid = GUID_BUS_TYPE_INTERNAL; > + Info->LegacyBusType = PNPBus; > + Info->BusNumber = 0; > + > + Irp->IoStatus.Information = (ULONG_PTR)Info; > + status = STATUS_SUCCESS; > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static NTSTATUS > +PdoDelegateIrp( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + return FdoDelegateIrp(__PdoGetFdo(Pdo), Irp); > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDeviceUsageNotification( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = PdoDelegateIrp(Pdo, Irp); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoEject( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PXENCONS_FDO Fdo = __PdoGetFdo(Pdo); > + NTSTATUS status; > + > + Trace("%s\n", __PdoGetName(Pdo)); > + > + FdoAcquireMutex(Fdo); > + > + __PdoSetDevicePnpState(Pdo, Deleted); > + __PdoSetMissing(Pdo, "device ejected"); > + > + FdoReleaseMutex(Fdo); > + > + IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo), > + BusRelations); > + > + status = STATUS_SUCCESS; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchPnp( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + Trace("====> (%s) (%02x:%s)\n", > + __PdoGetName(Pdo), > + MinorFunction, > + PnpMinorFunctionName(MinorFunction)); > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_START_DEVICE: > + status = PdoStartDevice(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_STOP_DEVICE: > + status = PdoQueryStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_CANCEL_STOP_DEVICE: > + status = PdoCancelStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_STOP_DEVICE: > + status = PdoStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_REMOVE_DEVICE: > + status = PdoQueryRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_CANCEL_REMOVE_DEVICE: > + status = PdoCancelRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_SURPRISE_REMOVAL: > + status = PdoSurpriseRemoval(Pdo, Irp); > + break; > + > + case IRP_MN_REMOVE_DEVICE: > + status = PdoRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_DEVICE_RELATIONS: > + status = PdoQueryDeviceRelations(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_CAPABILITIES: > + status = PdoQueryCapabilities(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_DEVICE_TEXT: > + status = PdoQueryDeviceText(Pdo, Irp); > + break; > + > + case IRP_MN_READ_CONFIG: > + status = PdoReadConfig(Pdo, Irp); > + break; > + > + case IRP_MN_WRITE_CONFIG: > + status = PdoWriteConfig(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_ID: > + status = PdoQueryId(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_BUS_INFORMATION: > + status = PdoQueryBusInformation(Pdo, Irp); > + break; > + > + case IRP_MN_DEVICE_USAGE_NOTIFICATION: > + status = PdoDeviceUsageNotification(Pdo, Irp); > + break; > + > + case IRP_MN_EJECT: > + status = PdoEject(Pdo, Irp); > + break; > + > + default: > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + break; > + } > + > + Trace("<==== (%02x:%s)(%08x)\n", > + MinorFunction, > + PnpMinorFunctionName(MinorFunction), > + status); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetDevicePower( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s) (%s:%s)\n", > + __PdoGetName(Pdo), > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + ASSERT3U(PowerAction, <, PowerActionShutdown); > + > + if (__PdoGetDevicePowerState(Pdo) > DeviceState) { > + Trace("%s: POWERING UP: %s -> %s\n", > + __PdoGetName(Pdo), > + PowerDeviceStateName(__PdoGetDevicePowerState(Pdo)), > + PowerDeviceStateName(DeviceState)); > + > + ASSERT3U(DeviceState, == , PowerDeviceD0); > + status = PdoD3ToD0(Pdo); > + ASSERT(NT_SUCCESS(status)); > + } else if (__PdoGetDevicePowerState(Pdo) < DeviceState) { > + Trace("%s: POWERING DOWN: %s -> %s\n", > + __PdoGetName(Pdo), > + PowerDeviceStateName(__PdoGetDevicePowerState(Pdo)), > + PowerDeviceStateName(DeviceState)); > + > + ASSERT3U(DeviceState, == , PowerDeviceD3); > + PdoD0ToD3(Pdo); > + } > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + Trace("<==== (%s:%s)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +PdoDevicePower( > + IN PXENCONS_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENCONS_PDO Pdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + > + if (Pdo->DevicePowerIrp == NULL) { > + (VOID)KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Pdo->DevicePowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Pdo->DevicePowerIrp = NULL; > + KeMemoryBarrier(); > + > + (VOID)__PdoSetDevicePower(Pdo, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +__drv_functionClass(REQUEST_POWER_COMPLETE) > +__drv_sameIRQL > +VOID > +__PdoRequestSetDevicePower( > + IN PDEVICE_OBJECT DeviceObject, > + IN UCHAR MinorFunction, > + IN POWER_STATE PowerState, > + IN PVOID Context, > + IN PIO_STATUS_BLOCK IoStatus > + ) > +{ > + PKEVENT Event = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + UNREFERENCED_PARAMETER(MinorFunction); > + UNREFERENCED_PARAMETER(PowerState); > + > + ASSERT(NT_SUCCESS(IoStatus->Status)); > + > + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); > +} > + > +static VOID > +PdoRequestSetDevicePower( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_POWER_STATE DeviceState > + ) > +{ > + POWER_STATE PowerState; > + KEVENT Event; > + NTSTATUS status; > + > + Trace("%s\n", PowerDeviceStateName(DeviceState)); > + > + ASSERT3U(KeGetCurrentIrql(), == , PASSIVE_LEVEL); > + > + PowerState.DeviceState = DeviceState; > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + status = PoRequestPowerIrp(__PdoGetDeviceObject(Pdo), > + IRP_MN_SET_POWER, > + PowerState, > + __PdoRequestSetDevicePower, > + &Event, > + NULL); > + ASSERT(NT_SUCCESS(status)); > + > + (VOID)KeWaitForSingleObject(&Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > +} > + > +// Define a static SystemPower to DevicePower map > +// This would normally be queried from the power policy owner, > +// but since this Pdo is "raw", the Pdo is the power policy owner > +static const DEVICE_POWER_STATE > +DevicePowerStateMap[PowerSystemMaximum] = > +{ > + PowerDeviceUnspecified, // PowerSystemUnspecified > + PowerDeviceD0, // PowerSystemWorking > + PowerDeviceD3, // PowerSystemSleeping1 > + PowerDeviceD3, // PowerSystemSleeping2 > + PowerDeviceD3, // PowerSystemSleeping3 > + PowerDeviceD3, // PowerSystemHibernate > + PowerDeviceD3 // PowerSystemShutdown > +}; > + > +static FORCEINLINE NTSTATUS > +__PdoSetSystemPower( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + POWER_ACTION PowerAction; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s) (%s:%s)\n", > + __PdoGetName(Pdo), > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + ASSERT3U(PowerAction, <, PowerActionShutdown); > + > + if (__PdoGetSystemPowerState(Pdo) > SystemState) { > + if (SystemState < PowerSystemHibernate && > + __PdoGetSystemPowerState(Pdo) >= PowerSystemHibernate) { > + __PdoSetSystemPowerState(Pdo, PowerSystemHibernate); > + PdoS4ToS3(Pdo); > + } > + > + Trace("%s: POWERING UP: %s -> %s\n", > + __PdoGetName(Pdo), > + PowerSystemStateName(__PdoGetSystemPowerState(Pdo)), > + PowerSystemStateName(SystemState)); > + > + PdoRequestSetDevicePower(Pdo, > DevicePowerStateMap[SystemState]); > + } else if (__PdoGetSystemPowerState(Pdo) < SystemState) { > + PdoRequestSetDevicePower(Pdo, > DevicePowerStateMap[SystemState]); > + > + Trace("%s: POWERING DOWN: %s -> %s\n", > + __PdoGetName(Pdo), > + PowerSystemStateName(__PdoGetSystemPowerState(Pdo)), > + PowerSystemStateName(SystemState)); > + > + if (SystemState >= PowerSystemHibernate && > + __PdoGetSystemPowerState(Pdo) < PowerSystemHibernate) { > + __PdoSetSystemPowerState(Pdo, PowerSystemSleeping3); > + PdoS3ToS4(Pdo); > + } > + } > + > + __PdoSetSystemPowerState(Pdo, SystemState); > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + Trace("<==== (%s:%s)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +PdoSystemPower( > + IN PXENCONS_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENCONS_PDO Pdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + > + if (Pdo->SystemPowerIrp == NULL) { > + (VOID)KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Pdo->SystemPowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Pdo->SystemPowerIrp = NULL; > + KeMemoryBarrier(); > + > + (VOID)__PdoSetSystemPower(Pdo, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoSetPower( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + POWER_STATE_TYPE PowerType; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + PowerType = StackLocation->Parameters.Power.Type; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + if (PowerAction >= PowerActionShutdown) { > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + switch (PowerType) { > + case DevicePowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Pdo->DevicePowerIrp, == , NULL); > + Pdo->DevicePowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Pdo->DevicePowerThread); > + > + status = STATUS_PENDING; > + break; > + > + case SystemPowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Pdo->SystemPowerIrp, == , NULL); > + Pdo->SystemPowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Pdo->SystemPowerThread); > + > + status = STATUS_PENDING; > + break; > + > + default: > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + break; > + } > + > +done: > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryPower( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + UNREFERENCED_PARAMETER(Pdo); > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchPower( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_SET_POWER: > + status = PdoSetPower(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_POWER: > + status = PdoQueryPower(Pdo, Irp); > + break; > + > + default: > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + break; > + } > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchDefault( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + UNREFERENCED_PARAMETER(Pdo); > + > + status = Irp->IoStatus.Status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +NTSTATUS > +PdoDispatch( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + switch (StackLocation->MajorFunction) { > + case IRP_MJ_PNP: > + status = PdoDispatchPnp(Pdo, Irp); > + break; > + > + case IRP_MJ_POWER: > + status = PdoDispatchPower(Pdo, Irp); > + break; > + > + default: > + status = PdoDispatchDefault(Pdo, Irp); > + break; > + } > + > + return status; > +} > + > +NTSTATUS > +PdoResume( > + IN PXENCONS_PDO Pdo > + ) > +{ > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > + return STATUS_SUCCESS; > +} > + > +VOID > +PdoSuspend( > + IN PXENCONS_PDO Pdo > + ) > +{ > + Trace("(%s) ====>\n", __PdoGetName(Pdo)); > + Trace("(%s) <====\n", __PdoGetName(Pdo)); > +} > + > +NTSTATUS > +PdoCreate( > + IN PXENCONS_FDO Fdo, > + IN PANSI_STRING Device > + ) > +{ > + PDEVICE_OBJECT PhysicalDeviceObject; > + PXENCONS_DX Dx; > + PXENCONS_PDO Pdo; > + NTSTATUS status; > + > +#pragma prefast(suppress:28197) // Possibly leaking memory > 'PhysicalDeviceObject' > + status = IoCreateDevice(DriverGetDriverObject(), > + sizeof(XENCONS_DX), > + NULL, > + FILE_DEVICE_UNKNOWN, > + FILE_DEVICE_SECURE_OPEN | > FILE_AUTOGENERATED_DEVICE_NAME, > + FALSE, > + &PhysicalDeviceObject); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Dx = (PXENCONS_DX)PhysicalDeviceObject->DeviceExtension; > + RtlZeroMemory(Dx, sizeof(XENCONS_DX)); > + > + Dx->Type = PHYSICAL_DEVICE_OBJECT; > + Dx->DeviceObject = PhysicalDeviceObject; > + Dx->DevicePnpState = Present; > + Dx->SystemPowerState = PowerSystemWorking; > + Dx->DevicePowerState = PowerDeviceD3; > + > + Pdo = __PdoAllocate(sizeof(XENCONS_PDO)); > + > + status = STATUS_NO_MEMORY; > + if (Pdo == NULL) > + goto fail2; > + > + Pdo->Dx = Dx; > + Pdo->Fdo = Fdo; > + > + status = ThreadCreate(PdoSystemPower, Pdo, &Pdo- > >SystemPowerThread); > + if (!NT_SUCCESS(status)) > + goto fail3; > + > + status = ThreadCreate(PdoDevicePower, Pdo, &Pdo- > >DevicePowerThread); > + if (!NT_SUCCESS(status)) > + goto fail4; > + > + __PdoSetName(Pdo, Device); > + > + FdoGetSuspendInterface(Fdo, &Pdo->SuspendInterface); > + > + Dx->Pdo = Pdo; > + > + status = FdoAddPhysicalDeviceObject(Fdo, Pdo); > + if (!NT_SUCCESS(status)) > + goto fail5; > + > + status = STATUS_UNSUCCESSFUL; > + if (__PdoIsEjectRequested(Pdo)) > + goto fail6; > + > + Info("%p (%s)\n", > + PhysicalDeviceObject, > + __PdoGetName(Pdo)); > + > + PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; > + return STATUS_SUCCESS; > + > +fail6: > + Error("fail6\n"); > + > + FdoRemovePhysicalDeviceObject(Fdo, Pdo); > + > +fail5: > + Error("fail5\n"); > + > + (VOID)__PdoClearEjectRequested(Pdo); > + > + Dx->Pdo = NULL; > + > + RtlZeroMemory(&Pdo->SuspendInterface, > + sizeof(XENBUS_SUSPEND_INTERFACE)); > + > + ThreadAlert(Pdo->DevicePowerThread); > + ThreadJoin(Pdo->DevicePowerThread); > + Pdo->DevicePowerThread = NULL; > + > +fail4: > + Error("fail4\n"); > + > + ThreadAlert(Pdo->SystemPowerThread); > + ThreadJoin(Pdo->SystemPowerThread); > + Pdo->SystemPowerThread = NULL; > + > +fail3: > + Error("fail3\n"); > + > + Pdo->Fdo = NULL; > + Pdo->Dx = NULL; > + > + ASSERT(IsZeroMemory(Pdo, sizeof(XENCONS_PDO))); > + __PdoFree(Pdo); > + > +fail2: > + Error("fail2\n"); > + > + IoDeleteDevice(PhysicalDeviceObject); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +VOID > +PdoDestroy( > + IN PXENCONS_PDO Pdo > + ) > +{ > + PXENCONS_DX Dx = Pdo->Dx; > + PDEVICE_OBJECT PhysicalDeviceObject = Dx->DeviceObject; > + PXENCONS_FDO Fdo = __PdoGetFdo(Pdo); > + > + ASSERT3U(__PdoGetDevicePnpState(Pdo), == , Deleted); > + > + ASSERT(__PdoIsMissing(Pdo)); > + Pdo->Missing = FALSE; > + > + Info("%p (%s) (%s)\n", > + PhysicalDeviceObject, > + __PdoGetName(Pdo), > + Pdo->Reason); > + > + Pdo->Reason = NULL; > + > + FdoRemovePhysicalDeviceObject(Fdo, Pdo); > + > + (VOID)__PdoClearEjectRequested(Pdo); > + > + Dx->Pdo = NULL; > + > + RtlZeroMemory(&Pdo->SuspendInterface, > + sizeof(XENBUS_SUSPEND_INTERFACE)); > + > + ThreadAlert(Pdo->DevicePowerThread); > + ThreadJoin(Pdo->DevicePowerThread); > + Pdo->DevicePowerThread = NULL; > + > + ThreadAlert(Pdo->SystemPowerThread); > + ThreadJoin(Pdo->SystemPowerThread); > + Pdo->SystemPowerThread = NULL; > + > + Pdo->Fdo = NULL; > + Pdo->Dx = NULL; > + > + ASSERT(IsZeroMemory(Pdo, sizeof(XENCONS_PDO))); > + __PdoFree(Pdo); > + > + IoDeleteDevice(PhysicalDeviceObject); > +} > + > diff --git a/src/xencons/pdo.h b/src/xencons/pdo.h > new file mode 100755 > index 0000000..0605483 > --- /dev/null > +++ b/src/xencons/pdo.h > @@ -0,0 +1,113 @@ > +/* 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_PDO_H > +#define _XENCONS_PDO_H > + > +#include <ntddk.h> > + > +#include "driver.h" > + > +extern VOID > +PdoSetDevicePnpState( > + IN PXENCONS_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ); > + > +extern DEVICE_PNP_STATE > +PdoGetDevicePnpState( > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +PdoSetMissing( > + IN PXENCONS_PDO Pdo, > + IN const CHAR *Reason > + ); > + > +extern BOOLEAN > +PdoIsMissing( > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +PdoRequestEject( > + IN PXENCONS_PDO Pdo > + ); > + > +extern BOOLEAN > +PdoIsEjectRequested( > + IN PXENCONS_PDO Pdo > + ); > + > +extern PCHAR > +PdoGetName( > + IN PXENCONS_PDO Pdo > + ); > + > +extern PXENCONS_FDO > +PdoGetFdo( > + IN PXENCONS_PDO Pdo > + ); > + > +extern PDEVICE_OBJECT > +PdoGetDeviceObject( > + IN PXENCONS_PDO Pdo > + ); > + > +extern NTSTATUS > +PdoCreate( > + IN PXENCONS_FDO Fdo, > + IN PANSI_STRING Device > + ); > + > +extern NTSTATUS > +PdoResume( > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +PdoSuspend( > + IN PXENCONS_PDO Pdo > + ); > + > +extern VOID > +PdoDestroy( > + IN PXENCONS_PDO Pdo > + ); > + > +extern NTSTATUS > +PdoDispatch( > + IN PXENCONS_PDO Pdo, > + IN PIRP Irp > + ); > + > +#endif // _XENCONS_PDO_H > diff --git a/vs2015/xencons/xencons.vcxproj > b/vs2015/xencons/xencons.vcxproj > index 12f5b70..2e9d208 100644 > --- a/vs2015/xencons/xencons.vcxproj > +++ b/vs2015/xencons/xencons.vcxproj > @@ -66,6 +66,7 @@ > <ItemGroup> > <ClCompile Include="../../src/xencons/driver.c" /> > <ClCompile Include="../../src/xencons/fdo.c" /> > + <ClCompile Include="../../src/xencons/pdo.c" /> > <ClCompile Include="../../src/xencons/registry.c" /> > <ClCompile Include="../../src/xencons/console.c" /> > <ClCompile Include="../../src/xencons/stream.c" /> > diff --git a/vs2017/xencons/xencons.vcxproj > b/vs2017/xencons/xencons.vcxproj > index 510acb6..6c67fe8 100644 > --- a/vs2017/xencons/xencons.vcxproj > +++ b/vs2017/xencons/xencons.vcxproj > @@ -74,6 +74,7 @@ > <ItemGroup> > <ClCompile Include="../../src/xencons/driver.c" /> > <ClCompile Include="../../src/xencons/fdo.c" /> > + <ClCompile Include="../../src/xencons/pdo.c" /> > <ClCompile Include="../../src/xencons/registry.c" /> > <ClCompile Include="../../src/xencons/console.c" /> > <ClCompile Include="../../src/xencons/stream.c" /> > -- > 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 |