[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 07/14 v2] Enumerate non-default consoles
From: Owen Smith <owen.smith@xxxxxxxxxx> * Add enumeration thread and watch * Non-default consoles will fail any read/write/iocontrol IRPs Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/xencons/fdo.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/xencons/pdo.c | 64 +++++++++-- src/xencons/pdo.h | 5 + 3 files changed, 376 insertions(+), 9 deletions(-) diff --git a/src/xencons/fdo.c b/src/xencons/fdo.c index 45a1fdd..4046acf 100644 --- a/src/xencons/fdo.c +++ b/src/xencons/fdo.c @@ -85,6 +85,9 @@ struct _XENCONS_FDO { CHAR VendorName[MAXNAMELEN]; + PXENCONS_THREAD ScanThread; + KEVENT ScanEvent; + PXENBUS_STORE_WATCH ScanWatch; MUTEX Mutex; ULONG References; @@ -653,6 +656,9 @@ done: RemoveEntryList(&Dx->ListEntry); ASSERT3U(Fdo->References, != , 0); --Fdo->References; + + if (Fdo->ScanThread) + ThreadWake(Fdo->ScanThread); } static FORCEINLINE VOID @@ -690,6 +696,112 @@ FdoReleaseMutex( FdoDestroy(Fdo); } +static FORCEINLINE BOOLEAN +__FdoEnumerate( + IN PXENCONS_FDO Fdo, + IN PANSI_STRING Devices + ) +{ + BOOLEAN NeedInvalidate; + HANDLE ParametersKey; + ULONG Enumerate; + PLIST_ENTRY ListEntry; + ULONG Index; + NTSTATUS status; + + Trace("====>\n"); + + NeedInvalidate = FALSE; + + ParametersKey = DriverGetParametersKey(); + + status = RegistryQueryDwordValue(ParametersKey, + "Enumerate", + &Enumerate); + if (!NT_SUCCESS(status)) + Enumerate = 1; + + if (Enumerate == 0) + goto done; + + __FdoAcquireMutex(Fdo); + + ListEntry = Fdo->Dx->ListEntry.Flink; + while (ListEntry != &Fdo->Dx->ListEntry) { + PLIST_ENTRY Next = ListEntry->Flink; + PXENCONS_DX Dx = CONTAINING_RECORD(ListEntry, XENCONS_DX, ListEntry); + PXENCONS_PDO Pdo = Dx->Pdo; + + // If the PDO is the default console, it wont exist in the + // the device list, as its statically created + if (PdoIsDefault(Pdo)) + continue; + + if (PdoGetDevicePnpState(Pdo) != Deleted) { + PCHAR Name; + BOOLEAN Missing; + + Name = PdoGetName(Pdo); + Missing = TRUE; + + // If the PDO already exists and its name is in the device list + // then we don't want to remove it. + for (Index = 0; Devices[Index].Buffer != NULL; Index++) { + PANSI_STRING Device = &Devices[Index]; + + if (Device->Length == 0) + continue; + + if (strcmp(Name, Device->Buffer) == 0) { + Missing = FALSE; + Device->Length = 0; // avoid duplication + break; + } + } + + if (!PdoIsMissing(Pdo)) { + if (PdoIsEjectRequested(Pdo)) { + IoRequestDeviceEject(PdoGetDeviceObject(Pdo)); + } else if (Missing) { + PdoSetMissing(Pdo, "device disappeared"); + + // If the PDO has not yet been enumerated then we can + // go ahead and mark it as deleted, otherwise we need + // to notify PnP manager and wait for the REMOVE_DEVICE + // IRP. + if (PdoGetDevicePnpState(Pdo) == Present) { + PdoSetDevicePnpState(Pdo, Deleted); + PdoDestroy(Pdo); + } else { + NeedInvalidate = TRUE; + } + } + } + } + + ListEntry = Next; + } + + // Walk the class list and create PDOs for any new device + for (Index = 0; Devices[Index].Buffer != NULL; Index++) { + PANSI_STRING Device = &Devices[Index]; + + if (Device->Length == 0) + continue; + + status = PdoCreate(Fdo, Device); + if (NT_SUCCESS(status)) + NeedInvalidate = TRUE; + } + + __FdoReleaseMutex(Fdo); + +done: + Trace("<====\n"); + + return NeedInvalidate; +} + static FORCEINLINE PANSI_STRING __FdoMultiSzToUpcaseAnsi( IN PCHAR Buffer @@ -768,6 +880,125 @@ __FdoFreeAnsi( __FdoFree(Ansi); } +static NTSTATUS +FdoScan( + PXENCONS_THREAD Self, + PVOID Context + ) +{ + PXENCONS_FDO Fdo = Context; + PKEVENT Event; + HANDLE ParametersKey; + NTSTATUS status; + + Trace("====>\n"); + + Event = ThreadGetEvent(Self); + + ParametersKey = DriverGetParametersKey(); + + for (;;) { + PCHAR Buffer; + PANSI_STRING Devices; + PANSI_STRING UnsupportedDevices; + ULONG Index; + BOOLEAN NeedInvalidate; + + Trace("waiting...\n"); + + (VOID)KeWaitForSingleObject(Event, + Executive, + KernelMode, + FALSE, + NULL); + KeClearEvent(Event); + + if (ThreadIsAlerted(Self)) + break; + + // It is not safe to use interfaces before this point + if (__FdoGetDevicePnpState(Fdo) != Started) { + KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE); + continue; + } + + status = XENBUS_STORE(Directory, + &Fdo->StoreInterface, + NULL, + "device", + "console", + &Buffer); + if (NT_SUCCESS(status)) { + Devices = __FdoMultiSzToUpcaseAnsi(Buffer); + + XENBUS_STORE(Free, + &Fdo->StoreInterface, + Buffer); + } else { + Devices = NULL; + } + + if (Devices == NULL) + goto loop; + + if (ParametersKey != NULL) { + status = RegistryQuerySzValue(ParametersKey, + "UnsupportedDevices", + NULL, + &UnsupportedDevices); + if (!NT_SUCCESS(status)) + UnsupportedDevices = NULL; + } else { + UnsupportedDevices = NULL; + } + + // NULL out anything in the Devices list that is in the + // UnsupportedDevices list + for (Index = 0; Devices[Index].Buffer != NULL; Index++) { + PANSI_STRING Device = &Devices[Index]; + ULONG Entry; + BOOLEAN Supported; + + Supported = TRUE; + + for (Entry = 0; + UnsupportedDevices != NULL && UnsupportedDevices[Entry].Buffer != NULL; + Entry++) { + if (strncmp(Device->Buffer, + UnsupportedDevices[Entry].Buffer, + Device->Length) == 0) { + Supported = FALSE; + break; + } + } + + if (!Supported) + Device->Length = 0; + } + + if (UnsupportedDevices != NULL) + RegistryFreeSzValue(UnsupportedDevices); + + NeedInvalidate = __FdoEnumerate(Fdo, Devices); + + __FdoFreeAnsi(Devices); + + if (NeedInvalidate) { + NeedInvalidate = FALSE; + IoInvalidateDeviceRelations(__FdoGetPhysicalDeviceObject(Fdo), + BusRelations); + } + + loop: + KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE); + } + + KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE); + + Trace("<====\n"); + return STATUS_SUCCESS; +} + static FORCEINLINE BOOLEAN __FdoMatchDistribution( IN PXENCONS_FDO Fdo, @@ -989,15 +1220,39 @@ __FdoD3ToD0( IN PXENCONS_FDO Fdo ) { + NTSTATUS status; + Trace("====>\n"); ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); (VOID) FdoSetDistribution(Fdo); + status = XENBUS_STORE(WatchAdd, + &Fdo->StoreInterface, + "device", + "console", + ThreadGetEvent(Fdo->ScanThread), + &Fdo->ScanWatch); + if (!NT_SUCCESS(status)) + goto fail1; + + (VOID)XENBUS_STORE(Printf, + &Fdo->StoreInterface, + NULL, + "feature/hotplug", + "console", + "%u", + TRUE); + Trace("<====\n"); return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; } static FORCEINLINE VOID @@ -1009,6 +1264,17 @@ __FdoD0ToD3( ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + (VOID)XENBUS_STORE(Remove, + &Fdo->StoreInterface, + NULL, + "feature/hotplug", + "console"); + + (VOID)XENBUS_STORE(WatchRemove, + &Fdo->StoreInterface, + Fdo->ScanWatch); + Fdo->ScanWatch = NULL; + FdoClearDistribution(Fdo); Trace("<====\n"); @@ -1221,17 +1487,31 @@ FdoStartDevice( StackLocation->Parameters.StartDevice.AllocatedResources, StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated); - status = FdoD3ToD0(Fdo); + KeInitializeEvent(&Fdo->ScanEvent, NotificationEvent, FALSE); + + status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread); if (!NT_SUCCESS(status)) goto fail2; + status = FdoD3ToD0(Fdo); + if (!NT_SUCCESS(status)) + goto fail3; + __FdoSetDevicePnpState(Fdo, Started); + ThreadWake(Fdo->ScanThread); status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; +fail3: + Error("fail3\n"); + + ThreadAlert(Fdo->ScanThread); + ThreadJoin(Fdo->ScanThread); + Fdo->ScanThread = NULL; + fail2: Error("fail2\n"); @@ -1292,6 +1572,12 @@ FdoStopDevice( if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) FdoD0ToD3(Fdo); + ThreadAlert(Fdo->ScanThread); + ThreadJoin(Fdo->ScanThread); + Fdo->ScanThread = NULL; + + RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT)); + RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) * RESOURCE_COUNT); __FdoSetDevicePnpState(Fdo, Stopped); @@ -1387,6 +1673,17 @@ FdoRemoveDevice( if (__FdoGetPreviousDevicePnpState(Fdo) != Started) goto done; + KeClearEvent(&Fdo->ScanEvent); + ThreadWake(Fdo->ScanThread); + + Trace("waiting for scan thread\n"); + + (VOID)KeWaitForSingleObject(&Fdo->ScanEvent, + Executive, + KernelMode, + FALSE, + NULL); + __FdoAcquireMutex(Fdo); ListEntry = Fdo->Dx->ListEntry.Flink; @@ -1414,6 +1711,12 @@ FdoRemoveDevice( if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) FdoD0ToD3(Fdo); + ThreadAlert(Fdo->ScanThread); + ThreadJoin(Fdo->ScanThread); + Fdo->ScanThread = NULL; + + RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT)); + RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) * RESOURCE_COUNT); done: @@ -1463,6 +1766,17 @@ FdoQueryDeviceRelations( goto done; } + KeClearEvent(&Fdo->ScanEvent); + ThreadWake(Fdo->ScanThread); + + Trace("waiting for scan thread\n"); + + (VOID)KeWaitForSingleObject(&Fdo->ScanEvent, + Executive, + KernelMode, + FALSE, + NULL); + __FdoAcquireMutex(Fdo); Count = 0; diff --git a/src/xencons/pdo.c b/src/xencons/pdo.c index 62f366c..2acd86a 100755 --- a/src/xencons/pdo.c +++ b/src/xencons/pdo.c @@ -71,6 +71,7 @@ struct _XENCONS_PDO { XENBUS_SUSPEND_INTERFACE SuspendInterface; PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; + BOOLEAN IsDefault; PXENCONS_CONSOLE Console; }; @@ -286,6 +287,14 @@ __PdoGetName( return Dx->Name; } +PCHAR +PdoGetName( + IN PXENCONS_PDO Pdo + ) +{ + return __PdoGetName(Pdo); +} + static FORCEINLINE PCHAR __PdoGetVendorName( IN PXENCONS_PDO Pdo @@ -295,6 +304,22 @@ __PdoGetVendorName( } static FORCEINLINE BOOLEAN +__PdoIsDefault( + IN PXENCONS_PDO Pdo + ) +{ + return Pdo->IsDefault; +} + +BOOLEAN +PdoIsDefault( + IN PXENCONS_PDO Pdo + ) +{ + return __PdoIsDefault(Pdo); +} + +static FORCEINLINE BOOLEAN __PdoSetEjectRequested( IN PXENCONS_PDO Pdo ) @@ -441,7 +466,10 @@ PdoD3ToD0( KeLowerIrql(Irql); - status = ConsoleD3ToD0(Pdo->Console); + if (__PdoIsDefault(Pdo)) + status = ConsoleD3ToD0(Pdo->Console); + else + status = STATUS_SUCCESS; if (!NT_SUCCESS(status)) goto fail4; @@ -495,7 +523,8 @@ PdoD0ToD3( #pragma prefast(suppress:28123) (VOID) IoSetDeviceInterfaceState(&Pdo->Dx->Link, FALSE); - ConsoleD0ToD3(Pdo->Console); + if (__PdoIsDefault(Pdo)) + ConsoleD0ToD3(Pdo->Console); KeRaiseIrql(DISPATCH_LEVEL, &Irql); @@ -1689,7 +1718,10 @@ PdoDispatchCreate( StackLocation = IoGetCurrentIrpStackLocation(Irp); - status = ConsoleOpen(Pdo->Console, StackLocation->FileObject); + if (__PdoIsDefault(Pdo)) + status = ConsoleOpen(Pdo->Console, StackLocation->FileObject); + else + status = STATUS_SUCCESS; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -1708,7 +1740,10 @@ PdoDispatchCleanup( StackLocation = IoGetCurrentIrpStackLocation(Irp); - status = ConsoleClose(Pdo->Console, StackLocation->FileObject); + if (__PdoIsDefault(Pdo)) + status = ConsoleClose(Pdo->Console, StackLocation->FileObject); + else + status = STATUS_SUCCESS; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -1742,7 +1777,10 @@ PdoDispatchReadWriteControl( { NTSTATUS status; - status = ConsolePutQueue(Pdo->Console, Irp); + if (__PdoIsDefault(Pdo)) + status = ConsolePutQueue(Pdo->Console, Irp); + else + status = STATUS_DEVICE_NOT_READY; if (status == STATUS_SUCCESS) goto done; if (status != STATUS_PENDING) @@ -1895,7 +1933,11 @@ PdoCreate( Dx->Pdo = Pdo; - status = ConsoleCreate(Fdo, &Pdo->Console); + Pdo->IsDefault = (Device == NULL); + if (Pdo->IsDefault) + status = ConsoleCreate(Fdo, &Pdo->Console); + else + status = STATUS_SUCCESS; if (!NT_SUCCESS(status)) goto fail5; @@ -1925,9 +1967,12 @@ fail6: (VOID)__PdoClearEjectRequested(Pdo); - ConsoleDestroy(Pdo->Console); + if (__PdoIsDefault(Pdo)) + ConsoleDestroy(Pdo->Console); Pdo->Console = NULL; + Pdo->IsDefault = FALSE; + fail5: Error("fail5\n"); @@ -1994,9 +2039,12 @@ PdoDestroy( Dx->Pdo = NULL; - ConsoleDestroy(Pdo->Console); + if (__PdoIsDefault(Pdo)) + ConsoleDestroy(Pdo->Console); Pdo->Console = NULL; + Pdo->IsDefault = FALSE; + RtlFreeUnicodeString(&Pdo->Dx->Link); RtlZeroMemory(&Pdo->SuspendInterface, diff --git a/src/xencons/pdo.h b/src/xencons/pdo.h index 0605483..85f73a3 100755 --- a/src/xencons/pdo.h +++ b/src/xencons/pdo.h @@ -83,6 +83,11 @@ PdoGetDeviceObject( IN PXENCONS_PDO Pdo ); +extern BOOLEAN +PdoIsDefault( + IN PXENCONS_PDO Pdo + ); + extern NTSTATUS PdoCreate( IN PXENCONS_FDO Fdo, -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |