[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 01/26] Rename Fdo -> Adapter Remove Adapter reference counts
From: Owen Smith <owen.smith@xxxxxxxxxx> Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- src/xenvbd/adapter.c | 2147 ++++++++++++++++++++++++++++++++++++++++ src/xenvbd/adapter.h | 162 ++++ src/xenvbd/blockring.c | 6 +- src/xenvbd/driver.c | 66 +- src/xenvbd/driver.h | 11 +- src/xenvbd/fdo.c | 2206 ------------------------------------------ src/xenvbd/fdo.h | 179 ---- src/xenvbd/frontend.c | 8 +- src/xenvbd/granter.c | 6 +- src/xenvbd/notifier.c | 8 +- src/xenvbd/pdo.c | 46 +- src/xenvbd/pdo.h | 8 +- vs2012/xenvbd/xenvbd.vcxproj | 2 +- vs2013/xenvbd/xenvbd.vcxproj | 2 +- vs2015/xenvbd/xenvbd.vcxproj | 2 +- 15 files changed, 2390 insertions(+), 2469 deletions(-) create mode 100644 src/xenvbd/adapter.c create mode 100644 src/xenvbd/adapter.h delete mode 100644 src/xenvbd/fdo.c delete mode 100644 src/xenvbd/fdo.h diff --git a/src/xenvbd/adapter.c b/src/xenvbd/adapter.c new file mode 100644 index 0000000..8334347 --- /dev/null +++ b/src/xenvbd/adapter.c @@ -0,0 +1,2147 @@ +/* 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 <storport.h> +#include <ntstrsafe.h> +#include <stdlib.h> + +#include <version.h> +#include <xencdb.h> +#include <names.h> +#include <store_interface.h> +#include <evtchn_interface.h> +#include <gnttab_interface.h> +#include <debug_interface.h> +#include <suspend_interface.h> +#include <emulated_interface.h> + +#include "adapter.h" +#include "driver.h" +#include "registry.h" +#include "pdo.h" +#include "srbext.h" +#include "thread.h" +#include "buffer.h" + +#include "util.h" +#include "debug.h" +#include "assert.h" + +#define MAXNAMELEN 128 + +#define ADAPTER_SIGNATURE 'odfX' + +struct _XENVBD_ADAPTER { + ULONG Signature; + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT LowerDeviceObject; + PDEVICE_OBJECT PhysicalDeviceObject; + KSPIN_LOCK Lock; + DEVICE_POWER_STATE DevicePower; + ANSI_STRING Enumerator; + + // Power + PXENVBD_THREAD DevicePowerThread; + PIRP DevicePowerIrp; + + // Interfaces to XenBus + XENBUS_EVTCHN_INTERFACE Evtchn; + XENBUS_STORE_INTERFACE Store; + XENBUS_GNTTAB_INTERFACE Gnttab; + XENBUS_DEBUG_INTERFACE Debug; + XENBUS_SUSPEND_INTERFACE Suspend; + XENBUS_UNPLUG_INTERFACE Unplug; + XENFILT_EMULATED_INTERFACE Emulated; + + // Debug Callback + PXENBUS_DEBUG_CALLBACK DebugCallback; + PXENBUS_SUSPEND_CALLBACK SuspendCallback; + + // Targets + KSPIN_LOCK TargetLock; + PXENVBD_PDO Targets[XENVBD_MAX_TARGETS]; + + // Target Enumeration + PXENVBD_THREAD ScanThread; + KEVENT ScanEvent; + PXENBUS_STORE_WATCH ScanWatch; + + // Statistics + LONG CurrentSrbs; + LONG MaximumSrbs; + LONG TotalSrbs; +}; + +//============================================================================= +static FORCEINLINE BOOLEAN +__AdapterSetDevicePowerState( + __in PXENVBD_ADAPTER Adapter, + __in DEVICE_POWER_STATE State + ) +{ + KIRQL Irql; + BOOLEAN Changed = FALSE; + + KeAcquireSpinLock(&Adapter->Lock, &Irql); + + if (Adapter->DevicePower != State) { + Verbose("POWER %s to %s\n", PowerDeviceStateName(Adapter->DevicePower), PowerDeviceStateName(State)); + Changed = TRUE; + Adapter->DevicePower = State; + } + + KeReleaseSpinLock(&Adapter->Lock, Irql); + + return Changed; +} + +static FORCEINLINE DEVICE_POWER_STATE +__AdapterGetDevicePowerState( + __in PXENVBD_ADAPTER Adapter + ) +{ + KIRQL Irql; + DEVICE_POWER_STATE State; + + KeAcquireSpinLock(&Adapter->Lock, &Irql); + State = Adapter->DevicePower; + KeReleaseSpinLock(&Adapter->Lock, Irql); + + return State; +} + +__checkReturn +static FORCEINLINE PXENVBD_PDO +__AdapterGetPdoAlways( + __in PXENVBD_ADAPTER Adapter, + __in ULONG TargetId, + __in PCHAR Caller + ) +{ + PXENVBD_PDO Pdo; + KIRQL Irql; + + ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); + + KeAcquireSpinLock(&Adapter->TargetLock, &Irql); + Pdo = Adapter->Targets[TargetId]; + if (Pdo) { + __PdoReference(Pdo, Caller); + } + KeReleaseSpinLock(&Adapter->TargetLock, Irql); + + return Pdo; +} + +__checkReturn +static FORCEINLINE PXENVBD_PDO +___AdapterGetPdo( + __in PXENVBD_ADAPTER Adapter, + __in ULONG TargetId, + __in PCHAR Caller + ) +{ + PXENVBD_PDO Pdo = NULL; + KIRQL Irql; + + ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); + + KeAcquireSpinLock(&Adapter->TargetLock, &Irql); + if (Adapter->Targets[TargetId] && + __PdoReference(Adapter->Targets[TargetId], Caller) > 0) { + Pdo = Adapter->Targets[TargetId]; + } + KeReleaseSpinLock(&Adapter->TargetLock, Irql); + + return Pdo; +} +#define __AdapterGetPdo(f, t) ___AdapterGetPdo(f, t, __FUNCTION__) + +BOOLEAN +AdapterLinkPdo( + __in PXENVBD_ADAPTER Adapter, + __in PXENVBD_PDO Pdo + ) +{ + KIRQL Irql; + PXENVBD_PDO Current; + BOOLEAN Result = FALSE; + ULONG TargetId = PdoGetTargetId(Pdo); + + KeAcquireSpinLock(&Adapter->TargetLock, &Irql); + Current = Adapter->Targets[TargetId]; + if (Adapter->Targets[TargetId] == NULL) { + Adapter->Targets[TargetId] = Pdo; + Result = TRUE; + } + KeReleaseSpinLock(&Adapter->TargetLock, Irql); + + if (!Result) { + Warning("Target[%d] : Current 0x%p, New 0x%p\n", TargetId, Current, Pdo); + } + return Result; +} +BOOLEAN +AdapterUnlinkPdo( + __in PXENVBD_ADAPTER Adapter, + __in PXENVBD_PDO Pdo + ) +{ + KIRQL Irql; + PXENVBD_PDO Current; + BOOLEAN Result = FALSE; + ULONG TargetId = PdoGetTargetId(Pdo); + + KeAcquireSpinLock(&Adapter->TargetLock, &Irql); + Current = Adapter->Targets[TargetId]; + if (Adapter->Targets[TargetId] == Pdo) { + Adapter->Targets[TargetId] = NULL; + Result = TRUE; + } + KeReleaseSpinLock(&Adapter->TargetLock, Irql); + + if (!Result) { + Warning("Target[%d] : Current 0x%p, Expected 0x%p\n", TargetId, Current, Pdo); + } + return Result; +} + +//============================================================================= +// QueryInterface + +__drv_requiresIRQL(PASSIVE_LEVEL) +static NTSTATUS +AdapterQueryInterface( + IN PXENVBD_ADAPTER Adapter, + IN const GUID *Guid, + IN ULONG Version, + OUT PINTERFACE Interface, + IN ULONG Size, + IN BOOLEAN Optional + ) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + Adapter->LowerDeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + + status = STATUS_UNSUCCESSFUL; + if (Irp == NULL) + goto fail1; + + StackLocation = IoGetNextIrpStackLocation(Irp); + StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + + StackLocation->Parameters.QueryInterface.InterfaceType = Guid; + StackLocation->Parameters.QueryInterface.Size = (USHORT)Size; + StackLocation->Parameters.QueryInterface.Version = (USHORT)Version; + StackLocation->Parameters.QueryInterface.Interface = Interface; + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + status = IoCallDriver(Adapter->LowerDeviceObject, Irp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = StatusBlock.Status; + } + + if (!NT_SUCCESS(status)) { + if (status == STATUS_NOT_SUPPORTED && Optional) + goto done; + + goto fail2; + } + +done: + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +#define QUERY_INTERFACE( \ + _Adapter, \ + _ProviderName, \ + _InterfaceName, \ + _Interface, \ + _Size, \ + _Optional) \ + AdapterQueryInterface((_Adapter), \ + &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE, \ + _ProviderName ## _ ## _InterfaceName ## _INTERFACE_VERSION_MAX, \ + (_Interface), \ + (_Size), \ + (_Optional)) + +//============================================================================= +// Debug + +static DECLSPEC_NOINLINE VOID +AdapterDebugCallback( + __in PVOID Context, + __in BOOLEAN Crashing + ) +{ + PXENVBD_ADAPTER Adapter = Context; + ULONG TargetId; + + if (Adapter == NULL || Adapter->DebugCallback == NULL) + return; + + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: Version: %d.%d.%d.%d (%d/%d/%d)\n", + MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION, BUILD_NUMBER, + DAY, MONTH, YEAR); + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: Adapter: 0x%p %s\n", + Context, + Crashing ? "CRASHING" : ""); + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: DevObj 0x%p LowerDevObj 0x%p PhysDevObj 0x%p\n", + Adapter->DeviceObject, + Adapter->LowerDeviceObject, + Adapter->PhysicalDeviceObject); + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: DevicePowerState: %s\n", + PowerDeviceStateName(Adapter->DevicePower)); + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: Enumerator : %s (0x%p)\n", + AdapterEnum(Adapter), Adapter->Enumerator.Buffer); + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: Srbs : %d / %d (%d Total)\n", + Adapter->CurrentSrbs, Adapter->MaximumSrbs, Adapter->TotalSrbs); + + BufferDebugCallback(&Adapter->Debug); + + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + // no need to use __AdapterGetPdo (which is locked at DISPATCH) as called at HIGH_LEVEL + PXENVBD_PDO Pdo = Adapter->Targets[TargetId]; + if (Pdo == NULL) + continue; + + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: ====> Target[%-3d] : 0x%p\n", + TargetId, Pdo); + + // call Target's debug callback directly + PdoDebugCallback(Pdo, &Adapter->Debug); + + XENBUS_DEBUG(Printf, &Adapter->Debug, + "ADAPTER: <==== Target[%-3d] : 0x%p\n", + TargetId, Pdo); + } + + Adapter->MaximumSrbs = Adapter->CurrentSrbs; + Adapter->TotalSrbs = 0; +} + +//============================================================================= +// Enumeration +static FORCEINLINE ULONG +__ParseVbd( + __in PCHAR DeviceIdStr + ) +{ + ULONG DeviceId = strtoul(DeviceIdStr, NULL, 10); + + ASSERT3U((DeviceId & ~((1 << 29) - 1)), ==, 0); + + if (DeviceId & (1 << 28)) { + return (DeviceId & ((1 << 20) - 1)) >> 8; /* xvd */ + } else { + switch (DeviceId >> 8) { + case 202: return (DeviceId & 0xF0) >> 4; /* xvd */ + case 8: return (DeviceId & 0xF0) >> 4; /* sd */ + case 3: return (DeviceId & 0xC0) >> 6; /* hda..b */ + case 22: return ((DeviceId & 0xC0) >> 6) + 2; /* hdc..d */ + case 33: return ((DeviceId & 0xC0) >> 6) + 4; /* hde..f */ + case 34: return ((DeviceId & 0xC0) >> 6) + 6; /* hdg..h */ + case 56: return ((DeviceId & 0xC0) >> 6) + 8; /* hdi..j */ + case 57: return ((DeviceId & 0xC0) >> 6) + 10; /* hdk..l */ + case 88: return ((DeviceId & 0xC0) >> 6) + 12; /* hdm..n */ + case 89: return ((DeviceId & 0xC0) >> 6) + 14; /* hdo..p */ + default: break; + } + } + Error("Invalid DeviceId %s (%08x)\n", DeviceIdStr, DeviceId); + return 0xFFFFFFFF; // OBVIOUS ERROR VALUE +} +static FORCEINLINE XENVBD_DEVICE_TYPE +__DeviceType( + __in PCHAR Type + ) +{ + if (strcmp(Type, "disk") == 0) + return XENVBD_DEVICE_TYPE_DISK; + if (strcmp(Type, "cdrom") == 0) + return XENVBD_DEVICE_TYPE_CDROM; + return XENVBD_DEVICE_TYPE_UNKNOWN; +} +__checkReturn +static FORCEINLINE BOOLEAN +__AdapterHiddenTarget( + __in PXENVBD_ADAPTER Adapter, + __in PCHAR DeviceId, + __out PXENVBD_DEVICE_TYPE DeviceType + ) +{ + NTSTATUS Status; + PCHAR FrontendPath; + PCHAR Buffer; + ULONG Value; + + *DeviceType = XENVBD_DEVICE_TYPE_UNKNOWN; + FrontendPath = DriverFormat("device/%s/%s", AdapterEnum(Adapter), DeviceId); + if (!FrontendPath) + goto fail; + + // Ejected? + Status = XENBUS_STORE(Read, &Adapter->Store, NULL, FrontendPath, "ejected", &Buffer); + if (NT_SUCCESS(Status)) { + Value = strtoul(Buffer, NULL, 10); + XENBUS_STORE(Free, &Adapter->Store, Buffer); + + if (Value) + goto ignore; + } + + // Not Disk? + Status = XENBUS_STORE(Read, &Adapter->Store, NULL, FrontendPath, "device-type", &Buffer); + if (!NT_SUCCESS(Status)) + goto ignore; + *DeviceType = __DeviceType(Buffer); + XENBUS_STORE(Free, &Adapter->Store, Buffer); + + switch (*DeviceType) { + case XENVBD_DEVICE_TYPE_DISK: + break; + case XENVBD_DEVICE_TYPE_CDROM: + if (DriverParameters.PVCDRom) + break; + // intentional fall-through + default: + goto ignore; + } + + // Try to Create + DriverFormatFree(FrontendPath); + return FALSE; + +fail: + Error("Fail\n"); + return TRUE; + +ignore: + DriverFormatFree(FrontendPath); + return TRUE; +} +__checkReturn +static FORCEINLINE BOOLEAN +__AdapterIsPdoUnplugged( + __in PXENVBD_ADAPTER Adapter, + __in PCHAR Enumerator, + __in PCHAR Device, + __in ULONG Target + ) +{ + // Only check targets that could be emulated + if (Target > 3) { + Verbose("Target[%d] : (%s/%s) Emulated NOT_APPLICABLE (non-IDE device)\n", + Target, Enumerator, Device); + return TRUE; + } + + // Check presense of Emulated interface. Absence indicates emulated cannot be unplugged + if (Adapter->Emulated.Interface.Context == NULL) { + Warning("Target[%d] : (%s/%s) Emulated NOT_KNOWN (assumed PRESENT)\n", + Target, Enumerator, Device); + return FALSE; + } + + // Ask XenFilt if Ctrlr(0), Target(Target), Lun(0) is present + if (XENFILT_EMULATED(IsDiskPresent, &Adapter->Emulated, 0, Target, 0)) { + Verbose("Target[%d] : (%s/%s) Emulated PRESENT\n", + Target, Enumerator, Device); + return FALSE; + } else { + Verbose("Target[%d] : (%s/%s) Emulated NOT_PRESENT\n", + Target, Enumerator, Device); + return TRUE; + } +} + +static FORCEINLINE VOID +__AdapterEnumerate( + __in PXENVBD_ADAPTER Adapter, + __in PANSI_STRING Devices, + __out PBOOLEAN NeedInvalidate, + __out PBOOLEAN NeedReboot + ) +{ + ULONG TargetId; + PANSI_STRING Device; + ULONG Index; + PXENVBD_PDO Pdo; + + *NeedInvalidate = FALSE; + *NeedReboot = FALSE; + + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + BOOLEAN Missing = TRUE; + + Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo == NULL) + continue; + + for (Index = 0; Devices[Index].Buffer != NULL; ++Index) { + ULONG DeviceTargetId; + Device = &Devices[Index]; + DeviceTargetId = __ParseVbd(Device->Buffer); + if (TargetId == DeviceTargetId) { + Missing = FALSE; + break; + } + } + + if (Missing && !PdoIsMissing(Pdo)) { + PdoSetMissing(Pdo, "Device Disappeared"); + if (PdoGetDevicePnpState(Pdo) == Present) + PdoSetDevicePnpState(Pdo, Deleted); + else + *NeedInvalidate = TRUE; + } + + if (PdoGetDevicePnpState(Pdo) == Deleted) { + PdoDereference(Pdo); + PdoDestroy(Pdo); + } else { + PdoDereference(Pdo); + } + } + + // add new targets + for (Index = 0; Devices[Index].Buffer != NULL; ++Index) { + XENVBD_DEVICE_TYPE DeviceType; + + Device = &Devices[Index]; + + TargetId = __ParseVbd(Device->Buffer); + if (TargetId == 0xFFFFFFFF) { + continue; + } + + Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + PdoDereference(Pdo); + continue; + } + + if (__AdapterHiddenTarget(Adapter, Device->Buffer, &DeviceType)) { + continue; + } + + if (!__AdapterIsPdoUnplugged(Adapter, + AdapterEnum(Adapter), + Device->Buffer, + TargetId)) { + *NeedReboot = TRUE; + continue; + } + + if (PdoCreate(Adapter, + Device->Buffer, + TargetId, + DeviceType)) { + *NeedInvalidate = TRUE; + } + } +} + +static FORCEINLINE PANSI_STRING +__AdapterMultiSzToAnsi( + IN PCHAR Buffer + ) +{ + PANSI_STRING Ansi; + LONG Index; + LONG Count; + NTSTATUS status; + + Index = 0; + Count = 0; + for (;;) { + if (Buffer[Index] == '\0') { + Count++; + Index++; + + // Check for double NUL + if (Buffer[Index] == '\0') + break; + } else { + Index++; + } + } + + Ansi = __AllocatePoolWithTag(NonPagedPool, + sizeof (ANSI_STRING) * (Count + 1), + ADAPTER_SIGNATURE); + + status = STATUS_NO_MEMORY; + if (Ansi == NULL) + goto fail1; + + for (Index = 0; Index < Count; Index++) { + ULONG Length; + + Length = (ULONG)strlen(Buffer); + Ansi[Index].MaximumLength = (USHORT)(Length + 1); + Ansi[Index].Buffer = __AllocatePoolWithTag(NonPagedPool, + Ansi[Index].MaximumLength, + ADAPTER_SIGNATURE); + + status = STATUS_NO_MEMORY; + if (Ansi[Index].Buffer == NULL) + goto fail2; + + RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); + Ansi[Index].Length = (USHORT)Length; + + Buffer += Length + 1; + } + + return Ansi; + +fail2: + Error("fail2\n"); + + while (--Index >= 0) + __FreePoolWithTag(Ansi[Index].Buffer, ADAPTER_SIGNATURE); + + __FreePoolWithTag(Ansi, ADAPTER_SIGNATURE); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; +} + +static FORCEINLINE PANSI_STRING +__AdapterMultiSzToUpcaseAnsi( + IN PCHAR Buffer + ) +{ + PANSI_STRING Ansi; + LONG Index; + LONG Count; + NTSTATUS status; + + Index = 0; + Count = 0; + for (;;) { + if (Buffer[Index] == '\0') { + Count++; + Index++; + + // Check for double NUL + if (Buffer[Index] == '\0') + break; + } else { + Buffer[Index] = __toupper(Buffer[Index]); + Index++; + } + } + + Ansi = __AllocatePoolWithTag(NonPagedPool, + sizeof (ANSI_STRING) * (Count + 1), + ADAPTER_SIGNATURE); + + status = STATUS_NO_MEMORY; + if (Ansi == NULL) + goto fail1; + + for (Index = 0; Index < Count; Index++) { + ULONG Length; + + Length = (ULONG)strlen(Buffer); + Ansi[Index].MaximumLength = (USHORT)(Length + 1); + Ansi[Index].Buffer = __AllocatePoolWithTag(NonPagedPool, + Ansi[Index].MaximumLength, + ADAPTER_SIGNATURE); + + status = STATUS_NO_MEMORY; + if (Ansi[Index].Buffer == NULL) + goto fail2; + + RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); + Ansi[Index].Length = (USHORT)Length; + + Buffer += Length + 1; + } + + return Ansi; + +fail2: + Error("fail2\n"); + + while (--Index >= 0) + __FreePoolWithTag(Ansi[Index].Buffer, ADAPTER_SIGNATURE); + + __FreePoolWithTag(Ansi, ADAPTER_SIGNATURE); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; +} + +static FORCEINLINE VOID +__AdapterFreeAnsi( + IN PANSI_STRING Ansi + ) +{ + ULONG Index; + + for (Index = 0; Ansi[Index].Buffer != NULL; Index++) + __FreePoolWithTag(Ansi[Index].Buffer, ADAPTER_SIGNATURE); + + __FreePoolWithTag(Ansi, ADAPTER_SIGNATURE); +} + +static DECLSPEC_NOINLINE VOID +AdapterScanTargets( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS Status; + PCHAR Buffer; + PANSI_STRING Devices; + BOOLEAN NeedInvalidate; + BOOLEAN NeedReboot; + + Status = XENBUS_STORE(Directory, &Adapter->Store, NULL, "device", AdapterEnum(Adapter), &Buffer); + if (!NT_SUCCESS(Status)) + return; + + Devices = __AdapterMultiSzToAnsi(Buffer); + XENBUS_STORE(Free, &Adapter->Store, Buffer); + + if (Devices == NULL) + return; + + __AdapterEnumerate(Adapter, Devices, &NeedInvalidate, &NeedReboot); + __AdapterFreeAnsi(Devices); + + if (NeedInvalidate) { + StorPortNotification(BusChangeDetected, Adapter, 0); + } + if (NeedReboot) { + DriverRequestReboot(); + } +} + +__checkReturn +static DECLSPEC_NOINLINE NTSTATUS +AdapterScan( + __in PXENVBD_THREAD Thread, + __in PVOID Context + ) +{ + PXENVBD_ADAPTER Adapter = Context; + PKEVENT Event = ThreadGetEvent(Thread); + + for (;;) { + Trace("waiting...\n"); + + (VOID) KeWaitForSingleObject(Event, + Executive, + KernelMode, + FALSE, + NULL); + KeClearEvent(Event); + + if (ThreadIsAlerted(Thread)) + break; + + if (__AdapterGetDevicePowerState(Adapter) == PowerDeviceD0) + AdapterScanTargets(Adapter); + + KeSetEvent(&Adapter->ScanEvent, IO_NO_INCREMENT, FALSE); + } + KeSetEvent(&Adapter->ScanEvent, IO_NO_INCREMENT, FALSE); + + return STATUS_SUCCESS; +} + +//============================================================================= +// Initialize, Start, Stop + +__drv_requiresIRQL(PASSIVE_LEVEL) +static FORCEINLINE NTSTATUS +__AdapterQueryInterfaces( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS Status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + // Get STORE Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + STORE, + (PINTERFACE)&Adapter->Store, + sizeof (Adapter->Store), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail1; + + // Get EVTCHN Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + EVTCHN, + (PINTERFACE)&Adapter->Evtchn, + sizeof (Adapter->Evtchn), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail2; + + // Get GNTTAB Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + GNTTAB, + (PINTERFACE)&Adapter->Gnttab, + sizeof (Adapter->Gnttab), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail3; + + // Get SUSPEND Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + SUSPEND, + (PINTERFACE)&Adapter->Suspend, + sizeof (Adapter->Suspend), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail4; + + // Get DEBUG Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + DEBUG, + (PINTERFACE)&Adapter->Debug, + sizeof (Adapter->Debug), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail5; + + // Get UNPLUG Interface + Status = QUERY_INTERFACE(Adapter, + XENBUS, + UNPLUG, + (PINTERFACE)&Adapter->Unplug, + sizeof (Adapter->Unplug), + FALSE); + if (!NT_SUCCESS(Status)) + goto fail6; + + // Get EMULATED Interface (optional) + Status = QUERY_INTERFACE(Adapter, + XENFILT, + EMULATED, + (PINTERFACE)&Adapter->Emulated, + sizeof (Adapter->Emulated), + TRUE); + if (!NT_SUCCESS(Status)) + goto fail7; + + return STATUS_SUCCESS; + +fail7: + RtlZeroMemory(&Adapter->Unplug, + sizeof (XENBUS_UNPLUG_INTERFACE)); +fail6: + RtlZeroMemory(&Adapter->Debug, + sizeof (XENBUS_DEBUG_INTERFACE)); +fail5: + RtlZeroMemory(&Adapter->Suspend, + sizeof (XENBUS_SUSPEND_INTERFACE)); +fail4: + RtlZeroMemory(&Adapter->Gnttab, + sizeof (XENBUS_GNTTAB_INTERFACE)); +fail3: + RtlZeroMemory(&Adapter->Evtchn, + sizeof (XENBUS_EVTCHN_INTERFACE)); +fail2: + RtlZeroMemory(&Adapter->Store, + sizeof (XENBUS_STORE_INTERFACE)); +fail1: + return Status; +} +static FORCEINLINE VOID +__AdapterZeroInterfaces( + __in PXENVBD_ADAPTER Adapter + ) +{ + RtlZeroMemory(&Adapter->Emulated, + sizeof (XENFILT_EMULATED_INTERFACE)); + RtlZeroMemory(&Adapter->Unplug, + sizeof (XENBUS_UNPLUG_INTERFACE)); + RtlZeroMemory(&Adapter->Debug, + sizeof (XENBUS_DEBUG_INTERFACE)); + RtlZeroMemory(&Adapter->Suspend, + sizeof (XENBUS_SUSPEND_INTERFACE)); + RtlZeroMemory(&Adapter->Gnttab, + sizeof (XENBUS_GNTTAB_INTERFACE)); + RtlZeroMemory(&Adapter->Evtchn, + sizeof (XENBUS_EVTCHN_INTERFACE)); + RtlZeroMemory(&Adapter->Store, + sizeof (XENBUS_STORE_INTERFACE)); +} +static FORCEINLINE NTSTATUS +__AdapterAcquire( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + if (Adapter->Emulated.Interface.Context) { + status = XENFILT_EMULATED(Acquire, &Adapter->Emulated); + if (!NT_SUCCESS(status)) + goto fail1; + } + + status = XENBUS_SUSPEND(Acquire, &Adapter->Suspend); + if (!NT_SUCCESS(status)) + goto fail2; + + status = XENBUS_DEBUG(Acquire, &Adapter->Debug); + if (!NT_SUCCESS(status)) + goto fail3; + + status = XENBUS_GNTTAB(Acquire, &Adapter->Gnttab); + if (!NT_SUCCESS(status)) + goto fail4; + + status = XENBUS_EVTCHN(Acquire, &Adapter->Evtchn); + if (!NT_SUCCESS(status)) + goto fail5; + + status = XENBUS_STORE(Acquire, &Adapter->Store); + if (!NT_SUCCESS(status)) + goto fail6; + + return STATUS_SUCCESS; + +fail6: + XENBUS_EVTCHN(Release, &Adapter->Evtchn); +fail5: + XENBUS_GNTTAB(Release, &Adapter->Gnttab); +fail4: + XENBUS_DEBUG(Release, &Adapter->Debug); +fail3: + XENBUS_SUSPEND(Release, &Adapter->Suspend); +fail2: + if (Adapter->Emulated.Interface.Context) + XENFILT_EMULATED(Release, &Adapter->Emulated); +fail1: + return status; +} +static FORCEINLINE VOID +__AdapterRelease( + __in PXENVBD_ADAPTER Adapter + ) +{ + XENBUS_STORE(Release, &Adapter->Store); + XENBUS_EVTCHN(Release, &Adapter->Evtchn); + XENBUS_GNTTAB(Release, &Adapter->Gnttab); + XENBUS_DEBUG(Release, &Adapter->Debug); + XENBUS_SUSPEND(Release, &Adapter->Suspend); + if (Adapter->Emulated.Interface.Context) + XENFILT_EMULATED(Release, &Adapter->Emulated); +} + +static FORCEINLINE BOOLEAN +__AdapterMatchDistribution( + IN PXENVBD_ADAPTER Adapter, + IN PCHAR Buffer + ) +{ + PCHAR Vendor; + PCHAR Product; + PCHAR Context; + const CHAR *Text; + BOOLEAN Match; + ULONG Index; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Adapter); + + status = STATUS_INVALID_PARAMETER; + + Vendor = __strtok_r(Buffer, " ", &Context); + if (Vendor == NULL) + goto fail1; + + Product = __strtok_r(NULL, " ", &Context); + if (Product == NULL) + goto fail2; + + Match = TRUE; + + Text = VENDOR_NAME_STR; + + for (Index = 0; Text[Index] != 0; Index++) { + if (!isalnum((UCHAR)Text[Index])) { + if (Vendor[Index] != '_') { + Match = FALSE; + break; + } + } else { + if (Vendor[Index] != Text[Index]) { + Match = FALSE; + break; + } + } + } + + Text = "XENVBD"; + + if (_stricmp(Product, Text) != 0) + Match = FALSE; + + return Match; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return FALSE; +} + +static VOID +AdapterClearDistribution( + IN PXENVBD_ADAPTER Adapter + ) +{ + PCHAR Buffer; + PANSI_STRING Distributions; + ULONG Index; + NTSTATUS status; + + Trace("====>\n"); + + status = XENBUS_STORE(Directory, + &Adapter->Store, + NULL, + NULL, + "drivers", + &Buffer); + if (NT_SUCCESS(status)) { + Distributions = __AdapterMultiSzToUpcaseAnsi(Buffer); + + XENBUS_STORE(Free, + &Adapter->Store, + Buffer); + } else { + Distributions = NULL; + } + + if (Distributions == NULL) + goto done; + + for (Index = 0; Distributions[Index].Buffer != NULL; Index++) { + PANSI_STRING Distribution = &Distributions[Index]; + + status = XENBUS_STORE(Read, + &Adapter->Store, + NULL, + "drivers", + Distribution->Buffer, + &Buffer); + if (!NT_SUCCESS(status)) + continue; + + if (__AdapterMatchDistribution(Adapter, Buffer)) + (VOID) XENBUS_STORE(Remove, + &Adapter->Store, + NULL, + "drivers", + Distribution->Buffer); + + XENBUS_STORE(Free, + &Adapter->Store, + Buffer); + } + + __AdapterFreeAnsi(Distributions); + +done: + Trace("<====\n"); +} + +#define MAXIMUM_INDEX 255 + +static NTSTATUS +AdapterSetDistribution( + IN PXENVBD_ADAPTER Adapter + ) +{ + ULONG Index; + CHAR Distribution[MAXNAMELEN]; + CHAR Vendor[MAXNAMELEN]; + const CHAR *Product; + NTSTATUS status; + + Trace("====>\n"); + + Index = 0; + while (Index <= MAXIMUM_INDEX) { + PCHAR Buffer; + + status = RtlStringCbPrintfA(Distribution, + MAXNAMELEN, + "%u", + Index); + ASSERT(NT_SUCCESS(status)); + + status = XENBUS_STORE(Read, + &Adapter->Store, + NULL, + "drivers", + Distribution, + &Buffer); + if (!NT_SUCCESS(status)) { + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + goto update; + + goto fail1; + } + + XENBUS_STORE(Free, + &Adapter->Store, + Buffer); + + Index++; + } + + status = STATUS_UNSUCCESSFUL; + goto fail2; + +update: + status = RtlStringCbPrintfA(Vendor, + MAXNAMELEN, + "%s", + VENDOR_NAME_STR); + ASSERT(NT_SUCCESS(status)); + + for (Index = 0; Vendor[Index] != '\0'; Index++) + if (!isalnum((UCHAR)Vendor[Index])) + Vendor[Index] = '_'; + + Product = "XENVBD"; + +#if DBG +#define ATTRIBUTES "(DEBUG)" +#else +#define ATTRIBUTES "" +#endif + + (VOID) XENBUS_STORE(Printf, + &Adapter->Store, + NULL, + "drivers", + Distribution, + "%s %s %u.%u.%u %s", + Vendor, + Product, + MAJOR_VERSION, + MINOR_VERSION, + MICRO_VERSION, + ATTRIBUTES + ); + +#undef ATTRIBUTES + + Trace("<====\n"); + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static FORCEINLINE NTSTATUS +__AdapterD3ToD0( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS Status; + + Trace("=====>\n"); + + (VOID) AdapterSetDistribution(Adapter); + + ASSERT3P(Adapter->ScanWatch, ==, NULL); + Status = XENBUS_STORE(WatchAdd, + &Adapter->Store, + "device", + AdapterEnum(Adapter), + ThreadGetEvent(Adapter->ScanThread), + &Adapter->ScanWatch); + if (!NT_SUCCESS(Status)) + goto fail1; + + (VOID) XENBUS_STORE(Printf, + &Adapter->Store, + NULL, + "feature/hotplug", + "vbd", + "%u", + TRUE); + + Trace("<=====\n"); + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", Status); + + return Status; +} + +static FORCEINLINE VOID +__AdapterD0ToD3( + __in PXENVBD_ADAPTER Adapter + ) +{ + Trace("=====>\n"); + + (VOID) XENBUS_STORE(Remove, + &Adapter->Store, + NULL, + "feature/hotplug", + "vbd"); + + (VOID) XENBUS_STORE(WatchRemove, + &Adapter->Store, + Adapter->ScanWatch); + Adapter->ScanWatch = NULL; + + AdapterClearDistribution(Adapter); + + Trace("<=====\n"); +} + +__drv_requiresIRQL(DISPATCH_LEVEL) +static VOID +AdapterSuspendLateCallback( + __in PVOID Argument + ) +{ + PXENVBD_ADAPTER Adapter = Argument; + NTSTATUS Status; + + Verbose("%s (%s)\n", + MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, + DAY_STR "/" MONTH_STR "/" YEAR_STR); + + __AdapterD0ToD3(Adapter); + + Status = __AdapterD3ToD0(Adapter); + ASSERT(NT_SUCCESS(Status)); +} + +static NTSTATUS +AdapterD3ToD0( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS Status; + ULONG TargetId; + + if (!__AdapterSetDevicePowerState(Adapter, PowerDeviceD0)) + return STATUS_SUCCESS; + + Trace("=====> (%d)\n", KeGetCurrentIrql()); + Verbose("D3->D0\n"); + + // Get Interfaces + Status = __AdapterAcquire(Adapter); + if (!NT_SUCCESS(Status)) + goto fail1; + + // register debug callback + ASSERT3P(Adapter->DebugCallback, ==, NULL); + Status = XENBUS_DEBUG(Register, + &Adapter->Debug, + __MODULE__, + AdapterDebugCallback, + Adapter, + &Adapter->DebugCallback); + if (!NT_SUCCESS(Status)) + goto fail2; + + // Power UP any PDOs + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + Status = PdoD3ToD0(Pdo); + PdoDereference(Pdo); + + if (!NT_SUCCESS(Status)) + goto fail3; + } + } + + Status = __AdapterD3ToD0(Adapter); + if (!NT_SUCCESS(Status)) + goto fail4; + + // register suspend callback to re-register the watch + ASSERT3P(Adapter->SuspendCallback, ==, NULL); + Status = XENBUS_SUSPEND(Register, + &Adapter->Suspend, + SUSPEND_CALLBACK_LATE, + AdapterSuspendLateCallback, + Adapter, + &Adapter->SuspendCallback); + if (!NT_SUCCESS(Status)) + goto fail5; + + Trace("<===== (%d)\n", KeGetCurrentIrql()); + return STATUS_SUCCESS; + +fail5: + Error("Fail5\n"); + + __AdapterD0ToD3(Adapter); + +fail4: + Error("Fail4\n"); + +fail3: + Error("Fail3\n"); + + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + PdoD0ToD3(Pdo); + PdoDereference(Pdo); + } + } + + XENBUS_DEBUG(Deregister, &Adapter->Debug, Adapter->DebugCallback); + Adapter->DebugCallback = NULL; + +fail2: + Error("Fail2\n"); + + __AdapterRelease(Adapter); + +fail1: + Error("Fail1 (%08x)\n", Status); + + __AdapterSetDevicePowerState(Adapter, PowerDeviceD3); + return Status; +} + +static VOID +AdapterD0ToD3( + __in PXENVBD_ADAPTER Adapter + ) +{ + ULONG TargetId; + + if (!__AdapterSetDevicePowerState(Adapter, PowerDeviceD3)) + return; + + Trace("=====> (%d)\n", KeGetCurrentIrql()); + Verbose("D0->D3\n"); + + // remove suspend callback + XENBUS_SUSPEND(Deregister, &Adapter->Suspend, Adapter->SuspendCallback); + Adapter->SuspendCallback = NULL; + + __AdapterD0ToD3(Adapter); + + // Power DOWN any PDOs + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + PdoD0ToD3(Pdo); + PdoDereference(Pdo); + } + } + + // free debug callback + if (Adapter->DebugCallback != NULL) { + XENBUS_DEBUG(Deregister, &Adapter->Debug, Adapter->DebugCallback); + Adapter->DebugCallback = NULL; + } + + // Release Interfaces + __AdapterRelease(Adapter); + + Trace("<===== (%d)\n", KeGetCurrentIrql()); +} + +__checkReturn +static DECLSPEC_NOINLINE NTSTATUS +AdapterDevicePower( + __in PXENVBD_THREAD Thread, + __in PVOID Context + ) +{ + PXENVBD_ADAPTER Adapter = Context; + + for (;;) { + PIRP Irp; + PIO_STACK_LOCATION Stack; + DEVICE_POWER_STATE DeviceState; + POWER_ACTION Action; + NTSTATUS Status; + + if (!ThreadWait(Thread)) + break; + + // must have a pended DevicePowerIrp + ASSERT3P(Adapter->DevicePowerIrp, !=, NULL); + + Irp = Adapter->DevicePowerIrp; + Adapter->DevicePowerIrp = NULL; + + Stack = IoGetCurrentIrpStackLocation(Irp); + DeviceState = Stack->Parameters.Power.State.DeviceState; + Action = Stack->Parameters.Power.ShutdownType; + + switch (Stack->MinorFunction) { + case IRP_MN_SET_POWER: + switch (DeviceState) { + case PowerDeviceD0: + Verbose("ADAPTER:PowerDeviceD0\n"); + AdapterD3ToD0(Adapter); + break; + + case PowerDeviceD3: + Verbose("ADAPTER:PowerDeviceD3 (%s)\n", PowerActionName(Action)); + AdapterD0ToD3(Adapter); + break; + + default: + break; + } + break; + case IRP_MN_QUERY_POWER: + default: + break; + } + Status = DriverDispatchPower(Adapter->DeviceObject, Irp); + if (!NT_SUCCESS(Status)) { + Warning("StorPort failed PowerIRP with %08x\n", Status); + } + } + + return STATUS_SUCCESS; +} + +__checkReturn +__drv_requiresIRQL(PASSIVE_LEVEL) +static NTSTATUS +__AdapterInitialize( + __in PXENVBD_ADAPTER Adapter + ) +{ + ULONG StorStatus; + NTSTATUS Status; + + Trace("=====> (%d)\n", KeGetCurrentIrql()); + + ASSERT3U(KeGetCurrentIrql(), <=, DISPATCH_LEVEL); + // initialize the memory + Adapter->DevicePower = PowerDeviceD3; + KeInitializeSpinLock(&Adapter->TargetLock); + KeInitializeSpinLock(&Adapter->Lock); + KeInitializeEvent(&Adapter->ScanEvent, SynchronizationEvent, FALSE); + + Adapter->Signature = ADAPTER_SIGNATURE; + + StorStatus = StorPortGetDeviceObjects(Adapter, + &Adapter->DeviceObject, + &Adapter->PhysicalDeviceObject, + &Adapter->LowerDeviceObject); + Status = STATUS_UNSUCCESSFUL; + if (StorStatus != STOR_STATUS_SUCCESS) { + Error("StorPortGetDeviceObjects() (%x:%s)\n", StorStatus, StorStatusName(StorStatus)); + goto fail1; + } + + // get interfaces + Status = __AdapterQueryInterfaces(Adapter); + if (!NT_SUCCESS(Status)) + goto fail2; + + // start enum thread + Status = ThreadCreate(AdapterScan, Adapter, &Adapter->ScanThread); + if (!NT_SUCCESS(Status)) + goto fail3; + + Status = ThreadCreate(AdapterDevicePower, Adapter, &Adapter->DevicePowerThread); + if (!NT_SUCCESS(Status)) + goto fail4; + + // query enumerator + // fix this up to query from device location(?) + //RtlInitAnsiString(&Adapter->Enumerator, "vbd"); + + // link fdo + DriverLinkAdapter(Adapter); + + Trace("<===== (%d)\n", KeGetCurrentIrql()); + return STATUS_SUCCESS; + +fail4: + Error("fail4\n"); + ThreadAlert(Adapter->ScanThread); + ThreadJoin(Adapter->ScanThread); + Adapter->ScanThread = NULL; +fail3: + Error("fail3\n"); + __AdapterZeroInterfaces(Adapter); +fail2: + Error("fail2\n"); + Adapter->DeviceObject = NULL; + Adapter->PhysicalDeviceObject = NULL; + Adapter->LowerDeviceObject = NULL; +fail1: + Error("fail1 (%08x)\n", Status); + return Status; +} +__drv_maxIRQL(PASSIVE_LEVEL) +static VOID +__AdapterTerminate( + __in PXENVBD_ADAPTER Adapter + ) +{ + ULONG TargetId; + + Trace("=====> (%d)\n", KeGetCurrentIrql()); + + DriverUnlinkAdapter(Adapter); + ASSERT3U(Adapter->DevicePower, ==, PowerDeviceD3); + + // stop device power thread + ThreadAlert(Adapter->DevicePowerThread); + ThreadJoin(Adapter->DevicePowerThread); + Adapter->DevicePowerThread = NULL; + + // stop enum thread + ThreadAlert(Adapter->ScanThread); + ThreadJoin(Adapter->ScanThread); + Adapter->ScanThread = NULL; + + // clear device objects + Adapter->DeviceObject = NULL; + Adapter->PhysicalDeviceObject = NULL; + Adapter->LowerDeviceObject = NULL; + + // delete targets + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdoAlways(Adapter, TargetId, __FUNCTION__); + if (Pdo) { + // Pdo may not be in Deleted state yet, force it as Adapter is terminating + if (PdoGetDevicePnpState(Pdo) != Deleted) + PdoSetDevicePnpState(Pdo, Deleted); + // update missing (for debug output more than anything else + PdoSetMissing(Pdo, "AdapterTerminate"); + // drop ref-count acquired in __AdapterGetPdo *before* destroying Pdo + PdoDereference(Pdo); + PdoDestroy(Pdo); + } + } + + // cleanup memory + ASSERT3U(Adapter->DevicePower, ==, PowerDeviceD3); + ASSERT3P(Adapter->DebugCallback, ==, NULL); + ASSERT3P(Adapter->SuspendCallback, ==, NULL); + + Adapter->Signature = 0; + Adapter->DevicePower = 0; + Adapter->CurrentSrbs = Adapter->MaximumSrbs = Adapter->TotalSrbs = 0; + RtlZeroMemory(&Adapter->Enumerator, sizeof(ANSI_STRING)); + RtlZeroMemory(&Adapter->TargetLock, sizeof(KSPIN_LOCK)); + RtlZeroMemory(&Adapter->Lock, sizeof(KSPIN_LOCK)); + RtlZeroMemory(&Adapter->ScanEvent, sizeof(KEVENT)); + __AdapterZeroInterfaces(Adapter); + + ASSERT(IsZeroMemory(Adapter, sizeof(XENVBD_ADAPTER))); + Trace("<===== (%d)\n", KeGetCurrentIrql()); +} +//============================================================================= +// Query Methods +__checkReturn +FORCEINLINE PDEVICE_OBJECT +AdapterGetDeviceObject( + __in PXENVBD_ADAPTER Adapter + ) +{ + if (Adapter) + return Adapter->DeviceObject; + return NULL; +} + +FORCEINLINE ULONG +AdapterSizeofXenvbdAdapter( + ) +{ + return (ULONG)sizeof(XENVBD_ADAPTER); +} + +FORCEINLINE PCHAR +AdapterEnum( + __in PXENVBD_ADAPTER Adapter + ) +{ + if (Adapter->Enumerator.Buffer) + return Adapter->Enumerator.Buffer; + else + return "vbd"; +} + +//============================================================================= +// SRB Methods +FORCEINLINE VOID +AdapterStartSrb( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ) +{ + LONG Value; + + UNREFERENCED_PARAMETER(Srb); + + Value = InterlockedIncrement(&Adapter->CurrentSrbs); + if (Value > Adapter->MaximumSrbs) + Adapter->MaximumSrbs = Value; + InterlockedIncrement(&Adapter->TotalSrbs); +} + +FORCEINLINE VOID +AdapterCompleteSrb( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ) +{ + ASSERT3U(Srb->SrbStatus, !=, SRB_STATUS_PENDING); + + InterlockedDecrement(&Adapter->CurrentSrbs); + + StorPortNotification(RequestComplete, Adapter, Srb); +} + +//============================================================================= +// StorPort Methods +BOOLEAN +AdapterResetBus( + __in PXENVBD_ADAPTER Adapter + ) +{ + ULONG TargetId; + + Verbose("====>\n"); + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + PdoReset(Pdo); + PdoDereference(Pdo); + } + } + Verbose("<====\n"); + + return TRUE; +} + +static VOID +AdapterUnplugRequest( + IN PXENVBD_ADAPTER Adapter, + IN BOOLEAN Make + ) +{ + NTSTATUS status; + + status = XENBUS_UNPLUG(Acquire, &Adapter->Unplug); + if (!NT_SUCCESS(status)) + return; + + XENBUS_UNPLUG(Request, + &Adapter->Unplug, + XENBUS_UNPLUG_DEVICE_TYPE_DISKS, + Make); + + XENBUS_UNPLUG(Release, &Adapter->Unplug); +} + +ULONG +AdapterFindAdapter( + __in PXENVBD_ADAPTER Adapter, + __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo + ) +{ + // setup config info + ConfigInfo->MaximumTransferLength = XENVBD_MAX_TRANSFER_LENGTH; + ConfigInfo->NumberOfPhysicalBreaks = XENVBD_MAX_PHYSICAL_BREAKS; + ConfigInfo->AlignmentMask = 0; // Byte-Aligned + ConfigInfo->NumberOfBuses = 1; + ConfigInfo->InitiatorBusId[0] = 1; + ConfigInfo->ScatterGather = TRUE; + ConfigInfo->Master = TRUE; + ConfigInfo->CachesData = FALSE; + ConfigInfo->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; + ConfigInfo->MaximumNumberOfTargets = XENVBD_MAX_TARGETS; + ConfigInfo->MaximumNumberOfLogicalUnits = 1; + ConfigInfo->WmiDataProvider = FALSE; // should be TRUE + ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; + + if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) { + Trace("64bit DMA\n"); + ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED; + } + + // gets called on resume from hibernate, so only setup if not already done + if (Adapter->Signature == ADAPTER_SIGNATURE) { + Verbose("ADAPTER already initalized (0x%p)\n", Adapter); + return SP_RETURN_FOUND; + } + + // We need to do this to avoid an assertion in a checked kernel + (VOID) StorPortGetUncachedExtension(Adapter, ConfigInfo, PAGE_SIZE); + + if (!NT_SUCCESS(__AdapterInitialize(Adapter))) + return SP_RETURN_ERROR; + + AdapterUnplugRequest(Adapter, TRUE); + + if (!NT_SUCCESS(AdapterD3ToD0(Adapter))) + return SP_RETURN_ERROR; + + return SP_RETURN_FOUND; +} + +static FORCEINLINE VOID +__AdapterSrbPnp( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_PNP_REQUEST_BLOCK Srb + ) +{ + if (!(Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)) { + PXENVBD_PDO Pdo; + + Pdo = __AdapterGetPdo(Adapter, Srb->TargetId); + if (Pdo) { + PdoSrbPnp(Pdo, Srb); + PdoDereference(Pdo); + } + } +} + +BOOLEAN +AdapterBuildIo( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ) +{ + InitSrbExt(Srb); + + switch (Srb->Function) { + case SRB_FUNCTION_EXECUTE_SCSI: + case SRB_FUNCTION_RESET_DEVICE: + case SRB_FUNCTION_FLUSH: + case SRB_FUNCTION_SHUTDOWN: + AdapterStartSrb(Adapter, Srb); + return TRUE; + + // dont pass to StartIo + case SRB_FUNCTION_PNP: + __AdapterSrbPnp(Adapter, (PSCSI_PNP_REQUEST_BLOCK)Srb); + Srb->SrbStatus = SRB_STATUS_SUCCESS; + break; + case SRB_FUNCTION_ABORT_COMMAND: + Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; + break; + case SRB_FUNCTION_RESET_BUS: + Srb->SrbStatus = SRB_STATUS_SUCCESS; + AdapterResetBus(Adapter); + break; + + default: + break; + } + + StorPortNotification(RequestComplete, Adapter, Srb); + return FALSE; +} + +BOOLEAN +AdapterStartIo( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ) +{ + PXENVBD_PDO Pdo; + BOOLEAN CompleteSrb = TRUE; + + Pdo = __AdapterGetPdo(Adapter, Srb->TargetId); + if (Pdo) { + CompleteSrb = PdoStartIo(Pdo, Srb); + PdoDereference(Pdo); + } + + if (CompleteSrb) { + AdapterCompleteSrb(Adapter, Srb); + } + return TRUE; +} + +static PXENVBD_PDO +AdapterGetPdoFromDeviceObject( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject + ) +{ + ULONG TargetId; + + ASSERT3P(DeviceObject, !=, NULL); + + for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { + PXENVBD_PDO Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo) { + if (PdoGetDeviceObject(Pdo) == DeviceObject) + return Pdo; + PdoDereference(Pdo); + } + } + + return NULL; +} + +static PXENVBD_PDO +AdapterMapDeviceObjectToPdo( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject + ) +{ + PXENVBD_PDO Pdo; + KEVENT Complete; + PIRP Irp; + IO_STATUS_BLOCK StatusBlock; + PIO_STACK_LOCATION Stack; + NTSTATUS Status; + PWCHAR String; + ULONG TargetId; + DECLARE_UNICODE_STRING_SIZE(UniStr, 4); + + KeInitializeEvent(&Complete, NotificationEvent, FALSE); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &Complete, &StatusBlock); + if (Irp == NULL) + goto fail1; + + Stack = IoGetNextIrpStackLocation(Irp); + Stack->MinorFunction = IRP_MN_QUERY_ID; + Stack->Parameters.QueryId.IdType = BusQueryInstanceID; + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Complete, Executive, KernelMode, FALSE, NULL); + Status = StatusBlock.Status; + } + if (!NT_SUCCESS(Status)) + goto fail2; + + String = (PWCHAR)StatusBlock.Information; + switch (wcslen(String)) { + case 3: + UniStr.Length = 1 * sizeof(WCHAR); + UniStr_buffer[0] = String[1]; + UniStr_buffer[1] = UNICODE_NULL; + break; + case 6: + UniStr.Length = 2 * sizeof(WCHAR); + UniStr_buffer[0] = String[2]; + UniStr_buffer[1] = String[3]; + UniStr_buffer[2] = UNICODE_NULL; + break; + default: + goto fail3; + } + + Status = RtlUnicodeStringToInteger(&UniStr, 16, &TargetId); + if (!NT_SUCCESS(Status)) + goto fail4; + + Pdo = __AdapterGetPdo(Adapter, TargetId); + if (Pdo == NULL) + goto fail5; + + PdoSetDeviceObject(Pdo, DeviceObject); + ExFreePool(String); + + return Pdo; + +fail5: +fail4: +fail3: + ExFreePool(String); +fail2: +fail1: + return NULL; +} + +__checkReturn +NTSTATUS +AdapterForwardPnp( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ) +{ + PIO_STACK_LOCATION Stack; + PXENVBD_PDO Pdo; + + ASSERT3P(DeviceObject, !=, Adapter->DeviceObject); + + Pdo = AdapterGetPdoFromDeviceObject(Adapter, DeviceObject); + if (Pdo != NULL) { + return PdoDispatchPnp(Pdo, DeviceObject, Irp); + } + + Stack = IoGetCurrentIrpStackLocation(Irp); + if (Stack->MinorFunction == IRP_MN_QUERY_ID && + Stack->Parameters.QueryId.IdType == BusQueryDeviceID) { + Pdo = AdapterMapDeviceObjectToPdo(Adapter, DeviceObject); + if (Pdo != NULL) { + return PdoDispatchPnp(Pdo, DeviceObject, Irp); + } + } + + return DriverDispatchPnp(DeviceObject, Irp); +} + +__checkReturn +NTSTATUS +AdapterDispatchPnp( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ) +{ + PIO_STACK_LOCATION Stack; + + ASSERT3P(DeviceObject, ==, Adapter->DeviceObject); + + Stack = IoGetCurrentIrpStackLocation(Irp); + + switch (Stack->MinorFunction) { + case IRP_MN_REMOVE_DEVICE: + Verbose("ADAPTER:IRP_MN_REMOVE_DEVICE\n"); + AdapterD0ToD3(Adapter); + AdapterUnplugRequest(Adapter, FALSE); + __AdapterTerminate(Adapter); + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + if (Stack->Parameters.QueryDeviceRelations.Type == BusRelations) { + KeClearEvent(&Adapter->ScanEvent); + ThreadWake(Adapter->ScanThread); + + Trace("waiting for scan thread\n"); + + (VOID) KeWaitForSingleObject(&Adapter->ScanEvent, + Executive, + KernelMode, + FALSE, + NULL); + } + break; + + default: + break; + } + + return DriverDispatchPnp(DeviceObject, Irp); +} + +__checkReturn +NTSTATUS +AdapterDispatchPower( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ) +{ + PIO_STACK_LOCATION Stack; + POWER_STATE_TYPE PowerType; + NTSTATUS status; + + ASSERT3P(DeviceObject, ==, Adapter->DeviceObject); + + Stack = IoGetCurrentIrpStackLocation(Irp); + PowerType = Stack->Parameters.Power.Type; + + switch (PowerType) { + case DevicePowerState: + if (Adapter->DevicePowerThread == NULL) { + Verbose("DevicePower IRP before DevicePowerThread ready\n"); + status = DriverDispatchPower(DeviceObject, Irp); + break; + } + + IoMarkIrpPending(Irp); + + ASSERT3P(Adapter->DevicePowerIrp, ==, NULL); + ASSERT3P(DeviceObject, ==, Adapter->DeviceObject); + + Adapter->DevicePowerIrp = Irp; + ThreadWake(Adapter->DevicePowerThread); + + status = STATUS_PENDING; + break; + + case SystemPowerState: + default: + status = DriverDispatchPower(DeviceObject, Irp); + break; + } + + return status; +} + +PXENBUS_STORE_INTERFACE +AdapterAcquireStore( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + status = XENBUS_STORE(Acquire, &Adapter->Store); + if (!NT_SUCCESS(status)) + return NULL; + + return &Adapter->Store; +} + +PXENBUS_EVTCHN_INTERFACE +AdapterAcquireEvtchn( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + status = XENBUS_EVTCHN(Acquire, &Adapter->Evtchn); + if (!NT_SUCCESS(status)) + return NULL; + + return &Adapter->Evtchn; +} + +PXENBUS_GNTTAB_INTERFACE +AdapterAcquireGnttab( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + status = XENBUS_GNTTAB(Acquire, &Adapter->Gnttab); + if (!NT_SUCCESS(status)) + return NULL; + + return &Adapter->Gnttab; +} + +PXENBUS_DEBUG_INTERFACE +AdapterAcquireDebug( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + status = XENBUS_DEBUG(Acquire, &Adapter->Debug); + if (!NT_SUCCESS(status)) + return NULL; + + return &Adapter->Debug; +} + +PXENBUS_SUSPEND_INTERFACE +AdapterAcquireSuspend( + __in PXENVBD_ADAPTER Adapter + ) +{ + NTSTATUS status; + + status = XENBUS_SUSPEND(Acquire, &Adapter->Suspend); + if (!NT_SUCCESS(status)) + return NULL; + + return &Adapter->Suspend; +} diff --git a/src/xenvbd/adapter.h b/src/xenvbd/adapter.h new file mode 100644 index 0000000..135aa51 --- /dev/null +++ b/src/xenvbd/adapter.h @@ -0,0 +1,162 @@ +/* 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 _XENVBD_ADAPTER_H +#define _XENVBD_ADAPTER_H + +#include <ntddk.h> + +typedef struct _XENVBD_ADAPTER XENVBD_ADAPTER, *PXENVBD_ADAPTER; + +#include <storport.h> +#include "pdo.h" +#include <store_interface.h> +#include <evtchn_interface.h> +#include <gnttab_interface.h> +#include <debug_interface.h> +#include <suspend_interface.h> +#include <unplug_interface.h> + +// Link PDOs +extern BOOLEAN +AdapterLinkPdo( + __in PXENVBD_ADAPTER Adapter, + __in PXENVBD_PDO Pdo + ); + +extern BOOLEAN +AdapterUnlinkPdo( + __in PXENVBD_ADAPTER Adapter, + __in PXENVBD_PDO Pdo + ); +// Query Methods +__checkReturn +extern PDEVICE_OBJECT +AdapterGetDeviceObject( + __in PXENVBD_ADAPTER Adapter + ); + +extern ULONG +AdapterSizeofXenvbdAdapter( + ); + +extern PCHAR +AdapterEnum( + __in PXENVBD_ADAPTER Adapter + ); + +// SRB Methods +extern VOID +AdapterStartSrb( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ); + +extern VOID +AdapterCompleteSrb( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ); + +// StorPort Methods +extern BOOLEAN +AdapterResetBus( + __in PXENVBD_ADAPTER Adapter + ); + +extern ULONG +AdapterFindAdapter( + __in PXENVBD_ADAPTER Adapter, + __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo + ); + +extern BOOLEAN +AdapterBuildIo( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ); + +extern BOOLEAN +AdapterStartIo( + __in PXENVBD_ADAPTER Adapter, + __in PSCSI_REQUEST_BLOCK Srb + ); + +__checkReturn +extern NTSTATUS +AdapterForwardPnp( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ); + +__checkReturn +extern NTSTATUS +AdapterDispatchPnp( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ); + +__checkReturn +extern NTSTATUS +AdapterDispatchPower( + __in PXENVBD_ADAPTER Adapter, + __in PDEVICE_OBJECT DeviceObject, + __in PIRP Irp + ); + +extern PXENBUS_STORE_INTERFACE +AdapterAcquireStore( + __in PXENVBD_ADAPTER Adapter + ); + +extern PXENBUS_EVTCHN_INTERFACE +AdapterAcquireEvtchn( + __in PXENVBD_ADAPTER Adapter + ); + +extern PXENBUS_GNTTAB_INTERFACE +AdapterAcquireGnttab( + __in PXENVBD_ADAPTER Adapter + ); + +extern PXENBUS_DEBUG_INTERFACE +AdapterAcquireDebug( + __in PXENVBD_ADAPTER Adapter + ); + +extern PXENBUS_SUSPEND_INTERFACE +AdapterAcquireSuspend( + __in PXENVBD_ADAPTER Adapter + ); + +#endif // _XENVBD_ADAPTER_H diff --git a/src/xenvbd/blockring.c b/src/xenvbd/blockring.c index 50d738b..b60f39e 100644 --- a/src/xenvbd/blockring.c +++ b/src/xenvbd/blockring.c @@ -32,7 +32,7 @@ #include "blockring.h" #include "frontend.h" #include "pdo.h" -#include "fdo.h" +#include "adapter.h" #include "util.h" #include "debug.h" #include "srbext.h" @@ -277,12 +277,12 @@ BlockRingConnect( NTSTATUS status; PCHAR Value; ULONG Index, RingPages; - PXENVBD_FDO Fdo = PdoGetFdo(FrontendGetPdo(BlockRing->Frontend)); + PXENVBD_ADAPTER Adapter = PdoGetAdapter(FrontendGetPdo(BlockRing->Frontend)); PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend); ASSERT(BlockRing->Connected == FALSE); - BlockRing->StoreInterface = FdoAcquireStore(Fdo); + BlockRing->StoreInterface = AdapterAcquireStore(Adapter); status = STATUS_UNSUCCESSFUL; if (BlockRing->StoreInterface == NULL) diff --git a/src/xenvbd/driver.c b/src/xenvbd/driver.c index 1f713c4..c202b78 100644 --- a/src/xenvbd/driver.c +++ b/src/xenvbd/driver.c @@ -30,7 +30,7 @@ */ #include "driver.h" -#include "fdo.h" +#include "adapter.h" #include "pdo.h" #include "registry.h" #include "srbext.h" @@ -48,7 +48,7 @@ typedef struct _XENVBD_DRIVER { PDRIVER_DISPATCH StorPortDispatchPnp; PDRIVER_DISPATCH StorPortDispatchPower; PDRIVER_UNLOAD StorPortDriverUnload; - PXENVBD_FDO Fdo; + PXENVBD_ADAPTER Adapter; KSPIN_LOCK Lock; } XENVBD_DRIVER; @@ -117,51 +117,50 @@ DriverDispatchPower( } VOID -DriverLinkFdo( - __in PXENVBD_FDO Fdo +DriverLinkAdapter( + __in PXENVBD_ADAPTER Adapter ) { KIRQL Irql; KeAcquireSpinLock(&Driver.Lock, &Irql); - Driver.Fdo = Fdo; + Driver.Adapter = Adapter; KeReleaseSpinLock(&Driver.Lock, Irql); } VOID -DriverUnlinkFdo( - __in PXENVBD_FDO Fdo +DriverUnlinkAdapter( + __in PXENVBD_ADAPTER Adapter ) { KIRQL Irql; - UNREFERENCED_PARAMETER(Fdo); + UNREFERENCED_PARAMETER(Adapter); KeAcquireSpinLock(&Driver.Lock, &Irql); - Driver.Fdo = NULL; + Driver.Adapter = NULL; KeReleaseSpinLock(&Driver.Lock, Irql); } static FORCEINLINE BOOLEAN -__DriverGetFdo( +__DriverGetAdapter( IN PDEVICE_OBJECT DeviceObject, - OUT PXENVBD_FDO *Fdo + OUT PXENVBD_ADAPTER *Adapter ) { KIRQL Irql; - BOOLEAN IsFdo = FALSE; + BOOLEAN IsAdapter = FALSE; KeAcquireSpinLock(&Driver.Lock, &Irql); - *Fdo = Driver.Fdo; - if (*Fdo) { - FdoReference(*Fdo); - if (FdoGetDeviceObject(*Fdo) == DeviceObject) { - IsFdo = TRUE; + *Adapter = Driver.Adapter; + if (*Adapter) { + if (AdapterGetDeviceObject(*Adapter) == DeviceObject) { + IsAdapter = TRUE; } } KeReleaseSpinLock(&Driver.Lock, Irql); - return IsFdo; + return IsAdapter; } #define MAXNAMELEN 256 @@ -365,7 +364,7 @@ HwResetBus( { UNREFERENCED_PARAMETER(PathId); - return FdoResetBus((PXENVBD_FDO)HwDeviceExtension); + return AdapterResetBus((PXENVBD_ADAPTER)HwDeviceExtension); } HW_FIND_ADAPTER HwFindAdapter; @@ -385,7 +384,7 @@ HwFindAdapter( UNREFERENCED_PARAMETER(ArgumentString); UNREFERENCED_PARAMETER(Again); - return FdoFindAdapter((PXENVBD_FDO)HwDeviceExtension, ConfigInfo); + return AdapterFindAdapter((PXENVBD_ADAPTER)HwDeviceExtension, ConfigInfo); } static FORCEINLINE BOOLEAN @@ -417,7 +416,7 @@ HwBuildIo( if (__FailStorageRequest(HwDeviceExtension, Srb)) return FALSE; // dont pass to HwStartIo - return FdoBuildIo((PXENVBD_FDO)HwDeviceExtension, Srb); + return AdapterBuildIo((PXENVBD_ADAPTER)HwDeviceExtension, Srb); } HW_STARTIO HwStartIo; @@ -431,7 +430,7 @@ HwStartIo( if (__FailStorageRequest(HwDeviceExtension, Srb)) return TRUE; // acknowledge the srb - return FdoStartIo((PXENVBD_FDO)HwDeviceExtension, Srb); + return AdapterStartIo((PXENVBD_ADAPTER)HwDeviceExtension, Srb); } __drv_dispatchType(IRP_MJ_PNP) @@ -443,13 +442,13 @@ DispatchPnp( IN PIRP Irp ) { - PXENVBD_FDO Fdo; + PXENVBD_ADAPTER Adapter; - if (__DriverGetFdo(DeviceObject, &Fdo)) - return FdoDispatchPnp(Fdo, DeviceObject, Irp); + if (__DriverGetAdapter(DeviceObject, &Adapter)) + return AdapterDispatchPnp(Adapter, DeviceObject, Irp); - if (Fdo != NULL) - return FdoForwardPnp(Fdo, DeviceObject, Irp); + if (Adapter != NULL) + return AdapterForwardPnp(Adapter, DeviceObject, Irp); return DriverDispatchPnp(DeviceObject, Irp); } @@ -463,13 +462,10 @@ DispatchPower( IN PIRP Irp ) { - PXENVBD_FDO Fdo; + PXENVBD_ADAPTER Adapter; - if (__DriverGetFdo(DeviceObject, &Fdo)) - return FdoDispatchPower(Fdo, DeviceObject, Irp); - - if (Fdo != NULL) - FdoDereference(Fdo); + if (__DriverGetAdapter(DeviceObject, &Adapter)) + return AdapterDispatchPower(Adapter, DeviceObject, Irp); return DriverDispatchPower(DeviceObject, Irp); } @@ -540,7 +536,7 @@ DriverEntry( ServiceKey = NULL; KeInitializeSpinLock(&Driver.Lock); - Driver.Fdo = NULL; + Driver.Adapter = NULL; BufferInitialize(); __DriverParseOption("XENVBD:SYNTH_INQ=", @@ -560,7 +556,7 @@ DriverEntry( InitData.HwResetBus = HwResetBus; InitData.HwDmaStarted = NULL; InitData.HwAdapterState = NULL; - InitData.DeviceExtensionSize = FdoSizeofXenvbdFdo(); + InitData.DeviceExtensionSize = AdapterSizeofXenvbdAdapter(); InitData.SpecificLuExtensionSize = sizeof (ULONG); // not actually used InitData.SrbExtensionSize = sizeof(XENVBD_SRBEXT); InitData.NumberOfAccessRanges = 2; diff --git a/src/xenvbd/driver.h b/src/xenvbd/driver.h index e7730a9..cea7b42 100644 --- a/src/xenvbd/driver.h +++ b/src/xenvbd/driver.h @@ -32,7 +32,6 @@ #ifndef _XENVBD_XENVBD_H #define _XENVBD_XENVBD_H -#include "fdo.h" #include <xen.h> // Global Constants @@ -57,6 +56,8 @@ typedef struct _XENVBD_PARAMETERS { extern XENVBD_PARAMETERS DriverParameters; +#include "adapter.h" + extern HANDLE DriverGetParametersKey( VOID @@ -76,13 +77,13 @@ DriverDispatchPower( // Fdo Device Extension management extern VOID -DriverLinkFdo( - __in PXENVBD_FDO Fdo +DriverLinkAdapter( + IN PXENVBD_ADAPTER Adapter ); extern VOID -DriverUnlinkFdo( - __in PXENVBD_FDO Fdo +DriverUnlinkAdapter( + IN PXENVBD_ADAPTER Adapter ); extern VOID diff --git a/src/xenvbd/fdo.c b/src/xenvbd/fdo.c deleted file mode 100644 index c1aeeb5..0000000 --- a/src/xenvbd/fdo.c +++ /dev/null @@ -1,2206 +0,0 @@ -/* 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 "fdo.h" -#include "driver.h" -#include "registry.h" -#include "pdo.h" -#include "srbext.h" -#include "thread.h" -#include "buffer.h" -#include "debug.h" -#include "assert.h" -#include "util.h" -#include <version.h> -#include <xencdb.h> -#include <names.h> -#include <store_interface.h> -#include <evtchn_interface.h> -#include <gnttab_interface.h> -#include <debug_interface.h> -#include <suspend_interface.h> -#include <emulated_interface.h> - -#include <stdlib.h> - -#define MAXNAMELEN 128 - -#define FDO_SIGNATURE 'odfX' - -struct _XENVBD_FDO { - ULONG Signature; - KEVENT RemoveEvent; - LONG ReferenceCount; - PDEVICE_OBJECT DeviceObject; - PDEVICE_OBJECT LowerDeviceObject; - PDEVICE_OBJECT PhysicalDeviceObject; - KSPIN_LOCK Lock; - DEVICE_POWER_STATE DevicePower; - ANSI_STRING Enumerator; - - // Power - PXENVBD_THREAD DevicePowerThread; - PIRP DevicePowerIrp; - - // Interfaces to XenBus - XENBUS_EVTCHN_INTERFACE Evtchn; - XENBUS_STORE_INTERFACE Store; - XENBUS_GNTTAB_INTERFACE Gnttab; - XENBUS_DEBUG_INTERFACE Debug; - XENBUS_SUSPEND_INTERFACE Suspend; - XENBUS_UNPLUG_INTERFACE Unplug; - XENFILT_EMULATED_INTERFACE Emulated; - - // Debug Callback - PXENBUS_DEBUG_CALLBACK DebugCallback; - PXENBUS_SUSPEND_CALLBACK SuspendCallback; - - // Targets - KSPIN_LOCK TargetLock; - PXENVBD_PDO Targets[XENVBD_MAX_TARGETS]; - - // Target Enumeration - PXENVBD_THREAD ScanThread; - KEVENT ScanEvent; - PXENBUS_STORE_WATCH ScanWatch; - - // Statistics - LONG CurrentSrbs; - LONG MaximumSrbs; - LONG TotalSrbs; -}; - -//============================================================================= -static FORCEINLINE BOOLEAN -__FdoSetDevicePowerState( - __in PXENVBD_FDO Fdo, - __in DEVICE_POWER_STATE State - ) -{ - KIRQL Irql; - BOOLEAN Changed = FALSE; - - KeAcquireSpinLock(&Fdo->Lock, &Irql); - - if (Fdo->DevicePower != State) { - Verbose("POWER %s to %s\n", PowerDeviceStateName(Fdo->DevicePower), PowerDeviceStateName(State)); - Changed = TRUE; - Fdo->DevicePower = State; - } - - KeReleaseSpinLock(&Fdo->Lock, Irql); - - 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( - __in PXENVBD_FDO Fdo, - __in ULONG TargetId, - __in PCHAR Caller - ) -{ - PXENVBD_PDO Pdo; - KIRQL Irql; - - ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); - - KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Pdo = Fdo->Targets[TargetId]; - if (Pdo) { - __PdoReference(Pdo, Caller); - } - KeReleaseSpinLock(&Fdo->TargetLock, Irql); - - return Pdo; -} - -__checkReturn -static FORCEINLINE PXENVBD_PDO -___FdoGetPdo( - __in PXENVBD_FDO Fdo, - __in ULONG TargetId, - __in PCHAR Caller - ) -{ - PXENVBD_PDO Pdo = NULL; - KIRQL Irql; - - ASSERT3U(TargetId, <, XENVBD_MAX_TARGETS); - - KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - if (Fdo->Targets[TargetId] && - __PdoReference(Fdo->Targets[TargetId], Caller) > 0) { - Pdo = Fdo->Targets[TargetId]; - } - KeReleaseSpinLock(&Fdo->TargetLock, Irql); - - return Pdo; -} -#define __FdoGetPdo(f, t) ___FdoGetPdo(f, t, __FUNCTION__) - -// Reference Counting -LONG -__FdoReference( - __in PXENVBD_FDO Fdo, - __in PCHAR Caller - ) -{ - LONG Result; - - ASSERT3P(Fdo, !=, NULL); - Result = InterlockedIncrement(&Fdo->ReferenceCount); - ASSERTREFCOUNT(Result, >, 0, Caller); - - if (Result == 1) { - Result = InterlockedDecrement(&Fdo->ReferenceCount); - Error("%s: Attempting to take reference of removed FDO from %d\n", Caller, Result); - return 0; - } else { - ASSERTREFCOUNT(Result, >, 1, Caller); - return Result; - } -} -FORCEINLINE LONG -__FdoDereference( - __in PXENVBD_FDO Fdo, - __in PCHAR Caller - ) -{ - LONG Result; - - ASSERT3P(Fdo, !=, NULL); - Result = InterlockedDecrement(&Fdo->ReferenceCount); - ASSERTREFCOUNT(Result, >=, 0, Caller); - - if (Result == 0) { - Verbose("Final ReferenceCount dropped, 0x%p able to be removed\n", Fdo); - KeSetEvent(&Fdo->RemoveEvent, IO_NO_INCREMENT, FALSE); - } - return Result; -} -BOOLEAN -FdoLinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo - ) -{ - KIRQL Irql; - PXENVBD_PDO Current; - BOOLEAN Result = FALSE; - ULONG TargetId = PdoGetTargetId(Pdo); - - KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Current = Fdo->Targets[TargetId]; - if (Fdo->Targets[TargetId] == NULL) { - Fdo->Targets[TargetId] = Pdo; - Result = TRUE; - } - KeReleaseSpinLock(&Fdo->TargetLock, Irql); - - if (!Result) { - Warning("Target[%d] : Current 0x%p, New 0x%p\n", TargetId, Current, Pdo); - } - return Result; -} -BOOLEAN -FdoUnlinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo - ) -{ - KIRQL Irql; - PXENVBD_PDO Current; - BOOLEAN Result = FALSE; - ULONG TargetId = PdoGetTargetId(Pdo); - - KeAcquireSpinLock(&Fdo->TargetLock, &Irql); - Current = Fdo->Targets[TargetId]; - if (Fdo->Targets[TargetId] == Pdo) { - Fdo->Targets[TargetId] = NULL; - Result = TRUE; - } - KeReleaseSpinLock(&Fdo->TargetLock, Irql); - - if (!Result) { - Warning("Target[%d] : Current 0x%p, Expected 0x%p\n", TargetId, Current, Pdo); - } - return Result; -} - -//============================================================================= -// QueryInterface - -__drv_requiresIRQL(PASSIVE_LEVEL) -static NTSTATUS -FdoQueryInterface( - IN PXENVBD_FDO Fdo, - IN const GUID *Guid, - IN ULONG Version, - OUT PINTERFACE Interface, - IN ULONG Size, - IN BOOLEAN Optional - ) -{ - KEVENT Event; - IO_STATUS_BLOCK StatusBlock; - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - NTSTATUS status; - - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - - KeInitializeEvent(&Event, NotificationEvent, FALSE); - RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); - - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, - Fdo->LowerDeviceObject, - NULL, - 0, - NULL, - &Event, - &StatusBlock); - - status = STATUS_UNSUCCESSFUL; - if (Irp == NULL) - goto fail1; - - StackLocation = IoGetNextIrpStackLocation(Irp); - StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; - - StackLocation->Parameters.QueryInterface.InterfaceType = Guid; - StackLocation->Parameters.QueryInterface.Size = (USHORT)Size; - StackLocation->Parameters.QueryInterface.Version = (USHORT)Version; - StackLocation->Parameters.QueryInterface.Interface = Interface; - - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - if (status == STATUS_PENDING) { - (VOID) KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); - status = StatusBlock.Status; - } - - if (!NT_SUCCESS(status)) { - if (status == STATUS_NOT_SUPPORTED && Optional) - goto done; - - goto fail2; - } - -done: - return STATUS_SUCCESS; - -fail2: - Error("fail2\n"); - -fail1: - Error("fail1 (%08x)\n", status); - - return status; -} - -#define QUERY_INTERFACE( \ - _Fdo, \ - _ProviderName, \ - _InterfaceName, \ - _Interface, \ - _Size, \ - _Optional) \ - FdoQueryInterface((_Fdo), \ - &GUID_ ## _ProviderName ## _ ## _InterfaceName ## _INTERFACE, \ - _ProviderName ## _ ## _InterfaceName ## _INTERFACE_VERSION_MAX, \ - (_Interface), \ - (_Size), \ - (_Optional)) - -//============================================================================= -// Debug - -static DECLSPEC_NOINLINE VOID -FdoDebugCallback( - __in PVOID Context, - __in BOOLEAN Crashing - ) -{ - PXENVBD_FDO Fdo = Context; - ULONG TargetId; - - if (Fdo == NULL || Fdo->DebugCallback == NULL) - return; - - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: Version: %d.%d.%d.%d (%d/%d/%d)\n", - MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION, BUILD_NUMBER, - DAY, MONTH, YEAR); - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: Fdo: 0x%p (ref-count %d) %s\n", - Context, - Fdo->ReferenceCount, - Crashing ? "CRASHING" : ""); - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: DevObj 0x%p LowerDevObj 0x%p PhysDevObj 0x%p\n", - Fdo->DeviceObject, - Fdo->LowerDeviceObject, - Fdo->PhysicalDeviceObject); - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: DevicePowerState: %s\n", - PowerDeviceStateName(Fdo->DevicePower)); - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: Enumerator : %s (0x%p)\n", - FdoEnum(Fdo), Fdo->Enumerator.Buffer); - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: Srbs : %d / %d (%d Total)\n", - Fdo->CurrentSrbs, Fdo->MaximumSrbs, Fdo->TotalSrbs); - - BufferDebugCallback(&Fdo->Debug); - - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - // no need to use __FdoGetPdo (which is locked at DISPATCH) as called at HIGH_LEVEL - PXENVBD_PDO Pdo = Fdo->Targets[TargetId]; - if (Pdo == NULL) - continue; - - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: ====> Target[%-3d] : 0x%p\n", - TargetId, Pdo); - - // call Target's debug callback directly - PdoDebugCallback(Pdo, &Fdo->Debug); - - XENBUS_DEBUG(Printf, &Fdo->Debug, - "FDO: <==== Target[%-3d] : 0x%p\n", - TargetId, Pdo); - } - - Fdo->MaximumSrbs = Fdo->CurrentSrbs; - Fdo->TotalSrbs = 0; -} - -//============================================================================= -// Enumeration -static FORCEINLINE ULONG -__ParseVbd( - __in PCHAR DeviceIdStr - ) -{ - ULONG DeviceId = strtoul(DeviceIdStr, NULL, 10); - - ASSERT3U((DeviceId & ~((1 << 29) - 1)), ==, 0); - - if (DeviceId & (1 << 28)) { - return (DeviceId & ((1 << 20) - 1)) >> 8; /* xvd */ - } else { - switch (DeviceId >> 8) { - case 202: return (DeviceId & 0xF0) >> 4; /* xvd */ - case 8: return (DeviceId & 0xF0) >> 4; /* sd */ - case 3: return (DeviceId & 0xC0) >> 6; /* hda..b */ - case 22: return ((DeviceId & 0xC0) >> 6) + 2; /* hdc..d */ - case 33: return ((DeviceId & 0xC0) >> 6) + 4; /* hde..f */ - case 34: return ((DeviceId & 0xC0) >> 6) + 6; /* hdg..h */ - case 56: return ((DeviceId & 0xC0) >> 6) + 8; /* hdi..j */ - case 57: return ((DeviceId & 0xC0) >> 6) + 10; /* hdk..l */ - case 88: return ((DeviceId & 0xC0) >> 6) + 12; /* hdm..n */ - case 89: return ((DeviceId & 0xC0) >> 6) + 14; /* hdo..p */ - default: break; - } - } - Error("Invalid DeviceId %s (%08x)\n", DeviceIdStr, DeviceId); - return 0xFFFFFFFF; // OBVIOUS ERROR VALUE -} -static FORCEINLINE XENVBD_DEVICE_TYPE -__DeviceType( - __in PCHAR Type - ) -{ - if (strcmp(Type, "disk") == 0) - return XENVBD_DEVICE_TYPE_DISK; - if (strcmp(Type, "cdrom") == 0) - return XENVBD_DEVICE_TYPE_CDROM; - return XENVBD_DEVICE_TYPE_UNKNOWN; -} -__checkReturn -static FORCEINLINE BOOLEAN -__FdoHiddenTarget( - __in PXENVBD_FDO Fdo, - __in PCHAR DeviceId, - __out PXENVBD_DEVICE_TYPE DeviceType - ) -{ - NTSTATUS Status; - PCHAR FrontendPath; - PCHAR Buffer; - ULONG Value; - - *DeviceType = XENVBD_DEVICE_TYPE_UNKNOWN; - FrontendPath = DriverFormat("device/%s/%s", FdoEnum(Fdo), DeviceId); - if (!FrontendPath) - goto fail; - - // Ejected? - Status = XENBUS_STORE(Read, &Fdo->Store, NULL, FrontendPath, "ejected", &Buffer); - if (NT_SUCCESS(Status)) { - Value = strtoul(Buffer, NULL, 10); - XENBUS_STORE(Free, &Fdo->Store, Buffer); - - if (Value) - goto ignore; - } - - // Not Disk? - Status = XENBUS_STORE(Read, &Fdo->Store, NULL, FrontendPath, "device-type", &Buffer); - if (!NT_SUCCESS(Status)) - goto ignore; - *DeviceType = __DeviceType(Buffer); - XENBUS_STORE(Free, &Fdo->Store, Buffer); - - switch (*DeviceType) { - case XENVBD_DEVICE_TYPE_DISK: - break; - case XENVBD_DEVICE_TYPE_CDROM: - if (DriverParameters.PVCDRom) - break; - // intentional fall-through - default: - goto ignore; - } - - // Try to Create - DriverFormatFree(FrontendPath); - return FALSE; - -fail: - Error("Fail\n"); - return TRUE; - -ignore: - DriverFormatFree(FrontendPath); - return TRUE; -} -__checkReturn -static FORCEINLINE BOOLEAN -__FdoIsPdoUnplugged( - __in PXENVBD_FDO Fdo, - __in PCHAR Enumerator, - __in PCHAR Device, - __in ULONG Target - ) -{ - // Only check targets that could be emulated - if (Target > 3) { - Verbose("Target[%d] : (%s/%s) Emulated NOT_APPLICABLE (non-IDE device)\n", - Target, Enumerator, Device); - return TRUE; - } - - // Check presense of Emulated interface. Absence indicates emulated cannot be unplugged - if (Fdo->Emulated.Interface.Context == NULL) { - Warning("Target[%d] : (%s/%s) Emulated NOT_KNOWN (assumed PRESENT)\n", - Target, Enumerator, Device); - return FALSE; - } - - // Ask XenFilt if Ctrlr(0), Target(Target), Lun(0) is present - if (XENFILT_EMULATED(IsDiskPresent, &Fdo->Emulated, 0, Target, 0)) { - Verbose("Target[%d] : (%s/%s) Emulated PRESENT\n", - Target, Enumerator, Device); - return FALSE; - } else { - Verbose("Target[%d] : (%s/%s) Emulated NOT_PRESENT\n", - Target, Enumerator, Device); - return TRUE; - } -} - -static FORCEINLINE VOID -__FdoEnumerate( - __in PXENVBD_FDO Fdo, - __in PANSI_STRING Devices, - __out PBOOLEAN NeedInvalidate, - __out PBOOLEAN NeedReboot - ) -{ - ULONG TargetId; - PANSI_STRING Device; - ULONG Index; - PXENVBD_PDO Pdo; - - *NeedInvalidate = FALSE; - *NeedReboot = FALSE; - - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - BOOLEAN Missing = TRUE; - - Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo == NULL) - continue; - - for (Index = 0; Devices[Index].Buffer != NULL; ++Index) { - ULONG DeviceTargetId; - Device = &Devices[Index]; - DeviceTargetId = __ParseVbd(Device->Buffer); - if (TargetId == DeviceTargetId) { - Missing = FALSE; - break; - } - } - - if (Missing && !PdoIsMissing(Pdo)) { - PdoSetMissing(Pdo, "Device Disappeared"); - if (PdoGetDevicePnpState(Pdo) == Present) - PdoSetDevicePnpState(Pdo, Deleted); - else - *NeedInvalidate = TRUE; - } - - if (PdoGetDevicePnpState(Pdo) == Deleted) { - PdoDereference(Pdo); - PdoDestroy(Pdo); - } else { - PdoDereference(Pdo); - } - } - - // add new targets - for (Index = 0; Devices[Index].Buffer != NULL; ++Index) { - XENVBD_DEVICE_TYPE DeviceType; - - Device = &Devices[Index]; - - TargetId = __ParseVbd(Device->Buffer); - if (TargetId == 0xFFFFFFFF) { - continue; - } - - Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - PdoDereference(Pdo); - continue; - } - - if (__FdoHiddenTarget(Fdo, Device->Buffer, &DeviceType)) { - continue; - } - - if (!__FdoIsPdoUnplugged(Fdo, - FdoEnum(Fdo), - Device->Buffer, - TargetId)) { - *NeedReboot = TRUE; - continue; - } - - if (PdoCreate(Fdo, - Device->Buffer, - TargetId, - DeviceType)) { - *NeedInvalidate = TRUE; - } - } -} - -static FORCEINLINE PANSI_STRING -__FdoMultiSzToAnsi( - IN PCHAR Buffer - ) -{ - PANSI_STRING Ansi; - LONG Index; - LONG Count; - NTSTATUS status; - - Index = 0; - Count = 0; - for (;;) { - if (Buffer[Index] == '\0') { - Count++; - Index++; - - // Check for double NUL - if (Buffer[Index] == '\0') - break; - } else { - Index++; - } - } - - Ansi = __AllocatePoolWithTag(NonPagedPool, - sizeof (ANSI_STRING) * (Count + 1), - FDO_SIGNATURE); - - status = STATUS_NO_MEMORY; - if (Ansi == NULL) - goto fail1; - - for (Index = 0; Index < Count; Index++) { - ULONG Length; - - Length = (ULONG)strlen(Buffer); - Ansi[Index].MaximumLength = (USHORT)(Length + 1); - Ansi[Index].Buffer = __AllocatePoolWithTag(NonPagedPool, - Ansi[Index].MaximumLength, - FDO_SIGNATURE); - - status = STATUS_NO_MEMORY; - if (Ansi[Index].Buffer == NULL) - goto fail2; - - RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); - Ansi[Index].Length = (USHORT)Length; - - Buffer += Length + 1; - } - - return Ansi; - -fail2: - Error("fail2\n"); - - while (--Index >= 0) - __FreePoolWithTag(Ansi[Index].Buffer, FDO_SIGNATURE); - - __FreePoolWithTag(Ansi, FDO_SIGNATURE); - -fail1: - Error("fail1 (%08x)\n", status); - - return NULL; -} - -static FORCEINLINE PANSI_STRING -__FdoMultiSzToUpcaseAnsi( - IN PCHAR Buffer - ) -{ - PANSI_STRING Ansi; - LONG Index; - LONG Count; - NTSTATUS status; - - Index = 0; - Count = 0; - for (;;) { - if (Buffer[Index] == '\0') { - Count++; - Index++; - - // Check for double NUL - if (Buffer[Index] == '\0') - break; - } else { - Buffer[Index] = __toupper(Buffer[Index]); - Index++; - } - } - - Ansi = __AllocatePoolWithTag(NonPagedPool, - sizeof (ANSI_STRING) * (Count + 1), - FDO_SIGNATURE); - - status = STATUS_NO_MEMORY; - if (Ansi == NULL) - goto fail1; - - for (Index = 0; Index < Count; Index++) { - ULONG Length; - - Length = (ULONG)strlen(Buffer); - Ansi[Index].MaximumLength = (USHORT)(Length + 1); - Ansi[Index].Buffer = __AllocatePoolWithTag(NonPagedPool, - Ansi[Index].MaximumLength, - FDO_SIGNATURE); - - status = STATUS_NO_MEMORY; - if (Ansi[Index].Buffer == NULL) - goto fail2; - - RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); - Ansi[Index].Length = (USHORT)Length; - - Buffer += Length + 1; - } - - return Ansi; - -fail2: - Error("fail2\n"); - - while (--Index >= 0) - __FreePoolWithTag(Ansi[Index].Buffer, FDO_SIGNATURE); - - __FreePoolWithTag(Ansi, FDO_SIGNATURE); - -fail1: - Error("fail1 (%08x)\n", status); - - return NULL; -} - -static FORCEINLINE VOID -__FdoFreeAnsi( - IN PANSI_STRING Ansi - ) -{ - ULONG Index; - - for (Index = 0; Ansi[Index].Buffer != NULL; Index++) - __FreePoolWithTag(Ansi[Index].Buffer, FDO_SIGNATURE); - - __FreePoolWithTag(Ansi, FDO_SIGNATURE); -} - -static DECLSPEC_NOINLINE VOID -FdoScanTargets( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS Status; - PCHAR Buffer; - PANSI_STRING Devices; - BOOLEAN NeedInvalidate; - BOOLEAN NeedReboot; - - Status = XENBUS_STORE(Directory, &Fdo->Store, NULL, "device", FdoEnum(Fdo), &Buffer); - if (!NT_SUCCESS(Status)) - return; - - Devices = __FdoMultiSzToAnsi(Buffer); - XENBUS_STORE(Free, &Fdo->Store, Buffer); - - if (Devices == NULL) - return; - - __FdoEnumerate(Fdo, Devices, &NeedInvalidate, &NeedReboot); - __FdoFreeAnsi(Devices); - - if (NeedInvalidate) { - StorPortNotification(BusChangeDetected, Fdo, 0); - } - if (NeedReboot) { - DriverRequestReboot(); - } -} - -__checkReturn -static DECLSPEC_NOINLINE NTSTATUS -FdoScan( - __in PXENVBD_THREAD Thread, - __in PVOID Context - ) -{ - PXENVBD_FDO Fdo = Context; - PKEVENT Event = ThreadGetEvent(Thread); - - for (;;) { - Trace("waiting...\n"); - - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - - if (ThreadIsAlerted(Thread)) - break; - - if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) - FdoScanTargets(Fdo); - - KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE); - } - KeSetEvent(&Fdo->ScanEvent, IO_NO_INCREMENT, FALSE); - - return STATUS_SUCCESS; -} - -//============================================================================= -// Initialize, Start, Stop - -__drv_requiresIRQL(PASSIVE_LEVEL) -static FORCEINLINE NTSTATUS -__FdoQueryInterfaces( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS Status; - - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - - // Get STORE Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - STORE, - (PINTERFACE)&Fdo->Store, - sizeof (Fdo->Store), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail1; - - // Get EVTCHN Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - EVTCHN, - (PINTERFACE)&Fdo->Evtchn, - sizeof (Fdo->Evtchn), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail2; - - // Get GNTTAB Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - GNTTAB, - (PINTERFACE)&Fdo->Gnttab, - sizeof (Fdo->Gnttab), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail3; - - // Get SUSPEND Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - SUSPEND, - (PINTERFACE)&Fdo->Suspend, - sizeof (Fdo->Suspend), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail4; - - // Get DEBUG Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - DEBUG, - (PINTERFACE)&Fdo->Debug, - sizeof (Fdo->Debug), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail5; - - // Get UNPLUG Interface - Status = QUERY_INTERFACE(Fdo, - XENBUS, - UNPLUG, - (PINTERFACE)&Fdo->Unplug, - sizeof (Fdo->Unplug), - FALSE); - if (!NT_SUCCESS(Status)) - goto fail6; - - // Get EMULATED Interface (optional) - Status = QUERY_INTERFACE(Fdo, - XENFILT, - EMULATED, - (PINTERFACE)&Fdo->Emulated, - sizeof (Fdo->Emulated), - TRUE); - if (!NT_SUCCESS(Status)) - goto fail7; - - return STATUS_SUCCESS; - -fail7: - RtlZeroMemory(&Fdo->Unplug, - sizeof (XENBUS_UNPLUG_INTERFACE)); -fail6: - RtlZeroMemory(&Fdo->Debug, - sizeof (XENBUS_DEBUG_INTERFACE)); -fail5: - RtlZeroMemory(&Fdo->Suspend, - sizeof (XENBUS_SUSPEND_INTERFACE)); -fail4: - RtlZeroMemory(&Fdo->Gnttab, - sizeof (XENBUS_GNTTAB_INTERFACE)); -fail3: - RtlZeroMemory(&Fdo->Evtchn, - sizeof (XENBUS_EVTCHN_INTERFACE)); -fail2: - RtlZeroMemory(&Fdo->Store, - sizeof (XENBUS_STORE_INTERFACE)); -fail1: - return Status; -} -static FORCEINLINE VOID -__FdoZeroInterfaces( - __in PXENVBD_FDO Fdo - ) -{ - RtlZeroMemory(&Fdo->Emulated, - sizeof (XENFILT_EMULATED_INTERFACE)); - RtlZeroMemory(&Fdo->Unplug, - sizeof (XENBUS_UNPLUG_INTERFACE)); - RtlZeroMemory(&Fdo->Debug, - sizeof (XENBUS_DEBUG_INTERFACE)); - RtlZeroMemory(&Fdo->Suspend, - sizeof (XENBUS_SUSPEND_INTERFACE)); - RtlZeroMemory(&Fdo->Gnttab, - sizeof (XENBUS_GNTTAB_INTERFACE)); - RtlZeroMemory(&Fdo->Evtchn, - sizeof (XENBUS_EVTCHN_INTERFACE)); - RtlZeroMemory(&Fdo->Store, - sizeof (XENBUS_STORE_INTERFACE)); -} -static FORCEINLINE NTSTATUS -__FdoAcquire( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - if (Fdo->Emulated.Interface.Context) { - status = XENFILT_EMULATED(Acquire, &Fdo->Emulated); - if (!NT_SUCCESS(status)) - goto fail1; - } - - status = XENBUS_SUSPEND(Acquire, &Fdo->Suspend); - if (!NT_SUCCESS(status)) - goto fail2; - - status = XENBUS_DEBUG(Acquire, &Fdo->Debug); - if (!NT_SUCCESS(status)) - goto fail3; - - status = XENBUS_GNTTAB(Acquire, &Fdo->Gnttab); - if (!NT_SUCCESS(status)) - goto fail4; - - status = XENBUS_EVTCHN(Acquire, &Fdo->Evtchn); - if (!NT_SUCCESS(status)) - goto fail5; - - status = XENBUS_STORE(Acquire, &Fdo->Store); - if (!NT_SUCCESS(status)) - goto fail6; - - return STATUS_SUCCESS; - -fail6: - XENBUS_EVTCHN(Release, &Fdo->Evtchn); -fail5: - XENBUS_GNTTAB(Release, &Fdo->Gnttab); -fail4: - XENBUS_DEBUG(Release, &Fdo->Debug); -fail3: - XENBUS_SUSPEND(Release, &Fdo->Suspend); -fail2: - if (Fdo->Emulated.Interface.Context) - XENFILT_EMULATED(Release, &Fdo->Emulated); -fail1: - return status; -} -static FORCEINLINE VOID -__FdoRelease( - __in PXENVBD_FDO Fdo - ) -{ - XENBUS_STORE(Release, &Fdo->Store); - XENBUS_EVTCHN(Release, &Fdo->Evtchn); - XENBUS_GNTTAB(Release, &Fdo->Gnttab); - XENBUS_DEBUG(Release, &Fdo->Debug); - XENBUS_SUSPEND(Release, &Fdo->Suspend); - if (Fdo->Emulated.Interface.Context) - XENFILT_EMULATED(Release, &Fdo->Emulated); -} - -static FORCEINLINE BOOLEAN -__FdoMatchDistribution( - IN PXENVBD_FDO Fdo, - IN PCHAR Buffer - ) -{ - PCHAR Vendor; - PCHAR Product; - PCHAR Context; - const CHAR *Text; - BOOLEAN Match; - ULONG Index; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Fdo); - - status = STATUS_INVALID_PARAMETER; - - Vendor = __strtok_r(Buffer, " ", &Context); - if (Vendor == NULL) - goto fail1; - - Product = __strtok_r(NULL, " ", &Context); - if (Product == NULL) - goto fail2; - - Match = TRUE; - - Text = VENDOR_NAME_STR; - - for (Index = 0; Text[Index] != 0; Index++) { - if (!isalnum((UCHAR)Text[Index])) { - if (Vendor[Index] != '_') { - Match = FALSE; - break; - } - } else { - if (Vendor[Index] != Text[Index]) { - Match = FALSE; - break; - } - } - } - - Text = "XENVBD"; - - if (_stricmp(Product, Text) != 0) - Match = FALSE; - - return Match; - -fail2: - Error("fail2\n"); - -fail1: - Error("fail1 (%08x)\n", status); - - return FALSE; -} - -static VOID -FdoClearDistribution( - IN PXENVBD_FDO Fdo - ) -{ - PCHAR Buffer; - PANSI_STRING Distributions; - ULONG Index; - NTSTATUS status; - - Trace("====>\n"); - - status = XENBUS_STORE(Directory, - &Fdo->Store, - NULL, - NULL, - "drivers", - &Buffer); - if (NT_SUCCESS(status)) { - Distributions = __FdoMultiSzToUpcaseAnsi(Buffer); - - XENBUS_STORE(Free, - &Fdo->Store, - Buffer); - } else { - Distributions = NULL; - } - - if (Distributions == NULL) - goto done; - - for (Index = 0; Distributions[Index].Buffer != NULL; Index++) { - PANSI_STRING Distribution = &Distributions[Index]; - - status = XENBUS_STORE(Read, - &Fdo->Store, - NULL, - "drivers", - Distribution->Buffer, - &Buffer); - if (!NT_SUCCESS(status)) - continue; - - if (__FdoMatchDistribution(Fdo, Buffer)) - (VOID) XENBUS_STORE(Remove, - &Fdo->Store, - NULL, - "drivers", - Distribution->Buffer); - - XENBUS_STORE(Free, - &Fdo->Store, - Buffer); - } - - __FdoFreeAnsi(Distributions); - -done: - Trace("<====\n"); -} - -#define MAXIMUM_INDEX 255 - -static NTSTATUS -FdoSetDistribution( - IN PXENVBD_FDO Fdo - ) -{ - ULONG Index; - CHAR Distribution[MAXNAMELEN]; - CHAR Vendor[MAXNAMELEN]; - const CHAR *Product; - NTSTATUS status; - - Trace("====>\n"); - - Index = 0; - while (Index <= MAXIMUM_INDEX) { - PCHAR Buffer; - - status = RtlStringCbPrintfA(Distribution, - MAXNAMELEN, - "%u", - Index); - ASSERT(NT_SUCCESS(status)); - - status = XENBUS_STORE(Read, - &Fdo->Store, - NULL, - "drivers", - Distribution, - &Buffer); - if (!NT_SUCCESS(status)) { - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - goto update; - - goto fail1; - } - - XENBUS_STORE(Free, - &Fdo->Store, - Buffer); - - Index++; - } - - status = STATUS_UNSUCCESSFUL; - goto fail2; - -update: - status = RtlStringCbPrintfA(Vendor, - MAXNAMELEN, - "%s", - VENDOR_NAME_STR); - ASSERT(NT_SUCCESS(status)); - - for (Index = 0; Vendor[Index] != '\0'; Index++) - if (!isalnum((UCHAR)Vendor[Index])) - Vendor[Index] = '_'; - - Product = "XENVBD"; - -#if DBG -#define ATTRIBUTES "(DEBUG)" -#else -#define ATTRIBUTES "" -#endif - - (VOID) XENBUS_STORE(Printf, - &Fdo->Store, - NULL, - "drivers", - Distribution, - "%s %s %u.%u.%u %s", - Vendor, - Product, - MAJOR_VERSION, - MINOR_VERSION, - MICRO_VERSION, - ATTRIBUTES - ); - -#undef ATTRIBUTES - - Trace("<====\n"); - return STATUS_SUCCESS; - -fail2: - Error("fail2\n"); - -fail1: - Error("fail1 (%08x)\n", status); - - return status; -} - -static FORCEINLINE NTSTATUS -__FdoD3ToD0( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS Status; - - Trace("=====>\n"); - - (VOID) FdoSetDistribution(Fdo); - - ASSERT3P(Fdo->ScanWatch, ==, NULL); - Status = XENBUS_STORE(WatchAdd, - &Fdo->Store, - "device", - FdoEnum(Fdo), - ThreadGetEvent(Fdo->ScanThread), - &Fdo->ScanWatch); - if (!NT_SUCCESS(Status)) - goto fail1; - - (VOID) XENBUS_STORE(Printf, - &Fdo->Store, - NULL, - "feature/hotplug", - "vbd", - "%u", - TRUE); - - Trace("<=====\n"); - return STATUS_SUCCESS; - -fail1: - Error("fail1 (%08x)\n", Status); - - return Status; -} - -static FORCEINLINE VOID -__FdoD0ToD3( - __in PXENVBD_FDO Fdo - ) -{ - Trace("=====>\n"); - - (VOID) XENBUS_STORE(Remove, - &Fdo->Store, - NULL, - "feature/hotplug", - "vbd"); - - (VOID) XENBUS_STORE(WatchRemove, - &Fdo->Store, - Fdo->ScanWatch); - Fdo->ScanWatch = NULL; - - FdoClearDistribution(Fdo); - - Trace("<=====\n"); -} - -__drv_requiresIRQL(DISPATCH_LEVEL) -static VOID -FdoSuspendLateCallback( - __in PVOID Argument - ) -{ - PXENVBD_FDO Fdo = Argument; - NTSTATUS Status; - - Verbose("%s (%s)\n", - MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, - DAY_STR "/" MONTH_STR "/" YEAR_STR); - - __FdoD0ToD3(Fdo); - - Status = __FdoD3ToD0(Fdo); - ASSERT(NT_SUCCESS(Status)); -} - -static NTSTATUS -FdoD3ToD0( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS Status; - ULONG TargetId; - - if (!__FdoSetDevicePowerState(Fdo, PowerDeviceD0)) - return STATUS_SUCCESS; - - Trace("=====> (%d)\n", KeGetCurrentIrql()); - Verbose("D3->D0\n"); - - // Get Interfaces - Status = __FdoAcquire(Fdo); - if (!NT_SUCCESS(Status)) - goto fail1; - - // register debug callback - ASSERT3P(Fdo->DebugCallback, ==, NULL); - Status = XENBUS_DEBUG(Register, - &Fdo->Debug, - __MODULE__, - FdoDebugCallback, - Fdo, - &Fdo->DebugCallback); - if (!NT_SUCCESS(Status)) - goto fail2; - - // Power UP any PDOs - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - Status = PdoD3ToD0(Pdo); - PdoDereference(Pdo); - - if (!NT_SUCCESS(Status)) - goto fail3; - } - } - - Status = __FdoD3ToD0(Fdo); - if (!NT_SUCCESS(Status)) - goto fail4; - - // register suspend callback to re-register the watch - ASSERT3P(Fdo->SuspendCallback, ==, NULL); - Status = XENBUS_SUSPEND(Register, - &Fdo->Suspend, - SUSPEND_CALLBACK_LATE, - FdoSuspendLateCallback, - Fdo, - &Fdo->SuspendCallback); - if (!NT_SUCCESS(Status)) - goto fail5; - - Trace("<===== (%d)\n", KeGetCurrentIrql()); - return STATUS_SUCCESS; - -fail5: - Error("Fail5\n"); - - __FdoD0ToD3(Fdo); - -fail4: - Error("Fail4\n"); - -fail3: - Error("Fail3\n"); - - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - PdoD0ToD3(Pdo); - PdoDereference(Pdo); - } - } - - XENBUS_DEBUG(Deregister, &Fdo->Debug, Fdo->DebugCallback); - Fdo->DebugCallback = NULL; - -fail2: - Error("Fail2\n"); - - __FdoRelease(Fdo); - -fail1: - Error("Fail1 (%08x)\n", Status); - - __FdoSetDevicePowerState(Fdo, PowerDeviceD3); - return Status; -} - -static VOID -FdoD0ToD3( - __in PXENVBD_FDO Fdo - ) -{ - ULONG TargetId; - - if (!__FdoSetDevicePowerState(Fdo, PowerDeviceD3)) - return; - - Trace("=====> (%d)\n", KeGetCurrentIrql()); - Verbose("D0->D3\n"); - - // remove suspend callback - XENBUS_SUSPEND(Deregister, &Fdo->Suspend, Fdo->SuspendCallback); - Fdo->SuspendCallback = NULL; - - __FdoD0ToD3(Fdo); - - // Power DOWN any PDOs - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - PdoD0ToD3(Pdo); - PdoDereference(Pdo); - } - } - - // free debug callback - if (Fdo->DebugCallback != NULL) { - XENBUS_DEBUG(Deregister, &Fdo->Debug, Fdo->DebugCallback); - Fdo->DebugCallback = NULL; - } - - // Release Interfaces - __FdoRelease(Fdo); - - Trace("<===== (%d)\n", KeGetCurrentIrql()); -} - -__checkReturn -static DECLSPEC_NOINLINE NTSTATUS -FdoDevicePower( - __in PXENVBD_THREAD Thread, - __in PVOID Context - ) -{ - PXENVBD_FDO Fdo = Context; - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION Stack; - DEVICE_POWER_STATE DeviceState; - POWER_ACTION Action; - NTSTATUS Status; - - if (!ThreadWait(Thread)) - break; - - // must have a pended DevicePowerIrp - ASSERT3P(Fdo->DevicePowerIrp, !=, NULL); - - Irp = Fdo->DevicePowerIrp; - Fdo->DevicePowerIrp = NULL; - - Stack = IoGetCurrentIrpStackLocation(Irp); - DeviceState = Stack->Parameters.Power.State.DeviceState; - Action = Stack->Parameters.Power.ShutdownType; - - switch (Stack->MinorFunction) { - case IRP_MN_SET_POWER: - switch (DeviceState) { - case PowerDeviceD0: - Verbose("FDO:PowerDeviceD0\n"); - FdoD3ToD0(Fdo); - break; - - case PowerDeviceD3: - Verbose("FDO:PowerDeviceD3 (%s)\n", PowerActionName(Action)); - FdoD0ToD3(Fdo); - break; - - default: - break; - } - break; - case IRP_MN_QUERY_POWER: - default: - break; - } - FdoDereference(Fdo); - Status = DriverDispatchPower(Fdo->DeviceObject, Irp); - if (!NT_SUCCESS(Status)) { - Warning("StorPort failed PowerIRP with %08x\n", Status); - } - } - - return STATUS_SUCCESS; -} - -__checkReturn -__drv_requiresIRQL(PASSIVE_LEVEL) -static NTSTATUS -__FdoInitialize( - __in PXENVBD_FDO Fdo - ) -{ - ULONG StorStatus; - NTSTATUS Status; - - Trace("=====> (%d)\n", KeGetCurrentIrql()); - - ASSERT3U(KeGetCurrentIrql(), <=, DISPATCH_LEVEL); - // initialize the memory - Fdo->DevicePower = PowerDeviceD3; - KeInitializeSpinLock(&Fdo->TargetLock); - KeInitializeSpinLock(&Fdo->Lock); - KeInitializeEvent(&Fdo->RemoveEvent, SynchronizationEvent, FALSE); - KeInitializeEvent(&Fdo->ScanEvent, SynchronizationEvent, FALSE); - - Fdo->ReferenceCount = 1; - Fdo->Signature = FDO_SIGNATURE; - - StorStatus = StorPortGetDeviceObjects(Fdo, - &Fdo->DeviceObject, - &Fdo->PhysicalDeviceObject, - &Fdo->LowerDeviceObject); - Status = STATUS_UNSUCCESSFUL; - if (StorStatus != STOR_STATUS_SUCCESS) { - Error("StorPortGetDeviceObjects() (%x:%s)\n", StorStatus, StorStatusName(StorStatus)); - goto fail1; - } - - // get interfaces - Status = __FdoQueryInterfaces(Fdo); - if (!NT_SUCCESS(Status)) - goto fail2; - - // start enum thread - Status = ThreadCreate(FdoScan, Fdo, &Fdo->ScanThread); - if (!NT_SUCCESS(Status)) - goto fail3; - - Status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread); - if (!NT_SUCCESS(Status)) - goto fail4; - - // query enumerator - // fix this up to query from device location(?) - //RtlInitAnsiString(&Fdo->Enumerator, "vbd"); - - // link fdo - DriverLinkFdo(Fdo); - - Trace("<===== (%d)\n", KeGetCurrentIrql()); - return STATUS_SUCCESS; - -fail4: - Error("fail4\n"); - ThreadAlert(Fdo->ScanThread); - ThreadJoin(Fdo->ScanThread); - Fdo->ScanThread = NULL; -fail3: - Error("fail3\n"); - __FdoZeroInterfaces(Fdo); -fail2: - Error("fail2\n"); - Fdo->DeviceObject = NULL; - Fdo->PhysicalDeviceObject = NULL; - Fdo->LowerDeviceObject = NULL; -fail1: - Error("fail1 (%08x)\n", Status); - return Status; -} -__drv_maxIRQL(PASSIVE_LEVEL) -static VOID -__FdoTerminate( - __in PXENVBD_FDO Fdo - ) -{ - ULONG TargetId; - - Trace("=====> (%d)\n", KeGetCurrentIrql()); - - DriverUnlinkFdo(Fdo); - ASSERT3U(Fdo->DevicePower, ==, PowerDeviceD3); - FdoDereference(Fdo); - - // should wait until ReferenceCount == 0 - Verbose("Terminating, %d Refs\n", Fdo->ReferenceCount); - ASSERT3S(Fdo->ReferenceCount, >=, 0); - KeWaitForSingleObject(&Fdo->RemoveEvent, Executive, KernelMode, FALSE, NULL); - ASSERT3S(Fdo->ReferenceCount, ==, 0); - - // stop device power thread - ThreadAlert(Fdo->DevicePowerThread); - ThreadJoin(Fdo->DevicePowerThread); - Fdo->DevicePowerThread = NULL; - - // stop enum thread - ThreadAlert(Fdo->ScanThread); - ThreadJoin(Fdo->ScanThread); - Fdo->ScanThread = NULL; - - // clear device objects - Fdo->DeviceObject = NULL; - Fdo->PhysicalDeviceObject = NULL; - Fdo->LowerDeviceObject = NULL; - - // delete targets - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdoAlways(Fdo, TargetId, __FUNCTION__); - if (Pdo) { - // Pdo may not be in Deleted state yet, force it as Fdo is terminating - if (PdoGetDevicePnpState(Pdo) != Deleted) - PdoSetDevicePnpState(Pdo, Deleted); - // update missing (for debug output more than anything else - PdoSetMissing(Pdo, "FdoTerminate"); - // drop ref-count acquired in __FdoGetPdo *before* destroying Pdo - PdoDereference(Pdo); - PdoDestroy(Pdo); - } - } - - // cleanup memory - ASSERT3U(Fdo->DevicePower, ==, PowerDeviceD3); - ASSERT3P(Fdo->DebugCallback, ==, NULL); - ASSERT3P(Fdo->SuspendCallback, ==, NULL); - - Fdo->Signature = 0; - Fdo->DevicePower = 0; - Fdo->CurrentSrbs = Fdo->MaximumSrbs = Fdo->TotalSrbs = 0; - 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); - - ASSERT(IsZeroMemory(Fdo, sizeof(XENVBD_FDO))); - Trace("<===== (%d)\n", KeGetCurrentIrql()); -} -//============================================================================= -// Query Methods -__checkReturn -FORCEINLINE PDEVICE_OBJECT -FdoGetDeviceObject( - __in PXENVBD_FDO Fdo - ) -{ - if (Fdo) - return Fdo->DeviceObject; - return NULL; -} - -FORCEINLINE ULONG -FdoSizeofXenvbdFdo( - ) -{ - return (ULONG)sizeof(XENVBD_FDO); -} - -FORCEINLINE PCHAR -FdoEnum( - __in PXENVBD_FDO Fdo - ) -{ - if (Fdo->Enumerator.Buffer) - return Fdo->Enumerator.Buffer; - else - return "vbd"; -} - -//============================================================================= -// SRB Methods -FORCEINLINE VOID -FdoStartSrb( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ) -{ - LONG Value; - - UNREFERENCED_PARAMETER(Srb); - - Value = InterlockedIncrement(&Fdo->CurrentSrbs); - if (Value > Fdo->MaximumSrbs) - Fdo->MaximumSrbs = Value; - InterlockedIncrement(&Fdo->TotalSrbs); -} - -FORCEINLINE VOID -FdoCompleteSrb( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ) -{ - ASSERT3U(Srb->SrbStatus, !=, SRB_STATUS_PENDING); - - InterlockedDecrement(&Fdo->CurrentSrbs); - - StorPortNotification(RequestComplete, Fdo, Srb); -} - -//============================================================================= -// StorPort Methods -BOOLEAN -FdoResetBus( - __in PXENVBD_FDO Fdo - ) -{ - ULONG TargetId; - - Verbose("====>\n"); - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - PdoReset(Pdo); - PdoDereference(Pdo); - } - } - Verbose("<====\n"); - - return TRUE; -} - -static VOID -FdoUnplugRequest( - IN PXENVBD_FDO Fdo, - IN BOOLEAN Make - ) -{ - NTSTATUS status; - - status = XENBUS_UNPLUG(Acquire, &Fdo->Unplug); - if (!NT_SUCCESS(status)) - return; - - XENBUS_UNPLUG(Request, - &Fdo->Unplug, - XENBUS_UNPLUG_DEVICE_TYPE_DISKS, - Make); - - XENBUS_UNPLUG(Release, &Fdo->Unplug); -} - -ULONG -FdoFindAdapter( - __in PXENVBD_FDO Fdo, - __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo - ) -{ - // setup config info - ConfigInfo->MaximumTransferLength = XENVBD_MAX_TRANSFER_LENGTH; - ConfigInfo->NumberOfPhysicalBreaks = XENVBD_MAX_PHYSICAL_BREAKS; - ConfigInfo->AlignmentMask = 0; // Byte-Aligned - ConfigInfo->NumberOfBuses = 1; - ConfigInfo->InitiatorBusId[0] = 1; - ConfigInfo->ScatterGather = TRUE; - ConfigInfo->Master = TRUE; - ConfigInfo->CachesData = FALSE; - ConfigInfo->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; - ConfigInfo->MaximumNumberOfTargets = XENVBD_MAX_TARGETS; - ConfigInfo->MaximumNumberOfLogicalUnits = 1; - ConfigInfo->WmiDataProvider = FALSE; // should be TRUE - ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; - - if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) { - Trace("64bit DMA\n"); - ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED; - } - - // gets called on resume from hibernate, so only setup if not already done - if (Fdo->Signature == FDO_SIGNATURE) { - Verbose("FDO already initalized (0x%p)\n", Fdo); - return SP_RETURN_FOUND; - } - - // We need to do this to avoid an assertion in a checked kernel - (VOID) StorPortGetUncachedExtension(Fdo, ConfigInfo, PAGE_SIZE); - - if (!NT_SUCCESS(__FdoInitialize(Fdo))) - return SP_RETURN_ERROR; - - FdoUnplugRequest(Fdo, TRUE); - - if (!NT_SUCCESS(FdoD3ToD0(Fdo))) - return SP_RETURN_ERROR; - - return SP_RETURN_FOUND; -} - -static FORCEINLINE VOID -__FdoSrbPnp( - __in PXENVBD_FDO Fdo, - __in PSCSI_PNP_REQUEST_BLOCK Srb - ) -{ - if (!(Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)) { - PXENVBD_PDO Pdo; - - Pdo = __FdoGetPdo(Fdo, Srb->TargetId); - if (Pdo) { - PdoSrbPnp(Pdo, Srb); - PdoDereference(Pdo); - } - } -} - -BOOLEAN -FdoBuildIo( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ) -{ - InitSrbExt(Srb); - - switch (Srb->Function) { - case SRB_FUNCTION_EXECUTE_SCSI: - case SRB_FUNCTION_RESET_DEVICE: - case SRB_FUNCTION_FLUSH: - case SRB_FUNCTION_SHUTDOWN: - FdoStartSrb(Fdo, Srb); - return TRUE; - - // dont pass to StartIo - case SRB_FUNCTION_PNP: - __FdoSrbPnp(Fdo, (PSCSI_PNP_REQUEST_BLOCK)Srb); - Srb->SrbStatus = SRB_STATUS_SUCCESS; - break; - case SRB_FUNCTION_ABORT_COMMAND: - Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; - break; - case SRB_FUNCTION_RESET_BUS: - Srb->SrbStatus = SRB_STATUS_SUCCESS; - FdoResetBus(Fdo); - break; - - default: - break; - } - - StorPortNotification(RequestComplete, Fdo, Srb); - return FALSE; -} - -BOOLEAN -FdoStartIo( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ) -{ - PXENVBD_PDO Pdo; - BOOLEAN CompleteSrb = TRUE; - - Pdo = __FdoGetPdo(Fdo, Srb->TargetId); - if (Pdo) { - CompleteSrb = PdoStartIo(Pdo, Srb); - PdoDereference(Pdo); - } - - if (CompleteSrb) { - FdoCompleteSrb(Fdo, Srb); - } - return TRUE; -} - -static PXENVBD_PDO -FdoGetPdoFromDeviceObject( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject - ) -{ - ULONG TargetId; - - ASSERT3P(DeviceObject, !=, NULL); - - for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) { - PXENVBD_PDO Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo) { - if (PdoGetDeviceObject(Pdo) == DeviceObject) - return Pdo; - PdoDereference(Pdo); - } - } - - return NULL; -} - -static PXENVBD_PDO -FdoMapDeviceObjectToPdo( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject - ) -{ - PXENVBD_PDO Pdo; - KEVENT Complete; - PIRP Irp; - IO_STATUS_BLOCK StatusBlock; - PIO_STACK_LOCATION Stack; - NTSTATUS Status; - PWCHAR String; - ULONG TargetId; - DECLARE_UNICODE_STRING_SIZE(UniStr, 4); - - KeInitializeEvent(&Complete, NotificationEvent, FALSE); - - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, DeviceObject, NULL, 0, NULL, &Complete, &StatusBlock); - if (Irp == NULL) - goto fail1; - - Stack = IoGetNextIrpStackLocation(Irp); - Stack->MinorFunction = IRP_MN_QUERY_ID; - Stack->Parameters.QueryId.IdType = BusQueryInstanceID; - - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) { - (VOID) KeWaitForSingleObject(&Complete, Executive, KernelMode, FALSE, NULL); - Status = StatusBlock.Status; - } - if (!NT_SUCCESS(Status)) - goto fail2; - - String = (PWCHAR)StatusBlock.Information; - switch (wcslen(String)) { - case 3: - UniStr.Length = 1 * sizeof(WCHAR); - UniStr_buffer[0] = String[1]; - UniStr_buffer[1] = UNICODE_NULL; - break; - case 6: - UniStr.Length = 2 * sizeof(WCHAR); - UniStr_buffer[0] = String[2]; - UniStr_buffer[1] = String[3]; - UniStr_buffer[2] = UNICODE_NULL; - break; - default: - goto fail3; - } - - Status = RtlUnicodeStringToInteger(&UniStr, 16, &TargetId); - if (!NT_SUCCESS(Status)) - goto fail4; - - Pdo = __FdoGetPdo(Fdo, TargetId); - if (Pdo == NULL) - goto fail5; - - PdoSetDeviceObject(Pdo, DeviceObject); - ExFreePool(String); - - return Pdo; - -fail5: -fail4: -fail3: - ExFreePool(String); -fail2: -fail1: - return NULL; -} - -__checkReturn -NTSTATUS -FdoForwardPnp( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ) -{ - PIO_STACK_LOCATION Stack; - PXENVBD_PDO Pdo; - - ASSERT3P(DeviceObject, !=, Fdo->DeviceObject); - - Pdo = FdoGetPdoFromDeviceObject(Fdo, DeviceObject); - if (Pdo != NULL) { - FdoDereference(Fdo); - return PdoDispatchPnp(Pdo, DeviceObject, Irp); - } - - Stack = IoGetCurrentIrpStackLocation(Irp); - if (Stack->MinorFunction == IRP_MN_QUERY_ID && - Stack->Parameters.QueryId.IdType == BusQueryDeviceID) { - Pdo = FdoMapDeviceObjectToPdo(Fdo, DeviceObject); - if (Pdo != NULL) { - FdoDereference(Fdo); - return PdoDispatchPnp(Pdo, DeviceObject, Irp); - } - } - - FdoDereference(Fdo); - return DriverDispatchPnp(DeviceObject, Irp); -} - -__checkReturn -NTSTATUS -FdoDispatchPnp( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ) -{ - PIO_STACK_LOCATION Stack; - - ASSERT3P(DeviceObject, ==, Fdo->DeviceObject); - - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->MinorFunction) { - case IRP_MN_REMOVE_DEVICE: - Verbose("FDO:IRP_MN_REMOVE_DEVICE\n"); - FdoD0ToD3(Fdo); - FdoUnplugRequest(Fdo, FALSE); - // drop ref-count acquired in DriverGetFdo *before* destroying Fdo - FdoDereference(Fdo); - __FdoTerminate(Fdo); - break; - - case IRP_MN_QUERY_DEVICE_RELATIONS: - if (Stack->Parameters.QueryDeviceRelations.Type == BusRelations) { - KeClearEvent(&Fdo->ScanEvent); - ThreadWake(Fdo->ScanThread); - - Trace("waiting for scan thread\n"); - - (VOID) KeWaitForSingleObject(&Fdo->ScanEvent, - Executive, - KernelMode, - FALSE, - NULL); - } - FdoDereference(Fdo); - break; - - default: - FdoDereference(Fdo); - break; - } - - return DriverDispatchPnp(DeviceObject, Irp); -} - -__checkReturn -NTSTATUS -FdoDispatchPower( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ) -{ - PIO_STACK_LOCATION Stack; - POWER_STATE_TYPE PowerType; - NTSTATUS status; - - ASSERT3P(DeviceObject, ==, Fdo->DeviceObject); - - Stack = IoGetCurrentIrpStackLocation(Irp); - PowerType = Stack->Parameters.Power.Type; - - switch (PowerType) { - case DevicePowerState: - if (Fdo->DevicePowerThread == NULL) { - Verbose("DevicePower IRP before DevicePowerThread ready\n"); - FdoDereference(Fdo); - status = DriverDispatchPower(DeviceObject, Irp); - break; - } - - IoMarkIrpPending(Irp); - - ASSERT3P(Fdo->DevicePowerIrp, ==, NULL); - ASSERT3P(DeviceObject, ==, Fdo->DeviceObject); - - Fdo->DevicePowerIrp = Irp; - ThreadWake(Fdo->DevicePowerThread); - - status = STATUS_PENDING; - break; - - case SystemPowerState: - default: - FdoDereference(Fdo); - status = DriverDispatchPower(DeviceObject, Irp); - break; - } - - return status; -} - -PXENBUS_STORE_INTERFACE -FdoAcquireStore( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - status = XENBUS_STORE(Acquire, &Fdo->Store); - if (!NT_SUCCESS(status)) - return NULL; - - return &Fdo->Store; -} - -PXENBUS_EVTCHN_INTERFACE -FdoAcquireEvtchn( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - status = XENBUS_EVTCHN(Acquire, &Fdo->Evtchn); - if (!NT_SUCCESS(status)) - return NULL; - - return &Fdo->Evtchn; -} - -PXENBUS_GNTTAB_INTERFACE -FdoAcquireGnttab( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - status = XENBUS_GNTTAB(Acquire, &Fdo->Gnttab); - if (!NT_SUCCESS(status)) - return NULL; - - return &Fdo->Gnttab; -} - -PXENBUS_DEBUG_INTERFACE -FdoAcquireDebug( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - status = XENBUS_DEBUG(Acquire, &Fdo->Debug); - if (!NT_SUCCESS(status)) - return NULL; - - return &Fdo->Debug; -} - -PXENBUS_SUSPEND_INTERFACE -FdoAcquireSuspend( - __in PXENVBD_FDO Fdo - ) -{ - NTSTATUS status; - - status = XENBUS_SUSPEND(Acquire, &Fdo->Suspend); - if (!NT_SUCCESS(status)) - return NULL; - - return &Fdo->Suspend; -} diff --git a/src/xenvbd/fdo.h b/src/xenvbd/fdo.h deleted file mode 100644 index 96c66a5..0000000 --- a/src/xenvbd/fdo.h +++ /dev/null @@ -1,179 +0,0 @@ -/* 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 _XENVBD_FDO_H -#define _XENVBD_FDO_H - -typedef struct _XENVBD_FDO XENVBD_FDO, *PXENVBD_FDO; - -#include <ntddk.h> -#include <ntstrsafe.h> -#include <xenvbd-storport.h> -#include "pdo.h" -#include <store_interface.h> -#include <evtchn_interface.h> -#include <gnttab_interface.h> -#include <debug_interface.h> -#include <suspend_interface.h> -#include <unplug_interface.h> - -// Reference Counting -extern LONG -__FdoReference( - __in PXENVBD_FDO Fdo, - __in PCHAR Caller - ); - -#define FdoReference(_x_) __FdoReference(_x_, __FUNCTION__) - -extern LONG -__FdoDereference( - __in PXENVBD_FDO Fdo, - __in PCHAR Caller - ); - -#define FdoDereference(_x_) __FdoDereference(_x_, __FUNCTION__) - -// Link PDOs -extern BOOLEAN -FdoLinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo - ); - -extern BOOLEAN -FdoUnlinkPdo( - __in PXENVBD_FDO Fdo, - __in PXENVBD_PDO Pdo - ); -// Query Methods -__checkReturn -extern PDEVICE_OBJECT -FdoGetDeviceObject( - __in PXENVBD_FDO Fdo - ); - -extern ULONG -FdoSizeofXenvbdFdo( - ); - -extern PCHAR -FdoEnum( - __in PXENVBD_FDO Fdo - ); - -// SRB Methods -extern VOID -FdoStartSrb( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ); - -extern VOID -FdoCompleteSrb( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ); - -// StorPort Methods -extern BOOLEAN -FdoResetBus( - __in PXENVBD_FDO Fdo - ); - -extern ULONG -FdoFindAdapter( - __in PXENVBD_FDO Fdo, - __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo - ); - -extern BOOLEAN -FdoBuildIo( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ); - -extern BOOLEAN -FdoStartIo( - __in PXENVBD_FDO Fdo, - __in PSCSI_REQUEST_BLOCK Srb - ); - -__checkReturn -extern NTSTATUS -FdoForwardPnp( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ); - -__checkReturn -extern NTSTATUS -FdoDispatchPnp( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ); - -__checkReturn -extern NTSTATUS -FdoDispatchPower( - __in PXENVBD_FDO Fdo, - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ); - -extern PXENBUS_STORE_INTERFACE -FdoAcquireStore( - __in PXENVBD_FDO Fdo - ); - -extern PXENBUS_EVTCHN_INTERFACE -FdoAcquireEvtchn( - __in PXENVBD_FDO Fdo - ); - -extern PXENBUS_GNTTAB_INTERFACE -FdoAcquireGnttab( - __in PXENVBD_FDO Fdo - ); - -extern PXENBUS_DEBUG_INTERFACE -FdoAcquireDebug( - __in PXENVBD_FDO Fdo - ); - -extern PXENBUS_SUSPEND_INTERFACE -FdoAcquireSuspend( - __in PXENVBD_FDO Fdo - ); - -#endif // _XENVBD_FDO_H diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c index 83a0f5e..daf5338 100644 --- a/src/xenvbd/frontend.c +++ b/src/xenvbd/frontend.c @@ -32,7 +32,7 @@ #include "frontend.h" #include "registry.h" #include "driver.h" -#include "fdo.h" +#include "adapter.h" #include "pdoinquiry.h" #include "srbext.h" #include "debug.h" @@ -1442,13 +1442,13 @@ FrontendD3ToD0( KeAcquireSpinLock(&Frontend->StateLock, &Irql); // acquire interfaces - Frontend->Store = FdoAcquireStore(PdoGetFdo(Frontend->Pdo)); + Frontend->Store = AdapterAcquireStore(PdoGetAdapter(Frontend->Pdo)); Status = STATUS_UNSUCCESSFUL; if (Frontend->Store == NULL) goto fail1; - Frontend->Suspend = FdoAcquireSuspend(PdoGetFdo(Frontend->Pdo)); + Frontend->Suspend = AdapterAcquireSuspend(PdoGetAdapter(Frontend->Pdo)); Status = STATUS_UNSUCCESSFUL; if (Frontend->Suspend == NULL) @@ -1601,7 +1601,7 @@ FrontendCreate( Frontend->BackendId = DOMID_INVALID; Status = STATUS_INSUFFICIENT_RESOURCES; - Frontend->FrontendPath = DriverFormat("device/%s/%s", FdoEnum(PdoGetFdo(Pdo)), DeviceId); + Frontend->FrontendPath = DriverFormat("device/%s/%s", AdapterEnum(PdoGetAdapter(Pdo)), DeviceId); if (Frontend->FrontendPath == NULL) goto fail2; diff --git a/src/xenvbd/granter.c b/src/xenvbd/granter.c index e8c1161..f670304 100644 --- a/src/xenvbd/granter.c +++ b/src/xenvbd/granter.c @@ -31,7 +31,7 @@ #include "frontend.h" #include "pdo.h" -#include "fdo.h" +#include "adapter.h" #include "util.h" #include "debug.h" #include "thread.h" @@ -139,13 +139,13 @@ GranterConnect( IN USHORT BackendDomain ) { - PXENVBD_FDO Fdo = PdoGetFdo(FrontendGetPdo(Granter->Frontend)); + PXENVBD_ADAPTER Adapter = PdoGetAdapter(FrontendGetPdo(Granter->Frontend)); CHAR Name[MAXNAMELEN]; NTSTATUS status; ASSERT(Granter->Connected == FALSE); - Granter->GnttabInterface = FdoAcquireGnttab(Fdo); + Granter->GnttabInterface = AdapterAcquireGnttab(Adapter); status = STATUS_UNSUCCESSFUL; if (Granter->GnttabInterface == NULL) diff --git a/src/xenvbd/notifier.c b/src/xenvbd/notifier.c index b3d2a7c..3bff2f6 100644 --- a/src/xenvbd/notifier.c +++ b/src/xenvbd/notifier.c @@ -32,7 +32,7 @@ #include "notifier.h" #include "frontend.h" #include "pdo.h" -#include "fdo.h" +#include "adapter.h" #include "util.h" #include "debug.h" #include <evtchn_interface.h> @@ -162,18 +162,18 @@ NotifierConnect( IN USHORT BackendDomain ) { - PXENVBD_FDO Fdo = PdoGetFdo(FrontendGetPdo(Notifier->Frontend)); + PXENVBD_ADAPTER Adapter = PdoGetAdapter(FrontendGetPdo(Notifier->Frontend)); NTSTATUS status; ASSERT(Notifier->Connected == FALSE); - Notifier->StoreInterface = FdoAcquireStore(Fdo); + Notifier->StoreInterface = AdapterAcquireStore(Adapter); status = STATUS_UNSUCCESSFUL; if (Notifier->StoreInterface == NULL) goto fail1; - Notifier->EvtchnInterface = FdoAcquireEvtchn(Fdo); + Notifier->EvtchnInterface = AdapterAcquireEvtchn(Adapter); status = STATUS_UNSUCCESSFUL; if (Notifier->EvtchnInterface == NULL) diff --git a/src/xenvbd/pdo.c b/src/xenvbd/pdo.c index 3ce48cc..7da3176 100644 --- a/src/xenvbd/pdo.c +++ b/src/xenvbd/pdo.c @@ -31,7 +31,7 @@ #include "pdo.h" #include "driver.h" -#include "fdo.h" +#include "adapter.h" #include "frontend.h" #include "queue.h" #include "srbext.h" @@ -73,7 +73,7 @@ typedef struct _XENVBD_LOOKASIDE { struct _XENVBD_PDO { ULONG Signature; - PXENVBD_FDO Fdo; + PXENVBD_ADAPTER Adapter; PDEVICE_OBJECT DeviceObject; KEVENT RemoveEvent; LONG ReferenceCount; @@ -268,8 +268,8 @@ PdoDebugCallback( return; XENBUS_DEBUG(Printf, DebugInterface, - "PDO: Fdo 0x%p DeviceObject 0x%p\n", - Pdo->Fdo, + "PDO: Adapter 0x%p DeviceObject 0x%p\n", + Pdo->Adapter, Pdo->DeviceObject); XENBUS_DEBUG(Printf, DebugInterface, "PDO: ReferenceCount %d\n", @@ -537,12 +537,12 @@ PdoOutstandingReqs( } __checkReturn -FORCEINLINE PXENVBD_FDO -PdoGetFdo( +FORCEINLINE PXENVBD_ADAPTER +PdoGetAdapter( __in PXENVBD_PDO Pdo ) { - return Pdo->Fdo; + return Pdo->Adapter; } FORCEINLINE ULONG @@ -1177,7 +1177,7 @@ PrepareReadWrite( SrbExt->Count = 0; RtlZeroMemory(&SGList, sizeof(SGList)); - SGList.SGList = StorPortGetScatterGatherList(PdoGetFdo(Pdo), Srb); + SGList.SGList = StorPortGetScatterGatherList(PdoGetAdapter(Pdo), Srb); while (SectorsLeft > 0) { ULONG MaxSegments; @@ -1370,7 +1370,7 @@ __PdoPauseDataPath( Verbose("Target[%d] : FreshSrb 0x%p -> SCSI_ABORTED\n", PdoGetTargetId(Pdo), SrbExt->Srb); SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED; SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED; - FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb); + AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb); } // Fail PreparedReqs @@ -1390,7 +1390,7 @@ __PdoPauseDataPath( if (InterlockedDecrement(&SrbExt->Count) == 0) { SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED - FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb); + AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb); } } } @@ -1502,7 +1502,7 @@ PdoCompleteShutdown( break; SrbExt = CONTAINING_RECORD(Entry, XENVBD_SRBEXT, Entry); SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS; - FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb); + AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb); } } @@ -1599,7 +1599,7 @@ PdoCompleteResponse( Srb->ScsiStatus = 0x40; // SCSI_ABORTED } - FdoCompleteSrb(PdoGetFdo(Pdo), Srb); + AdapterCompleteSrb(PdoGetAdapter(Pdo), Srb); } } @@ -2092,7 +2092,7 @@ __PdoExecuteScsi( break; case SCSIOP_INQUIRY: - if (!StorPortSetDeviceQueueDepth(PdoGetFdo(Pdo), + if (!StorPortSetDeviceQueueDepth(PdoGetAdapter(Pdo), 0, (UCHAR)PdoGetTargetId(Pdo), 0, @@ -2255,7 +2255,7 @@ __PdoCleanupSubmittedReqs( if (InterlockedDecrement(&SrbExt->Count) == 0) { SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED; SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED - FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb); + AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb); } } } @@ -2403,13 +2403,13 @@ __PdoRemoveDevice( case SurpriseRemovePending: PdoSetMissing(Pdo, "Surprise Remove"); PdoSetDevicePnpState(Pdo, Deleted); - StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + StorPortNotification(BusChangeDetected, PdoGetAdapter(Pdo), 0); break; default: PdoSetMissing(Pdo, "Removed"); PdoSetDevicePnpState(Pdo, Deleted); - StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + StorPortNotification(BusChangeDetected, PdoGetAdapter(Pdo), 0); break; } } @@ -2421,7 +2421,7 @@ __PdoEject( { PdoSetMissing(Pdo, "Ejected"); PdoSetDevicePnpState(Pdo, Deleted); - StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + StorPortNotification(BusChangeDetected, PdoGetAdapter(Pdo), 0); } __checkReturn @@ -2516,7 +2516,7 @@ PdoIssueDeviceEject( IoRequestDeviceEject(Pdo->DeviceObject); } else { Verbose("Target[%d] : Triggering BusChangeDetected to detect device\n", PdoGetTargetId(Pdo)); - StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0); + StorPortNotification(BusChangeDetected, PdoGetAdapter(Pdo), 0); } } @@ -2588,7 +2588,7 @@ PdoD0ToD3( __checkReturn BOOLEAN PdoCreate( - __in PXENVBD_FDO Fdo, + __in PXENVBD_ADAPTER Adapter, __in __nullterminated PCHAR DeviceId, __in ULONG TargetId, __in XENVBD_DEVICE_TYPE DeviceType @@ -2607,7 +2607,7 @@ PdoCreate( Verbose("Target[%d] : Creating\n", TargetId); Pdo->Signature = PDO_SIGNATURE; - Pdo->Fdo = Fdo; + Pdo->Adapter = Adapter; Pdo->DeviceObject = NULL; // filled in later KeInitializeEvent(&Pdo->RemoveEvent, SynchronizationEvent, FALSE); Pdo->ReferenceCount = 1; @@ -2633,7 +2633,7 @@ PdoCreate( if (!NT_SUCCESS(Status)) goto fail3; - if (!FdoLinkPdo(Fdo, Pdo)) + if (!AdapterLinkPdo(Adapter, Pdo)) goto fail4; Verbose("Target[%d] : Created (%s)\n", TargetId, Pdo); @@ -2674,8 +2674,8 @@ PdoDestroy( Verbose("Target[%d] : Destroying\n", TargetId); ASSERT3U(Pdo->Signature, ==, PDO_SIGNATURE); - if (!FdoUnlinkPdo(PdoGetFdo(Pdo), Pdo)) { - Error("Target[%d] : PDO 0x%p not linked to FDO 0x%p\n", TargetId, Pdo, PdoGetFdo(Pdo)); + if (!AdapterUnlinkPdo(PdoGetAdapter(Pdo), Pdo)) { + Error("Target[%d] : PDO 0x%p not linked to ADAPTER 0x%p\n", TargetId, Pdo, PdoGetAdapter(Pdo)); } PdoD0ToD3(Pdo); diff --git a/src/xenvbd/pdo.h b/src/xenvbd/pdo.h index 6e3eca5..82ac825 100644 --- a/src/xenvbd/pdo.h +++ b/src/xenvbd/pdo.h @@ -37,7 +37,7 @@ typedef struct _XENVBD_PDO XENVBD_PDO, *PXENVBD_PDO; #include <ntddk.h> #include <ntstrsafe.h> #include <xenvbd-storport.h> -#include "fdo.h" +#include "adapter.h" #include "srbext.h" #include "types.h" #include <debug_interface.h> @@ -52,7 +52,7 @@ PdoDebugCallback( __checkReturn extern BOOLEAN PdoCreate( - __in PXENVBD_FDO Fdo, + __in PXENVBD_ADAPTER Adapter, __in __nullterminated PCHAR DeviceId, __in ULONG TargetId, __in XENVBD_DEVICE_TYPE DeviceType @@ -158,8 +158,8 @@ PdoOutstandingReqs( ); __checkReturn -extern PXENVBD_FDO -PdoGetFdo( +extern PXENVBD_ADAPTER +PdoGetAdapter( __in PXENVBD_PDO Pdo ); diff --git a/vs2012/xenvbd/xenvbd.vcxproj b/vs2012/xenvbd/xenvbd.vcxproj index 78395f9..6a10b6a 100644 --- a/vs2012/xenvbd/xenvbd.vcxproj +++ b/vs2012/xenvbd/xenvbd.vcxproj @@ -75,7 +75,7 @@ <ClCompile Include="../../src/xenvbd/buffer.c" /> <ClCompile Include="../../src/xenvbd/driver.c" /> <ClCompile Include="../../src/xenvbd/registry.c" /> - <ClCompile Include="../../src/xenvbd/fdo.c" /> + <ClCompile Include="../../src/xenvbd/adapter.c" /> <ClCompile Include="../../src/xenvbd/frontend.c" /> <ClCompile Include="../../src/xenvbd/pdo.c" /> <ClCompile Include="../../src/xenvbd/pdoinquiry.c" /> diff --git a/vs2013/xenvbd/xenvbd.vcxproj b/vs2013/xenvbd/xenvbd.vcxproj index 453261a..f7ef464 100644 --- a/vs2013/xenvbd/xenvbd.vcxproj +++ b/vs2013/xenvbd/xenvbd.vcxproj @@ -103,7 +103,7 @@ <ClCompile Include="../../src/xenvbd/buffer.c" /> <ClCompile Include="../../src/xenvbd/driver.c" /> <ClCompile Include="../../src/xenvbd/registry.c" /> - <ClCompile Include="../../src/xenvbd/fdo.c" /> + <ClCompile Include="../../src/xenvbd/adapter.c" /> <ClCompile Include="../../src/xenvbd/frontend.c" /> <ClCompile Include="../../src/xenvbd/pdo.c" /> <ClCompile Include="../../src/xenvbd/pdoinquiry.c" /> diff --git a/vs2015/xenvbd/xenvbd.vcxproj b/vs2015/xenvbd/xenvbd.vcxproj index 18e753e..abd4b26 100644 --- a/vs2015/xenvbd/xenvbd.vcxproj +++ b/vs2015/xenvbd/xenvbd.vcxproj @@ -67,7 +67,7 @@ <ClCompile Include="../../src/xenvbd/buffer.c" /> <ClCompile Include="../../src/xenvbd/driver.c" /> <ClCompile Include="../../src/xenvbd/registry.c" /> - <ClCompile Include="../../src/xenvbd/fdo.c" /> + <ClCompile Include="../../src/xenvbd/adapter.c" /> <ClCompile Include="../../src/xenvbd/frontend.c" /> <ClCompile Include="../../src/xenvbd/pdo.c" /> <ClCompile Include="../../src/xenvbd/pdoinquiry.c" /> -- 2.8.3 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |