|
[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 |