--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
#include "blockring.h"
#include "frontend.h"
#include "pdo.h"
-#include "fdo.h"
+#include "adapter.h"
#include "util.h"
#include "debug.h"
#include "srbext.h"
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)
*/
#include "driver.h"
-#include "fdo.h"
+#include "adapter.h"
#include "pdo.h"
#include "registry.h"
#include "srbext.h"
PDRIVER_DISPATCH StorPortDispatchPnp;
PDRIVER_DISPATCH StorPortDispatchPower;
PDRIVER_UNLOAD StorPortDriverUnload;
- PXENVBD_FDO Fdo;
+ PXENVBD_ADAPTER Adapter;
KSPIN_LOCK Lock;
} XENVBD_DRIVER;
}
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
{
UNREFERENCED_PARAMETER(PathId);
- return FdoResetBus((PXENVBD_FDO)HwDeviceExtension);
+ return AdapterResetBus((PXENVBD_ADAPTER)HwDeviceExtension);
}
HW_FIND_ADAPTER HwFindAdapter;
UNREFERENCED_PARAMETER(ArgumentString);
UNREFERENCED_PARAMETER(Again);
- return FdoFindAdapter((PXENVBD_FDO)HwDeviceExtension, ConfigInfo);
+ return AdapterFindAdapter((PXENVBD_ADAPTER)HwDeviceExtension, ConfigInfo);
}
static FORCEINLINE BOOLEAN
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;
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)
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);
}
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);
}
ServiceKey = NULL;
KeInitializeSpinLock(&Driver.Lock);
- Driver.Fdo = NULL;
+ Driver.Adapter = NULL;
BufferInitialize();
__DriverParseOption("XENVBD:SYNTH_INQ=",
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;
#ifndef _XENVBD_XENVBD_H
#define _XENVBD_XENVBD_H
-#include "fdo.h"
#include <xen.h>
// Global Constants
extern XENVBD_PARAMETERS DriverParameters;
+#include "adapter.h"
+
extern HANDLE
DriverGetParametersKey(
VOID
// 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
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-/* 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
#include "frontend.h"
#include "registry.h"
#include "driver.h"
-#include "fdo.h"
+#include "adapter.h"
#include "pdoinquiry.h"
#include "srbext.h"
#include "debug.h"
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)
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;
#include "frontend.h"
#include "pdo.h"
-#include "fdo.h"
+#include "adapter.h"
#include "util.h"
#include "debug.h"
#include "thread.h"
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)
#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>
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)
#include "pdo.h"
#include "driver.h"
-#include "fdo.h"
+#include "adapter.h"
#include "frontend.h"
#include "queue.h"
#include "srbext.h"
struct _XENVBD_PDO {
ULONG Signature;
- PXENVBD_FDO Fdo;
+ PXENVBD_ADAPTER Adapter;
PDEVICE_OBJECT DeviceObject;
KEVENT RemoveEvent;
LONG ReferenceCount;
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",
}
__checkReturn
-FORCEINLINE PXENVBD_FDO
-PdoGetFdo(
+FORCEINLINE PXENVBD_ADAPTER
+PdoGetAdapter(
__in PXENVBD_PDO Pdo
)
{
- return Pdo->Fdo;
+ return Pdo->Adapter;
}
FORCEINLINE ULONG
SrbExt->Count = 0;
RtlZeroMemory(&SGList, sizeof(SGList));
- SGList.SGList = StorPortGetScatterGatherList(PdoGetFdo(Pdo), Srb);
+ SGList.SGList = StorPortGetScatterGatherList(PdoGetAdapter(Pdo), Srb);
while (SectorsLeft > 0) {
ULONG MaxSegments;
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
if (InterlockedDecrement(&SrbExt->Count) == 0) {
SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED
- FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb);
+ AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb);
}
}
}
break;
SrbExt = CONTAINING_RECORD(Entry, XENVBD_SRBEXT, Entry);
SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
- FdoCompleteSrb(PdoGetFdo(Pdo), SrbExt->Srb);
+ AdapterCompleteSrb(PdoGetAdapter(Pdo), SrbExt->Srb);
}
}
Srb->ScsiStatus = 0x40; // SCSI_ABORTED
}
- FdoCompleteSrb(PdoGetFdo(Pdo), Srb);
+ AdapterCompleteSrb(PdoGetAdapter(Pdo), Srb);
}
}
break;
case SCSIOP_INQUIRY:
- if (!StorPortSetDeviceQueueDepth(PdoGetFdo(Pdo),
+ if (!StorPortSetDeviceQueueDepth(PdoGetAdapter(Pdo),
0,
(UCHAR)PdoGetTargetId(Pdo),
0,
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);
}
}
}
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;
}
}
{
PdoSetMissing(Pdo, "Ejected");
PdoSetDevicePnpState(Pdo, Deleted);
- StorPortNotification(BusChangeDetected, PdoGetFdo(Pdo), 0);
+ StorPortNotification(BusChangeDetected, PdoGetAdapter(Pdo), 0);
}
__checkReturn
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);
}
}
__checkReturn
BOOLEAN
PdoCreate(
- __in PXENVBD_FDO Fdo,
+ __in PXENVBD_ADAPTER Adapter,
__in __nullterminated PCHAR DeviceId,
__in ULONG TargetId,
__in XENVBD_DEVICE_TYPE DeviceType
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;
if (!NT_SUCCESS(Status))
goto fail3;
- if (!FdoLinkPdo(Fdo, Pdo))
+ if (!AdapterLinkPdo(Adapter, Pdo))
goto fail4;
Verbose("Target[%d] : Created (%s)\n", TargetId, Pdo);
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);
#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>
__checkReturn
extern BOOLEAN
PdoCreate(
- __in PXENVBD_FDO Fdo,
+ __in PXENVBD_ADAPTER Adapter,
__in __nullterminated PCHAR DeviceId,
__in ULONG TargetId,
__in XENVBD_DEVICE_TYPE DeviceType
);
__checkReturn
-extern PXENVBD_FDO
-PdoGetFdo(
+extern PXENVBD_ADAPTER
+PdoGetAdapter(
__in PXENVBD_PDO Pdo
);
<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" />