PXENVBD_PDO Targets[XENVBD_MAX_TARGETS];
// Target Enumeration
- PXENVBD_THREAD RescanThread;
- PXENBUS_STORE_WATCH RescanWatch;
+ PXENVBD_THREAD ScanThread;
+ KEVENT ScanEvent;
+ PXENBUS_STORE_WATCH ScanWatch;
PXENVBD_THREAD FrontendThread;
// Statistics
return Changed;
}
+static FORCEINLINE DEVICE_POWER_STATE
+__FdoGetDevicePowerState(
+ __in PXENVBD_FDO Fdo
+ )
+{
+ KIRQL Irql;
+ DEVICE_POWER_STATE State;
+
+ KeAcquireSpinLock(&Fdo->Lock, &Irql);
+ State = Fdo->DevicePower;
+ KeReleaseSpinLock(&Fdo->Lock, Irql);
+
+ return State;
+}
+
__checkReturn
static FORCEINLINE PXENVBD_PDO
__FdoGetPdoAlways(
*NeedInvalidate |= (NT_SUCCESS(Status)) ? TRUE : FALSE;
}
}
-__drv_requiresIRQL(DISPATCH_LEVEL)
static DECLSPEC_NOINLINE VOID
FdoScanTargets(
- __in PXENVBD_FDO Fdo,
- __out PBOOLEAN NeedInvalidate,
- __out PBOOLEAN NeedReboot
+ __in PXENVBD_FDO Fdo
)
{
NTSTATUS Status;
PCHAR Buffer;
+ BOOLEAN NeedInvalidate;
+ BOOLEAN NeedReboot;
- Trace("====>\n");
Status = XENBUS_STORE(Directory, &Fdo->Store, NULL, "device", FdoEnum(Fdo), &Buffer);
- if (NT_SUCCESS(Status)) {
- __FdoEnumerate(Fdo, Buffer, NeedInvalidate, NeedReboot);
- XENBUS_STORE(Free, &Fdo->Store, Buffer);
- } else {
- *NeedInvalidate = FALSE;
- *NeedReboot = FALSE;
- }
- Trace("<====\n");
-}
+ if (!NT_SUCCESS(Status))
+ return;
-static DECLSPEC_NOINLINE VOID
-FdoLogTargets(
- __in PCHAR Caller,
- __in PXENVBD_FDO Fdo
- )
-{
- ULONG TargetId;
+ __FdoEnumerate(Fdo, Buffer, &NeedInvalidate, &NeedReboot);
+ XENBUS_STORE(Free, &Fdo->Store, Buffer);
- Verbose("%s ===>\n", Caller);
- for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) {
- PXENVBD_PDO Pdo = __FdoGetPdoAlways(Fdo, TargetId, __FUNCTION__);
- if (Pdo) {
- const CHAR* Reason = PdoMissingReason(Pdo);
- Verbose("%s : Target[%d] = 0x%p %s\n", Caller, TargetId, Pdo,
- (Reason != NULL) ? Reason : "(present)");
- PdoDereference(Pdo);
- }
+ if (NeedInvalidate) {
+ StorPortNotification(BusChangeDetected, Fdo, 0);
+ }
+ if (NeedReboot) {
+ DriverNotifyInstaller();
}
- Verbose("%s <===\n", Caller);
}
__checkReturn
)
{
PXENVBD_FDO Fdo = Context;
+ PKEVENT Event = ThreadGetEvent(Thread);
for (;;) {
- KIRQL Irql;
- BOOLEAN NeedInvalidate;
- BOOLEAN NeedReboot;
-
- if (!ThreadWait(Thread))
- break;
-
- KeAcquireSpinLock(&Fdo->Lock, &Irql);
- if (Fdo->DevicePower != PowerDeviceD0) {
- KeReleaseSpinLock(&Fdo->Lock, Irql);
- continue;
- }
-
- FdoScanTargets(Fdo, &NeedInvalidate, &NeedReboot);
+ Trace("waiting...\n");
- KeReleaseSpinLock(&Fdo->Lock, Irql);
+ (VOID) KeWaitForSingleObject(Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ KeClearEvent(Event);
- if (NeedInvalidate) {
- FdoLogTargets("ScanThread", Fdo);
- StorPortNotification(BusChangeDetected, Fdo, 0);
- }
+ if (ThreadIsAlerted(Thread))
+ break;
+
+ if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0)
+ FdoScanTargets(Fdo);
- if (NeedReboot)
- DriverNotifyInstaller();
+ KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
}
+ KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE);
return STATUS_SUCCESS;
}
(VOID) FdoSetDistribution(Fdo);
- ASSERT3P(Fdo->RescanWatch, ==, NULL);
+ ASSERT3P(Fdo->ScanWatch, ==, NULL);
Status = XENBUS_STORE(WatchAdd,
&Fdo->Store,
"device",
FdoEnum(Fdo),
- ThreadGetEvent(Fdo->RescanThread),
- &Fdo->RescanWatch);
+ ThreadGetEvent(Fdo->ScanThread),
+ &Fdo->ScanWatch);
if (!NT_SUCCESS(Status))
goto fail1;
(VOID) XENBUS_STORE(WatchRemove,
&Fdo->Store,
- Fdo->RescanWatch);
- Fdo->RescanWatch = NULL;
+ Fdo->ScanWatch);
+ Fdo->ScanWatch = NULL;
FdoClearDistribution(Fdo);
KeInitializeSpinLock(&Fdo->TargetLock);
KeInitializeSpinLock(&Fdo->Lock);
KeInitializeEvent(&Fdo->RemoveEvent, SynchronizationEvent, FALSE);
+ KeInitializeEvent(&Fdo->ScanEvent, SynchronizationEvent, FALSE);
Fdo->ReferenceCount = 1;
Fdo->Signature = FDO_SIGNATURE;
goto fail2;
// start enum thread
- Status = ThreadCreate(FdoScan, Fdo, &Fdo->RescanThread);
+ Status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread);
if (!NT_SUCCESS(Status))
goto fail3;
Fdo->FrontendThread = NULL;
fail4:
Error("fail4\n");
- ThreadAlert(Fdo->RescanThread);
- ThreadJoin(Fdo->RescanThread);
- Fdo->RescanThread = NULL;
+ ThreadAlert(Fdo->ScanThread);
+ ThreadJoin(Fdo->ScanThread);
+ Fdo->ScanThread = NULL;
fail3:
Error("fail3\n");
__FdoZeroInterfaces(Fdo);
Fdo->FrontendThread = NULL;
// stop enum thread
- ThreadAlert(Fdo->RescanThread);
- ThreadJoin(Fdo->RescanThread);
- Fdo->RescanThread = NULL;
+ ThreadAlert(Fdo->ScanThread);
+ ThreadJoin(Fdo->ScanThread);
+ Fdo->ScanThread = NULL;
// clear device objects
Fdo->DeviceObject = NULL;
RtlZeroMemory(&Fdo->Enumerator, sizeof(ANSI_STRING));
RtlZeroMemory(&Fdo->TargetLock, sizeof(KSPIN_LOCK));
RtlZeroMemory(&Fdo->Lock, sizeof(KSPIN_LOCK));
+ RtlZeroMemory(&Fdo->ScanEvent, sizeof(KEVENT));
RtlZeroMemory(&Fdo->RemoveEvent, sizeof(KEVENT));
__FdoZeroInterfaces(Fdo);
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (Stack->Parameters.QueryDeviceRelations.Type == BusRelations) {
- KIRQL Irql;
- BOOLEAN NeedInvalidate;
- BOOLEAN NeedReboot;
-
- KeAcquireSpinLock(&Fdo->Lock, &Irql);
-
- if (Fdo->DevicePower == PowerDeviceD0) {
- FdoScanTargets(Fdo, &NeedInvalidate, &NeedReboot);
- } else {
- NeedInvalidate = FALSE;
- NeedReboot = FALSE;
- }
-
- KeReleaseSpinLock(&Fdo->Lock, Irql);
+ KeClearEvent(&Fdo->ScanEvent);
+ ThreadWake(Fdo->ScanThread);
- if (NeedInvalidate)
- FdoLogTargets("QUERY_RELATIONS", Fdo);
+ Trace("waiting for scan thread\n");
- if (NeedReboot)
- DriverNotifyInstaller();
+ (VOID) KeWaitForSingleObject(&Fdo->ScanEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
}
FdoDereference(Fdo);
break;