[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 01/26] Rename Fdo -> Adapter Remove Adapter reference counts



From: Owen Smith <owen.smith@xxxxxxxxxx>

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/adapter.c         | 2147 ++++++++++++++++++++++++++++++++++++++++
 src/xenvbd/adapter.h         |  162 ++++
 src/xenvbd/blockring.c       |    6 +-
 src/xenvbd/driver.c          |   66 +-
 src/xenvbd/driver.h          |   11 +-
 src/xenvbd/fdo.c             | 2206 ------------------------------------------
 src/xenvbd/fdo.h             |  179 ----
 src/xenvbd/frontend.c        |    8 +-
 src/xenvbd/granter.c         |    6 +-
 src/xenvbd/notifier.c        |    8 +-
 src/xenvbd/pdo.c             |   46 +-
 src/xenvbd/pdo.h             |    8 +-
 vs2012/xenvbd/xenvbd.vcxproj |    2 +-
 vs2013/xenvbd/xenvbd.vcxproj |    2 +-
 vs2015/xenvbd/xenvbd.vcxproj |    2 +-
 15 files changed, 2390 insertions(+), 2469 deletions(-)
 create mode 100644 src/xenvbd/adapter.c
 create mode 100644 src/xenvbd/adapter.h
 delete mode 100644 src/xenvbd/fdo.c
 delete mode 100644 src/xenvbd/fdo.h

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


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.