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

[win-pv-devel] [PATCH 06/26] Refactor target.c



From: Owen Smith <owen.smith@xxxxxxxxxx>

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenvbd/adapter.c         |   52 +-
 src/xenvbd/blockring.c       |  783 +++++---
 src/xenvbd/blockring.h       |   46 +-
 src/xenvbd/frontend.c        | 1769 -----------------
 src/xenvbd/frontend.h        |  198 --
 src/xenvbd/granter.c         |  167 +-
 src/xenvbd/granter.h         |   48 +-
 src/xenvbd/notifier.c        |  334 ----
 src/xenvbd/notifier.h        |  101 -
 src/xenvbd/pdoinquiry.c      |  530 -----
 src/xenvbd/pdoinquiry.h      |   64 -
 src/xenvbd/queue.c           |  139 --
 src/xenvbd/queue.h           |   86 -
 src/xenvbd/srbext.h          |   53 +-
 src/xenvbd/target.c          | 4370 +++++++++++++++++++++++-------------------
 src/xenvbd/target.h          |  188 +-
 vs2012/xenvbd/xenvbd.vcxproj |    4 -
 vs2013/xenvbd/xenvbd.vcxproj |    4 -
 vs2015/xenvbd/xenvbd.vcxproj |    4 -
 19 files changed, 3164 insertions(+), 5776 deletions(-)
 delete mode 100644 src/xenvbd/frontend.c
 delete mode 100644 src/xenvbd/frontend.h
 delete mode 100644 src/xenvbd/notifier.c
 delete mode 100644 src/xenvbd/notifier.h
 delete mode 100644 src/xenvbd/pdoinquiry.c
 delete mode 100644 src/xenvbd/pdoinquiry.h
 delete mode 100644 src/xenvbd/queue.c
 delete mode 100644 src/xenvbd/queue.h

diff --git a/src/xenvbd/adapter.c b/src/xenvbd/adapter.c
index 3c5229b..4ce9711 100644
--- a/src/xenvbd/adapter.c
+++ b/src/xenvbd/adapter.c
@@ -111,7 +111,8 @@ __AdapterFree(
     IN  PVOID   Buffer
     )
 {
-    ExFreePoolWithTag(Buffer, ADAPTER_POOL_TAG);
+    if (Buffer)
+        ExFreePoolWithTag(Buffer, ADAPTER_POOL_TAG);
 }
 
 static FORCEINLINE PANSI_STRING
@@ -449,7 +450,7 @@ __AdapterEnumerate(
             }
         }
 
-        if (Missing && !TargetIsMissing(Target)) {
+        if (Missing && !TargetGetMissing(Target)) {
             TargetSetMissing(Target, "Device Disappeared");
             if (TargetGetDevicePnpState(Target) == Present)
                 TargetSetDevicePnpState(Target, Deleted);
@@ -480,7 +481,7 @@ __AdapterEnumerate(
             continue;
 
         status = TargetCreate(Adapter,
-                              Device->Buffer,
+                              Device,
                               &Target);
         if (status == STATUS_RETRY)
             NeedReboot = TRUE;
@@ -881,7 +882,6 @@ AdapterDebugCallback(
     )
 {
     PXENVBD_ADAPTER Adapter = Context;
-    ULONG           TargetId;
 
     XENBUS_DEBUG(Printf, 
                  &Adapter->DebugInterface,
@@ -911,24 +911,6 @@ AdapterDebugCallback(
                  Adapter->Completed);
 
     BufferDebugCallback(&Adapter->DebugInterface);
-    
-    for (TargetId = 0; TargetId < XENVBD_MAX_TARGETS; ++TargetId) {
-        // no need to use AdapterGetTarget (which is locked at DISPATCH) as 
called at HIGH_LEVEL
-        PXENVBD_TARGET Target = Adapter->TargetList[TargetId];
-        if (Target == NULL)
-            continue;
-
-        XENBUS_DEBUG(Printf, &Adapter->DebugInterface,
-                     "ADAPTER: ====> Target[%-3d]    : 0x%p\n",                
  
-                     TargetId, Target);
-
-        // call Target's debug callback directly
-        TargetDebugCallback(Target, &Adapter->DebugInterface);
-
-        XENBUS_DEBUG(Printf, &Adapter->DebugInterface,
-                     "ADAPTER: <==== Target[%-3d]    : 0x%p\n",                
  
-                     TargetId, Target);
-    }
 }
 
 static NTSTATUS
@@ -1476,13 +1458,27 @@ __AdapterSrbPnp(
     IN  PSCSI_PNP_REQUEST_BLOCK Srb
     )
 {
-    if (!(Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)) {
-        PXENVBD_TARGET          Target;
+    PXENVBD_TARGET              Target;
 
-        Target = AdapterGetTarget(Adapter, Srb->TargetId);
-        if (Target) {
-            TargetSrbPnp(Target, Srb);
-        }
+    if (Srb->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST)
+        return;
+
+    Target = AdapterGetTarget(Adapter, Srb->TargetId);
+    if (Target == NULL)
+        return;
+
+    switch (Srb->PnPAction) {
+    case StorQueryCapabilities: {
+        PSTOR_DEVICE_CAPABILITIES DeviceCaps = Srb->DataBuffer;
+
+        DeviceCaps->Removable       = TargetGetRemovable(Target);
+        DeviceCaps->EjectSupported  = TargetGetRemovable(Target);
+        DeviceCaps->SurpriseRemovalOK = TargetGetRemovable(Target);
+        DeviceCaps->UniqueID = 1;
+
+        } break;
+    default:
+        break;
     }
 }
 
diff --git a/src/xenvbd/blockring.c b/src/xenvbd/blockring.c
index bcef877..dac03b5 100644
--- a/src/xenvbd/blockring.c
+++ b/src/xenvbd/blockring.c
@@ -29,227 +29,218 @@
  * SUCH DAMAGE.
  */ 
 
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+
+#include <xen.h>
+#include <gnttab_interface.h>
+#include <debug_interface.h>
+#include <evtchn_interface.h>
+
 #include "blockring.h"
-#include "frontend.h"
 #include "target.h"
 #include "adapter.h"
+#include "granter.h"
+#include "adapter.h"
+
 #include "util.h"
 #include "debug.h"
-#include "srbext.h"
-#include "driver.h"
-#include <stdlib.h>
-#include <xenvbd-ntstrsafe.h>
+#include "assert.h"
 
-#define TAG_HEADER                  'gaTX'
+#define XEN_IO_PROTO_ABI            "x86_64-abi"
 #define XENVBD_MAX_RING_PAGE_ORDER  (4)
 #define XENVBD_MAX_RING_PAGES       (1 << XENVBD_MAX_RING_PAGE_ORDER)
 
 struct _XENVBD_BLOCKRING {
-    PXENVBD_FRONTEND                Frontend;
-    BOOLEAN                         Connected;
-    BOOLEAN                         Enabled;
-
-    XENBUS_STORE_INTERFACE          StoreInterface;
-
-    KSPIN_LOCK                      Lock;
-    PMDL                            Mdl;
-    blkif_sring_t*                  SharedRing;
-    blkif_front_ring_t              FrontRing;
-    ULONG                           DeviceId;
-    ULONG                           Order;
-    PVOID                           Grants[XENVBD_MAX_RING_PAGES];
-    ULONG                           Submitted;
-    ULONG                           Received;
+    PXENVBD_TARGET          Target;
+    BOOLEAN                 Connected;
+    BOOLEAN                 Enabled;
+
+    XENBUS_STORE_INTERFACE  StoreInterface;
+    XENBUS_DEBUG_INTERFACE  DebugInterface;
+    XENBUS_EVTCHN_INTERFACE EvtchnInterface;
+
+    PXENBUS_DEBUG_CALLBACK  DebugCallback;
+
+    KSPIN_LOCK              Lock;
+    PMDL                    Mdl;
+    blkif_sring_t*          Shared;
+    blkif_front_ring_t      Front;
+    ULONG                   Order;
+    PVOID                   Grants[XENVBD_MAX_RING_PAGES];
+
+    PXENBUS_EVTCHN_CHANNEL  Channel;
+    KDPC                    Dpc;
+
+    ULONG                   Submitted;
+    ULONG                   Completed;
+    ULONG                   Interrupts;
+    ULONG                   Dpcs;
 };
 
-#define MAX_NAME_LEN                64
-#define BLOCKRING_POOL_TAG          'gnRX'
-
-#define XEN_IO_PROTO_ABI    "x86_64-abi"
+#define BLOCKRING_POOL_TAG  'gnRX'
+#define xen_mb              KeMemoryBarrier
+#define xen_wmb             KeMemoryBarrier
+#define xen_rmb             KeMemoryBarrier
 
 static FORCEINLINE PVOID
 __BlockRingAllocate(
-    IN  ULONG                       Length
+    IN  ULONG   Size
     )
 {
-    return __AllocatePoolWithTag(NonPagedPool, Length, BLOCKRING_POOL_TAG);
+    PVOID       Buffer;
+    Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                   Size,
+                                   BLOCKRING_POOL_TAG);
+    if (Buffer)
+        RtlZeroMemory(Buffer, Size);
+    return Buffer;
 }
 
 static FORCEINLINE VOID
 __BlockRingFree(
-    IN  PVOID                       Buffer
+    IN  PVOID   Buffer
     )
 {
     if (Buffer)
-        __FreePoolWithTag(Buffer, BLOCKRING_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-xen_mb()
-{
-    KeMemoryBarrier();
-    _ReadWriteBarrier();
+        ExFreePoolWithTag(Buffer, BLOCKRING_POOL_TAG);
 }
 
-static FORCEINLINE VOID
-xen_wmb()
-{
-    KeMemoryBarrier();
-    _WriteBarrier();
-}
+KSERVICE_ROUTINE BlockRingInterrupt;
 
-static FORCEINLINE PFN_NUMBER
-__Pfn(
-    __in  PVOID                   VirtAddr
+BOOLEAN
+BlockRingInterrupt(
+    __in  PKINTERRUPT   Interrupt,
+    _In_opt_ PVOID      Context
     )
 {
-    return (PFN_NUMBER)(ULONG_PTR)(MmGetPhysicalAddress(VirtAddr).QuadPart >> 
PAGE_SHIFT);
-}
+    PXENVBD_BLOCKRING   BlockRing = Context;
+    
+    UNREFERENCED_PARAMETER(Interrupt);
 
-static FORCEINLINE ULONG64
-__BlockRingGetTag(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENVBD_REQUEST             Request
-    )
-{
-    UNREFERENCED_PARAMETER(BlockRing);
-    return ((ULONG64)TAG_HEADER << 32) | (ULONG64)Request->Id;
+    ASSERT(BlockRing != NULL);
+
+       ++BlockRing->Interrupts;
+       if (KeInsertQueueDpc(&BlockRing->Dpc, NULL, NULL))
+               ++BlockRing->Dpcs;
+
+    return TRUE;
 }
 
-static FORCEINLINE BOOLEAN
-__BlockRingPutTag(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  ULONG64                     Id,
-    OUT PULONG                      Tag
+KDEFERRED_ROUTINE BlockRingDpc;
+
+VOID 
+BlockRingDpc(
+    __in  PKDPC         Dpc,
+    __in_opt PVOID      Context,
+    __in_opt PVOID      Arg1,
+    __in_opt PVOID      Arg2
     )
 {
-    ULONG   Header = (ULONG)((Id >> 32) & 0xFFFFFFFF);
+    PXENVBD_BLOCKRING   BlockRing = Context;
 
-    UNREFERENCED_PARAMETER(BlockRing);
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Arg1);
+    UNREFERENCED_PARAMETER(Arg2);
 
-    *Tag    = (ULONG)(Id & 0xFFFFFFFF);
-    if (Header != TAG_HEADER) {
-        Error("PUT_TAG (%llx) TAG_HEADER (%08x%08x)\n", Id, Header, *Tag);
-        return FALSE;
-    }
+    ASSERT(BlockRing != NULL);
 
-    return TRUE;
+    (VOID) BlockRingPoll(BlockRing);
+
+    XENBUS_EVTCHN(Unmask,
+                  &BlockRing->EvtchnInterface,
+                  BlockRing->Channel,
+                  FALSE);
 }
 
-static FORCEINLINE VOID
-__BlockRingInsert(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENVBD_REQUEST             Request,
-    IN  blkif_request_t*            req
+static DECLSPEC_NOINLINE VOID
+BlockRingDebugCallback(
+    IN  PVOID           Context,
+    IN  BOOLEAN         Crashing
     )
 {
-    PXENVBD_GRANTER                 Granter = 
FrontendGetGranter(BlockRing->Frontend);
+    PXENVBD_BLOCKRING   BlockRing = Context;
+    PXENVBD_GRANTER     Granter;
+    ULONG               Port;
+    ULONG               Grant;
+    ULONG               Index;
 
-    switch (Request->Operation) {
-    case BLKIF_OP_READ:
-    case BLKIF_OP_WRITE:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-            // Indirect
-            ULONG                       PageIdx;
-            ULONG                       SegIdx;
-            PLIST_ENTRY                 PageEntry;
-            PLIST_ENTRY                 SegEntry;
-            blkif_request_indirect_t*   req_indirect;
-
-            req_indirect = (blkif_request_indirect_t*)req;
-            req_indirect->operation         = BLKIF_OP_INDIRECT;
-            req_indirect->indirect_op       = Request->Operation;
-            req_indirect->nr_segments       = Request->NrSegments;
-            req_indirect->id                = __BlockRingGetTag(BlockRing, 
Request);
-            req_indirect->sector_number     = Request->FirstSector;
-            req_indirect->handle            = (USHORT)BlockRing->DeviceId;
-
-            for (PageIdx = 0,
-                 PageEntry = Request->Indirects.Flink,
-                 SegEntry = Request->Segments.Flink;
-                    PageIdx < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
-                    PageEntry != &Request->Indirects &&
-                    SegEntry != &Request->Segments;
-                        ++PageIdx, PageEntry = PageEntry->Flink) {
-                PXENVBD_INDIRECT Page = CONTAINING_RECORD(PageEntry, 
XENVBD_INDIRECT, Entry);
-
-                req_indirect->indirect_grefs[PageIdx] = 
GranterReference(Granter, Page->Grant);
-
-                for (SegIdx = 0;
-                        SegIdx < XENVBD_MAX_SEGMENTS_PER_PAGE &&
-                        SegEntry != &Request->Segments;
-                            ++SegIdx, SegEntry = SegEntry->Flink) {
-                    PXENVBD_SEGMENT Segment = CONTAINING_RECORD(SegEntry, 
XENVBD_SEGMENT, Entry);
+    UNREFERENCED_PARAMETER(Crashing);
 
-                    Page->Page[SegIdx].GrantRef = GranterReference(Granter, 
Segment->Grant);
-                    Page->Page[SegIdx].First    = Segment->FirstSector;
-                    Page->Page[SegIdx].Last     = Segment->LastSector;
-                }
-            }
-        } else {
-            // Direct
-            ULONG           Index;
-            PLIST_ENTRY     Entry;
-
-            req->operation                  = Request->Operation;
-            req->nr_segments                = (UCHAR)Request->NrSegments;
-            req->handle                     = (USHORT)BlockRing->DeviceId;
-            req->id                         = __BlockRingGetTag(BlockRing, 
Request);
-            req->sector_number              = Request->FirstSector;
-
-            for (Index = 0, Entry = Request->Segments.Flink;
-                    Index < BLKIF_MAX_SEGMENTS_PER_REQUEST &&
-                    Entry != &Request->Segments;
-                        ++Index, Entry = Entry->Flink) {
-                PXENVBD_SEGMENT Segment = CONTAINING_RECORD(Entry, 
XENVBD_SEGMENT, Entry);
-                req->seg[Index].gref        = GranterReference(Granter, 
Segment->Grant);
-                req->seg[Index].first_sect  = Segment->FirstSector;
-                req->seg[Index].last_sect   = Segment->LastSector;
-            }
-        }
-        break;
-
-    case BLKIF_OP_WRITE_BARRIER:
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        req->operation                  = Request->Operation;
-        req->nr_segments                = 0;
-        req->handle                     = (USHORT)BlockRing->DeviceId;
-        req->id                         = __BlockRingGetTag(BlockRing, 
Request);
-        req->sector_number              = Request->FirstSector;
-        break;
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Order: %u\n",
+                 BlockRing->Order);
 
-    case BLKIF_OP_DISCARD: {
-        blkif_request_discard_t*        req_discard;
-        req_discard = (blkif_request_discard_t*)req;
-        req_discard->operation          = BLKIF_OP_DISCARD;
-        req_discard->flag               = Request->Flags;
-        req_discard->handle             = (USHORT)BlockRing->DeviceId;
-        req_discard->id                 = __BlockRingGetTag(BlockRing, 
Request);
-        req_discard->sector_number      = Request->FirstSector;
-        req_discard->nr_sectors         = Request->NrSectors;
-        } break;
+    Granter = TargetGetGranter(BlockRing->Target);
+    for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+        Grant = GranterReference(Granter, BlockRing->Grants[Index]);
 
-    default:
-        ASSERT(FALSE);
-        break;
+        XENBUS_DEBUG(Printf,
+                     &BlockRing->DebugInterface,
+                     "Grant[%02u] : 0x%p (%u)\n",
+                     Index,
+                     BlockRing->Grants[Index],
+                     Grant);
     }
-    ++BlockRing->Submitted;
+
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Shared:0x%p : req_prod:%u, req_event:%u, rsp_prod:%u, 
rsp_event:%u\n",
+                 BlockRing->Shared,
+                 BlockRing->Shared->req_prod,
+                 BlockRing->Shared->req_event,
+                 BlockRing->Shared->rsp_prod,
+                 BlockRing->Shared->rsp_event);
+
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Front: req_prod_pvt:%u, rsp_cons:%u, nr_ents:%u, 
sring:0x%p\n",
+                 BlockRing->Front.req_prod_pvt,
+                 BlockRing->Front.rsp_cons,
+                 BlockRing->Front.nr_ents,
+                 BlockRing->Front.sring);
+
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Submitted: %u, Completed: %u\n",
+                 BlockRing->Submitted,
+                 BlockRing->Completed);
+
+    Port = XENBUS_EVTCHN(GetPort,
+                         &BlockRing->EvtchnInterface,
+                         BlockRing->Channel);
+
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Channel: 0x%p (%u)\n",
+                 BlockRing->Channel,
+                 Port);
+
+    XENBUS_DEBUG(Printf,
+                 &BlockRing->DebugInterface,
+                 "Interrupts: %u, DPCs: %u\n",
+                 BlockRing->Interrupts,
+                 BlockRing->Dpcs);
+
+    BlockRing->Interrupts = 0;
+    BlockRing->Dpcs = 0;
 }
 
 NTSTATUS
 BlockRingCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    IN  ULONG                       DeviceId,
-    OUT PXENVBD_BLOCKRING*          BlockRing
+    IN  PXENVBD_TARGET      Target,
+    OUT PXENVBD_BLOCKRING*  BlockRing
     )
 {
     *BlockRing = __BlockRingAllocate(sizeof(XENVBD_BLOCKRING));
     if (*BlockRing == NULL)
         goto fail1;
 
-    (*BlockRing)->Frontend = Frontend;
-    (*BlockRing)->DeviceId = DeviceId;
+    (*BlockRing)->Target = Target;
     KeInitializeSpinLock(&(*BlockRing)->Lock);
+    KeInitializeDpc(&(*BlockRing)->Dpc, BlockRingDpc, *BlockRing);
 
     return STATUS_SUCCESS;
 
@@ -259,12 +250,12 @@ fail1:
 
 VOID
 BlockRingDestroy(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
-    BlockRing->Frontend = NULL;
-    BlockRing->DeviceId = 0;
+    BlockRing->Target = NULL;
     RtlZeroMemory(&BlockRing->Lock, sizeof(KSPIN_LOCK));
+    RtlZeroMemory(&BlockRing->Dpc, sizeof(KDPC));
     
     ASSERT(IsZeroMemory(BlockRing, sizeof(XENVBD_BLOCKRING)));
     
@@ -273,122 +264,201 @@ BlockRingDestroy(
 
 NTSTATUS
 BlockRingConnect(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
-    NTSTATUS        status;
-    PCHAR           Value;
-    ULONG           Index, RingPages;
-    PXENVBD_ADAPTER     Adapter = 
TargetGetAdapter(FrontendGetTarget(BlockRing->Frontend));
-    PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend);
+    PXENVBD_GRANTER         Granter;
+    PXENVBD_ADAPTER         Adapter;
+    PCHAR                   Buffer;
+    ULONG                   Index;
+    NTSTATUS                status;
 
     ASSERT(BlockRing->Connected == FALSE);
 
+    Adapter = TargetGetAdapter(BlockRing->Target);
+
     AdapterGetStoreInterface(Adapter, &BlockRing->StoreInterface);
-   
+    AdapterGetDebugInterface(Adapter, &BlockRing->DebugInterface);
+    AdapterGetEvtchnInterface(Adapter, &BlockRing->EvtchnInterface);
+
     status = XENBUS_STORE(Acquire, &BlockRing->StoreInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = FrontendStoreReadBackend(BlockRing->Frontend, 
"max-ring-page-order", &Value);
+    status = XENBUS_DEBUG(Acquire, &BlockRing->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = XENBUS_EVTCHN(Acquire, &BlockRing->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_STORE(Read,
+                          &BlockRing->StoreInterface,
+                          NULL,
+                          TargetGetBackendPath(BlockRing->Target),
+                          "max-ring-page-order",
+                          &Buffer);
     if (NT_SUCCESS(status)) {
-        BlockRing->Order = __min(strtoul(Value, NULL, 10), 
XENVBD_MAX_RING_PAGE_ORDER);
-        FrontendStoreFree(BlockRing->Frontend, Value);
+        BlockRing->Order = strtoul(Buffer, NULL, 10);
+        BlockRing->Order = min(BlockRing->Order, XENVBD_MAX_RING_PAGE_ORDER);
+
+        XENBUS_STORE(Free,
+                     &BlockRing->StoreInterface, 
+                     Buffer);
     } else {
         BlockRing->Order = 0;
     }
 
-    BlockRing->Mdl = __AllocatePages(1 << BlockRing->Order);
-
     status = STATUS_NO_MEMORY;
+    BlockRing->Mdl = __AllocatePages(1 << BlockRing->Order);
     if (BlockRing->Mdl == NULL)
-        goto fail2;
+        goto fail4;
 
-    BlockRing->SharedRing = MmGetSystemAddressForMdlSafe(BlockRing->Mdl,
-                                                         NormalPagePriority);
-    ASSERT(BlockRing->SharedRing != NULL);
+    BlockRing->Shared = MmGetSystemAddressForMdlSafe(BlockRing->Mdl, 
NormalPagePriority); 
+    ASSERT(BlockRing->Shared != NULL);
 
 #pragma warning(push)
 #pragma warning(disable: 4305)
 #pragma warning(disable: 4311)
-    SHARED_RING_INIT(BlockRing->SharedRing);
-    FRONT_RING_INIT(&BlockRing->FrontRing, BlockRing->SharedRing, PAGE_SIZE << 
BlockRing->Order);
+    SHARED_RING_INIT(BlockRing->Shared);
+    FRONT_RING_INIT(&BlockRing->Front, BlockRing->Shared, PAGE_SIZE << 
BlockRing->Order);
 #pragma warning(pop)
 
-    RingPages = (1 << BlockRing->Order);
-    for (Index = 0; Index < RingPages; ++Index) {
-        status = GranterGet(Granter, __Pfn((PUCHAR)BlockRing->SharedRing + 
(Index * PAGE_SIZE)), 
-                                FALSE, &BlockRing->Grants[Index]);
+    Granter = TargetGetGranter(BlockRing->Target);
+    for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+        status = GranterGet(Granter,
+                            MmGetMdlPfnArray(BlockRing->Mdl)[Index],
+                            FALSE,
+                            &BlockRing->Grants[Index]);
         if (!NT_SUCCESS(status))
-            goto fail3;
+            goto fail5;
     }
 
+    status = STATUS_NO_MEMORY;
+    BlockRing->Channel = XENBUS_EVTCHN(Open,
+                                       &BlockRing->EvtchnInterface,
+                                       XENBUS_EVTCHN_TYPE_UNBOUND,
+                                       BlockRingInterrupt,
+                                       BlockRing,
+                                       TargetGetBackendId(BlockRing->Target),
+                                       TRUE);
+    if (BlockRing->Channel == NULL)
+        goto fail6;
+
+    status = XENBUS_DEBUG(Register,
+                          &BlockRing->DebugInterface,
+                          __MODULE__,
+                          BlockRingDebugCallback,
+                          BlockRing,
+                          &BlockRing->DebugCallback);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
+    XENBUS_EVTCHN(Unmask,
+                  &BlockRing->EvtchnInterface,
+                  BlockRing->Channel,
+                  FALSE);
+
     BlockRing->Connected = TRUE;
     return STATUS_SUCCESS;
 
-fail3:
-    for (Index = 0; Index < XENVBD_MAX_RING_PAGES; ++Index) {
-        if (BlockRing->Grants[Index])
-            GranterPut(Granter, BlockRing->Grants[Index]);
-        BlockRing->Grants[Index] = 0;
+fail7:
+    Error("fail7\n");
+    XENBUS_EVTCHN(Close,
+                  &BlockRing->EvtchnInterface,
+                  BlockRing->Channel);
+    BlockRing->Channel = NULL;
+fail6:
+    Error("fail6\n");
+fail5:
+    Error("fail5\n");
+    for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+        if (BlockRing->Grants[Index] == NULL)
+            continue;
+
+        GranterPut(Granter, BlockRing->Grants[Index]);
+        BlockRing->Grants[Index] = NULL;
     }
 
-    RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing));
+    RtlZeroMemory(&BlockRing->Front, sizeof(blkif_front_ring_t));
+    BlockRing->Shared = NULL;
+
     __FreePages(BlockRing->Mdl);
-    BlockRing->SharedRing = NULL;
     BlockRing->Mdl = NULL;
-
+fail4:
+    Error("fail4\n");
+    XENBUS_EVTCHN(Release, &BlockRing->EvtchnInterface);
+    RtlZeroMemory(&BlockRing->EvtchnInterface, 
sizeof(XENBUS_EVTCHN_INTERFACE));
+fail3:
+    Error("fail3\n"); 
+    XENBUS_DEBUG(Release, &BlockRing->DebugInterface);
+    RtlZeroMemory(&BlockRing->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
 fail2:
+    Error("fail2\n"); 
+    XENBUS_STORE(Release, &BlockRing->StoreInterface);
+    RtlZeroMemory(&BlockRing->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
 fail1:
-    return status;
+     Error("fail1 %08x\n", status);
+     return status;
 }
 
 NTSTATUS
 BlockRingStoreWrite(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
+    IN  PXENVBD_BLOCKRING   BlockRing,
+    IN  PVOID               Transaction
     )
 {
-    PXENVBD_GRANTER                 Granter = 
FrontendGetGranter(BlockRing->Frontend);
-    NTSTATUS                        status;
+    PXENVBD_GRANTER         Granter;
+    ULONG                   Port;
+    ULONG                   Grant;
+    NTSTATUS                status;
 
+    Granter = TargetGetGranter(BlockRing->Target);
     if (BlockRing->Order == 0) {
+        Grant = GranterReference(Granter, BlockRing->Grants[0]);
+
         status = XENBUS_STORE(Printf, 
                               &BlockRing->StoreInterface, 
                               Transaction, 
-                              FrontendPath,
+                              TargetGetPath(BlockRing->Target),
                               "ring-ref", 
                               "%u", 
-                              GranterReference(Granter, BlockRing->Grants[0]));
+                              Grant);
         if (!NT_SUCCESS(status))
             return status;
     } else {
-        ULONG   Index, RingPages;
+        ULONG               Index;
 
         status = XENBUS_STORE(Printf, 
                               &BlockRing->StoreInterface, 
                               Transaction, 
-                              FrontendPath, 
+                              TargetGetPath(BlockRing->Target),
                               "ring-page-order", 
                               "%u", 
                               BlockRing->Order);
         if (!NT_SUCCESS(status))
             return status;
 
-        RingPages = (1 << BlockRing->Order);
-        for (Index = 0; Index < RingPages; ++Index) {
-            CHAR    Name[MAX_NAME_LEN+1];
-            status = RtlStringCchPrintfA(Name, MAX_NAME_LEN, "ring-ref%u", 
Index);
+        for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+            CHAR            Name[sizeof("ring-refXX")];
+
+            status = RtlStringCbPrintfA(Name,
+                                        sizeof(Name),
+                                        "ring-ref%u",
+                                        Index);
             if (!NT_SUCCESS(status))
                 return status;
+
+            Grant = GranterReference(Granter, BlockRing->Grants[Index]);
+
             status = XENBUS_STORE(Printf, 
                                   &BlockRing->StoreInterface, 
                                   Transaction, 
-                                  FrontendPath,
+                                  TargetGetPath(BlockRing->Target),
                                   Name, 
                                   "%u", 
-                                  GranterReference(Granter, 
BlockRing->Grants[Index]));
+                                  Grant);
             if (!NT_SUCCESS(status))
                 return status;
         }
@@ -397,28 +467,46 @@ BlockRingStoreWrite(
     status = XENBUS_STORE(Printf, 
                           &BlockRing->StoreInterface, 
                           Transaction, 
-                          FrontendPath,
+                          TargetGetPath(BlockRing->Target), 
                           "protocol", 
+                          "%s", 
                           XEN_IO_PROTO_ABI);
     if (!NT_SUCCESS(status))
         return status;
 
+    Port = XENBUS_EVTCHN(GetPort,
+                         &BlockRing->EvtchnInterface,
+                         BlockRing->Channel);
+
+    status = XENBUS_STORE(Printf, 
+                          &BlockRing->StoreInterface, 
+                          Transaction, 
+                          TargetGetPath(BlockRing->Target), 
+                          "event-channel", 
+                          "%u", 
+                          Port);
+    if (!NT_SUCCESS(status))
+        return status;
+
     return STATUS_SUCCESS;
 }
 
 VOID
 BlockRingEnable(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
     ASSERT(BlockRing->Enabled == FALSE);
-
     BlockRing->Enabled = TRUE;
+
+    XENBUS_EVTCHN(Trigger,
+                  &BlockRing->EvtchnInterface,
+                  BlockRing->Channel);
 }
 
 VOID
 BlockRingDisable(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
     ASSERT(BlockRing->Enabled == TRUE);
@@ -428,30 +516,44 @@ BlockRingDisable(
 
 VOID
 BlockRingDisconnect(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
-    ULONG           Index;
-    PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend);
+    PXENVBD_GRANTER         Granter;
+    ULONG                   Index;
 
     ASSERT(BlockRing->Connected == TRUE);
 
-    BlockRing->Submitted = 0;
-    BlockRing->Received = 0;
+    XENBUS_DEBUG(Deregister,
+                 &BlockRing->DebugInterface,
+                 BlockRing->DebugCallback);
+    BlockRing->DebugCallback = NULL;
 
-    for (Index = 0; Index < XENVBD_MAX_RING_PAGES; ++Index) {
-        if (BlockRing->Grants[Index]) {
-            GranterPut(Granter, BlockRing->Grants[Index]);
-        }
-        BlockRing->Grants[Index] = 0;
+    XENBUS_EVTCHN(Close,
+                  &BlockRing->EvtchnInterface,
+                  BlockRing->Channel);
+    BlockRing->Channel = NULL;
+
+    Granter = TargetGetGranter(BlockRing->Target);
+    for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
+        if (BlockRing->Grants[Index] == NULL)
+            continue;
+
+        GranterPut(Granter, BlockRing->Grants[Index]);
+        BlockRing->Grants[Index] = NULL;
     }
 
-    RtlZeroMemory(&BlockRing->FrontRing, sizeof(BlockRing->FrontRing));
+    RtlZeroMemory(&BlockRing->Front, sizeof(blkif_front_ring_t));
+    BlockRing->Shared = NULL;
+
     __FreePages(BlockRing->Mdl);
-    BlockRing->SharedRing = NULL;
     BlockRing->Mdl = NULL;
 
-    BlockRing->Order = 0;
+    XENBUS_EVTCHN(Release, &BlockRing->EvtchnInterface);
+    RtlZeroMemory(&BlockRing->EvtchnInterface, 
sizeof(XENBUS_EVTCHN_INTERFACE));
+
+    XENBUS_DEBUG(Release, &BlockRing->DebugInterface);
+    RtlZeroMemory(&BlockRing->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
 
     XENBUS_STORE(Release, &BlockRing->StoreInterface);
     RtlZeroMemory(&BlockRing->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
@@ -459,60 +561,11 @@ BlockRingDisconnect(
     BlockRing->Connected = FALSE;
 }
 
-VOID
-BlockRingDebugCallback(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
-    )
-{
-    ULONG           Index;
-    PXENVBD_GRANTER Granter = FrontendGetGranter(BlockRing->Frontend);
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "BLOCKRING: Requests  : %d / %d\n",
-                 BlockRing->Submitted,
-                 BlockRing->Received);
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "BLOCKRING: SharedRing : 0x%p\n", 
-                 BlockRing->SharedRing);
-
-    if (BlockRing->SharedRing) {
-        XENBUS_DEBUG(Printf, Debug,
-                     "BLOCKRING: SharedRing : %d / %d - %d / %d\n",
-                     BlockRing->SharedRing->req_prod,
-                     BlockRing->SharedRing->req_event,
-                     BlockRing->SharedRing->rsp_prod,
-                     BlockRing->SharedRing->rsp_event);
-    }
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "BLOCKRING: FrontRing  : %d / %d (%d)\n",
-                 BlockRing->FrontRing.req_prod_pvt,
-                 BlockRing->FrontRing.rsp_cons,
-                 BlockRing->FrontRing.nr_ents);
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "BLOCKRING: Order      : %d\n",
-                 BlockRing->Order);
-    for (Index = 0; Index < (1ul << BlockRing->Order); ++Index) {
-        XENBUS_DEBUG(Printf, Debug,
-                     "BLOCKRING: Grants[%-2d] : 0x%p (%u)\n", 
-                     Index,
-                     BlockRing->Grants[Index],
-                     GranterReference(Granter, BlockRing->Grants[Index]));
-    }
-
-    BlockRing->Submitted = BlockRing->Received = 0;
-}
-
-VOID
+ULONG
 BlockRingPoll(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     )
 {
-    PXENVBD_TARGET Target = FrontendGetTarget(BlockRing->Frontend);
-
     ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
     KeAcquireSpinLockAtDpcLevel(&BlockRing->Lock);
 
@@ -527,8 +580,8 @@ BlockRingPoll(
 
         KeMemoryBarrier();
 
-        rsp_prod = BlockRing->SharedRing->rsp_prod;
-        rsp_cons = BlockRing->FrontRing.rsp_cons;
+        rsp_prod = BlockRing->Shared->rsp_prod;
+        rsp_cons = BlockRing->Front.rsp_cons;
 
         KeMemoryBarrier();
 
@@ -536,56 +589,170 @@ BlockRingPoll(
             break;
 
         while (rsp_cons != rsp_prod) {
-            blkif_response_t*   Response;
-            ULONG               Tag;
-
-            Response = RING_GET_RESPONSE(&BlockRing->FrontRing, rsp_cons);
-            ++rsp_cons;
-
-            if (__BlockRingPutTag(BlockRing, Response->id, &Tag)) {
-                ++BlockRing->Received;
-                TargetCompleteResponse(Target, Tag, Response->status);
+            blkif_response_t*   rsp;
+
+            rsp = RING_GET_RESPONSE(&BlockRing->Front, rsp_cons);
+            if (rsp->id == 0) {
+                Warning("Bad Response (%llu, %u, &d) @ slot %u\n",
+                        rsp->id,
+                        rsp->operation,
+                        rsp->status,
+                        rsp_cons & (RING_SIZE(&BlockRing->Front) - 1));
+                // dump submitted reqs?
+            } else {
+                TargetCompleteResponse(BlockRing->Target,
+                                       rsp->id,
+                                       rsp->status);
+                ++BlockRing->Completed;
             }
+            ++rsp_cons;
 
-            RtlZeroMemory(Response, sizeof(union blkif_sring_entry));
+            RtlZeroMemory(rsp, sizeof(union blkif_sring_entry));
         }
 
         KeMemoryBarrier();
 
-        BlockRing->FrontRing.rsp_cons = rsp_cons;
-        BlockRing->SharedRing->rsp_event = rsp_cons + 1;
+        BlockRing->Front.rsp_cons = rsp_cons;
+        BlockRing->Shared->rsp_event = rsp_cons + 1;
     }
 
 done:
     KeReleaseSpinLockFromDpcLevel(&BlockRing->Lock);
+
+    // submit all prepared requests, prepare the next srb
+    TargetSubmitRequests(BlockRing->Target);
+
+    return BlockRing->Submitted - BlockRing->Completed;
 }
 
 BOOLEAN
 BlockRingSubmit(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENVBD_REQUEST             Request
+    IN  PXENVBD_BLOCKRING   BlockRing,
+    IN  PXENVBD_REQUEST     Request
     )
 {
-    KIRQL               Irql;
-    blkif_request_t*    req;
-    BOOLEAN             Notify;
+    PLIST_ENTRY             ListEntry;
+    ULONG                   Index;
+    PXENVBD_GRANTER         Granter;
+    KIRQL                   Irql;
+    blkif_request_t*        req;
+    BOOLEAN                 Notify;
 
     KeAcquireSpinLock(&BlockRing->Lock, &Irql);
-    if (RING_FULL(&BlockRing->FrontRing)) {
+    if (RING_FULL(&BlockRing->Front)) {
         KeReleaseSpinLock(&BlockRing->Lock, Irql);
         return FALSE;
     }
 
-    req = RING_GET_REQUEST(&BlockRing->FrontRing, 
BlockRing->FrontRing.req_prod_pvt);
-    __BlockRingInsert(BlockRing, Request, req);
+    req = RING_GET_REQUEST(&BlockRing->Front, BlockRing->Front.req_prod_pvt);
+    ++BlockRing->Front.req_prod_pvt;
+    ++BlockRing->Submitted;
+
+    Granter = TargetGetGranter(BlockRing->Target);
+    switch (Request->Operation) {
+    case BLKIF_OP_DISCARD: {
+        blkif_request_discard_t*        req_d;
+        req_d = (blkif_request_discard_t*)req;
+        req_d->operation        = BLKIF_OP_DISCARD;
+        req_d->flag             = Request->Flags;
+        req_d->handle           = (USHORT)TargetGetDeviceId(BlockRing->Target);
+        req_d->id               = Request->Id;
+        req_d->sector_number    = Request->FirstSector;
+        req_d->nr_sectors       = Request->NrSectors;
+        } break;
+
+    case BLKIF_OP_READ:
+    case BLKIF_OP_WRITE:
+        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+            // Indirect
+            blkif_request_indirect_t*   req_i;
+            ULONG                       PageIdx;
+            ULONG                       SegIdx;
+            PLIST_ENTRY                 PageEntry;
+            PLIST_ENTRY                 SegEntry;
+
+            req_i = (blkif_request_indirect_t*)req;
+            req_i->operation         = BLKIF_OP_INDIRECT;
+            req_i->indirect_op       = Request->Operation;
+            req_i->nr_segments       = Request->NrSegments;
+            req_i->id                = Request->Id;
+            req_i->sector_number     = Request->FirstSector;
+            req_i->handle            = 
(USHORT)TargetGetDeviceId(BlockRing->Target);
+
+            PageEntry = Request->Indirects.Flink;
+            SegEntry = Request->Segments.Flink;
+            for (PageIdx = 0; PageIdx < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST; 
++PageIdx) {
+                PXENVBD_INDIRECT Page;
+
+                if (PageEntry != &Request->Indirects)
+                    break;
+                if (SegEntry != &Request->Segments)
+                    break;
+
+                Page = CONTAINING_RECORD(PageEntry, XENVBD_INDIRECT, 
ListEntry);
+                req_i->indirect_grefs[PageIdx] = GranterReference(Granter, 
Page->Grant);
+
+                for (SegIdx = 0; SegIdx < XENVBD_MAX_SEGMENTS_PER_PAGE; 
++SegIdx) {
+                    PXENVBD_SEGMENT Segment;
+
+                    if (SegEntry != &Request->Segments)
+                        break;
+
+                    Segment = CONTAINING_RECORD(SegEntry, XENVBD_SEGMENT, 
ListEntry);
+                    Page->Page[SegIdx].GrantRef = GranterReference(Granter, 
Segment->Grant);
+                    Page->Page[SegIdx].First    = Segment->FirstSector;
+                    Page->Page[SegIdx].Last     = Segment->LastSector;
+
+                    SegEntry = SegEntry->Flink;
+                }
+
+                PageEntry = PageEntry->Flink;
+            }
+            break; // out of switch
+        }
+        // intentional fall through
+    case BLKIF_OP_WRITE_BARRIER:
+    case BLKIF_OP_FLUSH_DISKCACHE:
+    default:
+        req->operation      = Request->Operation;
+        req->nr_segments    = (UCHAR)Request->NrSegments;
+        req->handle         = (USHORT)TargetGetDeviceId(BlockRing->Target);
+        req->id             = Request->Id;
+        req->sector_number  = Request->FirstSector;
+
+        for (ListEntry = Request->Segments.Flink, Index = 0;
+             ListEntry != &Request->Segments && Index < 
BLKIF_MAX_SEGMENTS_PER_REQUEST;
+             ListEntry = ListEntry->Flink, ++Index) {
+            PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry, 
XENVBD_SEGMENT, ListEntry);
+            ULONG           Grant;
+
+            Grant = GranterReference(Granter, Segment->Grant);
+
+            req->seg[Index].first_sect = Segment->FirstSector;
+            req->seg[Index].last_sect  = Segment->LastSector;
+            req->seg[Index].gref       = Grant;
+        }
+        break;
+    }
+
     KeMemoryBarrier();
-    ++BlockRing->FrontRing.req_prod_pvt;
 
-    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlockRing->FrontRing, Notify);
+    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&BlockRing->Front, Notify);
     KeReleaseSpinLock(&BlockRing->Lock, Irql);
 
-    if (Notify)
-        NotifierSend(FrontendGetNotifier(BlockRing->Frontend));
+    if (Notify) {
+        XENBUS_EVTCHN(Send,
+                      &BlockRing->EvtchnInterface,
+                      BlockRing->Channel);
+    }
 
     return TRUE;
 }
+
+VOID
+BlockRingKick(
+    IN  PXENVBD_BLOCKRING   BlockRing
+    )
+{
+    KeInsertQueueDpc(&BlockRing->Dpc, NULL, NULL);
+}
diff --git a/src/xenvbd/blockring.h b/src/xenvbd/blockring.h
index 1117d73..2660e47 100644
--- a/src/xenvbd/blockring.h
+++ b/src/xenvbd/blockring.h
@@ -32,66 +32,64 @@
 #ifndef _XENVBD_BLOCKRING_H
 #define _XENVBD_BLOCKRING_H
 
+#include <ntddk.h>
+
 typedef struct _XENVBD_BLOCKRING XENVBD_BLOCKRING, *PXENVBD_BLOCKRING;
 
-#include "frontend.h"
-#include <debug_interface.h>
-#include <store_interface.h>
+#include "target.h"
+#include "srbext.h"
 
 extern NTSTATUS
 BlockRingCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    IN  ULONG                       DeviceId,
-    OUT PXENVBD_BLOCKRING*          BlockRing
+    IN  PXENVBD_TARGET      Target,
+    OUT PXENVBD_BLOCKRING*  BlockRing
     );
 
 extern VOID
 BlockRingDestroy(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 extern NTSTATUS
 BlockRingConnect(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 extern NTSTATUS
 BlockRingStoreWrite(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
+    IN  PXENVBD_BLOCKRING   BlockRing,
+    IN  PVOID               Transaction
     );
 
 extern VOID
 BlockRingEnable(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 extern VOID
 BlockRingDisable(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 extern VOID
 BlockRingDisconnect(
-    IN  PXENVBD_BLOCKRING           BlockRing
-    );
-
-extern VOID
-BlockRingDebugCallback(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
-extern VOID
+extern ULONG
 BlockRingPoll(
-    IN  PXENVBD_BLOCKRING           BlockRing
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 extern BOOLEAN
 BlockRingSubmit(
-    IN  PXENVBD_BLOCKRING           BlockRing,
-    IN  PXENVBD_REQUEST             Request
+    IN  PXENVBD_BLOCKRING   BlockRing,
+    IN  PXENVBD_REQUEST     Request
+    );
+
+extern VOID
+BlockRingKick(
+    IN  PXENVBD_BLOCKRING   BlockRing
     );
 
 #endif // _XENVBD_BLOCKRING_H
diff --git a/src/xenvbd/frontend.c b/src/xenvbd/frontend.c
deleted file mode 100644
index 691ea3a..0000000
--- a/src/xenvbd/frontend.c
+++ /dev/null
@@ -1,1769 +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.
- */ 
-
-#include <ntddk.h>
-#include <ntstrsafe.h>
-
-#include "frontend.h"
-#include "registry.h"
-#include "driver.h"
-#include "adapter.h"
-#include "pdoinquiry.h"
-#include "srbext.h"
-#include "debug.h"
-#include "assert.h"
-#include "util.h"
-#include "names.h"
-#include "notifier.h"
-#include "blockring.h"
-#include "granter.h"
-#include "thread.h"
-#include <store_interface.h>
-#include <suspend_interface.h>
-
-#include <stdlib.h>
-
-struct _XENVBD_FRONTEND {
-    // Frontend
-    PXENVBD_TARGET              Target;
-    ULONG                       TargetId;
-    ULONG                       DeviceId;
-    CHAR                        FrontendPath[sizeof("device/vbd/XXXXXXXX")];
-    PCHAR                       BackendPath;
-    CHAR                        TargetPath[sizeof("data/scsi/target/XXXX")];
-    USHORT                      BackendId;
-    XENVBD_STATE                State;
-    KSPIN_LOCK                  StateLock;
-
-    XENVBD_CAPS                 Caps;
-    XENVBD_FEATURES             Features;
-    XENVBD_DISKINFO             DiskInfo;
-    PVOID                       Inquiry;
-
-    // Interfaces to XenBus
-    XENBUS_STORE_INTERFACE      StoreInterface;
-    XENBUS_SUSPEND_INTERFACE    SuspendInterface;
-
-    PXENBUS_SUSPEND_CALLBACK    SuspendLateCallback;
-
-    // Ring
-    PXENVBD_NOTIFIER            Notifier;
-    PXENVBD_BLOCKRING           BlockRing;
-    PXENVBD_GRANTER             Granter;
-
-    // Backend State Watch
-    BOOLEAN                     Active;
-    PXENVBD_THREAD              BackendThread;
-    PXENBUS_STORE_WATCH         BackendWatch;
-};
-
-#define DOMID_INVALID (0x7FF4U)
-
-static const PCHAR
-__XenvbdStateName(
-    IN  XENVBD_STATE                        State
-    )
-{
-    switch (State) {
-    case XENVBD_STATE_INVALID:      return "STATE_INVALID";
-    case XENVBD_INITIALIZED:        return "INITIALIZED";
-    case XENVBD_CLOSING:            return "CLOSING";
-    case XENVBD_CLOSED:             return "CLOSED";
-    case XENVBD_PREPARED:           return "PREPARED";
-    case XENVBD_CONNECTED:          return "CONNECTED";
-    case XENVBD_ENABLED:            return "ENABLED";
-    default:                        return "UNKNOWN";
-    }
-}
-//=============================================================================
-#define FRONTEND_POOL_TAG            'tnFX'
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__FrontendAlloc(
-    __in  ULONG Size
-    )
-{
-    return __AllocatePoolWithTag(NonPagedPool, Size, FRONTEND_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__FrontendFree(
-    __in __drv_freesMem(mem) PVOID Buffer
-    )
-{
-    if (Buffer)
-        __FreePoolWithTag(Buffer, FRONTEND_POOL_TAG);
-}
-
-//=============================================================================
-// Accessors
-VOID
-FrontendRemoveFeature(
-    IN  PXENVBD_FRONTEND        Frontend,
-    IN  UCHAR                   BlkifOperation
-    )
-{
-    switch (BlkifOperation) {
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        Verbose("FLUSH_DISKCACHE\n");
-        Frontend->DiskInfo.FlushCache = FALSE;
-        break;
-    case BLKIF_OP_WRITE_BARRIER:    
-        Verbose("WRITE_BARRIER\n");
-        Frontend->DiskInfo.Barrier = FALSE;
-        break;
-    case BLKIF_OP_DISCARD:
-        Verbose("DISCARD\n");
-        Frontend->DiskInfo.Discard = FALSE;
-        break;
-    case BLKIF_OP_INDIRECT:
-        Verbose("INDIRECT\n");
-        Frontend->Features.Indirect = 0;
-        break;
-    default:
-        break;
-    }
-}
-PXENVBD_CAPS
-FrontendGetCaps(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return &Frontend->Caps;
-}
-PXENVBD_FEATURES
-FrontendGetFeatures(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return &Frontend->Features;
-}
-PXENVBD_DISKINFO
-FrontendGetDiskInfo(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return &Frontend->DiskInfo;
-}
-ULONG
-FrontendGetTargetId(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->TargetId;
-}
-ULONG
-FrontendGetDeviceId(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-     return Frontend->DeviceId;
-}
-PVOID
-FrontendGetInquiry(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->Inquiry;
-}
-PXENVBD_TARGET
-FrontendGetTarget(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->Target;
-}
-PXENVBD_BLOCKRING
-FrontendGetBlockRing(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->BlockRing;
-}
-PXENVBD_NOTIFIER
-FrontendGetNotifier(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->Notifier;
-}
-PXENVBD_GRANTER
-FrontendGetGranter(
-    __in  PXENVBD_FRONTEND      Frontend
-    )
-{
-    return Frontend->Granter;
-}
-
-NTSTATUS
-FrontendStoreWriteFrontend(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Name,
-    __in  PCHAR                 Value
-    )
-{
-    return XENBUS_STORE(Printf,
-                        &Frontend->StoreInterface,
-                        NULL,
-                        Frontend->FrontendPath,
-                        Name,
-                        Value);
-}
-NTSTATUS
-FrontendStoreReadBackend(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Name,
-    __out PCHAR*                Value
-    )
-{
-    NTSTATUS    Status;
-
-    Status = STATUS_INVALID_PARAMETER;
-    if (Frontend->BackendPath == NULL)
-        goto fail1;
-
-    Status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->BackendPath,
-                          Name,
-                          Value);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-
-    return STATUS_SUCCESS;
-
-fail2:
-fail1:
-    return Status;
-}
-VOID
-FrontendStoreFree(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Value
-    )
-{
-    XENBUS_STORE(Free,
-                 &Frontend->StoreInterface,
-                 Value);
-}
-__drv_maxIRQL(DISPATCH_LEVEL)
-NTSTATUS
-FrontendWriteUsage(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NTSTATUS    Status;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->TargetPath, 
-                          "paging",
-                          "%u",
-                          Frontend->Caps.Paging);
-    if (!NT_SUCCESS(Status))
-        goto out;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->TargetPath, 
-                          "hibernation",
-                          "%u",
-                          Frontend->Caps.Hibernation);
-    if (!NT_SUCCESS(Status))
-        goto out;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->TargetPath, 
-                          "dump",
-                          "%u",
-                          Frontend->Caps.DumpFile);
-    if (!NT_SUCCESS(Status))
-        goto out;
-
-    Verbose("Target[%d] : %s %s %s\n", Frontend->TargetId,
-            Frontend->Caps.DumpFile ? "DUMP" : "NOT_DUMP", 
-            Frontend->Caps.Hibernation ? "HIBER" : "NOT_HIBER",
-            Frontend->Caps.Paging ? "PAGE" : "NOT_PAGE");
-
-out:
-    return Status;
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-VOID
-FrontendNotifyResponses(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    BlockRingPoll(Frontend->BlockRing);
-    TargetSubmitRequests(Frontend->Target);
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__UpdateBackendPath(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NTSTATUS    Status;
-    PCHAR       Value;
-    ULONG       Length;
-
-    Status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->FrontendPath, 
-                          "backend-id",
-                          &Value);
-    if (NT_SUCCESS(Status)) {
-        Frontend->BackendId = (USHORT)strtoul(Value, NULL, 10);
-        XENBUS_STORE(Free,
-                     &Frontend->StoreInterface,
-                     Value);
-    } else {
-        Frontend->BackendId = 0;
-    }
-
-    Status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->FrontendPath,
-                          "backend",
-                          &Value);
-    if (NT_SUCCESS(Status)) {
-        if (Frontend->BackendPath) {
-            Trace("<< %s\n", Frontend->BackendPath);
-            __FrontendFree(Frontend->BackendPath);
-            Frontend->BackendPath = NULL;
-        }
-
-        Length = (ULONG)strlen(Value);
-        Frontend->BackendPath = (PCHAR)__FrontendAlloc(Length + 1);
-
-        if (Frontend->BackendPath) {
-            RtlCopyMemory(Frontend->BackendPath, Value, Length);
-            Trace(">> %s\n", Frontend->BackendPath);
-        }
-
-        XENBUS_STORE(Free,
-                     &Frontend->StoreInterface,
-                     Value);
-    } else {
-        Warning("Failed to read \'backend\' from \'%s\' (%08x)\n", 
-                    Frontend->FrontendPath, Status);
-    }
-
-    return Status;
-}
-__drv_maxIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__ReadState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in_opt PXENBUS_STORE_TRANSACTION Transaction,
-    __in  PCHAR                   Path,
-    __out XenbusState*            State
-    )
-{
-    NTSTATUS        Status;
-    PCHAR           Buffer;
-
-    Status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          Transaction,
-                          Path, 
-                          "state",
-                          &Buffer);
-    if (!NT_SUCCESS(Status))
-        goto fail;
-
-    *State = (XenbusState)strtoul(Buffer, NULL, 10);
-    XENBUS_STORE(Free,
-                 &Frontend->StoreInterface,
-                 Buffer);
-
-    return STATUS_SUCCESS;
-
-fail:
-    *State = XenbusStateUnknown;
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-__WaitState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __inout  XenbusState*         State
-    )
-{
-    NTSTATUS        Status;
-    XenbusState     OldState = *State;
-    PXENBUS_STORE_WATCH Watch;
-    KEVENT          Event;
-    LARGE_INTEGER   Timeout;
-
-    LARGE_INTEGER   StartTime;
-    LARGE_INTEGER   CurrentTime;
-    ULONG           Count = 0;
-
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    Timeout.QuadPart = 0;
-
-    ASSERT3P(Frontend->BackendPath, !=, NULL);
-    Status = XENBUS_STORE(WatchAdd,
-                          &Frontend->StoreInterface,
-                          Frontend->BackendPath,
-                          "state", 
-                          &Event,
-                          &Watch);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    KeQuerySystemTime(&StartTime);
-
-    while (OldState == *State) {
-        // check event and spin or read
-#pragma prefast(suppress:28121)
-        if (KeWaitForSingleObject(&Event, Executive, KernelMode, 
-                                    FALSE, &Timeout) == STATUS_TIMEOUT) {
-            XENBUS_STORE(Poll,
-                         &Frontend->StoreInterface);
-
-            KeQuerySystemTime(&CurrentTime);
-            if ((CurrentTime.QuadPart - StartTime.QuadPart) > 10000) {
-                Warning("Target[%d] : %d Waited for %d ms\n", 
Frontend->TargetId, 
-                            Count, (ULONG)((CurrentTime.QuadPart - 
StartTime.QuadPart) / 10));
-                StartTime.QuadPart = CurrentTime.QuadPart;
-                ++Count;
-            }
-
-            continue;
-        }
-
-        Status = __ReadState(Frontend, NULL, Frontend->BackendPath, State);
-        if (!NT_SUCCESS(Status))
-            goto fail2;
-    }
-
-    XENBUS_STORE(WatchRemove,
-                 &Frontend->StoreInterface,
-                 Watch);
-
-    Trace("Target[%d] : BACKEND_STATE  -> %s\n",
-          Frontend->TargetId,
-          XenbusStateName(*State));
-
-    return STATUS_SUCCESS;
-
-fail2:
-    Error("Fail2\n");
-
-    XENBUS_STORE(WatchRemove,
-                 &Frontend->StoreInterface,
-                 Watch);
-fail1:
-    Error("Fail1 (%08x)\n", Status);
-
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-___SetState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  XenbusState             State
-    )
-{
-    NTSTATUS    Status;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->FrontendPath,
-                          "state",
-                          "%u",
-                          State);
-    if (NT_SUCCESS(Status)) {
-        Trace("Target[%d] : FRONTEND_STATE -> %s\n",
-              Frontend->TargetId,
-              XenbusStateName(State));
-    } else {
-        Error("Fail (%08x)\n", Status);
-    }
-
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-__CheckBackendForEject(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    XenbusState     FrontendState;
-    XenbusState     BackendState;
-    BOOLEAN         Online;
-    ULONG           Attempt;
-    NTSTATUS        Status;
-
-    if (Frontend->FrontendPath == NULL)
-        return;
-    if (Frontend->BackendPath == NULL)
-        return;
-
-    // get FrontendState, BackendState and Online
-    Attempt         = 0;
-    FrontendState   = XenbusStateUnknown;
-    BackendState    = XenbusStateUnknown;
-    Online          = TRUE;
-    for (;;) {
-        PXENBUS_STORE_TRANSACTION   Transaction;
-        PCHAR                       Buffer;
-
-        Status = XENBUS_STORE(TransactionStart,
-                              &Frontend->StoreInterface,
-                              &Transaction);
-        if (!NT_SUCCESS(Status))
-            break;
-
-        Status = __ReadState(Frontend,
-                             Transaction,
-                             Frontend->FrontendPath,
-                             &FrontendState);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = __ReadState(Frontend,
-                             Transaction,
-                             Frontend->BackendPath,
-                             &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = XENBUS_STORE(Read,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              Frontend->BackendPath, 
-                              "online",
-                              &Buffer);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Online = (BOOLEAN)strtol(Buffer, NULL, 2);
-        XENBUS_STORE(Free,
-                     &Frontend->StoreInterface,
-                     Buffer);
-
-        Status = XENBUS_STORE(TransactionEnd,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              TRUE);
-        if (Status != STATUS_RETRY || ++Attempt > 10)
-            break;
-
-        continue;
-
-abort:
-        (VOID) XENBUS_STORE(TransactionEnd,
-                            &Frontend->StoreInterface,
-                            Transaction,
-                            FALSE);
-        break;
-    }
-    if (!NT_SUCCESS(Status))
-        return;
-
-    // check to see eject required
-    if (!Online && BackendState == XenbusStateClosing) {
-        Trace("Target[%d] : BackendState(%s) FrontendState(%s)\n", 
-                Frontend->TargetId, XenbusStateName(BackendState), 
XenbusStateName(FrontendState));
-
-        TargetIssueDeviceEject(Frontend->Target, 
XenbusStateName(BackendState));
-    }    
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadFeature(
-    IN  PXENVBD_FRONTEND            Frontend,
-    IN  PCHAR                       Name,
-    IN  PBOOLEAN                    Value
-    )
-{
-    NTSTATUS        status;
-    PCHAR           Buffer;
-    ULONG           Override;
-    BOOLEAN         Old = *Value;
-
-    status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->BackendPath,
-                          Name,
-                          &Buffer);
-    if (!NT_SUCCESS(status))
-        return FALSE;   // no value, unchanged
-
-    *Value = !!(strtoul(Buffer, NULL, 10));
-    XENBUS_STORE(Free,
-                    &Frontend->StoreInterface,
-                    Buffer);
-
-    // check registry for disable-override
-    status = RegistryQueryDwordValue(DriverGetParametersKey(),
-                                    Name,
-                                    &Override);
-    if (NT_SUCCESS(status)) {
-        if (Override == 0)
-            *Value = FALSE;
-    }
-
-    return Old != *Value;
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadValue32(
-    IN  PXENVBD_FRONTEND            Frontend,
-    IN  PCHAR                       Name,
-    IN  BOOLEAN                     AllowOverride,
-    IN  PULONG                      Value
-    )
-{
-    NTSTATUS        status;
-    PCHAR           Buffer;
-    ULONG           Override;
-    ULONG           Old = *Value;
-
-    status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->BackendPath,
-                          Name,
-                          &Buffer);
-    if (!NT_SUCCESS(status))
-        return FALSE;   // no value, unchanged
-
-    *Value = strtoul(Buffer, NULL, 10);
-    XENBUS_STORE(Free,
-                    &Frontend->StoreInterface,
-                    Buffer);
-
-    // check registry for disable-override
-    if (AllowOverride) {
-        status = RegistryQueryDwordValue(DriverGetParametersKey(),
-                                        Name,
-                                        &Override);
-        if (NT_SUCCESS(status)) {
-            *Value = Override;
-        }
-    }
-
-    return Old != *Value;
-}
-
-static FORCEINLINE BOOLEAN
-FrontendReadValue64(
-    IN  PXENVBD_FRONTEND            Frontend,
-    IN  PCHAR                       Name,
-    IN OUT PULONG64                 Value
-    )
-{
-    NTSTATUS        status;
-    PCHAR           Buffer;
-    ULONG64         Old = *Value;
-
-    status = XENBUS_STORE(Read,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->BackendPath,
-                          Name,
-                          &Buffer);
-    if (!NT_SUCCESS(status))
-        return FALSE;   // no value, unchanged
-
-    *Value = _strtoui64(Buffer, NULL, 10);
-    XENBUS_STORE(Free,
-                    &Frontend->StoreInterface,
-                    Buffer);
-
-    return Old != *Value;
-}
-
-static FORCEINLINE ULONG
-__Size(
-    __in  PXENVBD_DISKINFO          Info
-    )
-{
-    ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 
* 1024); 
-    if (MBytes < 10240)
-        return (ULONG)MBytes;
-    return (ULONG)(MBytes >> 10); // / 1024
-}
-static FORCEINLINE PCHAR
-__Units(
-    __in  PXENVBD_DISKINFO          Info
-    )
-{
-    ULONG64 MBytes = (Info->SectorSize * Info->SectorCount) >> 20; // / (1024 
* 1024); 
-    if (MBytes < 10240)
-        return "MB";
-    return "GB";
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static VOID
-__ReadDiskInfo(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    BOOLEAN Changed = FALSE;
-
-    Changed |= FrontendReadValue32(Frontend,
-                                  "info",
-                                  FALSE,
-                                  &Frontend->DiskInfo.DiskInfo);
-    Changed |= FrontendReadValue32(Frontend,
-                                  "sector-size",
-                                  FALSE,
-                                  &Frontend->DiskInfo.SectorSize);
-    Changed |= FrontendReadValue32(Frontend,
-                                  "physical-sector-size",
-                                  FALSE,
-                                  &Frontend->DiskInfo.PhysSectorSize);
-    Changed |= FrontendReadValue64(Frontend,
-                                  "sectors",
-                                  &Frontend->DiskInfo.SectorCount);
-
-    if (!Changed)
-        return;
-
-    Frontend->Caps.SurpriseRemovable = !!(Frontend->DiskInfo.DiskInfo & 
VDISK_REMOVABLE);
-    if (Frontend->DiskInfo.DiskInfo & VDISK_READONLY) {
-        Warning("Target[%d] : DiskInfo contains VDISK_READONLY flag!\n", 
Frontend->TargetId);
-    }
-    if (Frontend->DiskInfo.DiskInfo & VDISK_CDROM) {
-        Warning("Target[%d] : DiskInfo contains VDISK_CDROM flag!\n", 
Frontend->TargetId);
-    }
-    if (Frontend->DiskInfo.SectorSize == 0) {
-        Error("Target[%d] : Invalid SectorSize!\n", Frontend->TargetId);
-    }
-    if (Frontend->DiskInfo.SectorCount == 0) {
-        Error("Target[%d] : Invalid SectorCount!\n", Frontend->TargetId);
-    }
-    if (Frontend->DiskInfo.PhysSectorSize == 0) {
-        Frontend->DiskInfo.PhysSectorSize = Frontend->DiskInfo.SectorSize;
-    }
-
-    // dump actual values
-    Verbose("Target[%d] : %lld sectors of %d bytes (%d)\n", Frontend->TargetId,
-                Frontend->DiskInfo.SectorCount, Frontend->DiskInfo.SectorSize,
-                Frontend->DiskInfo.PhysSectorSize);
-    Verbose("Target[%d] : %d %s (%08x) %s\n", Frontend->TargetId,
-                __Size(&Frontend->DiskInfo), __Units(&Frontend->DiskInfo),
-                Frontend->DiskInfo.DiskInfo,
-                Frontend->Caps.SurpriseRemovable ? "SURPRISE_REMOVABLE" : "");
-}
-
-static FORCEINLINE VOID
-FrontendReadFeatures(
-    IN  PXENVBD_FRONTEND            Frontend
-    )
-{
-    BOOLEAN Changed = FALSE;
-
-    Changed |= FrontendReadFeature(Frontend,
-                                   "removable",
-                                   &Frontend->Caps.Removable);
-    Changed |= FrontendReadValue32(Frontend,
-                                   "feature-max-indirect-segments",
-                                   TRUE,
-                                   &Frontend->Features.Indirect);
-    Changed |= FrontendReadFeature(Frontend,
-                                   "feature-persistent",
-                                   &Frontend->Features.Persistent);
-
-    if (!Changed)
-        return;
-
-    Verbose("Target[%d] : Features: %s%s%s\n",
-                Frontend->TargetId,
-                Frontend->Features.Persistent ? "PERSISTENT " : "",
-                Frontend->Features.Indirect ? "INDIRECT " : "",
-                Frontend->Caps.Removable ? "REMOVABLE" : "");
-    if (Frontend->Features.Indirect) {
-        Verbose("Target[%d] : INDIRECT %x\n",
-                    Frontend->TargetId,
-                    Frontend->Features.Indirect);
-    }
-}
-
-static FORCEINLINE VOID
-FrontendReadDiskInfo(
-    IN  PXENVBD_FRONTEND            Frontend
-    )
-{
-    BOOLEAN Changed = FALSE;
-    BOOLEAN Discard;
-    BOOLEAN DiscardFeature = FALSE;
-    BOOLEAN DiscardEnable = TRUE;
-
-    Changed |= FrontendReadFeature(Frontend,
-                                   "feature-barrier",
-                                   &Frontend->DiskInfo.Barrier);
-    Changed |= FrontendReadFeature(Frontend,
-                                   "feature-flush-cache",
-                                   &Frontend->DiskInfo.FlushCache);
-
-    // discard related
-    FrontendReadFeature(Frontend,
-                        "feature-discard",
-                        &DiscardFeature);
-    FrontendReadFeature(Frontend,
-                        "discard-enable",
-                        &DiscardEnable);
-    Discard = DiscardFeature && DiscardEnable;
-    Changed |= (Discard != Frontend->DiskInfo.Discard);
-    Frontend->DiskInfo.Discard = Discard;
-    Changed |= FrontendReadFeature(Frontend,
-                                   "discard-secure",
-                                   &Frontend->DiskInfo.DiscardSecure);
-    Changed |= FrontendReadValue32(Frontend,
-                                   "discard-alignment",
-                                   TRUE,
-                                   &Frontend->DiskInfo.DiscardAlignment);
-    Changed |= FrontendReadValue32(Frontend,
-                                   "discard-granularity",
-                                   TRUE,
-                                   &Frontend->DiskInfo.DiscardGranularity);
-
-    if (!Changed)
-        return;
-
-    Verbose("Target[%d] : Features: %s%s%s\n",
-                Frontend->TargetId,
-                Frontend->DiskInfo.Barrier ? "BARRIER " : "",
-                Frontend->DiskInfo.FlushCache ?  "FLUSH " : "",
-                Frontend->DiskInfo.Discard ? "DISCARD " : "");
-    if (Frontend->DiskInfo.Discard) {
-        Verbose("Target[%d] : DISCARD %s%x/%x\n",
-                    Frontend->TargetId,
-                    Frontend->DiskInfo.DiscardSecure ? "SECURE " : "",
-                    Frontend->DiskInfo.DiscardAlignment,
-                    Frontend->DiskInfo.DiscardGranularity);
-    }
-}
-
-//=============================================================================
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendClose(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NTSTATUS        Status;
-    XenbusState     BackendState;
-
-    // unwatch backend (null check for initial close operation)
-    if (Frontend->BackendWatch)
-        XENBUS_STORE(WatchRemove,
-                     &Frontend->StoreInterface,
-                     Frontend->BackendWatch);
-    Frontend->BackendWatch = NULL;
-    
-    Frontend->BackendId = DOMID_INVALID;
-
-    // get/update backend path
-    Status = __UpdateBackendPath(Frontend);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    // Backend : -> !INITIALIZING
-    BackendState = XenbusStateUnknown;
-    do {
-        Status = __WaitState(Frontend, &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto fail2;
-    } while (BackendState == XenbusStateInitialising);
-
-    // Frontend: -> CLOSING 
-    // Backend : -> CLOSING 
-    while (BackendState != XenbusStateClosing &&
-           BackendState != XenbusStateClosed) {
-        Status = ___SetState(Frontend, XenbusStateClosing);
-        if (!NT_SUCCESS(Status))
-            goto fail3;
-        Status = __WaitState(Frontend, &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto fail4;
-    }
-
-    // Frontend: -> CLOSED
-    // Backend : -> CLOSED
-    while (BackendState != XenbusStateClosed) {
-        Status = ___SetState(Frontend, XenbusStateClosed);
-        if (!NT_SUCCESS(Status))
-            goto fail5;
-        Status = __WaitState(Frontend, &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto fail6;
-    }
-
-    return STATUS_SUCCESS;
-
-fail6:
-fail5:
-fail4:
-fail3:
-fail2:
-fail1:
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendPrepare(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NTSTATUS        Status;
-    XenbusState     BackendState;
-
-    // get/update backend path
-    Status = __UpdateBackendPath(Frontend);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    // watch backend (4 paths needed)
-    Status = XENBUS_STORE(WatchAdd,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->BackendPath,
-                          ThreadGetEvent(Frontend->BackendThread),
-                          &Frontend->BackendWatch);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-
-    // write targetpath
-    Status = FrontendWriteUsage(Frontend);
-    if (!NT_SUCCESS(Status))
-        goto fail3;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->TargetPath, 
-                          "frontend",
-                          "%s",
-                          Frontend->FrontendPath);
-    if (!NT_SUCCESS(Status))
-        goto fail4;
-
-    Status = XENBUS_STORE(Printf,
-                          &Frontend->StoreInterface,
-                          NULL,
-                          Frontend->TargetPath, 
-                          "device",
-                          "%u",
-                          Frontend->DeviceId);
-    if (!NT_SUCCESS(Status))
-        goto fail5;
-
-    // Frontend: -> INITIALIZING
-    Status = ___SetState(Frontend, XenbusStateInitialising);
-    if (!NT_SUCCESS(Status))
-        goto fail6;
-
-    // Backend : -> INITWAIT
-    BackendState = XenbusStateUnknown;
-    do {
-        Status = __WaitState(Frontend, &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto fail7;
-    } while (BackendState == XenbusStateClosed || 
-             BackendState == XenbusStateInitialising);
-    Status = STATUS_UNSUCCESSFUL;
-    if (BackendState != XenbusStateInitWait)
-        goto fail8;
-
-    // read inquiry data
-    if (Frontend->Inquiry == NULL)
-        PdoReadInquiryData(Frontend, &Frontend->Inquiry);
-    PdoUpdateInquiryData(Frontend, Frontend->Inquiry);
-
-    // read features and caps (removable, ring-order, ...)
-    Verbose("Target[%d] : BackendId %d (%s)\n",
-            Frontend->TargetId,
-            Frontend->BackendId,
-            Frontend->BackendPath);
-
-    FrontendReadFeatures(Frontend);
-    
-    return STATUS_SUCCESS;
-
-fail8:
-    Error("Fail8\n");
-fail7:
-    Error("Fail7\n");
-fail6:
-    Error("Fail6\n");
-fail5:
-    Error("Fail5\n");
-fail4:
-    Error("Fail4\n");
-fail3:
-    Error("Fail3\n");
-    (VOID) XENBUS_STORE(WatchRemove,
-                        &Frontend->StoreInterface,
-                        Frontend->BackendWatch);
-    Frontend->BackendWatch = NULL;
-fail2:
-    Error("Fail2\n");
-fail1:
-    Error("Fail1 (%08x)\n", Status);
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static NTSTATUS
-FrontendConnect(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NTSTATUS        Status;
-    XenbusState     BackendState;
-
-    // Alloc Ring, Create Evtchn, Gnttab map
-    Status = GranterConnect(Frontend->Granter, Frontend->BackendId);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    Status = BlockRingConnect(Frontend->BlockRing);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-
-    Status = NotifierConnect(Frontend->Notifier, Frontend->BackendId);
-    if (!NT_SUCCESS(Status))
-        goto fail3;
-
-    // write evtchn/gnttab details in xenstore
-    for (;;) {
-        PXENBUS_STORE_TRANSACTION   Transaction;
-        
-        Status = XENBUS_STORE(TransactionStart,
-                              &Frontend->StoreInterface,
-                              &Transaction);
-        if (!NT_SUCCESS(Status))
-            break;
-
-        Status = NotifierStoreWrite(Frontend->Notifier, Transaction, 
Frontend->FrontendPath);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = BlockRingStoreWrite(Frontend->BlockRing, Transaction, 
Frontend->FrontendPath);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = GranterStoreWrite(Frontend->Granter, Transaction, 
Frontend->FrontendPath);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = XENBUS_STORE(Printf,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              Frontend->FrontendPath,
-                              "target-id",
-                              "%u",
-                              Frontend->TargetId);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = XENBUS_STORE(Printf,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              Frontend->FrontendPath,
-                              "feature-surprise-remove",
-                              "%u",
-                              1);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = XENBUS_STORE(Printf,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              Frontend->FrontendPath,
-                              "feature-online-resize",
-                              "%u",
-                              1);
-        if (!NT_SUCCESS(Status))
-            goto abort;
-
-        Status = XENBUS_STORE(TransactionEnd,
-                              &Frontend->StoreInterface,
-                              Transaction,
-                              TRUE);
-        if (Status == STATUS_RETRY)
-            continue;
-
-        break;
-
-abort:
-        (VOID) XENBUS_STORE(TransactionEnd,
-                            &Frontend->StoreInterface,
-                            Transaction,
-                            FALSE);
-        break;
-    }
-    if (!NT_SUCCESS(Status))
-        goto fail4;
-
-    // Frontend: -> INITIALIZED
-    Status = ___SetState(Frontend, XenbusStateInitialised);
-    if (!NT_SUCCESS(Status))
-        goto fail5;
-
-    // Backend : -> CONNECTED
-    BackendState = XenbusStateUnknown;
-    do {
-        Status = __WaitState(Frontend, &BackendState);
-        if (!NT_SUCCESS(Status))
-            goto fail6;
-    } while (BackendState == XenbusStateInitWait ||
-             BackendState == XenbusStateInitialising ||
-             BackendState == XenbusStateInitialised);
-    Status = STATUS_UNSUCCESSFUL;
-    if (BackendState != XenbusStateConnected)
-        goto fail7;
-
-    // read disk info
-    __ReadDiskInfo(Frontend);
-    FrontendReadDiskInfo(Frontend);
-
-    // blkback doesnt write features before InitWait, blkback writes features 
before Connected!
-    FrontendReadFeatures(Frontend);
-
-    // Frontend: -> CONNECTED
-    Status = ___SetState(Frontend, XenbusStateConnected);
-    if (!NT_SUCCESS(Status))
-        goto fail8;
-
-    return STATUS_SUCCESS;
-
-fail8:
-    Error("Fail8\n");
-fail7:
-    Error("Fail7\n");
-fail6:
-    Error("Fail6\n");
-fail5:
-    Error("Fail5\n");
-fail4:
-    Error("Fail4\n");
-    NotifierDisconnect(Frontend->Notifier);
-fail3:
-    Error("Fail3\n");
-    BlockRingDisconnect(Frontend->BlockRing);
-fail2:
-    Error("Fail2\n");
-    GranterDisconnect(Frontend->Granter);
-fail1:
-    Error("Fail1 (%08x)\n", Status);
-    return Status;
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendDisconnect(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    NotifierDisconnect(Frontend->Notifier);
-    BlockRingDisconnect(Frontend->BlockRing);
-    GranterDisconnect(Frontend->Granter);
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendEnable(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    Frontend->Caps.Connected = TRUE;
-    KeMemoryBarrier();
-
-    GranterEnable(Frontend->Granter);
-    BlockRingEnable(Frontend->BlockRing);
-    NotifierEnable(Frontend->Notifier);
-}
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static FORCEINLINE VOID
-FrontendDisable(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    Frontend->Caps.Connected = FALSE;
-
-    NotifierDisable(Frontend->Notifier);
-    BlockRingDisable(Frontend->BlockRing);
-    GranterDisable(Frontend->Granter);
-}
-
-//=============================================================================
-// Init/Term
-static DECLSPEC_NOINLINE NTSTATUS
-__FrontendSetState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  XENVBD_STATE            State
-    )
-{
-    NTSTATUS    Status;
-    const ULONG TargetId = Frontend->TargetId;
-    BOOLEAN     Failed = FALSE;
-
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-    Verbose("Target[%d] : %s ----> %s\n", 
-                TargetId, 
-                __XenvbdStateName(Frontend->State), 
-                __XenvbdStateName(State));
-    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
-    
-    while (!Failed && Frontend->State != State) {
-        switch (Frontend->State) {
-        case XENVBD_INITIALIZED:
-            switch (State) {
-            case XENVBD_CLOSING:
-            case XENVBD_CLOSED:
-            case XENVBD_PREPARED:
-            case XENVBD_CONNECTED:
-            case XENVBD_ENABLED:
-                Status = FrontendClose(Frontend);
-                if (NT_SUCCESS(Status)) {
-                    Frontend->State = XENVBD_CLOSED;
-                } else {
-                    Failed = TRUE;
-                }
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-
-        case XENVBD_CLOSED:
-            switch (State) {
-            case XENVBD_INITIALIZED:
-                // ONLY Closed->Initialized is valid, which can occur with a 
very early resume from suspend
-                // i.e. VM was suspended before the Initianized->Closed 
transition, and each resume needs
-                //      the Close transition to properly close the frontend 
and backend devices.
-                Frontend->State = XENVBD_INITIALIZED;
-                break;
-            case XENVBD_PREPARED:
-            case XENVBD_CONNECTED:
-            case XENVBD_ENABLED:
-                Status = FrontendPrepare(Frontend);
-                if (NT_SUCCESS(Status)) {
-                    Frontend->State = XENVBD_PREPARED;
-                } else {
-                    Status = FrontendClose(Frontend);
-                    if (NT_SUCCESS(Status))
-                        Frontend->State = XENVBD_CLOSED;
-                    else
-                        Frontend->State = XENVBD_STATE_INVALID;
-                    Failed = TRUE;
-                }
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-
-        case XENVBD_PREPARED:
-            switch (State) {
-            case XENVBD_CONNECTED:
-            case XENVBD_ENABLED:
-                Status = FrontendConnect(Frontend);
-                if (NT_SUCCESS(Status)) {
-                    Frontend->State = XENVBD_CONNECTED;
-                } else {
-                    Status = FrontendClose(Frontend);
-                    if (NT_SUCCESS(Status))
-                        Frontend->State = XENVBD_CLOSED;
-                    else
-                        Frontend->State = XENVBD_STATE_INVALID;
-                    Failed = TRUE;
-                }
-                break;
-            case XENVBD_CLOSING:
-            case XENVBD_CLOSED:
-                Status = FrontendClose(Frontend);
-                if (NT_SUCCESS(Status)) {
-                    Frontend->State = XENVBD_CLOSED;
-                } else {
-                    Frontend->State = XENVBD_STATE_INVALID;
-                    Failed = TRUE;
-                }
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-            
-        case XENVBD_CONNECTED:
-            switch (State) {
-            case XENVBD_ENABLED:
-                FrontendEnable(Frontend);
-                Frontend->State = XENVBD_ENABLED;
-                break;
-            case XENVBD_CLOSING:
-            case XENVBD_CLOSED:
-            case XENVBD_PREPARED:
-                Status = FrontendClose(Frontend);
-                Frontend->State = XENVBD_CLOSING;
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-
-        case XENVBD_CLOSING:
-            switch (State) {
-            case XENVBD_INITIALIZED:
-            case XENVBD_CLOSED:
-            case XENVBD_PREPARED:
-            case XENVBD_CONNECTED:
-            case XENVBD_ENABLED:
-                FrontendDisconnect(Frontend);
-                Frontend->State = XENVBD_CLOSED;
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-
-        case XENVBD_ENABLED:
-            switch (State) {
-            case XENVBD_CLOSING:
-            case XENVBD_CLOSED:
-            case XENVBD_PREPARED:
-            case XENVBD_CONNECTED:
-                FrontendDisable(Frontend);
-                Frontend->State = XENVBD_CONNECTED;
-                break;
-            default:
-                Failed = TRUE;
-                break;
-            }
-            break;
-
-        default:
-            Failed = TRUE;
-            break;
-        }
-        Verbose("Target[%d] : in state %s\n", TargetId, 
__XenvbdStateName(Frontend->State));
-    }
-    Trace("Target[%d] @ (%d) <===== (%s)\n", TargetId, KeGetCurrentIrql(), 
Failed ? "FAILED" : "SUCCEEDED");
-    return Failed ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
-}
-
-__drv_requiresIRQL(DISPATCH_LEVEL)
-static DECLSPEC_NOINLINE VOID
-FrontendSuspendLateCallback(
-    __in  PVOID                   Argument
-    )
-{
-    NTSTATUS            Status;
-    XENVBD_STATE        State;
-    PXENVBD_FRONTEND    Frontend = (PXENVBD_FRONTEND)Argument;
-
-    Verbose("Target[%d] : ===> from %s\n", Frontend->TargetId, 
__XenvbdStateName(Frontend->State));
-    State = Frontend->State;
-
-    TargetPreResume(Frontend->Target);
-
-    // dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts 
enabled
-    Status = __FrontendSetState(Frontend, XENVBD_CLOSED);
-    if (!NT_SUCCESS(Status)) {
-        Error("Target[%d] : SetState CLOSED (%08x)\n", Frontend->TargetId, 
Status);
-        ASSERT(FALSE);
-    }
-
-    // dont acquire state lock - called at DISPATCH on 1 vCPU with interrupts 
enabled
-    Status = __FrontendSetState(Frontend, State);
-    if (!NT_SUCCESS(Status)) {
-        Error("Target[%d] : SetState %s (%08x)\n", Frontend->TargetId, 
__XenvbdStateName(State), Status);
-        ASSERT(FALSE);
-    }
-
-    TargetPostResume(Frontend->Target);
-    NotifierTrigger(Frontend->Notifier);
-
-    Verbose("Target[%d] : <=== restored %s\n", Frontend->TargetId, 
__XenvbdStateName(Frontend->State));
-}
-
-__checkReturn
-__drv_maxIRQL(DISPATCH_LEVEL)
-NTSTATUS
-FrontendD3ToD0(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    PXENVBD_ADAPTER Adapter = TargetGetAdapter(Frontend->Target);
-    NTSTATUS    Status;
-    KIRQL       Irql;
-
-    KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
-    // acquire interfaces
-    AdapterGetStoreInterface(Adapter, &Frontend->StoreInterface);
-    AdapterGetSuspendInterface(Adapter, &Frontend->SuspendInterface);
-
-    Status = XENBUS_STORE(Acquire, &Frontend->StoreInterface);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    Status = XENBUS_SUSPEND(Acquire, &Frontend->SuspendInterface);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-
-    // register suspend callback
-    ASSERT3P(Frontend->SuspendLateCallback, ==, NULL);
-    Status = XENBUS_SUSPEND(Register,
-                            &Frontend->SuspendInterface,
-                            SUSPEND_CALLBACK_LATE,
-                            FrontendSuspendLateCallback,
-                            Frontend,
-                            &Frontend->SuspendLateCallback);
-    if (!NT_SUCCESS(Status))
-        goto fail3;
-
-    // update state
-    Frontend->Active = TRUE;
-
-    KeReleaseSpinLock(&Frontend->StateLock, Irql);
-    return STATUS_SUCCESS;
-
-fail3:
-    Error("Fail3\n");
-
-    XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
-    RtlZeroMemory(&Frontend->SuspendInterface, 
sizeof(XENBUS_SUSPEND_INTERFACE));
-
-fail2:
-    Error("Fail2\n");
-
-    XENBUS_STORE(Release, &Frontend->StoreInterface);
-    RtlZeroMemory(&Frontend->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
-fail1:
-    Error("Fail1 (%08x)\n", Status);
-
-    KeReleaseSpinLock(&Frontend->StateLock, Irql);
-    return Status;
-}
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-VOID
-FrontendD0ToD3(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    KIRQL       Irql;
-
-    KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
-    // update state
-    Frontend->Active = FALSE;
-
-    // deregister suspend callback
-    if (Frontend->SuspendLateCallback != NULL) {
-        XENBUS_SUSPEND(Deregister,
-                       &Frontend->SuspendInterface,
-                       Frontend->SuspendLateCallback);
-        Frontend->SuspendLateCallback = NULL;
-    }
-    // Free backend path before dropping store interface
-    if (Frontend->BackendPath) {
-        __FrontendFree(Frontend->BackendPath);
-        Frontend->BackendPath = NULL;
-    }
-
-    // release interfaces
-    XENBUS_SUSPEND(Release, &Frontend->SuspendInterface);
-    RtlZeroMemory(&Frontend->SuspendInterface, 
sizeof(XENBUS_SUSPEND_INTERFACE));
-    
-    XENBUS_STORE(Release, &Frontend->StoreInterface);
-    RtlZeroMemory(&Frontend->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
-    KeReleaseSpinLock(&Frontend->StateLock, Irql);
-}
-
-__checkReturn
-NTSTATUS
-FrontendSetState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  XENVBD_STATE            State
-    )
-{
-    NTSTATUS    Status;
-    KIRQL       Irql;
-
-    KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-
-    Status = __FrontendSetState(Frontend, State);
-
-    KeReleaseSpinLock(&Frontend->StateLock, Irql);
-    return Status;
-}
-
-__checkReturn
-static DECLSPEC_NOINLINE NTSTATUS
-FrontendBackend(
-    __in PXENVBD_THREAD              Thread,
-    __in PVOID                       Context
-    )
-{
-    PXENVBD_FRONTEND                Frontend = Context;
-
-    for (;;) {
-        KIRQL       Irql;
-
-        if (!ThreadWait(Thread))
-            break;
-
-        KeAcquireSpinLock(&Frontend->StateLock, &Irql);
-        // Only attempt this if Active, Active is set/cleared on D3->D0/D0->D3
-        if (Frontend->Active) {
-            __ReadDiskInfo(Frontend);
-            __CheckBackendForEject(Frontend);
-        }
-        KeReleaseSpinLock(&Frontend->StateLock, Irql);
-    }
-
-    return STATUS_SUCCESS;
-
-}
-
-NTSTATUS
-FrontendCreate(
-    IN  PXENVBD_TARGET          Target,
-    IN  PCHAR                   DeviceId, 
-    IN  ULONG                   TargetId, 
-    OUT PXENVBD_FRONTEND*       _Frontend
-    )
-{
-    NTSTATUS            status;
-    PXENVBD_FRONTEND    Frontend;
-
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-
-    Frontend = __FrontendAlloc(sizeof(XENVBD_FRONTEND));
-
-    status = STATUS_NO_MEMORY;
-    if (Frontend == NULL)
-        goto fail1;
-
-    // populate members
-    Frontend->Target = Target;
-    Frontend->TargetId = TargetId;
-    Frontend->DeviceId = strtoul(DeviceId, NULL, 10);
-    Frontend->State = XENVBD_INITIALIZED;
-    Frontend->DiskInfo.SectorSize = 512; // default sector size
-    Frontend->BackendId = DOMID_INVALID;
-    
-    status = RtlStringCbPrintfA(Frontend->FrontendPath,
-                                sizeof(Frontend->FrontendPath),
-                                "device/vbd/%u",
-                                Frontend->DeviceId);
-    if (!NT_SUCCESS(status)) 
-        goto fail2;
-
-    status = RtlStringCbPrintfA(Frontend->TargetPath,
-                                sizeof(Frontend->TargetPath),
-                                "data/scsi/target/%u",
-                                TargetId);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    status = NotifierCreate(Frontend, &Frontend->Notifier);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
-    status = BlockRingCreate(Frontend, Frontend->DeviceId, 
&Frontend->BlockRing);
-    if (!NT_SUCCESS(status))
-        goto fail5;
-
-    status = GranterCreate(Frontend, &Frontend->Granter);
-    if (!NT_SUCCESS(status))
-        goto fail6;
-
-    status = ThreadCreate(FrontendBackend, Frontend, &Frontend->BackendThread);
-    if (!NT_SUCCESS(status))
-        goto fail7;
-
-    // kernel objects
-    KeInitializeSpinLock(&Frontend->StateLock);
-    
-    Trace("Target[%d] @ (%d) <===== (STATUS_SUCCESS)\n", Frontend->TargetId, 
KeGetCurrentIrql());
-    *_Frontend = Frontend;
-    return STATUS_SUCCESS;
-
-fail7:
-    Error("fail7\n");
-    GranterDestroy(Frontend->Granter);
-    Frontend->Granter = NULL;
-fail6:
-    Error("fail6\n");
-    BlockRingDestroy(Frontend->BlockRing);
-    Frontend->BlockRing = NULL;
-fail5:
-    Error("fail5\n");
-    NotifierDestroy(Frontend->Notifier);
-    Frontend->Notifier = NULL;
-fail4:
-    Error("fail4\n");
-fail3:
-    Error("fail3\n");
-fail2:
-    Error("Fail2\n");
-    __FrontendFree(Frontend);
-fail1:
-    Error("Fail1 (%08x)\n", status);
-    *_Frontend = NULL;
-    return status;
-}
-
-VOID
-FrontendDestroy(
-    __in  PXENVBD_FRONTEND        Frontend
-    )
-{
-    const ULONG TargetId = Frontend->TargetId;
-
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-
-    PdoFreeInquiryData(Frontend->Inquiry);
-    Frontend->Inquiry = NULL;
-
-    ThreadAlert(Frontend->BackendThread);
-    ThreadJoin(Frontend->BackendThread);
-    Frontend->BackendThread = NULL;
-
-    GranterDestroy(Frontend->Granter);
-    Frontend->Granter = NULL;
-
-    BlockRingDestroy(Frontend->BlockRing);
-    Frontend->BlockRing = NULL;
-
-    NotifierDestroy(Frontend->Notifier);
-    Frontend->Notifier = NULL;
-
-    ASSERT3P(Frontend->BackendPath, ==, NULL);
-    ASSERT3P(Frontend->Inquiry, ==, NULL);
-    ASSERT3P(Frontend->SuspendLateCallback, ==, NULL);
-    ASSERT3P(Frontend->BackendWatch, ==, NULL);
-
-    __FrontendFree(Frontend);
-    Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
-}
-
-//=============================================================================
-// Debug
-VOID
-FrontendDebugCallback(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  PXENBUS_DEBUG_INTERFACE Debug
-    )
-{
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: TargetId=%d DeviceId=%d BackendId=%d\n",
-                 Frontend->TargetId,
-                 Frontend->DeviceId,
-                 Frontend->BackendId);
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: FrontendPath %s\n",
-                 Frontend->FrontendPath);
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: BackendPath  %s\n",
-                 Frontend->BackendPath ? Frontend->BackendPath : "NULL");
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: TargetPath   %s\n",
-                 Frontend->TargetPath);
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: State   : %s\n",
-                 __XenvbdStateName(Frontend->State));
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: Caps    : %s%s%s%s%s%s\n",
-                 Frontend->Caps.Connected ? "CONNECTED " : "",
-                 Frontend->Caps.Removable ? "REMOVABLE " : "",
-                 Frontend->Caps.SurpriseRemovable ? "SURPRISE " : "",
-                 Frontend->Caps.Paging ? "PAGING " : "",
-                 Frontend->Caps.Hibernation ? "HIBER " : "",
-                 Frontend->Caps.DumpFile ? "DUMP " : "");
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: Features: %s%s%s%s%s\n",
-                 Frontend->Features.Persistent ? "PERSISTENT " : "",
-                 Frontend->Features.Indirect > 0 ? "INDIRECT " : "",
-                 Frontend->DiskInfo.Barrier ? "BARRIER " : "",
-                 Frontend->DiskInfo.FlushCache ? "FLUSH " : "",
-                 Frontend->DiskInfo.Discard ? "DISCARD " : "");
-
-    if (Frontend->Features.Indirect > 0) {
-        XENBUS_DEBUG(Printf, Debug,
-                     "FRONTEND: INDIRECT %x\n",
-                     Frontend->Features.Indirect);
-    }
-    if (Frontend->DiskInfo.Discard) {
-        XENBUS_DEBUG(Printf, Debug,
-                     "FRONTEND: DISCARD %s%x/%x\n",
-                     Frontend->DiskInfo.DiscardSecure ? "SECURE " : "",
-                     Frontend->DiskInfo.DiscardAlignment,
-                     Frontend->DiskInfo.DiscardGranularity);
-    }
-
-    XENBUS_DEBUG(Printf, Debug,
-                 "FRONTEND: DiskInfo: %llu @ %u (%u) %08x\n",
-                 Frontend->DiskInfo.SectorCount,
-                 Frontend->DiskInfo.SectorSize,
-                 Frontend->DiskInfo.PhysSectorSize,
-                 Frontend->DiskInfo.DiskInfo);
-
-    GranterDebugCallback(Frontend->Granter, Debug);
-    BlockRingDebugCallback(Frontend->BlockRing, Debug);
-    NotifierDebugCallback(Frontend->Notifier, Debug);
-}
-
diff --git a/src/xenvbd/frontend.h b/src/xenvbd/frontend.h
deleted file mode 100644
index f466ef8..0000000
--- a/src/xenvbd/frontend.h
+++ /dev/null
@@ -1,198 +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_FRONTEND_H
-#define _XENVBD_FRONTEND_H
-
-#include "target.h"
-#include <debug_interface.h>
-
-typedef enum _XENVBD_STATE {
-    XENVBD_STATE_INVALID,
-    XENVBD_INITIALIZED, // -> { CLOSED }
-    XENVBD_CLOSING,     // -> { CLOSED }
-    XENVBD_CLOSED,      // -> { PREPARED }
-    XENVBD_PREPARED,    // -> { CLOSING, CONNECTED }
-    XENVBD_CONNECTED,   // -> { ENABLED, CLOSING }
-    XENVBD_ENABLED      // -> { CLOSING }
-} XENVBD_STATE, *PXENVBD_STATE;
-
-typedef struct _XENVBD_CAPS {
-    BOOLEAN                     Connected;
-    BOOLEAN                     Removable;
-    BOOLEAN                     SurpriseRemovable;
-    BOOLEAN                     Paging;
-    BOOLEAN                     Hibernation;
-    BOOLEAN                     DumpFile;
-} XENVBD_CAPS, *PXENVBD_CAPS;
-
-typedef struct _XENVBD_FEATURES {
-    ULONG                       Indirect;
-    BOOLEAN                     Persistent;
-} XENVBD_FEATURES, *PXENVBD_FEATURES;
-
-typedef struct _XENVBD_DISKINFO {
-    ULONG64                     SectorCount;
-    ULONG                       SectorSize;
-    ULONG                       PhysSectorSize;
-    ULONG                       DiskInfo;
-    BOOLEAN                     Barrier;
-    BOOLEAN                     FlushCache;
-    BOOLEAN                     Discard;
-    BOOLEAN                     DiscardSecure;
-    ULONG                       DiscardAlignment;
-    ULONG                       DiscardGranularity;
-} XENVBD_DISKINFO, *PXENVBD_DISKINFO;
-
-typedef struct _XENVBD_FRONTEND XENVBD_FRONTEND, *PXENVBD_FRONTEND;
-
-// Accessors
-extern VOID
-FrontendRemoveFeature(
-    IN  PXENVBD_FRONTEND        Frontend,
-    IN  UCHAR                   BlkifOperation
-    );
-extern PXENVBD_CAPS
-FrontendGetCaps(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern PXENVBD_FEATURES
-FrontendGetFeatures(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern PXENVBD_DISKINFO
-FrontendGetDiskInfo(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern ULONG
-FrontendGetTargetId(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern ULONG
-FrontendGetDeviceId(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern PVOID
-FrontendGetInquiry(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-extern PXENVBD_TARGET
-FrontendGetTarget(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-#include "blockring.h"
-extern PXENVBD_BLOCKRING
-FrontendGetBlockRing(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-#include "notifier.h"
-extern PXENVBD_NOTIFIER
-FrontendGetNotifier(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-#include "granter.h"
-extern PXENVBD_GRANTER
-FrontendGetGranter(
-    __in  PXENVBD_FRONTEND      Frontend
-    );
-
-extern NTSTATUS
-FrontendStoreWriteFrontend(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Name,
-    __in  PCHAR                 Value
-    );
-extern NTSTATUS
-FrontendStoreReadBackend(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Name,
-    __out PCHAR*                Value
-    );
-extern VOID
-FrontendStoreFree(
-    __in  PXENVBD_FRONTEND      Frontend,
-    __in  PCHAR                 Value
-    );    
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern NTSTATUS
-FrontendWriteUsage(
-    __in  PXENVBD_FRONTEND        Frontend
-    );
-
-// Ring
-__drv_requiresIRQL(DISPATCH_LEVEL)
-extern VOID
-FrontendNotifyResponses(
-    __in  PXENVBD_FRONTEND        Frontend
-    );
-
-// Init/Term
-__checkReturn
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern NTSTATUS
-FrontendD3ToD0(
-    __in  PXENVBD_FRONTEND        Frontend
-    );
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-extern VOID
-FrontendD0ToD3(
-    __in  PXENVBD_FRONTEND        Frontend
-    );
-
-__checkReturn
-extern NTSTATUS
-FrontendSetState(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  XENVBD_STATE            State
-    );
-
-extern NTSTATUS
-FrontendCreate(
-    IN  PXENVBD_TARGET          Target,
-    IN  PCHAR                   DeviceId, 
-    IN  ULONG                   TargetId, 
-    OUT PXENVBD_FRONTEND*       _Frontend
-    );
-
-extern VOID
-FrontendDestroy(
-    __in  PXENVBD_FRONTEND        Frontend
-    );
-
-// Debug
-extern VOID
-FrontendDebugCallback(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __in  PXENBUS_DEBUG_INTERFACE Debug
-    );
-
-#endif // _XENVBD_FRONTEND_H
diff --git a/src/xenvbd/granter.c b/src/xenvbd/granter.c
index d61b8b2..22147f3 100644
--- a/src/xenvbd/granter.c
+++ b/src/xenvbd/granter.c
@@ -32,50 +32,62 @@
 #include <ntddk.h>
 #include <ntstrsafe.h>
 
-#include "frontend.h"
+#include <gnttab_interface.h>
+#include <debug_interface.h>
+
+#include "granter.h"
 #include "target.h"
 #include "adapter.h"
+
 #include "util.h"
 #include "debug.h"
-#include "thread.h"
-#include <gnttab_interface.h>
+#include "assert.h"
 
 struct _XENVBD_GRANTER {
-    PXENVBD_FRONTEND                Frontend;
-    BOOLEAN                         Connected;
-    BOOLEAN                         Enabled;
+    PXENVBD_TARGET          Target;
+    BOOLEAN                 Connected;
+    BOOLEAN                 Enabled;
+
+    XENBUS_DEBUG_INTERFACE  DebugInterface;
+    XENBUS_GNTTAB_INTERFACE GnttabInterface;
 
-    XENBUS_GNTTAB_INTERFACE         GnttabInterface;
-    PXENBUS_GNTTAB_CACHE            Cache;
-    KSPIN_LOCK                      Lock;
+    PXENBUS_DEBUG_CALLBACK  DebugCallback;
 
-    USHORT                          BackendDomain;
-    LONG                            Current;
-    LONG                            Maximum;
+    PXENBUS_GNTTAB_CACHE    Cache;
+    KSPIN_LOCK              Lock;
+
+    LONG                    Current;
+    LONG                    Maximum;
 };
-#define GRANTER_POOL_TAG            'tnGX'
+#define GRANTER_POOL_TAG    'tnGX'
 
 static FORCEINLINE PVOID
 __GranterAllocate(
-    IN  ULONG                       Length
+    IN  ULONG   Size
     )
 {
-    return __AllocatePoolWithTag(NonPagedPool, Length, GRANTER_POOL_TAG);
+    PVOID       Buffer;
+    Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                   Size,
+                                   GRANTER_POOL_TAG);
+    if (Buffer)
+        RtlZeroMemory(Buffer, Size);
+    return Buffer;
 }
 
 static FORCEINLINE VOID
 __GranterFree(
-    IN  PVOID                       Buffer
+    IN  PVOID   Buffer
     )
 {
     if (Buffer)
-        __FreePoolWithTag(Buffer, GRANTER_POOL_TAG);
+        ExFreePoolWithTag(Buffer, GRANTER_POOL_TAG);
 }
 
 NTSTATUS
 GranterCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    OUT PXENVBD_GRANTER*            Granter
+    IN  PXENVBD_TARGET      Target,
+    OUT PXENVBD_GRANTER*    Granter
     )
 {
     NTSTATUS    status;
@@ -85,7 +97,7 @@ GranterCreate(
     if (*Granter == NULL)
         goto fail1;
 
-    (*Granter)->Frontend = Frontend;
+    (*Granter)->Target = Target;
     KeInitializeSpinLock(&(*Granter)->Lock);
 
     return STATUS_SUCCESS;
@@ -96,10 +108,10 @@ fail1:
 
 VOID
 GranterDestroy(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     )
 {
-    Granter->Frontend = NULL;
+    Granter->Target = NULL;
     RtlZeroMemory(&Granter->Lock, sizeof(KSPIN_LOCK));
 
     ASSERT(IsZeroMemory(Granter, sizeof(XENVBD_GRANTER)));
@@ -134,34 +146,54 @@ GranterReleaseLock(
     KeReleaseSpinLockFromDpcLevel(&Granter->Lock);
 }
 
-#define MAXNAMELEN  32
+static DECLSPEC_NOINLINE VOID
+GranterDebugCallback(
+    IN  PVOID       Context,
+    IN  BOOLEAN     Crashing
+    )
+{
+    PXENVBD_GRANTER Granter = Context;
+
+    UNREFERENCED_PARAMETER(Crashing);
+
+    XENBUS_DEBUG(Printf,
+                 &Granter->DebugInterface,
+                 "%u / %u Grants\n",
+                 Granter->Current,
+                 Granter->Maximum);
+    Granter->Maximum = Granter->Current;
+}
 
 NTSTATUS
 GranterConnect(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  USHORT                      BackendDomain
+    IN  PXENVBD_GRANTER Granter
     )
 {
-    PXENVBD_ADAPTER Adapter = 
TargetGetAdapter(FrontendGetTarget(Granter->Frontend));
-    CHAR        Name[MAXNAMELEN];
-    NTSTATUS    status;
+    PXENVBD_ADAPTER     Adapter;
+    CHAR                Name[sizeof("xenvbd_XXXX_gnttab")];
+    NTSTATUS            status;
 
     ASSERT(Granter->Connected == FALSE);
 
+    Adapter = TargetGetAdapter(Granter->Target);
+
     AdapterGetGnttabInterface(Adapter, &Granter->GnttabInterface);
+    AdapterGetDebugInterface(Adapter, &Granter->DebugInterface);
 
     status = XENBUS_GNTTAB(Acquire, &Granter->GnttabInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    Granter->BackendDomain = BackendDomain;
+    status = XENBUS_DEBUG(Acquire, &Granter->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
     status = RtlStringCbPrintfA(Name,
-                                sizeof (Name),
-                                "disk_%u",
-                                FrontendGetTargetId(Granter->Frontend));
+                                sizeof(Name),
+                                "xenvbd_%u_gnttab",
+                                TargetGetTargetId(Granter->Target));
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail3;
 
     status = XENBUS_GNTTAB(CreateCache,
                            &Granter->GnttabInterface,
@@ -172,37 +204,56 @@ GranterConnect(
                            Granter,
                            &Granter->Cache);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail4;
+
+    status = XENBUS_DEBUG(Register,
+                          &Granter->DebugInterface,
+                          __MODULE__,
+                          GranterDebugCallback,
+                          Granter,
+                          &Granter->DebugCallback);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
     Granter->Connected = TRUE;
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+    XENBUS_GNTTAB(DestroyCache,
+                  &Granter->GnttabInterface,
+                  Granter->Cache);
+    Granter->Cache = NULL;
+fail4:
+    Error("fail4\n");
 fail3:
+    Error("fail3\n");
+    XENBUS_DEBUG(Release, &Granter->DebugInterface);
+    RtlZeroMemory(&Granter->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
 fail2:
-    Granter->BackendDomain = 0;
+    Error("fail2\n");
     XENBUS_GNTTAB(Release, &Granter->GnttabInterface);
     RtlZeroMemory(&Granter->GnttabInterface, sizeof(XENBUS_GNTTAB_INTERFACE));
 fail1:
+    Error("fail1 %08x\n", status);
     return status;
 }
 
 NTSTATUS
 GranterStoreWrite(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
+    IN  PXENVBD_GRANTER Granter,
+    IN  PVOID           Transaction
     )
 {
     UNREFERENCED_PARAMETER(Granter);
     UNREFERENCED_PARAMETER(Transaction);
-    UNREFERENCED_PARAMETER(FrontendPath);
 
     return STATUS_SUCCESS;
 }
 
 VOID
 GranterEnable(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     )
 {
     ASSERT(Granter->Enabled == FALSE);
@@ -212,7 +263,7 @@ GranterEnable(
 
 VOID
 GranterDisable(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     )
 {
     ASSERT(Granter->Enabled == TRUE);
@@ -222,43 +273,33 @@ GranterDisable(
 
 VOID
 GranterDisconnect(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     )
 {
     ASSERT(Granter->Connected == TRUE);
 
-    ASSERT3S(Granter->Current, ==, 0);
+    Granter->Current = 0;
     Granter->Maximum = 0;
 
+    XENBUS_DEBUG(Deregister,
+                 &Granter->DebugInterface,
+                 Granter->DebugCallback);
+    Granter->DebugCallback = NULL;
+
     XENBUS_GNTTAB(DestroyCache,
                   &Granter->GnttabInterface,
                   Granter->Cache);
     Granter->Cache = NULL;
 
+    XENBUS_DEBUG(Release, &Granter->DebugInterface);
+    RtlZeroMemory(&Granter->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+
     XENBUS_GNTTAB(Release, &Granter->GnttabInterface);
     RtlZeroMemory(&Granter->GnttabInterface, sizeof(XENBUS_GNTTAB_INTERFACE));
 
-    Granter->BackendDomain = 0;
     Granter->Connected = FALSE;
 }
 
-VOID
-GranterDebugCallback(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
-    )
-{
-    XENBUS_DEBUG(Printf, Debug,
-                 "GRANTER: %s %s\n", 
-                 Granter->Connected ? "CONNECTED" : "DISCONNECTED",
-                 Granter->Enabled ? "ENABLED" : "DISABLED");
-    XENBUS_DEBUG(Printf, Debug,
-                 "GRANTER: %d / %d\n",
-                 Granter->Current,
-                 Granter->Maximum);
-    Granter->Maximum = Granter->Current;
-}
-
 NTSTATUS
 GranterGet(
     IN  PXENVBD_GRANTER     Granter,
@@ -279,7 +320,7 @@ GranterGet(
                            &Granter->GnttabInterface, 
                            Granter->Cache,
                            FALSE,
-                           Granter->BackendDomain,
+                           TargetGetBackendId(Granter->Target),
                            Pfn,
                            ReadOnly,
                            &Entry);
@@ -294,7 +335,9 @@ GranterGet(
     return STATUS_SUCCESS;
 
 fail2:
+    Error("fail2\n");
 fail1:
+    Error("fail1 %08x\n", status);
     return status;
 }
 
diff --git a/src/xenvbd/granter.h b/src/xenvbd/granter.h
index de7701c..da17698 100644
--- a/src/xenvbd/granter.h
+++ b/src/xenvbd/granter.h
@@ -32,75 +32,67 @@
 #ifndef _XENVBD_GRANTER_H
 #define _XENVBD_GRANTER_H
 
+#include <ntddk.h>
+
 typedef struct _XENVBD_GRANTER XENVBD_GRANTER, *PXENVBD_GRANTER;
 
-#include <debug_interface.h>
-#include <store_interface.h>
-#include "frontend.h"
+#include "target.h"
 
 extern NTSTATUS
 GranterCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    OUT PXENVBD_GRANTER*            Granter
+    IN  PXENVBD_TARGET      Target,
+    OUT PXENVBD_GRANTER*    Granter
     );
 
 extern VOID
 GranterDestroy(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     );
 
 extern NTSTATUS
 GranterConnect(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  USHORT                      BackendDomain
+    IN  PXENVBD_GRANTER Granter
     );
 
 extern NTSTATUS
 GranterStoreWrite(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
+    IN  PXENVBD_GRANTER Granter,
+    IN  PVOID           Transaction
     );
 
 extern VOID
 GranterEnable(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     );
 
 extern VOID
 GranterDisable(
-    IN  PXENVBD_GRANTER             Granter
+    IN  PXENVBD_GRANTER Granter
     );
 
 extern VOID
 GranterDisconnect(
-    IN  PXENVBD_GRANTER             Granter
-    );
-
-extern VOID
-GranterDebugCallback(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
+    IN  PXENVBD_GRANTER Granter
     );
 
 extern NTSTATUS
 GranterGet(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PFN_NUMBER                  Pfn,
-    IN  BOOLEAN                     ReadOnly,
-    OUT PVOID                       *Handle
+    IN  PXENVBD_GRANTER Granter,
+    IN  PFN_NUMBER      Pfn,
+    IN  BOOLEAN         ReadOnly,
+    OUT PVOID           *Handle
     );
 
 extern VOID
 GranterPut(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PVOID                       Handle
+    IN  PXENVBD_GRANTER Granter,
+    IN  PVOID           Handle
     );
 
 extern ULONG
 GranterReference(
-    IN  PXENVBD_GRANTER             Granter,
-    IN  PVOID                       Handle
+    IN  PXENVBD_GRANTER Granter,
+    IN  PVOID           Handle
     );
 
 #endif // _XENVBD_GRANTER_H
diff --git a/src/xenvbd/notifier.c b/src/xenvbd/notifier.c
deleted file mode 100644
index 1e0c057..0000000
--- a/src/xenvbd/notifier.c
+++ /dev/null
@@ -1,334 +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.
- */ 
-
-#include "notifier.h"
-#include "frontend.h"
-#include "target.h"
-#include "adapter.h"
-#include "util.h"
-#include "debug.h"
-#include <evtchn_interface.h>
-
-struct _XENVBD_NOTIFIER {
-    PXENVBD_FRONTEND                Frontend;
-    BOOLEAN                         Connected;
-    BOOLEAN                         Enabled;
-
-    XENBUS_STORE_INTERFACE          StoreInterface;
-    XENBUS_EVTCHN_INTERFACE         EvtchnInterface;
-
-    PXENBUS_EVTCHN_CHANNEL          Channel;
-    ULONG                           Port;
-    ULONG                           NumInts;
-    ULONG                           NumDpcs;
-    KDPC                            Dpc;
-};
-
-#define NOTIFIER_POOL_TAG           'yfNX'
-
-static FORCEINLINE PVOID
-__NotifierAllocate(
-    IN  ULONG                       Length
-    )
-{
-    return __AllocatePoolWithTag(NonPagedPool, Length, NOTIFIER_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-__NotifierFree(
-    IN  PVOID                       Buffer
-    )
-{
-    if (Buffer)
-        __FreePoolWithTag(Buffer, NOTIFIER_POOL_TAG);
-}
-
-KSERVICE_ROUTINE NotifierInterrupt;
-
-BOOLEAN
-NotifierInterrupt(
-    __in  PKINTERRUPT               Interrupt,
-    _In_opt_ PVOID                  Context
-    )
-{
-    PXENVBD_NOTIFIER    Notifier = Context;
-    
-    UNREFERENCED_PARAMETER(Interrupt);
-
-    ASSERT(Notifier != NULL);
-
-       ++Notifier->NumInts;
-       if (Notifier->Connected) {
-               if (KeInsertQueueDpc(&Notifier->Dpc, NULL, NULL)) {
-                       ++Notifier->NumDpcs;
-        }
-       }
-
-    return TRUE;
-}
-
-KDEFERRED_ROUTINE NotifierDpc;
-
-VOID 
-NotifierDpc(
-    __in  PKDPC                     Dpc,
-    __in_opt PVOID                  Context,
-    __in_opt PVOID                  Arg1,
-    __in_opt PVOID                  Arg2
-    )
-{
-    PXENVBD_NOTIFIER    Notifier = Context;
-
-    UNREFERENCED_PARAMETER(Dpc);
-    UNREFERENCED_PARAMETER(Arg1);
-    UNREFERENCED_PARAMETER(Arg2);
-
-    ASSERT(Notifier != NULL);
-
-    if (!Notifier->Connected)
-        return;
-
-    FrontendNotifyResponses(Notifier->Frontend);
-
-    XENBUS_EVTCHN(Unmask,
-                  &Notifier->EvtchnInterface,
-                  Notifier->Channel,
-                  FALSE);
-}
-
-NTSTATUS
-NotifierCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    OUT PXENVBD_NOTIFIER*           Notifier
-    )
-{
-    *Notifier = __NotifierAllocate(sizeof(XENVBD_NOTIFIER));
-    if (*Notifier == NULL)
-        goto fail1;
-
-    (*Notifier)->Frontend = Frontend;
-    KeInitializeDpc(&(*Notifier)->Dpc, NotifierDpc, *Notifier);
-
-    return STATUS_SUCCESS;
-
-fail1:
-    return STATUS_NO_MEMORY;
-}
-
-VOID
-NotifierDestroy(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    Notifier->Frontend = NULL;
-    RtlZeroMemory(&Notifier->Dpc, sizeof(KDPC));
-
-    ASSERT(IsZeroMemory(Notifier, sizeof(XENVBD_NOTIFIER)));
-    
-    __NotifierFree(Notifier);
-}
-
-NTSTATUS
-NotifierConnect(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  USHORT                      BackendDomain
-    )
-{
-    PXENVBD_ADAPTER Adapter = 
TargetGetAdapter(FrontendGetTarget(Notifier->Frontend));
-    NTSTATUS    status;
-
-    ASSERT(Notifier->Connected == FALSE);
-
-    AdapterGetStoreInterface(Adapter, &Notifier->StoreInterface);
-    AdapterGetEvtchnInterface(Adapter, &Notifier->EvtchnInterface);
-
-    status = XENBUS_STORE(Acquire, &Notifier->StoreInterface);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = XENBUS_EVTCHN(Acquire, &Notifier->EvtchnInterface);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    Notifier->Channel = XENBUS_EVTCHN(Open, 
-                                      &Notifier->EvtchnInterface, 
-                                      XENBUS_EVTCHN_TYPE_UNBOUND, 
-                                      NotifierInterrupt,
-                                      Notifier, 
-                                      BackendDomain, 
-                                      TRUE);
-
-    status = STATUS_NO_MEMORY;
-    if (Notifier->Channel == NULL)
-        goto fail3;
-
-    Notifier->Port = XENBUS_EVTCHN(GetPort,
-                                   &Notifier->EvtchnInterface,
-                                   Notifier->Channel);
-
-    XENBUS_EVTCHN(Unmask,
-                  &Notifier->EvtchnInterface,
-                  Notifier->Channel,
-                  FALSE);
-
-    Notifier->Connected = TRUE;
-    return STATUS_SUCCESS;
-
-fail3:
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-    RtlZeroMemory(&Notifier->EvtchnInterface, sizeof(XENBUS_EVTCHN_INTERFACE));
-
-fail2:
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-    RtlZeroMemory(&Notifier->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
-fail1:
-    return status;
-}
-
-NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
-    )
-{
-    return XENBUS_STORE(Printf, 
-                        &Notifier->StoreInterface, 
-                        Transaction, 
-                        FrontendPath, 
-                        "event-channel", 
-                        "%u", 
-                        Notifier->Port);
-}
-
-VOID
-NotifierEnable(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    ASSERT(Notifier->Enabled == FALSE);
-
-    XENBUS_EVTCHN(Trigger,
-                  &Notifier->EvtchnInterface,
-                  Notifier->Channel);
-
-    Notifier->Enabled = TRUE;
-}
-
-VOID
-NotifierDisable(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    ASSERT(Notifier->Enabled == TRUE);
-
-    Notifier->Enabled = FALSE;
-}
-
-VOID
-NotifierDisconnect(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    ASSERT(Notifier->Connected == TRUE);
-
-    XENBUS_EVTCHN(Close,
-                  &Notifier->EvtchnInterface,
-                  Notifier->Channel);
-    Notifier->Channel = NULL;
-    Notifier->Port = 0;
-
-    XENBUS_EVTCHN(Release, &Notifier->EvtchnInterface);
-    RtlZeroMemory(&Notifier->EvtchnInterface, sizeof(XENBUS_EVTCHN_INTERFACE));
-
-    XENBUS_STORE(Release, &Notifier->StoreInterface);
-    RtlZeroMemory(&Notifier->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
-
-    Notifier->NumInts = Notifier->NumDpcs = 0;
-
-    Notifier->Connected = FALSE;
-}
-
-VOID
-NotifierDebugCallback(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
-    )
-{
-    XENBUS_DEBUG(Printf, Debug,
-                 "NOTIFIER: Int / DPC : %d / %d\n",
-                 Notifier->NumInts, Notifier->NumDpcs);
-
-    if (Notifier->Channel) {
-        XENBUS_DEBUG(Printf, Debug,
-                     "NOTIFIER: Channel : %p (%d)\n", 
-                     Notifier->Channel, Notifier->Port);
-    }
-
-    Notifier->NumInts = 0;
-    Notifier->NumDpcs = 0;
-}
-
-VOID
-NotifierKick(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    if (Notifier->Enabled) {
-               if (KeInsertQueueDpc(&Notifier->Dpc, NULL, NULL)) {
-                       ++Notifier->NumDpcs;
-        }
-    }
-}
-
-VOID
-NotifierTrigger(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    if (Notifier->Enabled)
-        XENBUS_EVTCHN(Trigger,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel);
-}
-
-VOID
-NotifierSend(
-    IN  PXENVBD_NOTIFIER            Notifier
-    )
-{
-    if (Notifier->Enabled)
-        XENBUS_EVTCHN(Send,
-                      &Notifier->EvtchnInterface,
-                      Notifier->Channel);
-}
-
diff --git a/src/xenvbd/notifier.h b/src/xenvbd/notifier.h
deleted file mode 100644
index 4cf35e7..0000000
--- a/src/xenvbd/notifier.h
+++ /dev/null
@@ -1,101 +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_NOTIFIER_H
-#define _XENVBD_NOTIFIER_H
-
-typedef struct _XENVBD_NOTIFIER XENVBD_NOTIFIER, *PXENVBD_NOTIFIER;
-
-#include "frontend.h"
-#include <debug_interface.h>
-#include <store_interface.h>
-
-extern NTSTATUS
-NotifierCreate(
-    IN  PXENVBD_FRONTEND            Frontend,
-    OUT PXENVBD_NOTIFIER*           Notifier
-    );
-
-extern VOID
-NotifierDestroy(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern NTSTATUS
-NotifierConnect(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  USHORT                      BackendDomain
-    );
-
-extern NTSTATUS
-NotifierStoreWrite(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  PXENBUS_STORE_TRANSACTION   Transaction,
-    IN  PCHAR                       FrontendPath
-    );
-
-extern VOID
-NotifierEnable(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern VOID
-NotifierDisable(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern VOID
-NotifierDisconnect(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern VOID
-NotifierDebugCallback(
-    IN  PXENVBD_NOTIFIER            Notifier,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug
-    );
-
-extern VOID
-NotifierKick(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern VOID
-NotifierTrigger(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-extern VOID
-NotifierSend(
-    IN  PXENVBD_NOTIFIER            Notifier
-    );
-
-#endif // _XENVBD_NOTIFIER_H
diff --git a/src/xenvbd/pdoinquiry.c b/src/xenvbd/pdoinquiry.c
deleted file mode 100644
index 2608fbf..0000000
--- a/src/xenvbd/pdoinquiry.c
+++ /dev/null
@@ -1,530 +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.
- */ 
-
-#include "pdoinquiry.h"
-#include "driver.h"
-#include "debug.h"
-#include "assert.h"
-#include "util.h"
-#include <xencdb.h>
-#include <xenvbd-ntstrsafe.h>
-#include <stdlib.h>
-
-// "00000000-0000-0000-0000-000000000000"
-#define GUID_LENGTH     36 
-
-// 00 00 00 00 00 00 00 00 "XENSRC  00000000"
-#define PAGE83_MIN_SIZE (4 + 4 + 16)
-
-// 00 00 00 00 + GUID_LENGTH
-#define VDI_ID_LENGTH   (4 + GUID_LENGTH)
-
-#define INQUIRY_POOL_TAG 'qnIX'
-
-typedef struct _XENVBD_PAGE {
-    PCHAR   Data;
-    ULONG   Length;
-} XENVBD_PAGE, *PXENVBD_PAGE;
-
-typedef struct _XENVBD_INQUIRY {
-    XENVBD_PAGE Page80;
-    XENVBD_PAGE Page83;
-    CHAR        VdiUuid[GUID_LENGTH + 1];
-} XENVBD_INQUIRY, *PXENVBD_INQUIRY;
-
-static FORCEINLINE ULONG
-__Min3(
-    __in ULONG  A,
-    __in ULONG  B,
-    __in ULONG  C
-    )
-{
-    return A < B ? __min(A, C) : __min(B, C);
-}
-
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID 
-#pragma warning(suppress: 28195)
-__InquiryAlloc(
-    __in SIZE_T Size
-    )
-{
-    return __AllocatePoolWithTag(NonPagedPool, Size, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__InquiryFree(
-    __in __drv_freesMem(mem) PVOID Buffer
-    )
-{
-    if (Buffer != NULL)
-        __FreePoolWithTag(Buffer, INQUIRY_POOL_TAG);
-}
-
-static FORCEINLINE UCHAR
-__DecodeChar(
-    __in CHAR    Char
-    )
-{
-    if (Char >= 'A' && Char <= 'Z') return Char - 'A';
-    if (Char >= 'a' && Char <= 'z') return Char - 'a' + 26;
-    if (Char >= '0' && Char <= '9') return Char - '0' + 52;
-    if (Char == '+')                return 62;
-    if (Char == '/')                return 63;
-    if (Char == '=')                return 0;
-    return 0xFF;
-}
-static DECLSPEC_NOINLINE UCHAR
-__Decode(
-    __in PUCHAR  Dest,
-    __in PCHAR   Src,
-    __in ULONG   RemainingChars
-    )
-{
-    UCHAR   Values[4]; 
-
-    if (RemainingChars < 4)
-        return 0xFF;
-
-    // take 4 Src chars -> 1, 2, or 3 Dest bytes
-    Values[0] = __DecodeChar(Src[0]);
-    Values[1] = __DecodeChar(Src[1]);
-    Values[2] = __DecodeChar(Src[2]);
-    Values[3] = __DecodeChar(Src[3]);
-
-    // sanity checks
-    if ((Src[0] == '=' || Src[1] == '=') ||
-        (Src[2] == '=' && Src[3] != '='))
-        return 0xFF;
-    if (Values[0] == 0xFF || Values[1] == 0xFF ||
-        Values[2] == 0xFF || Values[3] == 0xFF)
-        return 0xFF;
-
-    // convert
-    Dest[0] = (Values[1] >> 4) | (Values[0] << 2);
-    if (Src[2] == '=')  return 2;
-    Dest[1] = (Values[2] >> 2) | (Values[1] << 4);
-    if (Src[3] == '=')  return 1;
-    Dest[2] = (Values[3]     ) | (Values[2] << 6);
-    return 0;
-}
-__checkReturn
-static NTSTATUS
-__DecodeBase64(
-    __in  PCHAR   Base64,
-    __in  ULONG   Base64Length,
-    __out PVOID   *_Buffer,
-    __out PULONG  BufferLength
-    )
-{
-    // convert Base64(4chars) into Buffer(3bytes)
-    PUCHAR      Buffer;
-    ULONG       NumBlocks;
-    ULONG       i;
-    UCHAR       Pad = 0;
-
-    NumBlocks = Base64Length / 4;
-
-    Buffer = (PUCHAR)__InquiryAlloc(NumBlocks * 3);
-    if (Buffer == NULL) {
-        Error("__InquiryAlloc (STATUS_INSUFFICIENT_RESOURCES)\n");
-        goto fail1;
-    }
-
-    for (i = 0; i < NumBlocks; ++i) {
-        if (Pad)        goto invalid_base64;
-        Pad = __Decode(Buffer + (i * 3), Base64 + (i * 4), Base64Length - (i * 
4));
-        if (Pad > 2)    goto invalid_base64;
-    }
-
-    *BufferLength = (NumBlocks * 3) - Pad;
-    *_Buffer = Buffer;
-    return STATUS_SUCCESS;
-
-invalid_base64:
-    Error("Invalid BASE64 encoding\n");
-    __InquiryFree((PVOID)Buffer);
-    return STATUS_UNSUCCESSFUL;
-
-fail1:
-    return STATUS_INSUFFICIENT_RESOURCES;
-}
-static DECLSPEC_NOINLINE BOOLEAN 
-__ReadPage(
-    __in PXENVBD_FRONTEND       Frontend,
-    __in PXENVBD_PAGE           Page,
-    __in PCHAR                  Path
-    )
-{
-    NTSTATUS    Status;
-    PCHAR       Value;
-
-    Status = FrontendStoreReadBackend(Frontend, Path, &Value);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    Status = __DecodeBase64(Value, (ULONG)strlen(Value), (PVOID*)&Page->Data, 
&Page->Length);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-
-    FrontendStoreFree(Frontend, Value);
-    return TRUE;
-
-fail2:
-    FrontendStoreFree(Frontend, Value);
-fail1:
-    Page->Data = NULL;
-    Page->Length = 0;
-    return FALSE;
-}
-
-static FORCEINLINE BOOLEAN
-__HandlePageStd(
-    __in PSCSI_REQUEST_BLOCK        Srb
-    )
-{
-    PINQUIRYDATA    Data = (PINQUIRYDATA)Srb->DataBuffer;
-    ULONG           Length = Srb->DataTransferLength;
-
-    if (Length < INQUIRYDATABUFFERSIZE)
-        return FALSE;
-
-    Data->DeviceType            = DIRECT_ACCESS_DEVICE;
-    Data->DeviceTypeQualifier   = DEVICE_CONNECTED;
-    Data->Versions              = 4;
-    Data->ResponseDataFormat    = 2;
-    Data->AdditionalLength      = INQUIRYDATABUFFERSIZE - 4;
-    Data->CommandQueue          = 1;
-    RtlCopyMemory(Data->VendorId,               "XENSRC  ", 8);
-    RtlCopyMemory(Data->ProductId,              "PVDISK          ", 16);
-    RtlCopyMemory(Data->ProductRevisionLevel,   "2.0 ", 4);
-
-    Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
-    return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage00(
-    __in PSCSI_REQUEST_BLOCK        Srb
-    )
-{
-    PCHAR   Data = (PCHAR)Srb->DataBuffer;
-    ULONG   Length = Srb->DataTransferLength;
-
-    if (Length < 7)
-        return FALSE;
-    RtlZeroMemory(Data, Length);
-
-    // 00 00 00 NumPages+1 00 [Page [...]]
-    Data[3] = 3;
-    Data[4] = 0x00;
-    Data[5] = 0x80;
-    Data[6] = 0x83;
-    Srb->DataTransferLength = 7;
-
-    return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage80(
-    __in ULONG                      TargetId,
-    __in PXENVBD_INQUIRY            Inquiry,
-    __in PSCSI_REQUEST_BLOCK        Srb
-    )
-{
-    PCHAR   Data = (PCHAR)Srb->DataBuffer;
-    ULONG   Length = Srb->DataTransferLength;
-
-       RtlZeroMemory(Data, Length);
-       if (Inquiry == NULL || 
-        Inquiry->Page80.Data == NULL || 
-        Inquiry->Page80.Length == 0) {
-        // generate the serial number page
-        PVPD_SERIAL_NUMBER_PAGE Serial;
-        if (Length < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
-            return FALSE;
-
-        Serial = (PVPD_SERIAL_NUMBER_PAGE)Data;
-        Serial->PageCode        = 0x80;
-        Serial->PageLength      = 4;
-        (VOID) RtlStringCchPrintfA((PCHAR)Serial->SerialNumber, 5, "%04u", 
TargetId);
-
-        Verbose("Target[%u] : INQUIRY Using Fake Page80 Data\n", TargetId);
-
-        Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4; 
-        // VPD_SERIAL_NUMBER_PAGE includes 1 char already
-    } else {
-        if (Length < Inquiry->Page80.Length)
-            return FALSE;
-
-               RtlCopyMemory(Data, Inquiry->Page80.Data, 
Inquiry->Page80.Length);
-        Srb->DataTransferLength = Inquiry->Page80.Length;
-    }
-
-    // if possible, append additional data
-    //if (Inquiry && Length >= Srb->DataTransferLength + ADDITIONAL_LENGTH) {
-    //    Srb->DataTransferLength += ADDITIONAL_LENGTH;
-    //}
-    return TRUE;
-}
-static FORCEINLINE BOOLEAN
-__HandlePage83(
-    __in ULONG                      TargetId,
-    __in PXENVBD_INQUIRY            Inquiry,
-    __in PSCSI_REQUEST_BLOCK        Srb
-    )
-{
-    PCHAR   Data = (PCHAR)Srb->DataBuffer;
-    ULONG   Length = Srb->DataTransferLength;
-
-    RtlZeroMemory(Data, Length);
-    if (Inquiry == NULL || 
-        Inquiry->Page83.Data == NULL || 
-        Inquiry->Page83.Length == 0) {
-        // generate the id page data
-        PVPD_IDENTIFICATION_DESCRIPTOR  Id;
-        CHAR    Buffer[17];
-
-        if (Length < PAGE83_MIN_SIZE)
-            return FALSE;
-
-        Data[1]                 = 0x83;
-        Data[3]                 = 16;
-
-        Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + 4);
-        Id->CodeSet             = VpdCodeSetAscii;
-        Id->IdentifierType      = VpdIdentifierTypeVendorId;
-        Id->IdentifierLength    = 16;
-        (VOID)RtlStringCchPrintfA(Buffer, 17, "XENSRC  %08u", TargetId);
-        RtlCopyMemory((PCHAR)Id->Identifier, Buffer, 16);
-
-        Verbose("Target[%u] : INQUIRY Using Fake Page83 Data\n", TargetId);
-
-        Srb->DataTransferLength = PAGE83_MIN_SIZE;
-    } else {
-        if (Length < Inquiry->Page83.Length)
-            return FALSE;
-
-        RtlCopyMemory(Data, Inquiry->Page83.Data, Inquiry->Page83.Length);
-        Srb->DataTransferLength = Inquiry->Page83.Length;
-    }
-
-    // if possible, append vdi-uuid as VendorSpecific
-    if (Inquiry && Length >= Srb->DataTransferLength + VDI_ID_LENGTH) {
-        PVPD_IDENTIFICATION_DESCRIPTOR Id;
-        
-        // update internal size
-        *(Data + 3) += VDI_ID_LENGTH;
-
-        // copy new data
-        Id = (PVPD_IDENTIFICATION_DESCRIPTOR)(Data + Srb->DataTransferLength);
-        Id->CodeSet             = VpdCodeSetAscii;
-        Id->IdentifierType      = VpdIdentifierTypeVendorSpecific;
-        Id->IdentifierLength    = GUID_LENGTH;
-        RtlCopyMemory(Id->Identifier, Inquiry->VdiUuid, GUID_LENGTH);        
- 
-        Srb->DataTransferLength += VDI_ID_LENGTH;
-    }
-    return TRUE;
-}
-
-#define MAX_BUFFER      64
-
-static FORCEINLINE VOID
-__TracePage80(
-    __in ULONG                    TargetId,
-    __in PXENVBD_INQUIRY          Inquiry
-    )
-{
-    ULONG           Length;
-    CHAR            Buffer[MAX_BUFFER+1];
-
-    Length = __Min3(Inquiry->Page80.Data[3], MAX_BUFFER, 
Inquiry->Page80.Length - 4);
-    RtlCopyMemory(Buffer, Inquiry->Page80.Data + 4, Length);
-    Buffer[Length] = 0;
-    Verbose("Target[%u] : SerialNumber = \"%s\"\n", TargetId, Buffer);
-}
-static FORCEINLINE VOID
-__TracePage83(
-    __in ULONG                    TargetId,
-    __in PXENVBD_INQUIRY          Inquiry
-    )
-{
-    ULONG           Length;
-    ULONG           Index;
-    CHAR            Buffer[MAX_BUFFER+1];
-
-    for (Index = 4; Index < Inquiry->Page83.Length; ) {
-        PVPD_IDENTIFICATION_DESCRIPTOR Identifier = 
(PVPD_IDENTIFICATION_DESCRIPTOR)&Inquiry->Page83.Data[Index];
-
-        switch (Identifier->CodeSet) {
-        case VpdCodeSetAscii:
-            Length = __Min3(Identifier->IdentifierLength, MAX_BUFFER, 
Inquiry->Page83.Length - Index - 4);
-            RtlCopyMemory(Buffer, Identifier->Identifier, Length);
-            Buffer[Length] = 0;
-            Verbose("Target[%u] : Identifier (ASCII, Type %02x, \"%s\")\n", 
-                    TargetId, Identifier->IdentifierType, Buffer);
-            break;
-
-        default:
-            Verbose("Target[%u] : Identifier (CodeSet %02x, Type %02x, Length 
%02x)\n", 
-                    TargetId, Identifier->CodeSet, Identifier->IdentifierType, 
Identifier->IdentifierLength);
-            break;
-        }
-
-        Index += (4 + Identifier->IdentifierLength);
-    }
-}
-
-VOID
-#pragma warning(suppress: 28195)
-PdoReadInquiryData(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __out __drv_allocatesMem(mem) PVOID* _Inquiry
-    )
-{
-    PXENVBD_INQUIRY Inquiry;
-    const CHAR      GuidNull[] = "00000000-0000-0000-0000-000000000000";
-    const ULONG     TargetId = FrontendGetTargetId(Frontend);
-    
-    *_Inquiry = NULL;
-    Inquiry = (PXENVBD_INQUIRY)__InquiryAlloc(sizeof(XENVBD_INQUIRY));
-    if (Inquiry == NULL) {
-        Error("Target[%d] : Memory allocation getting INQUIRY data (%d bytes 
failed)\n", 
-                TargetId, sizeof(XENVBD_INQUIRY));
-        return;
-    }
-    
-    // initialize VDI-UUID
-    RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
-    Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
-    // read page80
-    if (!__ReadPage(Frontend, &Inquiry->Page80, "sm-data/scsi/0x12/0x80")) {
-        Warning("Target[%d] : Failed to get Page80 data\n", TargetId);
-    } else {
-        __TracePage80(TargetId, Inquiry);
-    }
-
-    // read page83
-    if (!__ReadPage(Frontend, &Inquiry->Page83, "sm-data/scsi/0x12/0x83")) {
-        Warning("Target[%d] : Failed to get Page83 data\n", TargetId);
-    } else {
-        __TracePage83(TargetId, Inquiry);
-    }
-
-    *_Inquiry = Inquiry;
-}
-
-VOID
-PdoFreeInquiryData(
-    __in __drv_freesMem(mem) PVOID _Inquiry
-    )
-{
-    PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
-
-    if (_Inquiry == NULL)
-        return;
-
-    __InquiryFree((PVOID)Inquiry->Page80.Data);
-    __InquiryFree((PVOID)Inquiry->Page83.Data);
-    __InquiryFree((PVOID)Inquiry);
-}
-
-VOID
-PdoUpdateInquiryData(
-    __in  PXENVBD_FRONTEND       Frontend,
-    __in  PVOID                  _Inquiry
-    )
-{
-    PXENVBD_INQUIRY Inquiry = (PXENVBD_INQUIRY)_Inquiry;
-    NTSTATUS        Status;
-    PCHAR           Value;
-    ULONG           Length;
-    const CHAR      GuidNull[] = "00000000-0000-0000-0000-000000000000";
-
-    if (_Inquiry == NULL)
-        return;
-
-    RtlCopyMemory(Inquiry->VdiUuid, GuidNull, GUID_LENGTH);
-    Inquiry->VdiUuid[GUID_LENGTH] = 0;
-
-    Status = FrontendStoreReadBackend(Frontend, "sm-data/vdi-uuid", &Value);
-    if (NT_SUCCESS(Status)) {
-        Length = (ULONG)strlen(Value);
-
-        if (Length == GUID_LENGTH) {
-            RtlCopyMemory(Inquiry->VdiUuid, Value, Length);
-            Inquiry->VdiUuid[GUID_LENGTH] = 0;
-        }
-
-        FrontendStoreFree(Frontend, Value);
-    }
-
-    Verbose("Target[%u] : VDI-UUID = {%s}\n", FrontendGetTargetId(Frontend), 
Inquiry->VdiUuid);
-}
-
-VOID
-PdoInquiry(
-    __in ULONG                   TargetId,
-    __in PVOID                   Inquiry,
-    __in PSCSI_REQUEST_BLOCK     Srb
-    )
-{
-    BOOLEAN         Success;
-    const UCHAR     Evpd = Cdb_EVPD(Srb);
-    const UCHAR     PageCode = Cdb_PageCode(Srb);
-
-    Trace("Target[%d] : INQUIRY %02x%s\n", TargetId, PageCode, Evpd ? " EVPD" 
: "");
-    if (Evpd) {
-        switch (PageCode) {
-        case 0x00:  Success = __HandlePage00(Srb);                      break;
-        case 0x80:  Success = __HandlePage80(TargetId, 
(PXENVBD_INQUIRY)Inquiry, Srb);   break;
-        case 0x83:  Success = __HandlePage83(TargetId, 
(PXENVBD_INQUIRY)Inquiry, Srb);   break;
-        default:    Success = FALSE;                                    break;
-        }
-    } else {
-        switch (PageCode) {
-        case 0x00:  Success = __HandlePageStd(Srb);                     break;
-        default:    Success = FALSE;                                    break;
-        }
-    }
-
-    if (Success) {
-        Srb->ScsiStatus = 0; /* SUCCESS */
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-    } else {
-        Error("Target[%d] : INQUIRY failed %02x%s\n", TargetId, PageCode, Evpd 
? " EVPD" : "");
-        Srb->ScsiStatus = 0x02; /* CHECK_CONDITION */
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-    }
-}
diff --git a/src/xenvbd/pdoinquiry.h b/src/xenvbd/pdoinquiry.h
deleted file mode 100644
index a8cb155..0000000
--- a/src/xenvbd/pdoinquiry.h
+++ /dev/null
@@ -1,64 +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_PDO_INQUIRY_H
-#define _XENVBD_PDO_INQUIRY_H
-
-#include <ntddk.h>
-#include <xenvbd-storport.h>
-#include "frontend.h"
-
-extern VOID
-PdoReadInquiryData(
-    __in  PXENVBD_FRONTEND        Frontend,
-    __out __drv_allocatesMem(mem) PVOID* _Inquiry
-    );
-
-extern VOID
-PdoFreeInquiryData(
-    __in __drv_freesMem(mem) PVOID Inquiry
-    );
-
-extern VOID
-PdoUpdateInquiryData(
-    __in  PXENVBD_FRONTEND       Frontend,
-    __in  PVOID                  _Inquiry
-    );
-
-extern VOID
-PdoInquiry(
-    __in ULONG                   TargetId,
-    __in PVOID                   Inquiry,
-    __in PSCSI_REQUEST_BLOCK     Srb
-    );
-
-#endif // _XENVBD_PDO_INQUIRY_H
-
diff --git a/src/xenvbd/queue.c b/src/xenvbd/queue.c
deleted file mode 100644
index fc70459..0000000
--- a/src/xenvbd/queue.c
+++ /dev/null
@@ -1,139 +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.
- */ 
-
-#include "queue.h"
-#include "debug.h"
-#include "assert.h"
-
-VOID
-QueueInit(
-    __in PXENVBD_QUEUE      Queue
-    )
-{
-    RtlZeroMemory(Queue, sizeof(XENVBD_QUEUE));
-    KeInitializeSpinLock(&Queue->Lock);
-    InitializeListHead(&Queue->List);
-}
-
-ULONG
-QueueCount(
-    __in PXENVBD_QUEUE      Queue
-    )
-{
-    return Queue->Current;
-}
-
-__checkReturn
-PLIST_ENTRY
-QueuePop(
-    __in PXENVBD_QUEUE      Queue
-    )
-{
-    KIRQL       Irql;
-    PLIST_ENTRY Entry = NULL;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
-
-    if (!IsListEmpty(&Queue->List)) {
-        Entry = RemoveHeadList(&Queue->List);
-        ASSERT3P(Entry, !=, &Queue->List);
-        --Queue->Current;
-    }
-
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-
-    return Entry;
-}
-
-VOID
-QueueUnPop(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    )
-{
-    KIRQL               Irql;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
-    
-    InsertHeadList(&Queue->List, Entry);
-    if (++Queue->Current > Queue->Maximum)
-        Queue->Maximum = Queue->Current;
-    
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueAppend(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    )
-{
-    KIRQL               Irql;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
-    
-    InsertTailList(&Queue->List, Entry);
-    if (++Queue->Current > Queue->Maximum)
-        Queue->Maximum = Queue->Current;
-    
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueRemove(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    )
-{
-    KIRQL               Irql;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
-
-    RemoveEntryList(Entry);
-    --Queue->Current;
-    
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-}
-
-VOID
-QueueDebugCallback(
-    __in PXENVBD_QUEUE                  Queue,
-    __in __nullterminated const CHAR*   Name,
-    __in PXENBUS_DEBUG_INTERFACE        Debug
-    )
-{
-    XENBUS_DEBUG(Printf, Debug,
-                 "QUEUE: %s : %u / %u\n",
-                 Name, Queue->Current, Queue->Maximum);
-
-    Queue->Maximum = Queue->Current;
-}
-
diff --git a/src/xenvbd/queue.h b/src/xenvbd/queue.h
deleted file mode 100644
index 0434198..0000000
--- a/src/xenvbd/queue.h
+++ /dev/null
@@ -1,86 +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_QUEUE_H
-#define _XENVBD_QUEUE_H
-
-#include <ntddk.h>
-#include <debug_interface.h>
-
-typedef struct _XENVBD_QUEUE {
-    KSPIN_LOCK          Lock;
-    LIST_ENTRY          List;
-    ULONG               Current;
-    ULONG               Maximum;
-} XENVBD_QUEUE, *PXENVBD_QUEUE;
-
-extern VOID
-QueueInit(
-    __in PXENVBD_QUEUE      Queue
-    );
-
-extern ULONG
-QueueCount(
-    __in PXENVBD_QUEUE      Queue
-    );
-
-__checkReturn
-extern PLIST_ENTRY
-QueuePop(
-    __in PXENVBD_QUEUE      Queue
-    );
-
-extern VOID
-QueueUnPop(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    );
-
-extern VOID
-QueueAppend(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    );
-
-extern VOID
-QueueRemove(
-    __in PXENVBD_QUEUE      Queue,
-    __in PLIST_ENTRY        Entry
-    );
-
-extern VOID
-QueueDebugCallback(
-    __in PXENVBD_QUEUE                  Queue,
-    __in __nullterminated const CHAR*   Name,
-    __in PXENBUS_DEBUG_INTERFACE        Debug
-    );
-
-#endif // _XENVBD_QUEUE_H
diff --git a/src/xenvbd/srbext.h b/src/xenvbd/srbext.h
index 51b5e77..2e79de8 100644
--- a/src/xenvbd/srbext.h
+++ b/src/xenvbd/srbext.h
@@ -37,6 +37,27 @@
 #include <xen.h>
 #include "assert.h"
 
+typedef struct _XENVBD_SRBEXT {
+    PSCSI_REQUEST_BLOCK     Srb;
+    LIST_ENTRY              ListEntry;
+    LONG                    RequestCount;
+} XENVBD_SRBEXT, *PXENVBD_SRBEXT;
+
+typedef struct _XENVBD_REQUEST {
+    PXENVBD_SRBEXT          SrbExt;
+    LIST_ENTRY              ListEntry;
+    ULONG64                 Id; // = (ULONG64)(ULONG_PTR)this
+
+    UCHAR                   Operation;  // 
BLKIF_OP_{READ/WRITE/BARRIER/DISCARD}
+    UCHAR                   Flags;      // BLKIF_OP_DISCARD only
+    USHORT                  NrSegments; // BLKIF_OP_{READ/WRITE} only, 0-11 
(direct) or 11-4096 (indirect)
+    LIST_ENTRY              Segments;   // BLKIF_OP_{READ/WRITE} only
+
+    ULONG64                 FirstSector;
+    ULONG64                 NrSectors;  // BLKIF_OP_DISCARD only
+    LIST_ENTRY              Indirects;  // BLKIF_OP_{READ/WRITE} with 
NrSegments > 11 only
+} XENVBD_REQUEST, *PXENVBD_REQUEST;
+
 #pragma pack(push, 1)
 typedef struct _BLKIF_SEGMENT {
     ULONG                   GrantRef;
@@ -46,19 +67,18 @@ typedef struct _BLKIF_SEGMENT {
 } BLKIF_SEGMENT, *PBLKIF_SEGMENT;
 #pragma pack(pop)
 
-#define XENVBD_MAX_SEGMENTS_PER_PAGE    (PAGE_SIZE / sizeof(BLKIF_SEGMENT))
+#define XENVBD_MAX_SEGMENTS_PER_PAGE        (PAGE_SIZE / sizeof(BLKIF_SEGMENT))
+#define XENVBD_MAX_SEGMENTS_PER_INDIRECT    (XENVBD_MAX_SEGMENTS_PER_PAGE * 2) 
// limited Indirecting
 
-// Internal indirect context
 typedef struct _XENVBD_INDIRECT {
-    LIST_ENTRY              Entry;
+    LIST_ENTRY              ListEntry;
     PBLKIF_SEGMENT          Page;
     PVOID                   Grant;
     PMDL                    Mdl;
 } XENVBD_INDIRECT, *PXENVBD_INDIRECT;
 
-// Internal segment context
 typedef struct _XENVBD_SEGMENT {
-    LIST_ENTRY              Entry;
+    LIST_ENTRY              ListEntry;
     PVOID                   Grant;
     UCHAR                   FirstSector;
     UCHAR                   LastSector;
@@ -69,27 +89,4 @@ typedef struct _XENVBD_SEGMENT {
     PFN_NUMBER              Pfn[2];
 } XENVBD_SEGMENT, *PXENVBD_SEGMENT;
 
-// Internal request context
-typedef struct _XENVBD_REQUEST {
-    PSCSI_REQUEST_BLOCK     Srb;
-    LIST_ENTRY              Entry;
-    ULONG                   Id;
-
-    UCHAR                   Operation;  // 
BLKIF_OP_{READ/WRITE/BARRIER/DISCARD}
-    UCHAR                   Flags;      // BLKIF_OP_DISCARD only
-    USHORT                  NrSegments; // BLKIF_OP_{READ/WRITE} only, 0-11 
(direct) or 11-4096 (indirect)
-    LIST_ENTRY              Segments;   // BLKIF_OP_{READ/WRITE} only
-
-    ULONG64                 FirstSector;
-    ULONG64                 NrSectors;  // BLKIF_OP_DISCARD only
-    LIST_ENTRY              Indirects;  // BLKIF_OP_{READ/WRITE} with 
NrSegments > 11 only
-} XENVBD_REQUEST, *PXENVBD_REQUEST;
-
-// SRBExtension - context for SRBs
-typedef struct _XENVBD_SRBEXT {
-    PSCSI_REQUEST_BLOCK     Srb;
-    LIST_ENTRY              ListEntry;
-    LONG                    RequestCount;
-} XENVBD_SRBEXT, *PXENVBD_SRBEXT;
-
 #endif // _XENVBD_SRBEXT_H
diff --git a/src/xenvbd/target.c b/src/xenvbd/target.c
index c939738..5b14a73 100644
--- a/src/xenvbd/target.c
+++ b/src/xenvbd/target.c
@@ -37,25 +37,91 @@
 #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 "target.h"
 #include "driver.h"
 #include "adapter.h"
-#include "frontend.h"
-#include "queue.h"
+#include "thread.h"
 #include "srbext.h"
 #include "buffer.h"
-#include "pdoinquiry.h"
+#include "granter.h"
+#include "blockring.h"
 
 #include "util.h"
 #include "debug.h"
 #include "assert.h"
 
-#define XENVBD_MAX_QUEUE_DEPTH          (254)
+#define TARGET_POOL_TAG         'raTX'
+#define REQUEST_POOL_TAG        'qeRX'
+#define SEGMENT_POOL_TAG        'geSX'
+#define INDIRECT_POOL_TAG       'dnIX'
+#define XENVBD_MAX_QUEUE_DEPTH  (254)
+
+typedef enum _XENVBD_STATE {
+    XENVBD_STATE_INVALID,
+    XENVBD_INITIALIZED, // -> { CLOSED }
+    XENVBD_CLOSING,     // -> { CLOSED }
+    XENVBD_CLOSED,      // -> { PREPARED }
+    XENVBD_PREPARED,    // -> { CLOSING, CONNECTED }
+    XENVBD_CONNECTED,   // -> { ENABLED, CLOSING }
+    XENVBD_ENABLED      // -> { CLOSING }
+} XENVBD_STATE;
+
+struct _XENVBD_TARGET {
+    PXENVBD_ADAPTER             Adapter;
+    PDEVICE_OBJECT              DeviceObject;
+    DEVICE_PNP_STATE            PrevPnpState;
+    DEVICE_PNP_STATE            DevicePnpState;
+    DEVICE_POWER_STATE          DevicePowerState;
+    XENVBD_STATE                State;
+    KSPIN_LOCK                  StateLock;
+    KSPIN_LOCK                  QueueLock;
+    BOOLEAN                     Missing;
+    PXENVBD_GRANTER             Granter;
+    PXENVBD_BLOCKRING           BlockRing;
+
+    ULONG                       DeviceId;
+    ULONG                       TargetId;
+    PCHAR                       Path;
+    PCHAR                       TargetPath;
+    PCHAR                       BackendPath;
+    USHORT                      BackendId;
+
+    BOOLEAN                     DeviceUsage[4];
+    ULONG64                     SectorCount;
+    ULONG                       SectorSize;
+    ULONG                       PhysicalSectorSize;
+    ULONG                       DiskInfo;
+    BOOLEAN                     Removable;
+    BOOLEAN                     FeatureBarrier;
+    BOOLEAN                     FeatureFlush;
+    BOOLEAN                     FeatureDiscard;
+    BOOLEAN                     DiscardSecure;
+    ULONG                       DiscardAlignment;
+    ULONG                       DiscardGranularity;
+    ULONG                       FeatureIndirect;
+
+    XENBUS_DEBUG_INTERFACE      DebugInterface;
+    XENBUS_SUSPEND_INTERFACE    SuspendInterface;
+    XENBUS_STORE_INTERFACE      StoreInterface;
+
+    PXENBUS_DEBUG_CALLBACK      DebugCallback;
+    PXENBUS_SUSPEND_CALLBACK    SuspendCallback;
+
+    PXENVBD_THREAD              BackendThread;
+    PXENBUS_STORE_WATCH         BackendWatch;
+
+    LIST_ENTRY                  Fresh;
+    LIST_ENTRY                  Prepared;
+    LIST_ENTRY                  Submitted;
+    LIST_ENTRY                  Shutdown;
+
+    NPAGED_LOOKASIDE_LIST       RequestList;
+    NPAGED_LOOKASIDE_LIST       SegmentList;
+    NPAGED_LOOKASIDE_LIST       IndirectList;
+};
 
 typedef struct _XENVBD_SG_LIST {
     // SGList from SRB
@@ -69,182 +135,129 @@ typedef struct _XENVBD_SG_LIST {
     ULONG                       Length;
 } XENVBD_SG_LIST, *PXENVBD_SG_LIST;
 
-#define TARGET_SIGNATURE           'odpX'
+static FORCEINLINE VOID
+SGListInit(
+    IN OUT  PXENVBD_SG_LIST     SGList,
+    IN  PVOID                   Adapter,
+    IN  PSCSI_REQUEST_BLOCK     Srb
+    )
+{
+    RtlZeroMemory(SGList, sizeof(XENVBD_SG_LIST));
+    SGList->SGList = StorPortGetScatterGatherList(Adapter, Srb);
+}
 
-typedef struct _XENVBD_LOOKASIDE {
-    KEVENT                      Empty;
-    LONG                        Used;
-    LONG                        Max;
-    ULONG                       Failed;
-    ULONG                       Size;
-    NPAGED_LOOKASIDE_LIST       List;
-} XENVBD_LOOKASIDE, *PXENVBD_LOOKASIDE;
+static FORCEINLINE VOID
+SGListGet(
+    IN OUT  PXENVBD_SG_LIST         SGList
+    )
+{
+    PSTOR_SCATTER_GATHER_ELEMENT    SGElement;
+    ULONG                           Offset;
 
-struct _XENVBD_TARGET {
-    ULONG                       Signature;
-    PXENVBD_ADAPTER                 Adapter;
-    PDEVICE_OBJECT              DeviceObject;
-    DEVICE_PNP_STATE            DevicePnpState;
-    DEVICE_PNP_STATE            PrevPnpState;
-    DEVICE_POWER_STATE          DevicePowerState;
-    KSPIN_LOCK                  Lock;
+    ASSERT3U(SGList->Index, <, SGList->SGList->NumberOfElements);
 
-    // Frontend (Ring, includes XenBus interfaces)
-    PXENVBD_FRONTEND            Frontend;
+    SGElement = &SGList->SGList->List[SGList->Index];
 
-    // State
-    LONG                        Paused;
+    SGList->PhysAddr.QuadPart = SGElement->PhysicalAddress.QuadPart + 
SGList->Offset;
+    Offset = (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
+    SGList->PhysLen           = __min(PAGE_SIZE - Offset - SGList->Length,
+                                      SGElement->Length - SGList->Offset);
 
-    // Eject
-    BOOLEAN                     WrittenEjected;
-    BOOLEAN                     EjectRequested;
-    BOOLEAN                     EjectPending;
-    BOOLEAN                     Missing;
-    const CHAR*                 Reason;
-
-    // SRBs
-    XENVBD_LOOKASIDE            RequestList;
-    XENVBD_LOOKASIDE            SegmentList;
-    XENVBD_LOOKASIDE            IndirectList;
-    XENVBD_QUEUE                FreshSrbs;
-    XENVBD_QUEUE                PreparedReqs;
-    XENVBD_QUEUE                SubmittedReqs;
-    XENVBD_QUEUE                ShutdownSrbs;
-    ULONG                       NextTag;
-
-    // Stats - SRB Counts by BLKIF_OP_
-    ULONG                       BlkOpRead;
-    ULONG                       BlkOpWrite;
-    ULONG                       BlkOpIndirectRead;
-    ULONG                       BlkOpIndirectWrite;
-    ULONG                       BlkOpBarrier;
-    ULONG                       BlkOpDiscard;
-    ULONG                       BlkOpFlush;
-    // Stats - Failures
-    ULONG                       FailedMaps;
-    ULONG                       FailedBounces;
-    ULONG                       FailedGrants;
-    // Stats - Segments
-    ULONG64                     SegsGranted;
-    ULONG64                     SegsBounced;
-};
+    ASSERT3U(SGList->PhysLen, <=, PAGE_SIZE);
+    ASSERT3U(SGList->Offset, <, SGElement->Length);
 
-//=============================================================================
-#define TARGET_POOL_TAG            'odPX'
-#define REQUEST_POOL_TAG        'qeRX'
-#define SEGMENT_POOL_TAG        'geSX'
-#define INDIRECT_POOL_TAG       'dnIX'
+    SGList->Length = SGList->PhysLen; // gets reset every time for Granted, 
every 1or2 times for Bounced
+    SGList->Offset = SGList->Offset + SGList->PhysLen;
+    if (SGList->Offset >= SGElement->Length) {
+        SGList->Index  = SGList->Index + 1;
+        SGList->Offset = 0;
+    }
+}
 
-__checkReturn
-__drv_allocatesMem(mem)
-__bcount(Size)
-static FORCEINLINE PVOID
-#pragma warning(suppress: 28195)
-__TargetAlloc(
-    __in ULONG  Size
+static FORCEINLINE BOOLEAN
+SGListNext(
+    IN OUT  PXENVBD_SG_LIST         SGList,
+    IN  ULONG                       AlignmentMask
     )
 {
-    return __AllocatePoolWithTag(NonPagedPool, Size, TARGET_POOL_TAG);
+    SGList->Length = 0;
+    SGListGet(SGList);  // get next PhysAddr and PhysLen
+    return !((SGList->PhysAddr.QuadPart & AlignmentMask) || (SGList->PhysLen & 
AlignmentMask));
 }
 
-static FORCEINLINE VOID
-#pragma warning(suppress: 28197)
-__TargetFree(
-    __in __drv_freesMem(mem) PVOID Buffer
+static FORCEINLINE PFN_NUMBER
+SGListPfn(
+    IN  PXENVBD_SG_LIST SGList
     )
 {
-    if (Buffer)
-        __FreePoolWithTag(Buffer, TARGET_POOL_TAG);
+    return (PFN_NUMBER)(SGList->PhysAddr.QuadPart >> PAGE_SHIFT);
 }
 
-//=============================================================================
-// Lookasides
-static FORCEINLINE VOID
-__LookasideInit(
-    IN OUT  PXENVBD_LOOKASIDE   Lookaside,
-    IN  ULONG                   Size,
-    IN  ULONG                   Tag
+static FORCEINLINE ULONG
+SGListOffset(
+    IN  PXENVBD_SG_LIST SGList
     )
 {
-    RtlZeroMemory(Lookaside, sizeof(XENVBD_LOOKASIDE));
-    Lookaside->Size = Size;
-    KeInitializeEvent(&Lookaside->Empty, SynchronizationEvent, TRUE);
-    ExInitializeNPagedLookasideList(&Lookaside->List, NULL, NULL, 0,
-                                    Size, Tag, 0);
+    return (ULONG)(SGList->PhysAddr.QuadPart & (PAGE_SIZE - 1));
 }
 
-static FORCEINLINE VOID
-__LookasideTerm(
-    IN  PXENVBD_LOOKASIDE       Lookaside
+static FORCEINLINE ULONG
+SGListLength(
+    IN  PXENVBD_SG_LIST SGList
     )
 {
-    ASSERT3U(Lookaside->Used, ==, 0);
-    ExDeleteNPagedLookasideList(&Lookaside->List);
-    RtlZeroMemory(Lookaside, sizeof(XENVBD_LOOKASIDE));
+    return SGList->PhysLen;
 }
 
 static FORCEINLINE PVOID
-__LookasideAlloc(
-    IN  PXENVBD_LOOKASIDE       Lookaside
+__TargetAllocate(
+    IN  ULONG   Size
     )
 {
-    LONG    Result;
-    PVOID   Buffer;
-
-    Buffer = ExAllocateFromNPagedLookasideList(&Lookaside->List);
-    if (Buffer == NULL) {
-        ++Lookaside->Failed;
-        return NULL;
-    }
-
-    RtlZeroMemory(Buffer, Lookaside->Size);
-    Result = InterlockedIncrement(&Lookaside->Used);
-    ASSERT3S(Result, >, 0);
-    if (Result > Lookaside->Max)
-        Lookaside->Max = Result;
-    KeClearEvent(&Lookaside->Empty);
-
+    PVOID       Buffer;
+    Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                   Size,
+                                   TARGET_POOL_TAG);
+    if (Buffer)
+        RtlZeroMemory(Buffer, Size);
     return Buffer;
 }
 
 static FORCEINLINE VOID
-__LookasideFree(
-    IN  PXENVBD_LOOKASIDE       Lookaside,
-    IN  PVOID                   Buffer
+__TargetFree(
+    IN  PVOID   Buffer
     )
 {
-    LONG            Result;
+    if (Buffer)
+        ExFreePoolWithTag(Buffer, TARGET_POOL_TAG);
+}
 
-    ExFreeToNPagedLookasideList(&Lookaside->List, Buffer);
-    Result = InterlockedDecrement(&Lookaside->Used);
-    ASSERT3S(Result, >=, 0);
-        
-    if (Result == 0) {
-        KeSetEvent(&Lookaside->Empty, IO_NO_INCREMENT, FALSE);
-    }
+#define TARGET_GET_PROPERTY(_name, _type)       \
+_type                                           \
+TargetGet ## _name ## (                         \
+    IN  PXENVBD_TARGET  Target                  \
+    )                                           \
+{                                               \
+    return Target-> ## _name ## ;               \
 }
 
-static FORCEINLINE VOID
-__LookasideDebug(
-    IN  PXENVBD_LOOKASIDE           Lookaside,
-    IN  PXENBUS_DEBUG_INTERFACE     Debug,
-    IN  PCHAR                       Name
-    )
-{
-    XENBUS_DEBUG(Printf, Debug,
-                 "LOOKASIDE: %s: %u / %u (%u failed)\n",
-                 Name, Lookaside->Used,
-                 Lookaside->Max, Lookaside->Failed);
+TARGET_GET_PROPERTY(DeviceId, ULONG)
+TARGET_GET_PROPERTY(TargetId, ULONG)
+TARGET_GET_PROPERTY(DeviceObject, PDEVICE_OBJECT)
+TARGET_GET_PROPERTY(Missing, BOOLEAN)
+TARGET_GET_PROPERTY(DevicePnpState, DEVICE_PNP_STATE)
+TARGET_GET_PROPERTY(Adapter, PXENVBD_ADAPTER)
+TARGET_GET_PROPERTY(Granter, PXENVBD_GRANTER)
+TARGET_GET_PROPERTY(Path, PCHAR)
+TARGET_GET_PROPERTY(BackendPath, PCHAR)
+TARGET_GET_PROPERTY(BackendId, USHORT)
+TARGET_GET_PROPERTY(Removable, BOOLEAN)
 
-    Lookaside->Max = Lookaside->Used;
-    Lookaside->Failed = 0;
-}
+#undef TARGET_GET_PROPERTY
 
-//=============================================================================
-// Debug
 static FORCEINLINE PCHAR
-__PnpStateName(
-    __in DEVICE_PNP_STATE        State
+DevicePnpStateName(
+    IN  DEVICE_PNP_STATE    State
     )
 {
     switch (State) {
@@ -258,294 +271,81 @@ __PnpStateName(
     case RemovePending:         return "RemovePending";
     case SurpriseRemovePending: return "SurpriseRemovePending";
     case Deleted:               return "Deleted";
-    default:                    return "UNKNOWN";
-    }
-}
-
-DECLSPEC_NOINLINE VOID
-TargetDebugCallback(
-    __in PXENVBD_TARGET Target,
-    __in PXENBUS_DEBUG_INTERFACE DebugInterface
-    )
-{
-    if (Target == NULL || DebugInterface == NULL)
-        return;
-    if (Target->Signature != TARGET_SIGNATURE)
-        return;
-
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: Adapter 0x%p DeviceObject 0x%p\n",
-                 Target->Adapter,
-                 Target->DeviceObject);
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: DevicePnpState %s (%s)\n",
-                 __PnpStateName(Target->DevicePnpState),
-                 __PnpStateName(Target->PrevPnpState));
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: DevicePowerState %s\n",
-                 PowerDeviceStateName(Target->DevicePowerState));
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: %s\n",
-                 Target->Missing ? Target->Reason : "Not Missing");
-
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: BLKIF_OPs: READ=%u WRITE=%u\n",
-                 Target->BlkOpRead, Target->BlkOpWrite);
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: BLKIF_OPs: INDIRECT_READ=%u INDIRECT_WRITE=%u\n",
-                 Target->BlkOpIndirectRead, Target->BlkOpIndirectWrite);
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: BLKIF_OPs: BARRIER=%u DISCARD=%u FLUSH=%u\n",
-                 Target->BlkOpBarrier, Target->BlkOpDiscard, 
Target->BlkOpFlush);
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: Failed: Maps=%u Bounces=%u Grants=%u\n",
-                 Target->FailedMaps, Target->FailedBounces, 
Target->FailedGrants);
-    XENBUS_DEBUG(Printf, DebugInterface,
-                 "TARGET: Segments Granted=%llu Bounced=%llu\n",
-                 Target->SegsGranted, Target->SegsBounced);
-
-    __LookasideDebug(&Target->RequestList, DebugInterface, "REQUESTs");
-    __LookasideDebug(&Target->SegmentList, DebugInterface, "SEGMENTs");
-    __LookasideDebug(&Target->IndirectList, DebugInterface, "INDIRECTs");
-
-    QueueDebugCallback(&Target->FreshSrbs,    "Fresh    ", DebugInterface);
-    QueueDebugCallback(&Target->PreparedReqs, "Prepared ", DebugInterface);
-    QueueDebugCallback(&Target->SubmittedReqs, "Submitted", DebugInterface);
-    QueueDebugCallback(&Target->ShutdownSrbs, "Shutdown ", DebugInterface);
-
-    FrontendDebugCallback(Target->Frontend, DebugInterface);
-
-    Target->BlkOpRead = Target->BlkOpWrite = 0;
-    Target->BlkOpIndirectRead = Target->BlkOpIndirectWrite = 0;
-    Target->BlkOpBarrier = Target->BlkOpDiscard = Target->BlkOpFlush = 0;
-    Target->FailedMaps = Target->FailedBounces = Target->FailedGrants = 0;
-    Target->SegsGranted = Target->SegsBounced = 0;
-}
-
-//=============================================================================
-// Power States
-__checkReturn
-static FORCEINLINE BOOLEAN
-TargetSetDevicePowerState(
-    __in PXENVBD_TARGET             Target,
-    __in DEVICE_POWER_STATE      State
-    )
-{
-    KIRQL       Irql;
-    BOOLEAN     Changed = FALSE;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    if (Target->DevicePowerState != State) {
-        Verbose("Target[%d] : POWER %s to %s\n", TargetGetTargetId(Target), 
PowerDeviceStateName(Target->DevicePowerState), PowerDeviceStateName(State));
-        Target->DevicePowerState = State;
-        Changed = TRUE;
-    }
-    KeReleaseSpinLock(&Target->Lock, Irql);
-    
-    return Changed;
-}
-
-//=============================================================================
-// PnP States
-FORCEINLINE VOID
-TargetSetMissing(
-    __in PXENVBD_TARGET             Target,
-    __in __nullterminated const CHAR* Reason
-    )
-{
-    KIRQL   Irql;
-
-    ASSERT3P(Reason, !=, NULL);
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    if (Target->Missing) {
-        Verbose("Target[%d] : Already MISSING (%s) when trying to set (%s)\n", 
TargetGetTargetId(Target), Target->Reason, Reason);
-    } else {
-        Verbose("Target[%d] : MISSING %s\n", TargetGetTargetId(Target), 
Reason);
-        Target->Missing = TRUE;
-        Target->Reason = Reason;
+    default:                    return "<UNKNOWN>";
     }
-    KeReleaseSpinLock(&Target->Lock, Irql);
-}
-
-__checkReturn
-FORCEINLINE BOOLEAN
-TargetIsMissing(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    KIRQL   Irql;
-    BOOLEAN Missing;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    Missing = Target->Missing;
-    KeReleaseSpinLock(&Target->Lock, Irql);
-
-    return Missing;
 }
 
-FORCEINLINE const CHAR*
-TargetMissingReason(
-    __in PXENVBD_TARGET            Target
+static FORCEINLINE VOID
+TargetRestoreDevicePnpState(
+    IN  PXENVBD_TARGET      Target
     )
 {
-    KIRQL       Irql;
-    const CHAR* Reason;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    Reason = Target->Reason;
-    KeReleaseSpinLock(&Target->Lock, Irql);
-
-    return Reason;
+    Verbose("[%u] %s --> %s\n",
+            Target->TargetId,
+            DevicePnpStateName(Target->DevicePnpState),
+            DevicePnpStateName(Target->PrevPnpState));
+    Target->DevicePnpState = Target->PrevPnpState;
 }
 
-FORCEINLINE VOID
+VOID
 TargetSetDevicePnpState(
-    __in PXENVBD_TARGET             Target,
-    __in DEVICE_PNP_STATE        State
+    IN  PXENVBD_TARGET      Target,
+    IN  DEVICE_PNP_STATE    State
     )
 {
-    Verbose("Target[%d] : PNP %s to %s\n",
-            TargetGetTargetId(Target),
-            __PnpStateName(Target->DevicePnpState),
-            __PnpStateName(State));
-
-    if (Target->DevicePnpState == Deleted)
-        return;
-
+    Verbose("[%u] %s --> %s\n",
+            Target->TargetId,
+            DevicePnpStateName(Target->DevicePnpState),
+            DevicePnpStateName(State));
     Target->PrevPnpState = Target->DevicePnpState;
     Target->DevicePnpState = State;
 }
-
-__checkReturn
-FORCEINLINE DEVICE_PNP_STATE
-TargetGetDevicePnpState(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    return Target->DevicePnpState;
-}
-
-static FORCEINLINE VOID
-__TargetRestoreDevicePnpState(
-    __in PXENVBD_TARGET             Target,
-    __in DEVICE_PNP_STATE        State
-    )
-{
-    if (Target->DevicePnpState == State) {
-        Verbose("Target[%d] : PNP %s to %s\n", TargetGetTargetId(Target), 
__PnpStateName(Target->DevicePnpState), __PnpStateName(Target->PrevPnpState));
-        Target->DevicePnpState = Target->PrevPnpState;
-    }
-}
-
-//=============================================================================
-// Query Methods
-FORCEINLINE ULONG
-TargetGetTargetId(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    ASSERT3P(Target, !=, NULL);
-    return FrontendGetTargetId(Target->Frontend);
-}
-
-ULONG
-TargetGetDeviceId(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    ASSERT3P(Target, !=, NULL);
-    return FrontendGetDeviceId(Target->Frontend);
-}
-
-__checkReturn
-FORCEINLINE PDEVICE_OBJECT
-TargetGetDeviceObject(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    ASSERT3P(Target, !=, NULL);
-    return Target->DeviceObject;
-}
-
-FORCEINLINE VOID
+VOID
 TargetSetDeviceObject(
-    __in PXENVBD_TARGET             Target,
-    __in PDEVICE_OBJECT          DeviceObject
+    IN  PXENVBD_TARGET  Target,
+    IN  PDEVICE_OBJECT  DeviceObject
     )
 {
-    Verbose("Target[%d] : Setting DeviceObject = 0x%p\n", 
TargetGetTargetId(Target), DeviceObject);
-
-    ASSERT3P(Target->DeviceObject, ==, NULL);
+    Verbose("[%u] DevObj = 0x%p\n",
+            Target->TargetId,
+            DeviceObject);
     Target->DeviceObject = DeviceObject;
 }
 
-__checkReturn
-FORCEINLINE BOOLEAN
-TargetIsPaused(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    BOOLEAN Paused;
-    KIRQL   Irql;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    Paused = (Target->Paused > 0);
-    KeReleaseSpinLock(&Target->Lock, Irql);
-    
-    return Paused;
-}
-
-__checkReturn
-FORCEINLINE ULONG
-TargetOutstandingReqs(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    return QueueCount(&Target->SubmittedReqs);
-}
-
-__checkReturn
-FORCEINLINE PXENVBD_ADAPTER
-TargetGetAdapter( 
-    __in PXENVBD_TARGET             Target
-    )
-{
-    return Target->Adapter;
-}
-
-FORCEINLINE ULONG
-TargetSectorSize(
-    __in PXENVBD_TARGET             Target
+VOID
+TargetSetMissing(
+    IN  PXENVBD_TARGET  Target,
+    IN  const CHAR*     Reason
     )
 {
-    return FrontendGetDiskInfo(Target->Frontend)->SectorSize;
+    Verbose("[%u] Missing: %s\n", Target->TargetId, Reason);
+    Target->Missing = TRUE;
 }
 
-//=============================================================================
 static PXENVBD_INDIRECT
 TargetGetIndirect(
-    IN  PXENVBD_TARGET             Target
+    IN  PXENVBD_TARGET  Target
     )
 {
     PXENVBD_INDIRECT    Indirect;
     NTSTATUS            status;
-    PXENVBD_GRANTER     Granter = FrontendGetGranter(Target->Frontend);
 
-    Indirect = __LookasideAlloc(&Target->IndirectList);
+    Indirect = ExAllocateFromNPagedLookasideList(&Target->IndirectList);
     if (Indirect == NULL)
         goto fail1;
 
     RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
 
+    InitializeListHead(&Indirect->ListEntry);
     Indirect->Mdl = __AllocatePage();
     if (Indirect->Mdl == NULL)
         goto fail2;
 
     Indirect->Page = MmGetSystemAddressForMdlSafe(Indirect->Mdl,
                                                   NormalPagePriority);
+    ASSERT(Indirect->Page != NULL);
 
-    status = GranterGet(Granter,
+    status = GranterGet(Target->Granter,
                         MmGetMdlPfnArray(Indirect->Mdl)[0],
                         TRUE,
                         &Indirect->Grant);
@@ -557,40 +357,43 @@ TargetGetIndirect(
 fail3:
     __FreePage(Indirect->Mdl);
 fail2:
-    __LookasideFree(&Target->IndirectList, Indirect);
+    RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
+    ExFreeToNPagedLookasideList(&Target->IndirectList, Indirect);
 fail1:
     return NULL;
 }
 
 static VOID
 TargetPutIndirect(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_INDIRECT        Indirect
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_INDIRECT    Indirect
     )
 {
-    PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
-
     if (Indirect->Grant)
-        GranterPut(Granter, Indirect->Grant);
+        GranterPut(Target->Granter, Indirect->Grant);
+
     if (Indirect->Page)
         __FreePage(Indirect->Mdl);
 
     RtlZeroMemory(Indirect, sizeof(XENVBD_INDIRECT));
-    __LookasideFree(&Target->IndirectList, Indirect);
+    ExFreeToNPagedLookasideList(&Target->IndirectList, Indirect);
 }
 
 static PXENVBD_SEGMENT
 TargetGetSegment(
-    IN  PXENVBD_TARGET             Target
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_SEGMENT             Segment;
+    PXENVBD_SEGMENT     Segment;
 
-    Segment = __LookasideAlloc(&Target->SegmentList);
+    Segment = ExAllocateFromNPagedLookasideList(&Target->SegmentList);
     if (Segment == NULL)
         goto fail1;
 
     RtlZeroMemory(Segment, sizeof(XENVBD_SEGMENT));
+
+    InitializeListHead(&Segment->ListEntry);
+
     return Segment;
 
 fail1:
@@ -599,38 +402,38 @@ fail1:
 
 static VOID
 TargetPutSegment(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_SEGMENT         Segment
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SEGMENT Segment
     )
 {
-    PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
-
     if (Segment->Grant)
-        GranterPut(Granter, Segment->Grant);
+        GranterPut(Target->Granter, Segment->Grant);
+ 
+    if (Segment->Buffer)
+        MmUnmapLockedPages(Segment->Buffer, &Segment->Mdl);
 
     if (Segment->BufferId)
         BufferPut(Segment->BufferId);
 
-    if (Segment->Buffer)
-        MmUnmapLockedPages(Segment->Buffer, &Segment->Mdl);
-
     RtlZeroMemory(Segment, sizeof(XENVBD_SEGMENT));
-    __LookasideFree(&Target->SegmentList, Segment);
+    ExFreeToNPagedLookasideList(&Target->SegmentList, Segment);
 }
 
 static PXENVBD_REQUEST
 TargetGetRequest(
-    IN  PXENVBD_TARGET             Target
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_REQUEST             Request;
+    PXENVBD_REQUEST     Request;
 
-    Request = __LookasideAlloc(&Target->RequestList);
+    Request = ExAllocateFromNPagedLookasideList(&Target->RequestList);
     if (Request == NULL)
         goto fail1;
 
     RtlZeroMemory(Request, sizeof(XENVBD_REQUEST));
-    Request->Id = (ULONG)InterlockedIncrement((PLONG)&Target->NextTag);
+    Request->Id = (ULONG64)(ULONG_PTR)Request;
+
+    InitializeListHead(&Request->ListEntry);
     InitializeListHead(&Request->Segments);
     InitializeListHead(&Request->Indirects);
 
@@ -642,1694 +445,2398 @@ fail1:
 
 static VOID
 TargetPutRequest(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_REQUEST         Request
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_REQUEST     Request
     )
 {
-    PLIST_ENTRY     Entry;
-
     for (;;) {
-        PXENVBD_SEGMENT Segment;
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_INDIRECT    Indirect;
 
-        Entry = RemoveHeadList(&Request->Segments);
-        if (Entry == &Request->Segments)
+        ListEntry = RemoveHeadList(&Request->Indirects);
+        if (ListEntry == &Request->Indirects)
             break;
-        Segment = CONTAINING_RECORD(Entry, XENVBD_SEGMENT, Entry);
-        TargetPutSegment(Target, Segment);
-    }
 
+        Indirect = CONTAINING_RECORD(ListEntry, XENVBD_INDIRECT, ListEntry);
+        TargetPutIndirect(Target, Indirect);
+    }
     for (;;) {
-        PXENVBD_INDIRECT    Indirect;
+        PLIST_ENTRY         ListEntry;
+        PXENVBD_SEGMENT     Segment;
 
-        Entry = RemoveHeadList(&Request->Indirects);
-        if (Entry == &Request->Indirects)
+        ListEntry = RemoveHeadList(&Request->Segments);
+        if (ListEntry == &Request->Segments)
             break;
-        Indirect = CONTAINING_RECORD(Entry, XENVBD_INDIRECT, Entry);
-        TargetPutIndirect(Target, Indirect);
+
+        Segment = CONTAINING_RECORD(ListEntry, XENVBD_SEGMENT, ListEntry);
+        TargetPutSegment(Target, Segment);
     }
 
     RtlZeroMemory(Request, sizeof(XENVBD_REQUEST));
-    __LookasideFree(&Target->RequestList, Request);
+    ExFreeToNPagedLookasideList(&Target->RequestList, Request);
 }
 
-static FORCEINLINE PXENVBD_REQUEST
-TargetRequestFromTag(
-    IN  PXENVBD_TARGET             Target,
-    IN  ULONG                   Tag
+static FORCEINLINE BOOLEAN
+BufferMap(
+    IN  PXENVBD_SEGMENT Segment,
+    IN  PXENVBD_SG_LIST SGList,
+    IN  ULONG           Length
     )
 {
-    KIRQL           Irql;
-    PLIST_ENTRY     Entry;
-    PXENVBD_QUEUE   Queue = &Target->SubmittedReqs;
-
-    KeAcquireSpinLock(&Queue->Lock, &Irql);
-
-    for (Entry = Queue->List.Flink; Entry != &Queue->List; Entry = 
Entry->Flink) {
-        PXENVBD_REQUEST Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, 
Entry);
-        if (Request->Id == Tag) {
-            RemoveEntryList(&Request->Entry);
-            --Queue->Current;
-            KeReleaseSpinLock(&Queue->Lock, Irql);
-            return Request;
-        }
+    // map PhysAddr to 1 or 2 pages and lock for VirtAddr
+#pragma warning(push)
+#pragma warning(disable:28145)
+    Segment->Mdl.Next           = NULL;
+    Segment->Mdl.Size           = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
+    Segment->Mdl.MdlFlags       = MDL_PAGES_LOCKED;
+    Segment->Mdl.Process        = NULL;
+    Segment->Mdl.MappedSystemVa = NULL;
+    Segment->Mdl.StartVa        = NULL;
+    Segment->Mdl.ByteCount      = SGListLength(SGList);
+    Segment->Mdl.ByteOffset     = SGListOffset(SGList);
+    Segment->Pfn[0]             = SGListPfn(SGList);
+
+    if (Segment->Mdl.ByteCount < Length) {
+        // need part of next page
+        SGListGet(SGList);
+        Segment->Mdl.Size       += sizeof(PFN_NUMBER);
+        Segment->Mdl.ByteCount  = Segment->Mdl.ByteCount + 
SGListLength(SGList);
+        Segment->Pfn[1]         = SGListPfn(SGList);
     }
+#pragma warning(pop)
 
-    KeReleaseSpinLock(&Queue->Lock, Irql);
-    Warning("Target[%d] : Tag %x not found in submitted list (%u items)\n",
-            TargetGetTargetId(Target), Tag, QueueCount(Queue));
-    return NULL;
-}
+    ASSERT3U(Segment->Mdl.ByteCount, <=, PAGE_SIZE);
+    ASSERT3U(Segment->Mdl.ByteCount, ==, Length);
+                
+    Segment->Length = min(Segment->Mdl.ByteCount, PAGE_SIZE);
+    Segment->Buffer = MmMapLockedPagesSpecifyCache(&Segment->Mdl,
+                                                   KernelMode,
+                                                   MmCached,
+                                                   NULL,
+                                                   FALSE,
+                                                   NormalPagePriority);
+    if (Segment->Buffer == NULL)
+        goto fail;
 
-static FORCEINLINE VOID
-__TargetIncBlkifOpCount(
-    __in PXENVBD_TARGET             Target,
-    __in PXENVBD_REQUEST         Request
-    )
-{
-    switch (Request->Operation) {
-    case BLKIF_OP_READ:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
-            ++Target->BlkOpIndirectRead;
-        else
-            ++Target->BlkOpRead;
-        break;
-    case BLKIF_OP_WRITE:
-        if (Request->NrSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST)
-            ++Target->BlkOpIndirectWrite;
-        else
-            ++Target->BlkOpWrite;
-        break;
-    case BLKIF_OP_WRITE_BARRIER:
-        ++Target->BlkOpBarrier;
-        break;
-    case BLKIF_OP_DISCARD:
-        ++Target->BlkOpDiscard;
-        break;
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        ++Target->BlkOpFlush;
-        break;
-    default:
-        ASSERT(FALSE);
-        break;
-    }
-}
+    ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[0], ==, Segment->Pfn[0]);
+    // if only 1 Pfn is used, this triggers an array-out-of-bounds condition!
+    //ASSERT3P(MmGetMdlPfnArray(&Segment->Mdl)[1], ==, Segment->Pfn[1]);
+ 
+    return TRUE;
 
-static FORCEINLINE ULONG
-__SectorsPerPage(
-    __in ULONG                   SectorSize
-    )
-{
-    ASSERT3U(SectorSize, !=, 0);
-    return PAGE_SIZE / SectorSize;
+fail:
+    return FALSE;
 }
 
-static FORCEINLINE VOID
-__Operation(
-    __in UCHAR                   CdbOp,
-    __out PUCHAR                 RingOp,
-    __out PBOOLEAN               ReadOnly
+static BOOLEAN
+TargetPrepareRW(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt,
+    IN  UCHAR           Operation
     )
 {
-    switch (CdbOp) {
-    case SCSIOP_READ:
-        *RingOp     = BLKIF_OP_READ;
-        *ReadOnly   = FALSE;
-        break;
-    case SCSIOP_WRITE:
-        *RingOp     = BLKIF_OP_WRITE;
-        *ReadOnly   = TRUE;
-        break;
-    default:
-        ASSERT(FALSE);
-    }
-}
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    ULONG64             SectorStart = Cdb_LogicalBlock(Srb);
+    ULONG               SectorsLeft = Cdb_TransferBlock(Srb);
+    LIST_ENTRY          List;
+    XENVBD_SG_LIST      SGList;
+    KIRQL               Irql;
+    const ULONG         SectorSize = Target->SectorSize;
+    const ULONG         SectorMask = SectorSize - 1;
+    const ULONG         SectorsPerPage = PAGE_SIZE / SectorSize;
 
-static FORCEINLINE ULONG
-__Offset(
-    __in STOR_PHYSICAL_ADDRESS   PhysAddr
-    )
-{
-    return (ULONG)(PhysAddr.QuadPart & (PAGE_SIZE - 1));
-}
+    InitializeListHead(&List);
+    SGListInit(&SGList, TargetGetAdapter(Target), Srb);
 
-static FORCEINLINE PFN_NUMBER
-__Phys2Pfn(
-    __in STOR_PHYSICAL_ADDRESS   PhysAddr
-    )
-{
-    return (PFN_NUMBER)(PhysAddr.QuadPart >> PAGE_SHIFT);
-}
+    // validate SectorStart, SectorsLeft fits in this target (prevent 
read/write beyond extents)
 
-static FORCEINLINE PFN_NUMBER
-__Virt2Pfn(
-    __in PVOID                   VirtAddr
-    )
-{
-    return (PFN_NUMBER)(MmGetPhysicalAddress(VirtAddr).QuadPart >> PAGE_SHIFT);
-}
+    while (SectorsLeft > 0) {
+        PXENVBD_REQUEST Request;
+        ULONG           Index;
+        ULONG           MaxSegments;
 
-static FORCEINLINE MM_PAGE_PRIORITY
-__TargetPriority(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    PXENVBD_CAPS   Caps = FrontendGetCaps(Target->Frontend);
-    if (!(Caps->Paging || 
-          Caps->Hibernation || 
-          Caps->DumpFile))
-        return NormalPagePriority;
+        MaxSegments = Target->FeatureIndirect;
+        MaxSegments = min(MaxSegments, XENVBD_MAX_SEGMENTS_PER_INDIRECT); // 
limit to sensible value
+        MaxSegments = max(MaxSegments, BLKIF_MAX_SEGMENTS_PER_REQUEST);   // 
ensure at least 11
+        ASSERT3U(MaxSegments, >=, BLKIF_MAX_SEGMENTS_PER_REQUEST);
+        ASSERT3U(MaxSegments, <=, XENVBD_MAX_SEGMENTS_PER_INDIRECT);
 
-    return HighPagePriority;
-}
-
-static FORCEINLINE VOID
-SGListGet(
-    IN OUT  PXENVBD_SG_LIST         SGList
-    )
-{
-    PSTOR_SCATTER_GATHER_ELEMENT    SGElement;
-
-    ASSERT3U(SGList->Index, <, SGList->SGList->NumberOfElements);
+        Request = TargetGetRequest(Target);
+        if (Request == NULL) 
+            goto fail1;
+        InsertTailList(&List, &Request->ListEntry);
+        InterlockedIncrement(&SrbExt->RequestCount);
+        
+        Request->SrbExt     = SrbExt;
+        Request->Operation  = Operation;
+        Request->FirstSector = SectorStart;
+
+        // build segments
+        for (Index = 0; Index < MaxSegments; ++Index) {
+            PXENVBD_SEGMENT Segment;
+            ULONG           SectorsNow;
+            PFN_NUMBER      Pfn;
+            NTSTATUS        status;
+
+            if (SectorsLeft == 0)
+                break;
+
+            Segment = TargetGetSegment(Target);
+            if (Segment == NULL)
+                goto fail2;
+            InsertTailList(&Request->Segments, &Segment->ListEntry);
+            ++Request->NrSegments;
+
+            if (SGListNext(&SGList, SectorMask)) {
+                ASSERT((SGListOffset(&SGList) & SectorMask) == 0);
+
+                Segment->FirstSector = (UCHAR)(SGListOffset(&SGList) / 
SectorSize);
+                SectorsNow           = min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
+                Segment->LastSector  = (UCHAR)(Segment->FirstSector + 
SectorsNow - 1);
+
+                Pfn = SGListPfn(&SGList);
+            } else {
+                ASSERT((SGListOffset(&SGList) & SectorMask) != 0);
+
+                Segment->FirstSector = (UCHAR)0;
+                SectorsNow           = min(SectorsLeft, SectorsPerPage);
+                Segment->LastSector  = (UCHAR)(SectorsNow - 1);
+
+                if (!BufferMap(Segment, &SGList, SectorsNow * SectorSize))
+                    goto fail3;
+
+                if (!BufferGet(Segment, &Segment->BufferId, &Pfn))
+                    goto fail4;
+
+                if (Operation == BLKIF_OP_WRITE) {
+                    BufferCopyIn(Segment->BufferId,
+                                 Segment->Buffer,
+                                 Segment->Length);
+                }
+            }
+
+            status = GranterGet(Target->Granter,
+                                Pfn,
+                                Operation == BLKIF_OP_WRITE,
+                                &Segment->Grant);
+            if (!NT_SUCCESS(status))
+                goto fail5;
+
+            SectorStart += SectorsNow;
+            SectorsLeft -= SectorsNow;
+        }
 
-    SGElement = &SGList->SGList->List[SGList->Index];
+        // build indirects
+        if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+            // round up
+            ULONG   NumInd = (Request->NrSegments + 
XENVBD_MAX_SEGMENTS_PER_PAGE - 1) /
+                              XENVBD_MAX_SEGMENTS_PER_PAGE;
 
-    SGList->PhysAddr.QuadPart = SGElement->PhysicalAddress.QuadPart + 
SGList->Offset;
-    SGList->PhysLen           = __min(PAGE_SIZE - __Offset(SGList->PhysAddr) - 
SGList->Length, SGElement->Length - SGList->Offset);
+            ASSERT(NumInd <= BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST);
+            while (NumInd--) {
+                PXENVBD_INDIRECT    Indirect;
 
-    ASSERT3U(SGList->PhysLen, <=, PAGE_SIZE);
-    ASSERT3U(SGList->Offset, <, SGElement->Length);
+                Indirect = TargetGetIndirect(Target);
+                if (Indirect == NULL)
+                    goto fail6;
 
-    SGList->Length = SGList->PhysLen; // gets reset every time for Granted, 
every 1or2 times for Bounced
-    SGList->Offset = SGList->Offset + SGList->PhysLen;
-    if (SGList->Offset >= SGElement->Length) {
-        SGList->Index  = SGList->Index + 1;
-        SGList->Offset = 0;
+                InsertTailList(&Request->Indirects, &Indirect->ListEntry);
+            }
+        }
     }
-}
-
-static FORCEINLINE BOOLEAN
-SGListNext(
-    IN OUT  PXENVBD_SG_LIST         SGList,
-    IN  ULONG                       AlignmentMask
-    )
-{
-    SGList->Length = 0;
-    SGListGet(SGList);  // get next PhysAddr and PhysLen
-    return !((SGList->PhysAddr.QuadPart & AlignmentMask) || (SGList->PhysLen & 
AlignmentMask));
-}
 
-static FORCEINLINE BOOLEAN
-MapSegmentBuffer(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_SEGMENT         Segment,
-    IN  PXENVBD_SG_LIST         SGList,
-    IN  ULONG                   SectorSize,
-    IN  ULONG                   SectorsNow
-    )
-{
-    PMDL    Mdl;
+    Srb->SrbStatus = SRB_STATUS_PENDING;
 
-    // map PhysAddr to 1 or 2 pages and lock for VirtAddr
-#pragma warning(push)
-#pragma warning(disable:28145)
-    Mdl = &Segment->Mdl;
-    Mdl->Next           = NULL;
-    Mdl->Size           = (SHORT)(sizeof(MDL) + sizeof(PFN_NUMBER));
-    Mdl->MdlFlags       = MDL_PAGES_LOCKED;
-    Mdl->Process        = NULL;
-    Mdl->MappedSystemVa = NULL;
-    Mdl->StartVa        = NULL;
-    Mdl->ByteCount      = SGList->PhysLen;
-    Mdl->ByteOffset     = __Offset(SGList->PhysAddr);
-    Segment->Pfn[0]     = __Phys2Pfn(SGList->PhysAddr);
-
-    if (SGList->PhysLen < SectorsNow * SectorSize) {
-        SGListGet(SGList);
-        Mdl->Size       += sizeof(PFN_NUMBER);
-        Mdl->ByteCount  = Mdl->ByteCount + SGList->PhysLen;
-        Segment->Pfn[1] = __Phys2Pfn(SGList->PhysAddr);
-    }
-#pragma warning(pop)
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
 
-    ASSERT((Mdl->ByteCount & (SectorSize - 1)) == 0);
-    ASSERT3U(Mdl->ByteCount, <=, PAGE_SIZE);
-    ASSERT3U(SectorsNow, ==, (Mdl->ByteCount / SectorSize));
-                
-    Segment->Length = __min(Mdl->ByteCount, PAGE_SIZE);
-    Segment->Buffer = MmMapLockedPagesSpecifyCache(Mdl, KernelMode,
-                            MmCached, NULL, FALSE, __TargetPriority(Target));
-    if (!Segment->Buffer) {
-        goto fail;
+        ListEntry = RemoveHeadList(&List);
+        if (ListEntry == &List)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        InsertTailList(&Target->Prepared, &Request->ListEntry);
     }
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-    ASSERT3P(MmGetMdlPfnArray(Mdl)[0], ==, Segment->Pfn[0]);
-    ASSERT3P(MmGetMdlPfnArray(Mdl)[1], ==, Segment->Pfn[1]);
- 
     return TRUE;
 
-fail:
+fail6:
+fail5:
+fail4:
+fail3:
+fail2:
+fail1:
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
+
+        ListEntry = RemoveHeadList(&List);
+        if (ListEntry == &List)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        TargetPutRequest(Target, Request);
+    }
     return FALSE;
 }
 
-static FORCEINLINE VOID
-RequestCopyOutput(
-    __in PXENVBD_REQUEST         Request
+static BOOLEAN
+TargetPrepareUnmap(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    PLIST_ENTRY     Entry;
-
-    if (Request->Operation != BLKIF_OP_READ)
-        return;
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PUNMAP_LIST_HEADER  Unmap = Srb->DataBuffer;
+       ULONG               Count;
+    ULONG               Index;
+    LIST_ENTRY          List;
+    KIRQL               Irql;
 
-    for (Entry = Request->Segments.Flink;
-            Entry != &Request->Segments;
-            Entry = Entry->Flink) {
-        PXENVBD_SEGMENT Segment = CONTAINING_RECORD(Entry, XENVBD_SEGMENT, 
Entry);
+    InitializeListHead(&List);
+    Count = _byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) / 
+            sizeof(UNMAP_BLOCK_DESCRIPTOR);
 
-        if (Segment->BufferId)
-            BufferCopyOut(Segment->BufferId, Segment->Buffer, Segment->Length);
-    }
-}
+    for (Index = 0; Index < Count; ++Index) {
+        PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
+        PXENVBD_REQUEST         Request;
 
-static BOOLEAN
-PrepareSegment(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_SEGMENT         Segment,
-    IN  PXENVBD_SG_LIST         SGList,
-    IN  BOOLEAN                 ReadOnly,
-    IN  ULONG                   SectorsLeft,
-    OUT PULONG                  SectorsNow
-    )
-{
-    PFN_NUMBER      Pfn;
-    NTSTATUS        Status;
-    PXENVBD_GRANTER Granter = FrontendGetGranter(Target->Frontend);
-    const ULONG     SectorSize = TargetSectorSize(Target);
-    const ULONG     SectorsPerPage = __SectorsPerPage(SectorSize);
-
-    if (SGListNext(SGList, SectorSize - 1)) {
-        ++Target->SegsGranted;
-        // get first sector, last sector and count
-        Segment->FirstSector    = (UCHAR)((__Offset(SGList->PhysAddr) + 
SectorSize - 1) / SectorSize);
-        *SectorsNow             = __min(SectorsLeft, SectorsPerPage - 
Segment->FirstSector);
-        Segment->LastSector     = (UCHAR)(Segment->FirstSector + *SectorsNow - 
1);
-        Segment->BufferId       = NULL; // granted, ensure its null
-        Segment->Buffer         = NULL; // granted, ensure its null
-        Segment->Length         = 0;    // granted, ensure its 0
-        Pfn                     = __Phys2Pfn(SGList->PhysAddr);
-
-        ASSERT3U((SGList->PhysLen / SectorSize), ==, *SectorsNow);
-        ASSERT3U((SGList->PhysLen & (SectorSize - 1)), ==, 0);
-    } else {
-        ++Target->SegsBounced;
-        // get first sector, last sector and count
-        Segment->FirstSector    = 0;
-        *SectorsNow             = __min(SectorsLeft, SectorsPerPage);
-        Segment->LastSector     = (UCHAR)(*SectorsNow - 1);
-
-        // map SGList to Virtual Address. Populates Segment->Buffer and 
Segment->Length
-        if (!MapSegmentBuffer(Target, Segment, SGList, SectorSize, 
*SectorsNow)) {
-            ++Target->FailedMaps;
+        Request = TargetGetRequest(Target);
+        if (Request == NULL)
             goto fail1;
-        }
-
-        // get a buffer
-        if (!BufferGet(Segment, &Segment->BufferId, &Pfn)) {
-            ++Target->FailedBounces;
-            goto fail2;
-        }
+        InsertTailList(&List, &Request->ListEntry);
+        InterlockedIncrement(&SrbExt->RequestCount);
 
-        // copy contents in
-        if (ReadOnly) { // Operation == BLKIF_OP_WRITE
-            BufferCopyIn(Segment->BufferId, Segment->Buffer, Segment->Length);
-        }
+        Request->SrbExt         = SrbExt;
+        Request->Operation      = BLKIF_OP_DISCARD;
+        Request->FirstSector    = 
_byteswap_uint64(*(PULONG64)Descr->StartingLba);
+        Request->NrSectors      = _byteswap_ulong(*(PULONG)Descr->LbaCount);
+        Request->Flags          = 0;
     }
 
-    // Grant segment's page
-    Status = GranterGet(Granter, Pfn, ReadOnly, &Segment->Grant);
-    if (!NT_SUCCESS(Status)) {
-        ++Target->FailedGrants;
-        goto fail3;
+    Srb->SrbStatus = SRB_STATUS_PENDING;
+
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
+
+        ListEntry = RemoveHeadList(&List);
+        if (ListEntry == &List)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        InsertTailList(&Target->Prepared, &Request->ListEntry);
     }
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
     return TRUE;
 
-fail3:
-fail2:
-fail1:
+fail1: 
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
+
+        ListEntry = RemoveHeadList(&List);
+        if (ListEntry == &List)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        TargetPutRequest(Target, Request);
+    }
     return FALSE;
 }
 
 static BOOLEAN
-PrepareBlkifReadWrite(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_REQUEST         Request,
-    IN  PXENVBD_SG_LIST         SGList,
-    IN  ULONG                   MaxSegments,
-    IN  ULONG64                 SectorStart,
-    IN  ULONG                   SectorsLeft,
-    OUT PULONG                  SectorsDone
+TargetPrepareSync(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt,
+    IN  UCHAR           Operation
     )
 {
-    UCHAR           Operation;
-    BOOLEAN         ReadOnly;
-    ULONG           Index;
-    __Operation(Cdb_OperationEx(Request->Srb), &Operation, &ReadOnly);
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PXENVBD_REQUEST     Request;
+    KIRQL               Irql;
 
-    Request->Operation  = Operation;
-    Request->NrSegments = 0;
-    Request->FirstSector = SectorStart;
-
-    for (Index = 0;
-                Index < MaxSegments &&
-                SectorsLeft > 0;
-                        ++Index) {
-        PXENVBD_SEGMENT Segment;
-        ULONG           SectorsNow;
-
-        Segment = TargetGetSegment(Target);
-        if (Segment == NULL)
-            goto fail1;
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    Request = TargetGetRequest(Target);
+    if (Request == NULL)
+        return FALSE;
+    InterlockedIncrement(&SrbExt->RequestCount);
 
-        InsertTailList(&Request->Segments, &Segment->Entry);
-        ++Request->NrSegments;
+    Request->SrbExt     = SrbExt;
+    Request->Operation  = Operation;
+    Request->FirstSector = Cdb_LogicalBlock(Srb);
 
-        if (!PrepareSegment(Target,
-                            Segment,
-                            SGList,
-                            ReadOnly,
-                            SectorsLeft,
-                            &SectorsNow))
-            goto fail2;
+    Srb->SrbStatus = SRB_STATUS_PENDING;
 
-        *SectorsDone += SectorsNow;
-        SectorsLeft  -= SectorsNow;
-    }
-    ASSERT3U(Request->NrSegments, >, 0);
-    ASSERT3U(Request->NrSegments, <=, MaxSegments);
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    InsertTailList(&Target->Prepared, &Request->ListEntry);
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
     return TRUE;
-
-fail2:
-fail1:
-    return FALSE;
 }
 
 static BOOLEAN
-PrepareBlkifIndirect(
-    IN  PXENVBD_TARGET             Target,
-    IN  PXENVBD_REQUEST         Request
+TargetPrepareRequest(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    ULONG           Index;
-    ULONG           NrSegments = 0;
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    UCHAR               Operation;
 
-    for (Index = 0;
-            Index < BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST &&
-            NrSegments < Request->NrSegments;
-                ++Index) {
-        PXENVBD_INDIRECT    Indirect;
+    Operation = Cdb_OperationEx(SrbExt->Srb);
+    switch (Operation) {
+    case SCSIOP_READ:
+        return TargetPrepareRW(Target, SrbExt, BLKIF_OP_READ);
 
-        Indirect = TargetGetIndirect(Target);
-        if (Indirect == NULL)
-            goto fail1;
-        InsertTailList(&Request->Indirects, &Indirect->Entry);
+    case SCSIOP_WRITE:
+        return TargetPrepareRW(Target, SrbExt, BLKIF_OP_WRITE);
 
-        NrSegments += XENVBD_MAX_SEGMENTS_PER_PAGE;
-    }
+    case SCSIOP_UNMAP:
+        return TargetPrepareUnmap(Target, SrbExt);
 
-    return TRUE;
+    case SCSIOP_SYNCHRONIZE_CACHE:
+        if (Target->FeatureFlush)
+            return TargetPrepareSync(Target, SrbExt, BLKIF_OP_FLUSH_DISKCACHE);
+        if (Target->FeatureBarrier)
+            return TargetPrepareSync(Target, SrbExt, BLKIF_OP_WRITE_BARRIER);
+        
+        // nothing supported - shouldnt really get here, but just complete if 
it did
+        Warning("[%u] FLUSH & BARRIER not supported, SCSIOP_SYNCHRONIZE_CACHE 
got to Prepare\n",
+                Target->TargetId);
+        Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        AdapterCompleteSrb(Target->Adapter, SrbExt);
+        return TRUE;
 
-fail1:
+    default:
+        ASSERT(FALSE);
+        break;
+    }
     return FALSE;
 }
 
-static FORCEINLINE ULONG
-UseIndirect(
-    IN  PXENVBD_TARGET             Target,
-    IN  ULONG                   SectorsLeft
-    )
+static FORCEINLINE BOOLEAN
+TargetPrepareFresh(
+    IN  PXENVBD_TARGET  Target
+    ) 
 {
-    const ULONG SectorsPerPage = __SectorsPerPage(TargetSectorSize(Target));
-    const ULONG MaxIndirectSegs = 
FrontendGetFeatures(Target->Frontend)->Indirect;
+    PXENVBD_SRBEXT      SrbExt;
+    PLIST_ENTRY         ListEntry;
+    KIRQL               Irql;
+
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    ListEntry = RemoveHeadList(&Target->Fresh);
+    if (ListEntry == &Target->Fresh) {
+        KeReleaseSpinLock(&Target->QueueLock, Irql);
+        return FALSE;
+    }
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+    SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
 
-    if (MaxIndirectSegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
-        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // not supported
+    if (TargetPrepareRequest(Target, SrbExt))
+        return TRUE;
 
-    if (SectorsLeft < BLKIF_MAX_SEGMENTS_PER_REQUEST * SectorsPerPage)
-        return BLKIF_MAX_SEGMENTS_PER_REQUEST; // first into a single 
BLKIF_OP_{READ/WRITE}
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    InsertHeadList(&Target->Fresh, ListEntry);
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-    return MaxIndirectSegs;
+    return FALSE;
 }
 
-static FORCEINLINE ULONG
-TargetQueueRequestList(
-    IN  PXENVBD_TARGET     Target,
-    IN  PLIST_ENTRY     List
+static FORCEINLINE BOOLEAN
+TargetSubmitPrepared(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    ULONG               Count = 0;
     for (;;) {
+        PLIST_ENTRY     ListEntry;
         PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry;
+        KIRQL           Irql;
 
-        Entry = RemoveHeadList(List);
-        if (Entry == List)
+        KeAcquireSpinLock(&Target->QueueLock, &Irql);
+        ListEntry = RemoveHeadList(&Target->Prepared);
+        if (ListEntry == &Target->Prepared) {
+            KeReleaseSpinLock(&Target->QueueLock, Irql);
             break;
+        }
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+
+        InsertTailList(&Target->Submitted, ListEntry);
+        KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-        ++Count;
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
-        __TargetIncBlkifOpCount(Target, Request);
-        QueueAppend(&Target->PreparedReqs, &Request->Entry);
+        if (BlockRingSubmit(Target->BlockRing, Request))
+            continue;
+
+        KeAcquireSpinLock(&Target->QueueLock, &Irql);
+        RemoveEntryList(&Request->ListEntry);
+        InsertHeadList(&Target->Prepared, &Request->ListEntry);
+        KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+        return FALSE;
     }
-    return Count;
+
+    return TRUE;
 }
 
 static FORCEINLINE VOID
-TargetCancelRequestList(
-    IN  PXENVBD_TARGET     Target,
-    IN  PLIST_ENTRY     List
+TargetCompleteShutdown(
+    IN  PXENVBD_TARGET  Target
     )
 {
+    if (IsListEmpty(&Target->Shutdown))
+        return;
+    if (!IsListEmpty(&Target->Fresh))
+        return;
+    if (!IsListEmpty(&Target->Prepared))
+        return;
+    if (!IsListEmpty(&Target->Shutdown))
+        return;
+
     for (;;) {
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry;
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_SRBEXT  SrbExt;
+        KIRQL           Irql;
 
-        Entry = RemoveHeadList(List);
-        if (Entry == List)
+        KeAcquireSpinLock(&Target->QueueLock, &Irql);
+        ListEntry = RemoveHeadList(&Target->Shutdown);
+        if (ListEntry == &Target->Shutdown) {
+            KeReleaseSpinLock(&Target->QueueLock, Irql);
             break;
+        }
+        KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
-        TargetPutRequest(Target, Request);
+        SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+        SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
     }
 }
 
-__checkReturn
-static BOOLEAN
-PrepareReadWrite(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+VOID
+TargetSubmitRequests(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_SRBEXT  SrbExt = Srb->SrbExtension;
-    ULONG64         SectorStart = Cdb_LogicalBlock(Srb);
-    ULONG           SectorsLeft = Cdb_TransferBlock(Srb);
-    LIST_ENTRY      List;
-    XENVBD_SG_LIST  SGList;
-    ULONG           DebugCount;
+    for (;;) {
+        // submit all prepared requests (0 or more requests)
+        // return TRUE if submitted 0 or more requests from prepared queue
+        // return FALSE iff ring is full
+        if (!TargetSubmitPrepared(Target))
+            break;
 
-    Srb->SrbStatus = SRB_STATUS_PENDING;
+        // prepare a single SRB (into 1 or more requests)
+        // return TRUE if prepare succeeded
+        // return FALSE if prepare failed or fresh queue empty
+        if (!TargetPrepareFresh(Target))
+            break;
+    }
 
-    InitializeListHead(&List);
-    SrbExt->RequestCount = 0;
+    // if no requests/SRBs outstanding, complete any shutdown SRBs
+    TargetCompleteShutdown(Target);
+}
+
+static FORCEINLINE VOID
+TargetDisableFeature(
+    IN  PXENVBD_TARGET  Target,
+    IN  UCHAR           Operation
+    )
+{
+    switch (Operation) {
+    case BLKIF_OP_WRITE_BARRIER:
+        Target->FeatureBarrier = FALSE;
+        break;
+    case BLKIF_OP_FLUSH_DISKCACHE:
+        Target->FeatureFlush = FALSE;
+        break;
+    case BLKIF_OP_DISCARD:
+        Target->FeatureDiscard = FALSE;
+        break;
+    default:
+        break;
+    }
+}
 
-    RtlZeroMemory(&SGList, sizeof(SGList));
-    SGList.SGList = StorPortGetScatterGatherList(TargetGetAdapter(Target), 
Srb);
+VOID
+TargetCompleteResponse(
+    IN  PXENVBD_TARGET  Target,
+    IN  ULONG64         Id,
+    IN  SHORT           Status
+    )
+{
+    PLIST_ENTRY         ListEntry;
+    PXENVBD_REQUEST     Request;
+    PXENVBD_SRBEXT      SrbExt;
+    PSCSI_REQUEST_BLOCK Srb;
+    KIRQL               Irql;
 
-    while (SectorsLeft > 0) {
-        ULONG           MaxSegments;
-        ULONG           SectorsDone = 0;
-        PXENVBD_REQUEST Request;
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    Request = NULL;
+    for (ListEntry = Target->Submitted.Flink;
+         ListEntry != &Target->Submitted;
+         ListEntry = ListEntry->Flink) {
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
 
-        Request = TargetGetRequest(Target);
-        if (Request == NULL) 
-            goto fail1;
-        InsertTailList(&List, &Request->Entry);
-        InterlockedIncrement(&SrbExt->RequestCount);
-        
-        Request->Srb    = Srb;
-        MaxSegments = UseIndirect(Target, SectorsLeft);
-
-        if (!PrepareBlkifReadWrite(Target,
-                                   Request,
-                                   &SGList,
-                                   MaxSegments,
-                                   SectorStart,
-                                   SectorsLeft,
-                                   &SectorsDone))
-            goto fail2;
+        if (Request->Id == Id) {
+            RemoveEntryList(&Request->ListEntry);
 
-        if (MaxSegments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-            if (!PrepareBlkifIndirect(Target, Request))
-                goto fail3;
+            ASSERT3P(Request, ==, (PVOID)(ULONG_PTR)Id);
+            break;
         }
 
-        SectorsLeft -= SectorsDone;
-        SectorStart += SectorsDone;
+        Request = NULL;
     }
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-    DebugCount = TargetQueueRequestList(Target, &List);
-    if (DebugCount != (ULONG)SrbExt->RequestCount) {
-        Trace("[%u] %d != %u\n", TargetGetTargetId(Target), 
SrbExt->RequestCount, DebugCount);
-    }
-    return TRUE;
+    ASSERT3P(Request, !=, NULL);
+    SrbExt = Request->SrbExt;
+    ASSERT3P(SrbExt, !=, NULL);
+    Srb = SrbExt->Srb;
+    ASSERT3P(Srb, !=, NULL);
 
-fail3:
-fail2:
-fail1:
-    TargetCancelRequestList(Target, &List);
-    SrbExt->RequestCount = 0;
-    Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
+    switch (Status) {
+    case BLKIF_RSP_OKAY:
+        if (Request->Operation == BLKIF_OP_READ) {
+            for (ListEntry = Request->Segments.Flink;
+                 ListEntry != &Request->Segments;
+                 ListEntry = ListEntry->Flink) {
+                PXENVBD_SEGMENT Segment = CONTAINING_RECORD(ListEntry, 
XENVBD_SEGMENT, ListEntry);
+
+                if (Segment->BufferId) {
+                    ASSERT(Segment->Buffer);
+                    ASSERT(Segment->Length);
+                    BufferCopyOut(Segment->BufferId,
+                                  Segment->Buffer,
+                                  Segment->Length);
+                }
+            }
+        }
+        break;
+    case BLKIF_RSP_EOPNOTSUPP:
+        TargetDisableFeature(Target, Request->Operation);
+        break;
+    case BLKIF_RSP_ERROR:
+    default:
+        Srb->SrbStatus = SRB_STATUS_ERROR;
+        break;
+    }
+
+    TargetPutRequest(Target, Request);
+
+    if (InterlockedDecrement(&SrbExt->RequestCount) != 0)
+        return;
+
+    if (Srb->SrbStatus == SRB_STATUS_PENDING)
+        Srb->SrbStatus = SRB_STATUS_SUCCESS;
+
+    AdapterCompleteSrb(Target->Adapter, SrbExt);
 }
 
-__checkReturn
-static BOOLEAN
-PrepareSyncCache(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+VOID
+TargetReset(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_SRBEXT      SrbExt = Srb->SrbExtension;
-    PXENVBD_REQUEST     Request;
-    LIST_ENTRY          List;
-    UCHAR               Operation;
-    ULONG               DebugCount;
+    ULONG               Outstanding;
 
-    Srb->SrbStatus = SRB_STATUS_PENDING;
-    
-    if (FrontendGetDiskInfo(Target->Frontend)->FlushCache)
-        Operation = BLKIF_OP_FLUSH_DISKCACHE;
-    else
-        Operation = BLKIF_OP_WRITE_BARRIER;
+    Verbose("[%u] =====>\n", Target->TargetId);
 
-    InitializeListHead(&List);
-    SrbExt->RequestCount = 0;
+    ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL);
 
-    Request = TargetGetRequest(Target);
-    if (Request == NULL)
-        goto fail1;
-    InsertTailList(&List, &Request->Entry);
-    InterlockedIncrement(&SrbExt->RequestCount);
+    Trace("polling...\n");
+    Outstanding = BlockRingPoll(Target->BlockRing);
+    Trace("%u requests outstanding\n", Outstanding);
 
-    Request->Srb        = Srb;
-    Request->Operation  = Operation;
-    Request->FirstSector = Cdb_LogicalBlock(Srb);
+    Verbose("[%u] <=====\n", Target->TargetId);
+}
 
-    DebugCount = TargetQueueRequestList(Target, &List);
-    if (DebugCount != (ULONG)SrbExt->RequestCount) {
-        Trace("[%u] %d != %u\n", TargetGetTargetId(Target), 
SrbExt->RequestCount, DebugCount);
-    }
-    return TRUE;
+VOID
+TargetFlush(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    KIRQL               Irql;
 
-fail1:
-    TargetCancelRequestList(Target, &List);
-    SrbExt->RequestCount = 0;
-    Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
+    SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    InsertTailList(&Target->Shutdown, &SrbExt->ListEntry);
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+    BlockRingKick(Target->BlockRing);
 }
 
-__checkReturn
-static BOOLEAN
-PrepareUnmap(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_REQUEST_BLOCK     Srb
+VOID
+TargetShutdown(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    PXENVBD_SRBEXT      SrbExt = Srb->SrbExtension;
-    PUNMAP_LIST_HEADER  Unmap = Srb->DataBuffer;
-       ULONG               Count = 
_byteswap_ushort(*(PUSHORT)Unmap->BlockDescrDataLength) / 
sizeof(UNMAP_BLOCK_DESCRIPTOR);
-    ULONG               Index;
-    LIST_ENTRY          List;
-    ULONG               DebugCount;
+    KIRQL               Irql;
+
+    SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    InsertTailList(&Target->Shutdown, &SrbExt->ListEntry);
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
+
+    BlockRingKick(Target->BlockRing);
+}
+
+VOID
+TargetPrepareSrb(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+
+    UNREFERENCED_PARAMETER(Target);
 
     Srb->SrbStatus = SRB_STATUS_PENDING;
+}
 
-    InitializeListHead(&List);
-    SrbExt->RequestCount = 0;
+static FORCEINLINE VOID
+TargetQueueSrb(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    KIRQL               Irql;
 
-    for (Index = 0; Index < Count; ++Index) {
-        PUNMAP_BLOCK_DESCRIPTOR Descr = &Unmap->Descriptors[Index];
-        PXENVBD_REQUEST         Request;
+    SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
 
-        Request = TargetGetRequest(Target);
-        if (Request == NULL)
-            goto fail1;
-        InsertTailList(&List, &Request->Entry);
-        InterlockedIncrement(&SrbExt->RequestCount);
+    KeAcquireSpinLock(&Target->QueueLock, &Irql);
+    InsertTailList(&Target->Fresh, &SrbExt->ListEntry);
+    KeReleaseSpinLock(&Target->QueueLock, Irql);
 
-        Request->Srb            = Srb;
-        Request->Operation      = BLKIF_OP_DISCARD;
-        Request->FirstSector    = 
_byteswap_uint64(*(PULONG64)Descr->StartingLba);
-        Request->NrSectors      = _byteswap_ulong(*(PULONG)Descr->LbaCount);
-        Request->Flags          = 0;
-    }
+    BlockRingKick(Target->BlockRing);
+}
 
-    DebugCount = TargetQueueRequestList(Target, &List);
-    if (DebugCount != (ULONG)SrbExt->RequestCount) {
-        Trace("[%u] %d != %u\n", TargetGetTargetId(Target), 
SrbExt->RequestCount, DebugCount);
-    }
-    return TRUE;
+static FORCEINLINE VOID
+TargetInquiryStd(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PINQUIRYDATA        Data = Srb->DataBuffer;
+   
+    UNREFERENCED_PARAMETER(Target);
 
-fail1:
-    TargetCancelRequestList(Target, &List);
-    SrbExt->RequestCount = 0;
-    Srb->SrbStatus = SRB_STATUS_ERROR;
-    return FALSE;
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(INQUIRYDATA))
+        return;
+
+    RtlZeroMemory(Data, Srb->DataTransferLength);
+    Data->DeviceType            = DIRECT_ACCESS_DEVICE;
+    Data->DeviceTypeQualifier   = DEVICE_CONNECTED;
+    Data->Versions              = 4;
+    Data->ResponseDataFormat    = 2;
+    Data->AdditionalLength      = INQUIRYDATABUFFERSIZE - 4;
+    Data->CommandQueue          = 1;
+    RtlCopyMemory(Data->VendorId,               "XENSRC  ", 8);
+    RtlCopyMemory(Data->ProductId,              "PVDISK          ", 16);
+    RtlCopyMemory(Data->ProductRevisionLevel,   "3.0 ", 4);
+
+    Srb->DataTransferLength = sizeof(INQUIRYDATA);
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry00(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PUCHAR              Data = Srb->DataBuffer;
+
+    UNREFERENCED_PARAMETER(Target);
+
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < 7)
+        return;
+
+    RtlZeroMemory(Data, Srb->DataTransferLength);
+    Data[3] = 3;
+    Data[5] = 0x80;
+    Data[6] = 0x83;
+
+    Srb->DataTransferLength = 7;
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
-//=============================================================================
-// Queue-Related
 static FORCEINLINE VOID
-__TargetPauseDataPath(
-    __in PXENVBD_TARGET             Target,
-    __in BOOLEAN                 Timeout
+TargetInquiry80(
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_SRBEXT      SrbExt
     )
 {
-    KIRQL               Irql;
-    ULONG               Requests;
-    ULONG               Count = 0;
-    PXENVBD_NOTIFIER    Notifier = FrontendGetNotifier(Target->Frontend);
-    PXENVBD_BLOCKRING   BlockRing = FrontendGetBlockRing(Target->Frontend);
+    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
+    PVPD_SERIAL_NUMBER_PAGE Data = Srb->DataBuffer;
+   
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(VPD_SERIAL_NUMBER_PAGE) + 4)
+        return;
 
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    ++Target->Paused;
-    KeReleaseSpinLock(&Target->Lock, Irql);
+    RtlZeroMemory(Data, Srb->DataTransferLength);
+    Data->PageCode = 0x80;
+    Data->PageLength = 4;
+    RtlStringCchPrintfA((PCHAR)Data->SerialNumber, 4, "%04u", 
Target->TargetId);
 
-    Requests = QueueCount(&Target->SubmittedReqs);
-    KeMemoryBarrier();
+    Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + 4;
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
 
-    Verbose("Target[%d] : Waiting for %d Submitted requests\n", 
TargetGetTargetId(Target), Requests);
+static FORCEINLINE VOID
+TargetInquiry83(
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK         Srb = SrbExt->Srb;
+    PVPD_IDENTIFICATION_PAGE    Data = Srb->DataBuffer;
+    PVPD_IDENTIFICATION_DESCRIPTOR  Descr;
 
-    // poll ring and send event channel notification every 1ms (for up to 3 
minutes)
-    while (QueueCount(&Target->SubmittedReqs)) {
-        if (Timeout && Count > 180000)
-            break;
-        KeRaiseIrql(DISPATCH_LEVEL, &Irql);
-        BlockRingPoll(BlockRing);
-        KeLowerIrql(Irql);
-        NotifierSend(Notifier);         // let backend know it needs to do 
some work
-        StorPortStallExecution(1000);   // 1000 micro-seconds
-        ++Count;
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(VPD_IDENTIFICATION_PAGE) - 1 +
+                                  sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16)
+        return;
+
+    RtlZeroMemory(Data, Srb->DataTransferLength);
+    Data->PageCode = 0x83;
+    Data->PageLength = sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+
+    Descr = (PVPD_IDENTIFICATION_DESCRIPTOR)Data->Descriptors;
+    Descr->CodeSet          = VpdCodeSetAscii;
+    Descr->IdentifierType   = VpdIdentifierTypeVendorId;
+    Descr->IdentifierLength = 16;
+    RtlStringCbPrintfA((PCHAR)Descr->Identifier,
+                       16,
+                       "XEN:%u:%u",
+                       Target->DeviceId,
+                       Target->TargetId);
+
+    Srb->DataTransferLength = sizeof(VPD_IDENTIFICATION_PAGE) - 1 +
+                              sizeof(VPD_IDENTIFICATION_DESCRIPTOR) + 16;
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetInquiry(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    if (Cdb_EVPD(SrbExt->Srb)) {
+        switch (Cdb_PageCode(SrbExt->Srb)) {
+        case 0x00:  TargetInquiry00(Target, SrbExt);            break;
+        case 0x80:  TargetInquiry80(Target, SrbExt);            break;
+        case 0x83:  TargetInquiry83(Target, SrbExt);            break;
+        default:    SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR;  break;
+        }
+    } else {
+        switch (Cdb_PageCode(SrbExt->Srb)) {
+        case 0x00:  TargetInquiryStd(Target, SrbExt);           break;
+        default:    SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR;  break;
+        }
     }
+}
+
+static FORCEINLINE VOID
+TargetModeSense(
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
+    PMODE_PARAMETER_HEADER  Header;
+    ULONG                   Offset;
+    UCHAR                   PageCode;
 
-    Verbose("Target[%d] : %u/%u Submitted requests left (%u iterrations)\n",
-            TargetGetTargetId(Target), QueueCount(&Target->SubmittedReqs), 
Requests, Count);
+    UNREFERENCED_PARAMETER(Target);
 
-    // Abort Fresh SRBs
-    for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PLIST_ENTRY     ListEntry = QueuePop(&Target->FreshSrbs);
-        if (ListEntry == NULL)
-            break;
-        SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(MODE_PARAMETER_HEADER))
+        return;
+    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
 
-        Verbose("Target[%d] : FreshSrb 0x%p -> SCSI_ABORTED\n", 
TargetGetTargetId(Target), SrbExt->Srb);
-        SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
-        SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED;
-        AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
+    Header = Srb->DataBuffer;
+    Header->ModeDataLength = sizeof(MODE_PARAMETER_HEADER) - 1;
+
+    Offset = sizeof(MODE_PARAMETER_HEADER);
+    PageCode = Cdb_PageCode(Srb);
+    if (Cdb_Dbd(Srb) == 0 &&
+        Srb->DataTransferLength >= Offset + sizeof(MODE_PARAMETER_BLOCK)) {
+        PMODE_PARAMETER_BLOCK   Block = (PMODE_PARAMETER_BLOCK)((PUCHAR)Header 
+ Offset);
+         
+        // Block is ZEROed
+        UNREFERENCED_PARAMETER(Block);
+
+        Header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
+        Header->ModeDataLength += sizeof(MODE_PARAMETER_BLOCK);
+        Offset += sizeof(MODE_PARAMETER_BLOCK);
     }
 
-    // Fail PreparedReqs
-    for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry = QueuePop(&Target->PreparedReqs);
-        if (Entry == NULL)
-            break;
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
-        SrbExt = Request->Srb->SrbExtension;
+    if ((PageCode == MODE_PAGE_CACHING || PageCode == MODE_SENSE_RETURN_ALL) &&
+        Srb->DataTransferLength >= Offset + sizeof(MODE_CACHING_PAGE)) {
+        PMODE_CACHING_PAGE  Caching = (PMODE_CACHING_PAGE)((PUCHAR)Header + 
Offset);
 
-        Verbose("Target[%d] : PreparedReq 0x%p -> FAILED\n", 
TargetGetTargetId(Target), Request);
+        Caching->PageCode   = MODE_PAGE_CACHING;
+        Caching->PageLength = sizeof(MODE_CACHING_PAGE);
+        // Caching is ZEROed
 
-        SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
-        TargetPutRequest(Target, Request);
+        Header->ModeDataLength += sizeof(MODE_CACHING_PAGE);
+        Offset += sizeof(MODE_CACHING_PAGE);
+    }
 
-        if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
-            SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORTED
-            AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
-        }
+    if ((PageCode == MODE_PAGE_FAULT_REPORTING || PageCode == 
MODE_SENSE_RETURN_ALL) &&
+        Srb->DataTransferLength >= Offset + sizeof(MODE_CACHING_PAGE)) {
+        PMODE_INFO_EXCEPTIONS  Info = (PMODE_INFO_EXCEPTIONS)((PUCHAR)Header + 
Offset);
+
+        Info->PageCode      = MODE_PAGE_FAULT_REPORTING;
+        Info->PageLength    = sizeof(MODE_INFO_EXCEPTIONS);
+        Info->Dexcpt        = 1;
+        // Info is ZEROed
+
+        Header->ModeDataLength += sizeof(MODE_CACHING_PAGE);
+        Offset += sizeof(MODE_CACHING_PAGE);
     }
+
+    Srb->DataTransferLength = Offset;
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
 static FORCEINLINE VOID
-__TargetUnpauseDataPath(
-    __in PXENVBD_TARGET             Target
+TargetRequestSense(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    KIRQL   Irql;
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PSENSE_DATA         Sense = Srb->DataBuffer;
 
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    --Target->Paused;
-    KeReleaseSpinLock(&Target->Lock, Irql);
+    UNREFERENCED_PARAMETER(Target);
+
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(SENSE_DATA))
+        return;
+    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+    Sense->ErrorCode            = 0x70;
+    Sense->Valid                = 1;
+    Sense->SenseKey             = SCSI_SENSE_NO_SENSE;
+    Sense->AdditionalSenseCode  = SCSI_ADSENSE_NO_SENSE;
+
+    Srb->DataTransferLength     = sizeof(SENSE_DATA);
+    Srb->SrbStatus              = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetReportLuns(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    ULONG               Length;
+    ULONG               Offset;
+    ULONG               AllocLength = Cdb_AllocationLength(Srb);
+    PUCHAR              Buffer = Srb->DataBuffer;
+
+    UNREFERENCED_PARAMETER(Target);
+     
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < 8)
+        return;
+    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+    Length = 0;
+    Offset = 8;
+
+    if (Offset + 8 <= AllocLength) {
+        Buffer[Offset] = 0;
+        Offset += 8;
+        Length += 8;
+    }
+
+    if (Offset + 8 <= AllocLength) {
+        Buffer[Offset] = XENVBD_MAX_TARGETS;
+        Offset += 8;
+        Length += 8;
+    }
+
+    REVERSE_BYTES(Buffer, &Length);
+
+    Srb->DataTransferLength = __min(Length, AllocLength);
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+}
+
+static FORCEINLINE VOID
+TargetReadCapacity(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    PREAD_CAPACITY_DATA Capacity = Srb->DataBuffer;
+    ULONG64             SectorCount = Target->SectorCount;
+    ULONG               SectorSize = Target->SectorSize;
+    ULONG               LastBlock;
+
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(READ_CAPACITY_DATA))
+        return;
+    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
+        return;
+
+    if (SectorCount == (ULONG)SectorCount)
+        LastBlock = (ULONG)SectorCount - 1;
+    else
+        LastBlock = ~0ul;
+
+    Capacity->LogicalBlockAddress   = _byteswap_ulong(LastBlock);
+    Capacity->BytesPerBlock         = _byteswap_ulong(SectorSize);
+
+    Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
+    Srb->SrbStatus = SRB_STATUS_SUCCESS; 
+}
+
+static FORCEINLINE VOID
+TargetReadCapacity16(
+    IN  PXENVBD_TARGET      Target,
+    IN  PXENVBD_SRBEXT      SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
+    PREAD_CAPACITY16_DATA   Capacity = Srb->DataBuffer;
+    ULONG64                 SectorCount = Target->SectorCount;
+    ULONG                   SectorSize = Target->SectorSize;
+    ULONG                   LogPerPhysExp;
+
+    Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
+    if (Srb->DataTransferLength < sizeof(READ_CAPACITY16_DATA))
+        return;
+    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+
+    Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0)
+        return;
+
+    if (Target->PhysicalSectorSize == 0)
+        LogPerPhysExp = 0;
+    else if (!_BitScanReverse(&LogPerPhysExp, Target->PhysicalSectorSize / 
SectorSize))
+        LogPerPhysExp = 0;
+
+    Capacity->LogicalBlockAddress.QuadPart  = _byteswap_uint64(SectorCount - 
1);
+    Capacity->BytesPerBlock                 = _byteswap_ulong(SectorSize);
+    Capacity->LogicalPerPhysicalExponent    = (UCHAR)LogPerPhysExp;
+
+    Srb->DataTransferLength = sizeof(READ_CAPACITY16_DATA);
+    Srb->SrbStatus = SRB_STATUS_SUCCESS;
 }
 
 static FORCEINLINE BOOLEAN
-TargetPrepareFresh(
-    IN  PXENVBD_TARGET         Target
+TargetCheckSectors(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
     )
 {
-    PXENVBD_SRBEXT  SrbExt;
-    PLIST_ENTRY     ListEntry;
+    ULONG64             StartSector = Cdb_LogicalBlock(SrbExt->Srb);
+    ULONG               SectorCount = Cdb_TransferBlock(SrbExt->Srb);
 
-    ListEntry = QueuePop(&Target->FreshSrbs);
-    if (ListEntry == NULL)
-        return FALSE;   // fresh queue is empty
+    // prevent read/write beyond the end of the disk
+    if (StartSector >= Target->SectorCount)
+        return FALSE;
+    if (StartSector + SectorCount >= Target->SectorCount)
+        return FALSE;
+    return TRUE;
+}
 
-    SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+VOID
+TargetStartSrb(
+    IN  PXENVBD_TARGET  Target,
+    IN  PXENVBD_SRBEXT  SrbExt
+    )
+{
+    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    UCHAR               Operation;
 
-    switch (Cdb_OperationEx(SrbExt->Srb)) {
+    Operation = Cdb_OperationEx(Srb);
+    switch (Operation) {
     case SCSIOP_READ:
     case SCSIOP_WRITE:
-        if (PrepareReadWrite(Target, SrbExt->Srb))
-            return TRUE;    // prepared this SRB
+        if (!TargetCheckSectors(Target, SrbExt))
+            Srb->SrbStatus = SRB_STATUS_ERROR;
+        else
+            TargetQueueSrb(Target, SrbExt);
         break;
+
+    case SCSIOP_UNMAP:
+        if (Target->FeatureDiscard)
+            TargetQueueSrb(Target, SrbExt);
+        else
+            Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        break;
+
     case SCSIOP_SYNCHRONIZE_CACHE:
-        if (PrepareSyncCache(Target, SrbExt->Srb))
-            return TRUE;    // prepared this SRB
+        if (Target->FeatureBarrier || Target->FeatureFlush)
+            TargetQueueSrb(Target, SrbExt);
+        else
+            Srb->SrbStatus = SRB_STATUS_SUCCESS;
         break;
-    case SCSIOP_UNMAP:
-        if (PrepareUnmap(Target, SrbExt->Srb))
-            return TRUE;    // prepared this SRB
+
+    case SCSIOP_INQUIRY:
+        TargetInquiry(Target, SrbExt);
+        break;
+    case SCSIOP_MODE_SENSE:
+        TargetModeSense(Target, SrbExt);
+        break;
+    case SCSIOP_REQUEST_SENSE:
+        TargetRequestSense(Target, SrbExt);
+        break;
+    case SCSIOP_REPORT_LUNS:
+        TargetReportLuns(Target, SrbExt);
+        break;
+    case SCSIOP_READ_CAPACITY:
+        TargetReadCapacity(Target, SrbExt);
         break;
+    case SCSIOP_READ_CAPACITY16:
+        TargetReadCapacity16(Target, SrbExt);
+        break;
+
+    case SCSIOP_MEDIUM_REMOVAL:
+    case SCSIOP_TEST_UNIT_READY:
+    case SCSIOP_RESERVE_UNIT:
+    case SCSIOP_RESERVE_UNIT10:
+    case SCSIOP_RELEASE_UNIT:
+    case SCSIOP_RELEASE_UNIT10:
+    case SCSIOP_VERIFY:
+    case SCSIOP_VERIFY16:
+    case SCSIOP_START_STOP_UNIT:
+        Srb->SrbStatus = SRB_STATUS_SUCCESS;
+        break;
+
     default:
-        ASSERT(FALSE);
+        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
         break;
     }
-    QueueUnPop(&Target->FreshSrbs, &SrbExt->ListEntry);
-
-    return FALSE;       // prepare failed
 }
 
-static FORCEINLINE BOOLEAN
-TargetSubmitPrepared(
-    __in PXENVBD_TARGET             Target
+static VOID
+TargetStoreReadDiskInfo(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_BLOCKRING   BlockRing = FrontendGetBlockRing(Target->Frontend);
-    if (TargetIsPaused(Target)) {
-        if (QueueCount(&Target->PreparedReqs))
-            Warning("Target[%d] : Paused, not submitting new requests (%u)\n",
-                    TargetGetTargetId(Target),
-                    QueueCount(&Target->PreparedReqs));
-        return FALSE;
+    PCHAR               Buffer;
+    NTSTATUS            status;
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "info",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->DiskInfo = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "sectors",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->SectorCount = _strtoui64(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "sector-size",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->SectorSize = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "physical-sector-size",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->PhysicalSectorSize = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    } else {
+        Target->PhysicalSectorSize = Target->SectorSize;
     }
+}
 
-    for (;;) {
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry;
+static VOID
+TargetStoreReadFeatures(
+    IN  PXENVBD_TARGET  Target
+    )
+{
+    PCHAR               Buffer;
+    NTSTATUS            status;
 
-        Entry = QueuePop(&Target->PreparedReqs);
-        if (Entry == NULL)
-            break;
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "removable",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->Removable = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "feature-barrier",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->FeatureBarrier = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "feature-flush-cache",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->FeatureFlush = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "feature-discard",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->FeatureDiscard = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "discard-enable",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        BOOLEAN Enabled = (BOOLEAN)strtoul(Buffer, NULL, 2);
+        if (!Enabled)
+            Target->FeatureDiscard = FALSE;
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "discard-secure",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->DiscardSecure = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "discard-alignment",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->DiscardAlignment = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "discard-secure",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->DiscardGranularity = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          "feature-max-indirect-segments",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->FeatureIndirect = strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    }
+}
+
+static NTSTATUS
+TargetStoreWrite(
+    IN  PXENVBD_TARGET              Target,
+    IN  PXENBUS_STORE_TRANSACTION   Transaction
+    )
+{
+    NTSTATUS                        status;
+
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          Transaction,
+                          Target->Path,
+                          "target-id",
+                          "%u",
+                          Target->TargetId);
+    if (!NT_SUCCESS(status))
+        return status;
+
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          Transaction,
+                          Target->Path,
+                          "feature-surprise-remove",
+                          "%u",
+                          TRUE);
+    if (!NT_SUCCESS(status))
+        return status;
+
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          Transaction,
+                          Target->Path,
+                          "feature-online-resize",
+                          "%u",
+                          TRUE);
+    if (!NT_SUCCESS(status))
+        return status;
 
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
+    return STATUS_SUCCESS;
+}
 
-        QueueAppend(&Target->SubmittedReqs, &Request->Entry);
-        KeMemoryBarrier();
+static NTSTATUS
+TargetWriteTargetPath(
+    IN  PXENVBD_TARGET  Target
+    )
+{
+    NTSTATUS            status;
 
-        if (BlockRingSubmit(BlockRing, Request))
-            continue;
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->TargetPath,
+                          "frontend",
+                          "%s",
+                          Target->Path);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        QueueRemove(&Target->SubmittedReqs, &Request->Entry);
-        QueueUnPop(&Target->PreparedReqs, &Request->Entry);
-        return FALSE;   // ring full
-    }
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->TargetPath,
+                          "device",
+                          "%u",
+                          Target->DeviceId);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    return TRUE;
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-static FORCEINLINE VOID
-TargetCompleteShutdown(
-    __in PXENVBD_TARGET             Target
+static VOID
+TargetWaitForBackendStateChange(
+    IN  PXENVBD_TARGET  Target,
+    OUT XenbusState*    State
     )
 {
-    if (QueueCount(&Target->ShutdownSrbs) == 0)
-        return;
+    KEVENT              Event;
+    PXENBUS_STORE_WATCH Watch;
+    LARGE_INTEGER       Start;
+    ULONGLONG           TimeDelta;
+    LARGE_INTEGER       Timeout;
+    XenbusState         Old = *State;
+    NTSTATUS            status;
 
-    if (QueueCount(&Target->FreshSrbs) ||
-        QueueCount(&Target->PreparedReqs) ||
-        QueueCount(&Target->SubmittedReqs))
-        return;
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
 
-    for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PLIST_ENTRY     ListEntry = QueuePop(&Target->ShutdownSrbs);
-        if (ListEntry == NULL)
-            break;
-        SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
-        SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
+    status = XENBUS_STORE(WatchAdd,
+                          &Target->StoreInterface,
+                          Target->BackendPath,
+                          "state",
+                          &Event,
+                          &Watch);
+    if (!NT_SUCCESS(status))
+        Watch = NULL;
+
+    KeQuerySystemTime(&Start);
+    TimeDelta = 0;
+
+    Timeout.QuadPart = 0;
+
+    while (*State == Old && TimeDelta < 120000) {
+        PCHAR           Buffer;
+        LARGE_INTEGER   Now;
+
+        if (Watch != NULL) {
+            ULONG   Attempt = 0;
+
+            while (++Attempt < 1000) {
+                status = KeWaitForSingleObject(&Event,
+                                               Executive,
+                                               KernelMode,
+                                               FALSE,
+                                               &Timeout);
+                if (status != STATUS_TIMEOUT)
+                    break;
+
+                // We are waiting for a watch event at DISPATCH_LEVEL so
+                // it is our responsibility to poll the store ring.
+                XENBUS_STORE(Poll,
+                             &Target->StoreInterface);
+
+                KeStallExecutionProcessor(1000);   // 1ms
+            }
+
+            KeClearEvent(&Event);
+        }
+
+        status = XENBUS_STORE(Read,
+                              &Target->StoreInterface,
+                              NULL,
+                              Target->BackendPath,
+                              "state",
+                              &Buffer);
+        if (!NT_SUCCESS(status)) {
+            *State = XenbusStateUnknown;
+        } else {
+            *State = (XenbusState)strtol(Buffer, NULL, 10);
+
+            XENBUS_STORE(Free,
+                         &Target->StoreInterface,
+                         Buffer);
+        }
+
+        KeQuerySystemTime(&Now);
+
+        TimeDelta = (Now.QuadPart - Start.QuadPart) / 10000ull;
     }
+
+    if (Watch != NULL)
+        (VOID) XENBUS_STORE(WatchRemove,
+                            &Target->StoreInterface,
+                            Watch);
 }
 
-static FORCEINLINE PCHAR
-BlkifOperationName(
-    IN  UCHAR                   Operation
+static NTSTATUS
+TargetUpdatePath(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    switch (Operation) {
-    case BLKIF_OP_READ:             return "READ";
-    case BLKIF_OP_WRITE:            return "WRITE";
-    case BLKIF_OP_WRITE_BARRIER:    return "WRITE_BARRIER";
-    case BLKIF_OP_FLUSH_DISKCACHE:  return "FLUSH_DISKCACHE";
-    case BLKIF_OP_RESERVED_1:       return "RESERVED_1";
-    case BLKIF_OP_DISCARD:          return "DISCARD";
-    case BLKIF_OP_INDIRECT:         return "INDIRECT";
-    default:                        return "<unknown>";
+    ULONG               Length;
+    PCHAR               Buffer;
+    NTSTATUS            status;
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->Path,
+                          "backend-id",
+                          &Buffer);
+    if (NT_SUCCESS(status)) {
+        Target->BackendId = (USHORT)strtoul(Buffer, NULL, 10);
+
+        XENBUS_STORE(Free,
+                     &Target->StoreInterface,
+                     Buffer);
+    } else {
+        Target->BackendId = 0;
     }
+
+    status = XENBUS_STORE(Read,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->Path,
+                          "backend",
+                          &Buffer);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    __TargetFree(Target->BackendPath);
+    Target->BackendPath = NULL;
+
+    Length = (ULONG)strlen(Buffer);
+
+    status = STATUS_NO_MEMORY;
+    Target->BackendPath = __TargetAllocate(Length + 1);
+    if (Target->BackendPath == NULL)
+        goto fail2;
+
+    RtlCopyMemory(Target->BackendPath, Buffer, Length);
+
+    XENBUS_STORE(Free,
+                 &Target->StoreInterface,
+                 Buffer);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+    XENBUS_STORE(Free,
+                 &Target->StoreInterface,
+                 Buffer);
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
+
 }
 
-VOID
-TargetSubmitRequests(
-    __in PXENVBD_TARGET             Target
+static NTSTATUS
+TargetClose(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    for (;;) {
-        // submit all prepared requests (0 or more requests)
-        // return TRUE if submitted 0 or more requests from prepared queue
-        // return FALSE iff ring is full
-        if (!TargetSubmitPrepared(Target))
-            break;
+    XenbusState         State;
+    NTSTATUS            status;
 
-        // prepare a single SRB (into 1 or more requests)
-        // return TRUE if prepare succeeded
-        // return FALSE if prepare failed or fresh queue empty
-        if (!TargetPrepareFresh(Target))
-            break;
-    }
+    Trace("[%u] ----->\n", Target->TargetId);
 
-    // if no requests/SRBs outstanding, complete any shutdown SRBs
-    TargetCompleteShutdown(Target);
+    if (Target->BackendWatch)
+        XENBUS_STORE(WatchRemove,
+                     &Target->StoreInterface,
+                     Target->BackendWatch);
+    Target->BackendWatch = NULL;
+
+    status = TargetUpdatePath(Target);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    State = XenbusStateUnknown;
+    do {
+        TargetWaitForBackendStateChange(Target, &State);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (State == XenbusStateUnknown)
+            goto fail2;
+    } while (State == XenbusStateInitialising);
+
+    while (State != XenbusStateClosing && 
+           State != XenbusStateClosed) {
+        status = XENBUS_STORE(Printf,
+                                &Target->StoreInterface,
+                                NULL,
+                                Target->Path,
+                                "state",
+                                "%u",
+                                (ULONG)XenbusStateClosing);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+
+        TargetWaitForBackendStateChange(Target, &State);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (State == XenbusStateUnknown)
+            goto fail4;
+    }
+
+    while (State != XenbusStateClosed) {
+        status = XENBUS_STORE(Printf,
+                                &Target->StoreInterface,
+                                NULL,
+                                Target->Path,
+                                "state",
+                                "%u",
+                                (ULONG)XenbusStateClosed);
+        if (!NT_SUCCESS(status))
+            goto fail3;
+
+        TargetWaitForBackendStateChange(Target, &State);
+
+        status = STATUS_UNSUCCESSFUL;
+        if (State == XenbusStateUnknown)
+            goto fail4;
+    }
+
+    Trace("[%u] <-----\n", Target->TargetId);
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+fail3:
+    Error("fail3\n");
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-VOID
-TargetCompleteResponse(
-    __in PXENVBD_TARGET             Target,
-    __in ULONG                   Tag,
-    __in SHORT                   Status
+static NTSTATUS
+TargetPrepare(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PXENVBD_REQUEST     Request;
-    PSCSI_REQUEST_BLOCK Srb;
-    PXENVBD_SRBEXT      SrbExt;
+    XenbusState         State;
+    NTSTATUS            status;
 
-    Request = TargetRequestFromTag(Target, Tag);
-    if (Request == NULL)
-        return;
+    Trace("[%u] ----->\n", Target->TargetId);
+
+    status = TargetUpdatePath(Target);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = XENBUS_STORE(WatchAdd,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->BackendPath,
+                          ThreadGetEvent(Target->BackendThread),
+                          &Target->BackendWatch);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    Srb     = Request->Srb;
-    SrbExt  = Srb->SrbExtension;
-    ASSERT3P(SrbExt, !=, NULL);
+    status = TargetWriteTargetPath(Target);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    switch (Status) {
-    case BLKIF_RSP_OKAY:
-        RequestCopyOutput(Request);
-        break;
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->Path,
+                          "state",
+                          "%u",
+                          (ULONG)XenbusStateInitialising);
+    if (!NT_SUCCESS(status))
+        goto fail4;
 
-    case BLKIF_RSP_EOPNOTSUPP:
-        // Remove appropriate feature support
-        FrontendRemoveFeature(Target->Frontend, Request->Operation);
-        // Succeed this SRB, subsiquent SRBs will be succeeded instead of 
being passed to the backend.
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        break;
+    State = XenbusStateUnknown;
+    do {
+        TargetWaitForBackendStateChange(Target, &State);
 
-    case BLKIF_RSP_ERROR:
-    default:
-        Warning("Target[%d] : %s BLKIF_RSP_ERROR (Tag %x)\n",
-                TargetGetTargetId(Target), 
BlkifOperationName(Request->Operation), Tag);
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-        break;
-    }
+        status = STATUS_UNSUCCESSFUL;
+        if (State == XenbusStateUnknown)
+            goto fail5;
+    } while (State == XenbusStateClosed || 
+             State == XenbusStateInitialising);
 
-    TargetPutRequest(Target, Request);
+    status = STATUS_UNSUCCESSFUL;
+    if (State != XenbusStateInitWait)
+        goto fail6;
 
-    // complete srb
-    if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
-        if (Srb->SrbStatus == SRB_STATUS_PENDING) {
-            // SRB has not hit a failure condition (BLKIF_RSP_ERROR | 
BLKIF_RSP_EOPNOTSUPP)
-            // from any of its responses. SRB must have succeeded
-            Srb->SrbStatus = SRB_STATUS_SUCCESS;
-            Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        } else {
-            // Srb->SrbStatus has already been set by 1 or more requests with 
Status != BLKIF_RSP_OKAY
-            Srb->ScsiStatus = 0x40; // SCSI_ABORTED
-        }
+    Trace("[%u] <-----\n", Target->TargetId);
+    return STATUS_SUCCESS;
 
-        AdapterCompleteSrb(TargetGetAdapter(Target), SrbExt);
-    }
+fail6:
+    Error("fail6\n");
+fail5:
+    Error("fail5\n");
+fail4:
+    Error("fail4\n");
+fail3:
+    Error("fail3\n");
+    XENBUS_STORE(WatchRemove,
+                 &Target->StoreInterface,
+                 Target->BackendWatch);
+    Target->BackendWatch = NULL;
+fail2:
+    Error("fail2\n");
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-VOID
-TargetPreResume(
-    __in PXENVBD_TARGET             Target
+static NTSTATUS
+TargetConnect(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    LIST_ENTRY          List;
-
-    InitializeListHead(&List);
+    XenbusState         State;
+    NTSTATUS            status;
 
-    // pop all submitted requests, cleanup and add associated SRB to a list
-    for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry = QueuePop(&Target->SubmittedReqs);
-        if (Entry == NULL)
-            break;
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
-        SrbExt = Request->Srb->SrbExtension;
+    Trace("[%u] ----->\n", Target->TargetId);
 
-        TargetPutRequest(Target, Request);
+    status = GranterConnect(Target->Granter);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-        if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
-            InsertTailList(&List, &SrbExt->ListEntry);
-        }
-    }
+    status = BlockRingConnect(Target->BlockRing);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    // pop all prepared requests, cleanup and add associated SRB to a list
     for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PXENVBD_REQUEST Request;
-        PLIST_ENTRY     Entry = QueuePop(&Target->PreparedReqs);
-        if (Entry == NULL)
+        PXENBUS_STORE_TRANSACTION   Transaction;
+
+        status = XENBUS_STORE(TransactionStart,
+                              &Target->StoreInterface,
+                              &Transaction);
+        if (!NT_SUCCESS(status))
             break;
-        Request = CONTAINING_RECORD(Entry, XENVBD_REQUEST, Entry);
-        SrbExt = Request->Srb->SrbExtension;
 
-        TargetPutRequest(Target, Request);
+        status = BlockRingStoreWrite(Target->BlockRing, Transaction);
+        if (!NT_SUCCESS(status))
+            goto abort;
 
-        if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
-            InsertTailList(&List, &SrbExt->ListEntry);
-        }
-    }
+        status = GranterStoreWrite(Target->Granter, Transaction);
+        if (!NT_SUCCESS(status))
+            goto abort;
 
-    // foreach SRB in list, put on start of FreshSrbs
-    for (;;) {
-        PXENVBD_SRBEXT  SrbExt;
-        PLIST_ENTRY     ListEntry = RemoveTailList(&List);
-        if (ListEntry == &List)
-            break;
-        SrbExt = CONTAINING_RECORD(ListEntry, XENVBD_SRBEXT, ListEntry);
+        status = TargetStoreWrite(Target, Transaction);
+        if (!NT_SUCCESS(status))
+            goto abort;
+
+        status = XENBUS_STORE(TransactionEnd,
+                              &Target->StoreInterface,
+                              Transaction,
+                              TRUE);
+        if (status == STATUS_RETRY)
+            continue;
+        break;
 
-        QueueUnPop(&Target->FreshSrbs, &SrbExt->ListEntry);
+abort:
+        (VOID) XENBUS_STORE(TransactionEnd,
+                            &Target->StoreInterface,
+                            Transaction,
+                            FALSE);   
+        break;
     }
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    // now the first set of requests popped off submitted list is the next SRB 
-    // to be popped off the fresh list
-}
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->Path,
+                          "state",
+                          "%u",
+                          (ULONG)XenbusStateInitialised);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    State = XenbusStateUnknown;
+    do {
+       TargetWaitForBackendStateChange(Target, &State);
+
+       status = STATUS_UNSUCCESSFUL;
+       if (State == XenbusStateUnknown)
+           goto fail5;
+    } while (State == XenbusStateInitWait ||
+             State == XenbusStateInitialising ||
+             State == XenbusStateInitialised);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (State != XenbusStateConnected)
+        goto fail6;
+
+    TargetStoreReadDiskInfo(Target);
+    TargetStoreReadFeatures(Target);
+
+    status = XENBUS_STORE(Printf,
+                          &Target->StoreInterface,
+                          NULL,
+                          Target->Path,
+                          "state",
+                          "%u",
+                          (ULONG)XenbusStateConnected);
+    if (!NT_SUCCESS(status))
+        goto fail7;
 
-VOID
-TargetPostResume(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    KIRQL   Irql;
+    Trace("[%u] <-----\n", Target->TargetId);
+    return STATUS_SUCCESS;
 
-    Verbose("Target[%d] : %d Fresh SRBs\n", TargetGetTargetId(Target), 
QueueCount(&Target->FreshSrbs));
-    
-    // clear missing flag
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    Verbose("Target[%d] : %s (%s)\n", TargetGetTargetId(Target), 
Target->Missing ? "MISSING" : "NOT_MISSING", Target->Reason);
-    Target->Missing = FALSE;
-    Target->Reason = NULL;
-    KeReleaseSpinLock(&Target->Lock, Irql);
+fail7:
+    Error("fail7\n");
+fail6:
+    Error("fail6\n");
+fail5:
+    Error("fail5\n");
+fail4:
+    Error("fali4\n");
+fail3:
+    Error("fail3\n");
+    BlockRingDisconnect(Target->BlockRing);
+fail2:
+    Error("fail2\n");
+    GranterDisconnect(Target->Granter);
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-//=============================================================================
-// SRBs
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSectors(
-    __in ULONG64                 SectorCount,
-    __in ULONG64                 Start,
-    __in ULONG                   Length
+static VOID
+TargetEnable(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    // Deal with overflow
-    return (Start < SectorCount) && ((Start + Length) <= SectorCount);
-}
+    Trace("[%u] ----->\n", Target->TargetId);
 
-__checkReturn
-static FORCEINLINE BOOLEAN
-__ValidateSrbBuffer(
-    __in PCHAR                  Caller,
-    __in PSCSI_REQUEST_BLOCK    Srb,
-    __in ULONG                  MinLength
-    )
-{
-    if (Srb->DataBuffer == NULL) {
-        Error("%s: Srb[0x%p].DataBuffer = NULL\n", Caller, Srb);
-        return FALSE;
-    }
-    if (MinLength) {
-        if (Srb->DataTransferLength < MinLength) {
-            Error("%s: Srb[0x%p].DataTransferLength < %d\n", Caller, Srb, 
MinLength);
-            return FALSE;
-        }
-    } else {
-        if (Srb->DataTransferLength == 0) {
-            Error("%s: Srb[0x%p].DataTransferLength = 0\n", Caller, Srb);
-            return FALSE;
-        }
-    }
+    GranterEnable(Target->Granter);
+    BlockRingEnable(Target->BlockRing);
 
-    return TRUE;
+    Trace("[%u] <-----\n", Target->TargetId);
 }
 
-static DECLSPEC_NOINLINE VOID
-TargetReadWrite(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
+static VOID
+TargetDisable(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
-    PXENVBD_NOTIFIER        Notifier = FrontendGetNotifier(Target->Frontend);
-
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-        return;
-    }
+    Trace("[%u] ----->\n", Target->TargetId);
 
-    // check valid sectors
-    if (!__ValidateSectors(DiskInfo->SectorCount, Cdb_LogicalBlock(Srb), 
Cdb_TransferBlock(Srb))) {
-        Trace("Target[%d] : Invalid Sector (%d @ %lld < %lld)\n", 
TargetGetTargetId(Target), Cdb_TransferBlock(Srb), Cdb_LogicalBlock(Srb), 
DiskInfo->SectorCount);
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-        return; // Complete now
-    }
+    BlockRingDisable(Target->BlockRing);
+    GranterDisable(Target->Granter);
 
-    QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
-    NotifierKick(Notifier);
+    Trace("[%u] <-----\n", Target->TargetId);
 }
 
-static DECLSPEC_NOINLINE VOID
-TargetSyncCache(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
+static VOID
+TargetDisconnect(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PXENVBD_NOTIFIER        Notifier = FrontendGetNotifier(Target->Frontend);
-
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-        return;
-    }
+    Trace("[%u] ----->\n", Target->TargetId);
 
-    if (FrontendGetDiskInfo(Target->Frontend)->FlushCache == FALSE &&
-        FrontendGetDiskInfo(Target->Frontend)->Barrier == FALSE) {
-        Trace("Target[%d] : FLUSH and BARRIER not supported, suppressing\n", 
TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        return;
-    }
+    BlockRingDisconnect(Target->BlockRing);
+    GranterDisconnect(Target->Granter);
 
-    QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
-    NotifierKick(Notifier);
+    Trace("[%u] <-----\n", Target->TargetId);
 }
 
-static DECLSPEC_NOINLINE VOID
-TargetUnmap(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
+static FORCEINLINE PCHAR
+XenvbdStateName(
+    IN  XENVBD_STATE    State
     )
 {
-    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
-    PXENVBD_NOTIFIER    Notifier = FrontendGetNotifier(Target->Frontend);
-
-    if (FrontendGetCaps(Target->Frontend)->Connected == FALSE) {
-        Trace("Target[%d] : Not Ready, fail SRB\n", TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x40; // SCSI_ABORT;
-        Srb->SrbStatus = SRB_STATUS_ERROR;
-        return;
-    }
-
-    if (FrontendGetDiskInfo(Target->Frontend)->Discard == FALSE) {
-        Trace("Target[%d] : DISCARD not supported, suppressing\n", 
TargetGetTargetId(Target));
-        Srb->ScsiStatus = 0x00; // SCSI_GOOD
-        Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        return;
+    switch (State) {
+    case XENVBD_STATE_INVALID:  return "INVALID";
+    case XENVBD_INITIALIZED:    return "INITIAIZED";
+    case XENVBD_CLOSING:        return "CLOSING";
+    case XENVBD_CLOSED:         return "CLOSED";
+    case XENVBD_PREPARED:       return "PREPARED";
+    case XENVBD_CONNECTED:      return "CONNECTED";
+    case XENVBD_ENABLED:        return "ENABLED";
+    default:                    return "<UNKNOWN>";
     }
-
-    QueueAppend(&Target->FreshSrbs, &SrbExt->ListEntry);
-    NotifierKick(Notifier);
 }
 
-#define MODE_CACHING_PAGE_LENGTH 20
-static DECLSPEC_NOINLINE VOID
-TargetModeSense(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
-    )
-{
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PMODE_PARAMETER_HEADER  Header = Srb->DataBuffer;
-    const UCHAR             PageCode = Cdb_PageCode(Srb);
-    ULONG                   LengthLeft = Cdb_AllocationLength(Srb);
-    PVOID                   CurrentPage = Srb->DataBuffer;
+static NTSTATUS
+TargetSetState(
+    IN  PXENVBD_TARGET  Target,
+    IN  XENVBD_STATE    State
+    )
+{
+    NTSTATUS            status = STATUS_SUCCESS;
+
+    Verbose("[%u] %s -> %s\n",
+            Target->TargetId,
+            XenvbdStateName(Target->State),
+            XenvbdStateName(State));
+
+    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+    while (NT_SUCCESS(status) && Target->State != State) {
+        switch (Target->State) {
+        case XENVBD_INITIALIZED:
+            switch (State) {
+            case XENVBD_CLOSING:
+            case XENVBD_CLOSED:
+            case XENVBD_PREPARED:
+            case XENVBD_CONNECTED:
+            case XENVBD_ENABLED:
+                status = TargetClose(Target);
+                if (!NT_SUCCESS(status))
+                    break;
+                Target->State = XENVBD_CLOSED;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-    UNREFERENCED_PARAMETER(Target);
+        case XENVBD_CLOSING:
+            switch (State) {
+            case XENVBD_INITIALIZED:
+            case XENVBD_CLOSED:
+            case XENVBD_PREPARED:
+            case XENVBD_CONNECTED:
+            case XENVBD_ENABLED:
+                TargetDisconnect(Target);
+                Target->State = XENVBD_CLOSED;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-    RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
+        case XENVBD_CLOSED:
+            switch (State) {
+            //case XENVBD_INITIALIZING:
+            //    Target->State = XENVBD_INITIALISED;
+            //    break;
+            case XENVBD_PREPARED:
+            case XENVBD_CONNECTED:
+            case XENVBD_ENABLED:
+                status = TargetPrepare(Target);
+                if (!NT_SUCCESS(status)) {
+                    TargetClose(Target);
+                    Target->State = XENVBD_CLOSED;
+                    break;
+                }
+                Target->State = XENVBD_PREPARED;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(struct 
_MODE_SENSE))) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-        Srb->DataTransferLength = 0;
-        return;
-    }
+        case XENVBD_PREPARED:
+            switch (State) {
+            case XENVBD_CLOSING:
+            case XENVBD_CLOSED:
+                status = TargetClose(Target);
+                if (!NT_SUCCESS(status))
+                    break;
+                Target->State = XENVBD_CLOSED;
+                break;
+            case XENVBD_CONNECTED:
+            case XENVBD_ENABLED:
+                status = TargetConnect(Target);
+                if (!NT_SUCCESS(status)) {
+                    TargetClose(Target);
+                    Target->State = XENVBD_CLOSED;
+                    break;
+                }
+                Target->State = XENVBD_CONNECTED;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-    // TODO : CDROM requires more ModePage entries
-    // Header
-    Header->ModeDataLength  = sizeof(MODE_PARAMETER_HEADER) - 1;
-    Header->MediumType      = 0;
-    Header->DeviceSpecificParameter = 0;
-    Header->BlockDescriptorLength   = 0;
-    LengthLeft -= sizeof(MODE_PARAMETER_HEADER);
-    CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_HEADER));
-
-    // Fill in Block Parameters (if Specified and space)
-    // when the DBD (Disable Block Descriptor) is set, ignore the block page
-    if (Cdb_Dbd(Srb) == 0 && 
-        LengthLeft >= sizeof(MODE_PARAMETER_BLOCK)) {
-        PMODE_PARAMETER_BLOCK Block = (PMODE_PARAMETER_BLOCK)CurrentPage;
-        // Fill in BlockParams
-        Block->DensityCode                  =   0;
-        Block->NumberOfBlocks[0]            =   0;
-        Block->NumberOfBlocks[1]            =   0;
-        Block->NumberOfBlocks[2]            =   0;
-        Block->BlockLength[0]               =   0;
-        Block->BlockLength[1]               =   0;
-        Block->BlockLength[2]               =   0;
+        case XENVBD_CONNECTED:
+            switch (State) {
+            case XENVBD_ENABLED:
+                TargetEnable(Target);
+                Target->State = XENVBD_ENABLED;
+                break;
+            case XENVBD_CLOSING:
+            case XENVBD_CLOSED:
+                status = TargetClose(Target);
+                if (!NT_SUCCESS(status))
+                    break;
+                Target->State = XENVBD_CLOSING;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-        Header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
-        Header->ModeDataLength += sizeof(MODE_PARAMETER_BLOCK);
-        LengthLeft -= sizeof(MODE_PARAMETER_BLOCK);
-        CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_PARAMETER_BLOCK));
-    }
+        case XENVBD_ENABLED:
+            switch (State) {
+            case XENVBD_CLOSING:
+            case XENVBD_CLOSED:
+            case XENVBD_CONNECTED:
+                TargetDisable(Target);
+                Target->State = XENVBD_CONNECTED;
+                break;
+            default:
+                status = STATUS_UNSUCCESSFUL;
+                break;
+            }
+            break;
 
-    // Fill in Cache Parameters (if Specified and space)
-    if ((PageCode == MODE_PAGE_CACHING || PageCode == MODE_SENSE_RETURN_ALL) &&
-        LengthLeft >= MODE_CACHING_PAGE_LENGTH) {
-        PMODE_CACHING_PAGE Caching = (PMODE_CACHING_PAGE)CurrentPage;
-        // Fill in CachingParams
-        Caching->PageCode                   = MODE_PAGE_CACHING;
-        Caching->PageSavable                = 0;
-        Caching->PageLength                 = MODE_CACHING_PAGE_LENGTH;
-        Caching->ReadDisableCache           = 0;
-        Caching->MultiplicationFactor       = 0;
-        Caching->WriteCacheEnable           = 
FrontendGetDiskInfo(Target->Frontend)->FlushCache ? 1 : 0;
-        Caching->WriteRetensionPriority     = 0;
-        Caching->ReadRetensionPriority      = 0;
-        Caching->DisablePrefetchTransfer[0] = 0;
-        Caching->DisablePrefetchTransfer[1] = 0;
-        Caching->MinimumPrefetch[0]         = 0;
-        Caching->MinimumPrefetch[1]         = 0;
-        Caching->MaximumPrefetch[0]         = 0;
-        Caching->MaximumPrefetch[1]         = 0;
-        Caching->MaximumPrefetchCeiling[0]  = 0;
-        Caching->MaximumPrefetchCeiling[1]  = 0;
-
-        Header->ModeDataLength += MODE_CACHING_PAGE_LENGTH;
-        LengthLeft -= MODE_CACHING_PAGE_LENGTH;
-        CurrentPage = ((PUCHAR)CurrentPage + MODE_CACHING_PAGE_LENGTH);
+        default:
+            status = STATUS_UNSUCCESSFUL;
+            break;
+        }
     }
 
-    // Fill in Informational Exception Parameters (if Specified and space)
-    if ((PageCode == MODE_PAGE_FAULT_REPORTING || PageCode == 
MODE_SENSE_RETURN_ALL) &&
-        LengthLeft >= sizeof(MODE_INFO_EXCEPTIONS)) {
-        PMODE_INFO_EXCEPTIONS Exceptions = (PMODE_INFO_EXCEPTIONS)CurrentPage;
-        // Fill in Exceptions
-        Exceptions->PageCode                = MODE_PAGE_FAULT_REPORTING;
-        Exceptions->PSBit                   = 0;
-        Exceptions->PageLength              = sizeof(MODE_INFO_EXCEPTIONS);
-        Exceptions->Flags                   = 0;
-        Exceptions->Dexcpt                  = 1; // disabled
-        Exceptions->ReportMethod            = 0;
-        Exceptions->IntervalTimer[0]        = 0;
-        Exceptions->IntervalTimer[1]        = 0;
-        Exceptions->IntervalTimer[2]        = 0;
-        Exceptions->IntervalTimer[3]        = 0;
-        Exceptions->ReportCount[0]          = 0;
-        Exceptions->ReportCount[1]          = 0;
-        Exceptions->ReportCount[2]          = 0;
-        Exceptions->ReportCount[3]          = 0;
-
-        Header->ModeDataLength += sizeof(MODE_INFO_EXCEPTIONS);
-        LengthLeft -= sizeof(MODE_INFO_EXCEPTIONS);
-        CurrentPage = ((PUCHAR)CurrentPage + sizeof(MODE_INFO_EXCEPTIONS));
-    }
+    Verbose("[%u] in state %s\n",
+            Target->TargetId,
+            XenvbdStateName(Target->State));
 
-    // Finish this SRB
-    Srb->SrbStatus = SRB_STATUS_SUCCESS;
-    Srb->DataTransferLength = __min(Cdb_AllocationLength(Srb), 
(ULONG)(Header->ModeDataLength + 1));
+    return status;
 }
 
-static DECLSPEC_NOINLINE VOID
-TargetRequestSense(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
+static FORCEINLINE NTSTATUS
+__TargetD3ToD0(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
-    PSENSE_DATA         Sense = Srb->DataBuffer;
+    NTSTATUS            status;
 
-    UNREFERENCED_PARAMETER(Target);
+    status = XENBUS_STORE(Acquire, &Target->StoreInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, (ULONG)sizeof(SENSE_DATA))) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-        return;
-    }
+    status = TargetSetState(Target, XENVBD_ENABLED);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    RtlZeroMemory(Sense, sizeof(SENSE_DATA));
+    return STATUS_SUCCESS;
 
-    Sense->ErrorCode            = 0x70;
-    Sense->Valid                = 1;
-    Sense->AdditionalSenseCodeQualifier = 0;
-    Sense->SenseKey             = SCSI_SENSE_NO_SENSE;
-    Sense->AdditionalSenseCode  = SCSI_ADSENSE_NO_SENSE;
-    Srb->DataTransferLength     = sizeof(SENSE_DATA);
-    Srb->SrbStatus              = SRB_STATUS_SUCCESS;
+fail2:
+    Error("fail2\n");
+    XENBUS_STORE(Release, &Target->StoreInterface);
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
-static DECLSPEC_NOINLINE VOID
-TargetReportLuns(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
+static FORCEINLINE VOID
+__TargetD0ToD3(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
-    ULONG               Length;
-    ULONG               Offset;
-    ULONG               AllocLength = Cdb_AllocationLength(Srb);
-    PUCHAR              Buffer = Srb->DataBuffer;
-
-    UNREFERENCED_PARAMETER(Target);
+    TargetSetState(Target, XENVBD_CLOSED);
 
-    if (!__ValidateSrbBuffer(__FUNCTION__, Srb, 8)) {
-        Srb->ScsiStatus = 0x40;
-        Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
-        Srb->DataTransferLength = 0;
-        return;
-    }
+    XENBUS_STORE(Release, &Target->StoreInterface);
+}
 
-    RtlZeroMemory(Buffer, AllocLength);
+static DECLSPEC_NOINLINE VOID
+TargetSuspendCallback(
+    IN  PVOID       Context
+    )
+{
+    PXENVBD_TARGET  Target = Context;
+    LIST_ENTRY      List;
+    NTSTATUS        status;
 
-    Length = 0;
-    Offset = 8;
+    // Any outstanding requests are going to cause problems...
+    // Submitted requests are lost
+    // Prepared requests will need re-preparing (different grant/backend)
+    // Fresh SRBs will be ok
+    InitializeListHead(&List);
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
+        PXENVBD_SRBEXT  SrbExt;
 
-    if (Offset + 8 <= AllocLength) {
-        Buffer[Offset] = 0;
-        Offset += 8;
-        Length += 8;
-    }
+        ListEntry = RemoveHeadList(&Target->Submitted);
+        if (ListEntry == &Target->Submitted)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        SrbExt = Request->SrbExt;
 
-    if (Offset + 8 <= AllocLength) {
-        Buffer[Offset] = XENVBD_MAX_TARGETS;
-        Offset += 8;
-        Length += 8;
+        TargetPutRequest(Target, Request);
+        if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
+            SrbExt->Srb->SrbStatus = SRB_STATUS_ABORTED;
+            AdapterCompleteSrb(Target->Adapter, SrbExt);
+        }
     }
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
+        PXENVBD_REQUEST Request;
+        PXENVBD_SRBEXT  SrbExt;
 
-    REVERSE_BYTES(Buffer, &Length);
-
-    Srb->DataTransferLength = __min(Length, AllocLength);
-    Srb->SrbStatus = SRB_STATUS_SUCCESS;
-}
+        ListEntry = RemoveHeadList(&Target->Prepared);
+        if (ListEntry == &Target->Prepared)
+            break;
+        Request = CONTAINING_RECORD(ListEntry, XENVBD_REQUEST, ListEntry);
+        SrbExt = Request->SrbExt;
 
-static DECLSPEC_NOINLINE VOID
-TargetReadCapacity(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
-    )
-{
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PREAD_CAPACITY_DATA     Capacity = Srb->DataBuffer;
-    PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
-    ULONG64                 SectorCount;
-    ULONG                   SectorSize;
-    ULONG                   LastBlock;
-
-    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
-        Srb->ScsiStatus = 0x02; // CHECK_CONDITION
-        return;
+        TargetPutRequest(Target, Request);
+        if (InterlockedDecrement(&SrbExt->RequestCount) == 0) {
+            InsertHeadList(&List, &SrbExt->ListEntry);
+        }
     }
-    
-    SectorCount = DiskInfo->SectorCount;
-    SectorSize = DiskInfo->SectorSize;
+    for (;;) {
+        PLIST_ENTRY     ListEntry;
 
-    if (SectorCount == (ULONG)SectorCount)
-        LastBlock = (ULONG)SectorCount - 1;
-    else
-        LastBlock = ~(ULONG)0;
+        ListEntry = RemoveHeadList(&List);
+        if (ListEntry == &List)
+            break;
 
-    if (Capacity) {
-        Capacity->LogicalBlockAddress = _byteswap_ulong(LastBlock);
-        Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
+        InsertHeadList(&Target->Fresh, ListEntry);
     }
 
-    Srb->SrbStatus = SRB_STATUS_SUCCESS;
+    __TargetD0ToD3(Target);
+
+    status = __TargetD3ToD0(Target);
+    ASSERT(NT_SUCCESS(status));
 }
 
 static DECLSPEC_NOINLINE VOID
-TargetReadCapacity16(
-    IN  PXENVBD_TARGET      Target,
-    IN  PXENVBD_SRBEXT      SrbExt
+TargetDebugCallback(
+    IN  PVOID       Context,
+    IN  BOOLEAN     Crashing
     )
-{
-    PSCSI_REQUEST_BLOCK     Srb = SrbExt->Srb;
-    PREAD_CAPACITY16_DATA   Capacity = Srb->DataBuffer;
-    PXENVBD_DISKINFO        DiskInfo = FrontendGetDiskInfo(Target->Frontend);
-    ULONG64                 SectorCount;
-    ULONG                   SectorSize;
-    ULONG                   PhysSectorSize;
-    ULONG                   LogicalPerPhysical;
-    ULONG                   LogicalPerPhysicalExponent;
-
-    if (Cdb_PMI(Srb) == 0 && Cdb_LogicalBlock(Srb) != 0) {
-        Srb->ScsiStatus = 0x02; // CHECK_CONDITION
-        return;
-    }
-
-    SectorCount = DiskInfo->SectorCount;
-    SectorSize = DiskInfo->SectorSize;
-    PhysSectorSize = DiskInfo->PhysSectorSize;
+{
+    PXENVBD_TARGET  Target = Context;
 
-    LogicalPerPhysical = PhysSectorSize / SectorSize;
+    UNREFERENCED_PARAMETER(Crashing);
 
-    if (!_BitScanReverse(&LogicalPerPhysicalExponent, LogicalPerPhysical))
-        LogicalPerPhysicalExponent = 0;
+    XENBUS_DEBUG(Printf,
+                 &Target->DebugInterface,
+                 "Adapter: 0x%p DeviceObject: 0x%p\n",
+                 Target->Adapter,
+                 Target->DeviceObject);
 
-    if (Capacity) {
-        Capacity->LogicalBlockAddress.QuadPart = _byteswap_uint64(SectorCount 
- 1);
-        Capacity->BytesPerBlock = _byteswap_ulong(SectorSize);
-        Capacity->LogicalPerPhysicalExponent = 
(UCHAR)LogicalPerPhysicalExponent;
-    }
+    XENBUS_DEBUG(Printf,
+                 &Target->DebugInterface,
+                 "TargetI: %u DeviceId: %u BackendId: %u\n",
+                 Target->TargetId,
+                 Target->DeviceId,
+                 Target->BackendId);
+
+    XENBUS_DEBUG(Printf,
+                 &Target->DebugInterface,
+                 "Path: %s\n",
+                 Target->Path);
+
+    XENBUS_DEBUG(Printf,
+                 &Target->DebugInterface,
+                 "BackendPath: %s\n",
+                 Target->BackendPath ? Target->BackendPath : "NULL");
+
+    XENBUS_DEBUG(Printf,
+                 &Target->DebugInterface,
+                 "TargetPath: %s\n",
+                 Target->TargetPath);
+
+    XENBUS_DEBUG(Printf,
+                &Target->DebugInterface,
+                "Features: %s%s%s%s%s\n",
+                Target->Removable ? "REMOVABLE " : "",
+                Target->FeatureBarrier ? "BARRIER " : "",
+                Target->FeatureDiscard ? "DISCARD " : "",
+                Target->FeatureFlush ? "FLUSH " : "",
+                Target->FeatureIndirect ? "INDIRECT " : "");
+
+    if (Target->FeatureDiscard) {
+        XENBUS_DEBUG(Printf,
+                    &Target->DebugInterface,
+                    "DISCARD: %s%u @ %u\n",
+                    Target->DiscardSecure ? "SECURE " : "",
+                    Target->DiscardAlignment,
+                    Target->DiscardGranularity);
+    }
+
+    if (Target->FeatureIndirect) {
+        XENBUS_DEBUG(Printf,
+                    &Target->DebugInterface,
+                    "INDIRECT: %u MaxSegsPerInd\n",
+                    Target->FeatureIndirect);
+    }
+
+    XENBUS_DEBUG(Printf,
+                &Target->DebugInterface,
+                "%llu sectors @ %u (%u) %08x\n",
+                Target->SectorCount,
+                Target->SectorSize,
+                Target->PhysicalSectorSize,
+                Target->DiskInfo);
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+TargetBackendThread(
+    IN  PXENVBD_THREAD  Self,
+    IN  PVOID           Context
+    )
+{
+    PXENVBD_TARGET      Target = Context;
+    PKEVENT             Event = ThreadGetEvent(Self); 
+    LARGE_INTEGER       Start;
+    LARGE_INTEGER       Now;
+
+    KeQuerySystemTime(&Start);
+    for (;;) {
+        PCHAR           Buffer;
+        NTSTATUS        status;
+        KIRQL           Irql;
+        BOOLEAN         Online = TRUE;
+
+        (VOID) KeWaitForSingleObject(Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        if (ThreadIsAlerted(Self))
+            break;
 
-    Srb->SrbStatus = SRB_STATUS_SUCCESS;
-}
+        KeQuerySystemTime(&Now);
+        // Rate limit checking to once a second
+        if ((Now.QuadPart - Start.QuadPart) < 10000000ull)
+            continue;
+        Start.QuadPart = Now.QuadPart;
 
-static FORCEINLINE VOID
-__TargetQueueShutdown(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
-    )
-{
-    PXENVBD_NOTIFIER    Notifier = FrontendGetNotifier(Target->Frontend);
+        KeAcquireSpinLock(&Target->StateLock, &Irql);
+        if (Target->DevicePowerState != PowerDeviceD0) {
+            KeReleaseSpinLock(&Target->StateLock, Irql);
+            continue;
+        }
+        KeReleaseSpinLock(&Target->StateLock, Irql);
+
+        TargetStoreReadDiskInfo(Target);
+
+        status = XENBUS_STORE(Read,
+                              &Target->StoreInterface,
+                              NULL,
+                              Target->BackendPath,
+                              "online",
+                              &Buffer);
+        if (NT_SUCCESS(status)) {
+            Online = (BOOLEAN)strtoul(Buffer, NULL, 2);
+
+            XENBUS_STORE(Free,
+                            &Target->StoreInterface,
+                            Buffer);
+        }
 
-    QueueAppend(&Target->ShutdownSrbs, &SrbExt->ListEntry);
-    NotifierKick(Notifier);
+        if (!Online) {
+            // eject!
+            TargetSetMissing(Target, "Ejecting");
+            AdapterTargetListChanged(TargetGetAdapter(Target));
+        }
+    }
 
-    SrbExt->Srb->SrbStatus = SRB_STATUS_PENDING;
+    return STATUS_SUCCESS;
 }
 
-VOID
-TargetReset(
+NTSTATUS
+TargetD3ToD0(
     IN  PXENVBD_TARGET  Target
     )
 {
+    KIRQL               Irql;
+    NTSTATUS            status;
+
+    if (Target->DevicePowerState == PowerDeviceD0)
+        return STATUS_SUCCESS;
+
     Verbose("[%u] =====>\n",
-            TargetGetTargetId(Target));
+            Target->TargetId);
 
-    __TargetPauseDataPath(Target, TRUE);
+    status = XENBUS_DEBUG(Acquire, &Target->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    if (QueueCount(&Target->SubmittedReqs)) {
-        Error("Target[%d] : backend has %u outstanding requests after a 
TargetReset\n",
-                TargetGetTargetId(Target), QueueCount(&Target->SubmittedReqs));
-    }
+    status = XENBUS_SUSPEND(Acquire, &Target->SuspendInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    __TargetUnpauseDataPath(Target);
+    status = XENBUS_DEBUG(Register,
+                          &Target->DebugInterface,
+                         __MODULE__,
+                         TargetDebugCallback,
+                         Target,
+                         &Target->DebugCallback);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    Verbose("[%u] <=====\n",
-            TargetGetTargetId(Target));
-}
+    status = XENBUS_SUSPEND(Register,
+                            &Target->SuspendInterface,
+                            SUSPEND_CALLBACK_LATE,
+                            TargetSuspendCallback,
+                            Target,
+                            &Target->SuspendCallback);
+    if (!NT_SUCCESS(status))
+        goto fail4;
 
-VOID
-TargetPrepareSrb(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
-    )
-{
-    PSCSI_REQUEST_BLOCK Srb = SrbExt->Srb;
+    KeAcquireSpinLock(&Target->StateLock, &Irql);
+    status = __TargetD3ToD0(Target);
+    KeReleaseSpinLock(&Target->StateLock, Irql);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
-    SrbExt->Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
-    if (TargetIsMissing(Target))
-        return;
+    Target->DevicePowerState = PowerDeviceD0;
+    Verbose("[%u] <=====\n",
+            Target->TargetId);
+    return STATUS_SUCCESS;
 
-    Srb->SrbStatus = SRB_STATUS_PENDING;
+fail5:
+    Error("fail5\n");
+    XENBUS_SUSPEND(Deregister,
+                    &Target->SuspendInterface,
+                    Target->SuspendCallback);
+    Target->SuspendCallback = NULL;
+fail4:
+    Error("fail4\n");
+    XENBUS_DEBUG(Deregister,
+                 &Target->DebugInterface,
+                 Target->DebugCallback);
+    Target->DebugCallback = NULL;
+fail3:
+    Error("fail3\n");
+    XENBUS_SUSPEND(Release,
+                   &Target->SuspendInterface);
+fail2:
+    Error("fail2\n");
+    XENBUS_DEBUG(Release,
+                 &Target->DebugInterface);
+fail1:
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
 VOID
-TargetStartSrb(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
+TargetD0ToD3(
+    IN  PXENVBD_TARGET  Target
     )
 {
-    const UCHAR         Operation = Cdb_OperationEx(SrbExt->Srb);
-    PXENVBD_DISKINFO    DiskInfo = FrontendGetDiskInfo(Target->Frontend);
+    KIRQL               Irql;
 
-    if (DiskInfo->DiskInfo & VDISK_READONLY) {
-        Trace("Target[%d] : (%08x) Read-Only, fail SRB (%02x:%s)\n", 
TargetGetTargetId(Target),
-                DiskInfo->DiskInfo, Operation, Cdb_OperationName(Operation));
-        SrbExt->Srb->ScsiStatus = 0x40; // SCSI_ABORT
-        SrbExt->Srb->SrbStatus = SRB_STATUS_ERROR;
+    if (Target->DevicePowerState == PowerDeviceD3)
         return;
-    }
-
-    switch (Operation) {
-    case SCSIOP_READ:
-        TargetReadWrite(Target, SrbExt);
 
-    case SCSIOP_WRITE:
-        TargetReadWrite(Target, SrbExt);
-        break;
-        
-    case SCSIOP_SYNCHRONIZE_CACHE:
-        TargetSyncCache(Target, SrbExt);
-        break;
+    Verbose("[%u] =====>\n",
+            Target->TargetId);
+    Target->DevicePowerState = PowerDeviceD3;
 
-    case SCSIOP_UNMAP:
-        TargetUnmap(Target, SrbExt);
-        break;
+    KeAcquireSpinLock(&Target->StateLock, &Irql);
+    __TargetD0ToD3(Target);
+    KeReleaseSpinLock(&Target->StateLock, Irql);
 
-    case SCSIOP_INQUIRY:
-        if (!StorPortSetDeviceQueueDepth(TargetGetAdapter(Target),
-                                         0,
-                                         (UCHAR)TargetGetTargetId(Target),
-                                         0,
-                                         XENVBD_MAX_QUEUE_DEPTH))
-            Verbose("Target[%d] : Failed to set queue depth\n",
-                    TargetGetTargetId(Target));
-        PdoInquiry(TargetGetTargetId(Target), 
FrontendGetInquiry(Target->Frontend), SrbExt->Srb);
-        break;
-    case SCSIOP_MODE_SENSE:
-        TargetModeSense(Target, SrbExt);
-        break;
-    case SCSIOP_REQUEST_SENSE:
-        TargetRequestSense(Target, SrbExt);
-        break;
-    case SCSIOP_REPORT_LUNS:
-        TargetReportLuns(Target, SrbExt);
-        break;
-    case SCSIOP_READ_CAPACITY:
-        TargetReadCapacity(Target, SrbExt);
-        break;
-    case SCSIOP_READ_CAPACITY16:
-        TargetReadCapacity16(Target, SrbExt);
-        break;
+    XENBUS_SUSPEND(Deregister,
+                    &Target->SuspendInterface,
+                    Target->SuspendCallback);
+    Target->SuspendCallback = NULL;
 
-    case SCSIOP_MEDIUM_REMOVAL:
-    case SCSIOP_TEST_UNIT_READY:
-    case SCSIOP_RESERVE_UNIT:
-    case SCSIOP_RESERVE_UNIT10:
-    case SCSIOP_RELEASE_UNIT:
-    case SCSIOP_RELEASE_UNIT10:
-    case SCSIOP_VERIFY:
-    case SCSIOP_VERIFY16:
-    case SCSIOP_START_STOP_UNIT:
-        SrbExt->Srb->SrbStatus = SRB_STATUS_SUCCESS;
-        break;
+    XENBUS_DEBUG(Deregister,
+                 &Target->DebugInterface,
+                 Target->DebugCallback);
+    Target->DebugCallback = NULL;
 
-    default:
-        Trace("Target[%d] : Unsupported CDB (%02x:%s)\n",
-               TargetGetTargetId(Target),
-               Operation,
-               Cdb_OperationName(Operation));
-        SrbExt->Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
-        break;
-    }
-}
+    XENBUS_SUSPEND(Release,
+                   &Target->SuspendInterface);
 
-VOID
-TargetFlush(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
-    )
-{
-    __TargetQueueShutdown(Target, SrbExt);
-}
+    XENBUS_DEBUG(Release,
+                 &Target->DebugInterface);
 
-VOID
-TargetShutdown(
-    IN  PXENVBD_TARGET  Target,
-    IN  PXENVBD_SRBEXT  SrbExt
-    )
-{
-    __TargetQueueShutdown(Target, SrbExt);
+    Verbose("[%u] <=====\n",
+            Target->TargetId);
 }
 
-VOID
-TargetSrbPnp(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_PNP_REQUEST_BLOCK Srb
+static FORCEINLINE PCHAR
+__DeviceUsageName(
+    IN  ULONG   Index
     )
 {
-    switch (Srb->PnPAction) {
-    case StorQueryCapabilities: {
-        PSTOR_DEVICE_CAPABILITIES DeviceCaps = Srb->DataBuffer;
-        PXENVBD_CAPS    Caps = FrontendGetCaps(Target->Frontend);
-
-        if (Caps->Removable)
-            DeviceCaps->Removable = 1;
-        if (Caps->Removable)
-            DeviceCaps->EjectSupported = 1;
-        if (Caps->SurpriseRemovable)
-            DeviceCaps->SurpriseRemovalOK = 1;
-
-        DeviceCaps->UniqueID = 1;
-
-        } break;
-
-    default:
-        break;
+    switch (Index) {
+    case DeviceUsageTypeUndefined:      return NULL;
+    case DeviceUsageTypePaging:         return "paging";
+    case DeviceUsageTypeHibernation:    return "hibernation";
+    case DeviceUsageTypeDumpFile:       return "dump";
+    default:                            return NULL;
     }
 }
 
-//=============================================================================
-// PnP Handler
 static FORCEINLINE VOID
 __TargetDeviceUsageNotification(
-    __in PXENVBD_TARGET             Target,
-    __in PIRP                    Irp
+    IN  PXENVBD_TARGET      Target,
+    IN  PIRP                Irp
     )
 {
     PIO_STACK_LOCATION      StackLocation;
+    ULONG                   Index;
     BOOLEAN                 Value;
-    DEVICE_USAGE_NOTIFICATION_TYPE  Type;
-    PXENVBD_CAPS            Caps = FrontendGetCaps(Target->Frontend);
 
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
     Value = StackLocation->Parameters.UsageNotification.InPath;
-    Type  = StackLocation->Parameters.UsageNotification.Type;
-
-    switch (Type) {
-    case DeviceUsageTypePaging:
-        if (Caps->Paging == Value)
-            return;
-        Caps->Paging = Value;
-        break;
-
-    case DeviceUsageTypeHibernation:
-        if (Caps->Hibernation == Value)
-            return;
-        Caps->Hibernation = Value;
-        break;
-
-    case DeviceUsageTypeDumpFile:
-        if (Caps->DumpFile == Value)
-            return;
-        Caps->DumpFile = Value;
-        break;
+    Index = (ULONG)StackLocation->Parameters.UsageNotification.Type;
 
-    default:
+    if (__DeviceUsageName(Index) == NULL)
+        return;
+    if (Target->DeviceUsage[Index] == Value)
         return;
-    }
-    FrontendWriteUsage(Target->Frontend);
-}
-
-static FORCEINLINE VOID
-__TargetCheckEjectPending(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    KIRQL               Irql;
-    BOOLEAN             EjectPending = FALSE;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    if (Target->EjectPending) {
-        EjectPending = TRUE;
-        Target->EjectPending = FALSE;
-        Target->EjectRequested = TRUE;
-    }
-    KeReleaseSpinLock(&Target->Lock, Irql);
-
-    if (EjectPending) {
-        Verbose("Target[%d] : IoRequestDeviceEject(0x%p)\n", 
TargetGetTargetId(Target), Target->DeviceObject);
-        IoRequestDeviceEject(Target->DeviceObject);
-    }
-}
-
-static FORCEINLINE VOID
-__TargetCheckEjectFailed(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    KIRQL               Irql;
-    BOOLEAN             EjectFailed = FALSE;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    if (Target->EjectRequested) {
-        EjectFailed = TRUE;
-        Target->EjectRequested = FALSE;
-    }
-    KeReleaseSpinLock(&Target->Lock, Irql);
-
-    if (EjectFailed) {
-        Error("Target[%d] : Unplug failed due to open handle(s)!\n", 
TargetGetTargetId(Target));
-        FrontendStoreWriteFrontend(Target->Frontend, "error", "Unplug failed 
due to open handle(s)!");
-    }
-}
-
-static FORCEINLINE VOID
-__TargetRemoveDevice(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    TargetD0ToD3(Target);
 
-    switch (TargetGetDevicePnpState(Target)) {
-    case SurpriseRemovePending:
-        TargetSetMissing(Target, "Surprise Remove");
-        TargetSetDevicePnpState(Target, Deleted);
-        AdapterTargetListChanged(TargetGetAdapter(Target));
-        break;
+    Target->DeviceUsage[Index] = Value;
 
-    default:
-        TargetSetMissing(Target, "Removed");
-        TargetSetDevicePnpState(Target, Deleted);
-        AdapterTargetListChanged(TargetGetAdapter(Target));
-        break;
-    }
-}
+    Verbose("[%u] %s %s\n",
+            Target->TargetId,
+            Value ? "ADDING" : "REMOVING",
+            __DeviceUsageName(Index));
 
-static FORCEINLINE VOID
-__TargetEject(
-    __in PXENVBD_TARGET             Target
-    )
-{
-    TargetSetMissing(Target, "Ejected");
-    TargetSetDevicePnpState(Target, Deleted);
-    AdapterTargetListChanged(TargetGetAdapter(Target));
+    (VOID) XENBUS_STORE(Printf,
+                        &Target->StoreInterface,
+                        NULL,
+                        Target->TargetPath,
+                        __DeviceUsageName(Index),
+                        "%u",
+                        Value);
 }
 
-__checkReturn
 NTSTATUS
 TargetDispatchPnp(
-    __in PXENVBD_TARGET             Target,
-    __in PDEVICE_OBJECT          DeviceObject,
-    __in PIRP                    Irp
+    IN  PXENVBD_TARGET  Target,
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp
     )
 {
-    PIO_STACK_LOCATION  Stack = IoGetCurrentIrpStackLocation(Irp);
-
-    __TargetCheckEjectPending(Target);
-
-    switch (Stack->MinorFunction) {
+    PIO_STACK_LOCATION  StackLocation;
+    
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    switch (StackLocation->MinorFunction) {
     case IRP_MN_START_DEVICE:
         (VOID) TargetD3ToD0(Target);
         TargetSetDevicePnpState(Target, Started);
@@ -2340,7 +2847,7 @@ TargetDispatchPnp(
         break;
 
     case IRP_MN_CANCEL_STOP_DEVICE:
-        __TargetRestoreDevicePnpState(Target, StopPending);
+        TargetRestoreDevicePnpState(Target);
         break;
 
     case IRP_MN_STOP_DEVICE:
@@ -2353,8 +2860,8 @@ TargetDispatchPnp(
         break;
 
     case IRP_MN_CANCEL_REMOVE_DEVICE:
-        __TargetCheckEjectFailed(Target);
-        __TargetRestoreDevicePnpState(Target, RemovePending);
+        // Should write something to Xenstore to indicate the VETO on 
deviceeject
+        TargetRestoreDevicePnpState(Target);
         break;
 
     case IRP_MN_SURPRISE_REMOVAL:
@@ -2362,11 +2869,16 @@ TargetDispatchPnp(
         break;
 
     case IRP_MN_REMOVE_DEVICE:
-        __TargetRemoveDevice(Target);
+        TargetD0ToD3(Target);
+        TargetSetMissing(Target, DevicePnpStateName(Target->DevicePnpState));
+        TargetSetDevicePnpState(Target, Deleted);
+        AdapterTargetListChanged(TargetGetAdapter(Target));
         break;
 
     case IRP_MN_EJECT:
-        __TargetEject(Target);
+        TargetSetMissing(Target, "Ejected");
+        TargetSetDevicePnpState(Target, Deleted);
+        AdapterTargetListChanged(TargetGetAdapter(Target));
         break;
 
     case IRP_MN_DEVICE_USAGE_NOTIFICATION:
@@ -2376,114 +2888,15 @@ TargetDispatchPnp(
     default:
         break;
     }
-    return DriverDispatchPnp(DeviceObject, Irp);
-}
-
-__drv_maxIRQL(DISPATCH_LEVEL)
-VOID
-TargetIssueDeviceEject(
-    __in PXENVBD_TARGET             Target,
-    __in __nullterminated const CHAR* Reason
-    )
-{
-    KIRQL       Irql;
-    BOOLEAN     DoEject = FALSE;
-
-    KeAcquireSpinLock(&Target->Lock, &Irql);
-    if (Target->DeviceObject) {
-        DoEject = TRUE;
-        Target->EjectRequested = TRUE;
-    } else {
-        Target->EjectPending = TRUE;
-    }
-    KeReleaseSpinLock(&Target->Lock, Irql);
-
-    Verbose("Target[%d] : Ejecting (%s - %s)\n", TargetGetTargetId(Target), 
DoEject ? "Now" : "Next PnP IRP", Reason);
-    if (!Target->WrittenEjected) {
-        Target->WrittenEjected = TRUE;
-        FrontendStoreWriteFrontend(Target->Frontend, "ejected", "1");
-    }
-    if (DoEject) {
-        Verbose("Target[%d] : IoRequestDeviceEject(0x%p)\n", 
TargetGetTargetId(Target), Target->DeviceObject);
-        IoRequestDeviceEject(Target->DeviceObject);
-    } else {
-        Verbose("Target[%d] : Triggering BusChangeDetected to detect 
device\n", TargetGetTargetId(Target));
-        AdapterTargetListChanged(TargetGetAdapter(Target));
-    }
-}
-
-__checkReturn
-NTSTATUS
-TargetD3ToD0(
-    __in PXENVBD_TARGET            Target
-    )
-{
-    NTSTATUS                    Status;
-    const ULONG                 TargetId = TargetGetTargetId(Target);
-
-    if (!TargetSetDevicePowerState(Target, PowerDeviceD0))
-        return STATUS_SUCCESS;
-
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-    Verbose("Target[%d] : D3->D0\n", TargetId);
-
-    // power up frontend
-    Status = FrontendD3ToD0(Target->Frontend);
-    if (!NT_SUCCESS(Status))
-        goto fail1;
-
-    // connect frontend
-    Status = FrontendSetState(Target->Frontend, XENVBD_ENABLED);
-    if (!NT_SUCCESS(Status))
-        goto fail2;
-    __TargetUnpauseDataPath(Target);
-
-    Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
-    return STATUS_SUCCESS;
-
-fail2:
-    Error("Fail2\n");
-    FrontendD0ToD3(Target->Frontend);
-
-fail1:
-    Error("Fail1 (%08x)\n", Status);
-
-    Target->DevicePowerState = PowerDeviceD3;
-
-    return Status;
-}
-
-VOID
-TargetD0ToD3(
-    __in PXENVBD_TARGET            Target
-    )
-{
-    const ULONG                 TargetId = TargetGetTargetId(Target);
-
-    if (!TargetSetDevicePowerState(Target, PowerDeviceD3))
-        return;
-
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-    Verbose("Target[%d] : D0->D3\n", TargetId);
-
-    // close frontend
-    __TargetPauseDataPath(Target, FALSE);
-    (VOID) FrontendSetState(Target->Frontend, XENVBD_CLOSED);
-    ASSERT3U(QueueCount(&Target->SubmittedReqs), ==, 0);
-
-    // power down frontend
-    FrontendD0ToD3(Target->Frontend);
 
-    Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
+    return DriverDispatchPnp(DeviceObject, Irp);
 }
 
 static FORCEINLINE ULONG
 __ParseVbd(
-    IN  PCHAR   DeviceIdStr
+    IN  ULONG   DeviceId
     )
-{
-    ULONG   DeviceId = strtoul(DeviceIdStr, NULL, 10);
-    
+{    
     ASSERT3U((DeviceId & ~((1 << 29) - 1)), ==, 0);
 
     if (DeviceId & (1 << 28))
@@ -2504,140 +2917,235 @@ __ParseVbd(
     }
 }
 
-__checkReturn
 NTSTATUS
 TargetCreate(
-    __in PXENVBD_ADAPTER             Adapter,
-    __in __nullterminated PCHAR  DeviceId,
-    OUT PXENVBD_TARGET*         _Target
+    IN  PXENVBD_ADAPTER Adapter,
+    IN  PANSI_STRING    Device,
+    OUT PXENVBD_TARGET* _Target
     )
 {
-    NTSTATUS    Status;
-    PXENVBD_TARGET Target;
-    ULONG           TargetId;
+    PXENVBD_TARGET      Target;
+    ULONG               DeviceId;
+    ULONG               TargetId;
+    ULONG               Size;
+    NTSTATUS            status;
 
+    DeviceId = strtoul(Device->Buffer, NULL, 10);
     TargetId = __ParseVbd(DeviceId);
     if (TargetId >= XENVBD_MAX_TARGETS)
         return STATUS_RETRY;
-
     if (AdapterIsTargetEmulated(Adapter, TargetId))
         return STATUS_RETRY;
 
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
+    Verbose("[%u] =====> %s\n", TargetId, Device->Buffer);
 
-    Status = STATUS_INSUFFICIENT_RESOURCES;
-#pragma warning(suppress: 6014)
-    Target = __TargetAlloc(sizeof(XENVBD_TARGET));
-    if (!Target)
+    status = STATUS_NO_MEMORY; 
+    Target = __TargetAllocate(sizeof(XENVBD_TARGET));
+    if (Target == NULL)
         goto fail1;
 
-    Verbose("Target[%d] : Creating\n", TargetId);
-    Target->Signature      = TARGET_SIGNATURE;
-    Target->Adapter            = Adapter;
-    Target->DeviceObject   = NULL; // filled in later
-    Target->Paused         = 1; // Paused until D3->D0 transition
-    Target->DevicePnpState = Present;
+    Target->Adapter         = Adapter;
+    Target->DeviceObject    = NULL; // filled in later
+    Target->DevicePnpState  = Present;
     Target->DevicePowerState = PowerDeviceD3;
-
-    KeInitializeSpinLock(&Target->Lock);
-    QueueInit(&Target->FreshSrbs);
-    QueueInit(&Target->PreparedReqs);
-    QueueInit(&Target->SubmittedReqs);
-    QueueInit(&Target->ShutdownSrbs);
-    __LookasideInit(&Target->RequestList, sizeof(XENVBD_REQUEST), 
REQUEST_POOL_TAG);
-    __LookasideInit(&Target->SegmentList, sizeof(XENVBD_SEGMENT), 
SEGMENT_POOL_TAG);
-    __LookasideInit(&Target->IndirectList, sizeof(XENVBD_INDIRECT), 
INDIRECT_POOL_TAG);
-
-    Status = FrontendCreate(Target, DeviceId, TargetId, &Target->Frontend);
-    if (!NT_SUCCESS(Status))
+    Target->DeviceId        = DeviceId;
+    Target->TargetId        = TargetId;
+    Target->State           = XENVBD_INITIALIZED;
+    Target->BackendId       = DOMID_INVALID;
+    KeInitializeSpinLock(&Target->StateLock);
+    KeInitializeSpinLock(&Target->QueueLock);
+
+    AdapterGetDebugInterface(Adapter, &Target->DebugInterface);
+    AdapterGetStoreInterface(Adapter, &Target->StoreInterface);
+    AdapterGetSuspendInterface(Adapter, &Target->SuspendInterface);
+
+    status = STATUS_NO_MEMORY;
+    Size = sizeof("device/vbd/") + Device->Length + 1;
+    Target->Path = __TargetAllocate(Size);
+    if (Target->Path == NULL)
         goto fail2;
 
-    Status = TargetD3ToD0(Target);
-    if (!NT_SUCCESS(Status))
+    status = RtlStringCbPrintfA(Target->Path,
+                                Size,
+                                "device/vbd/%s",
+                                Device->Buffer);
+    if (!NT_SUCCESS(status))
         goto fail3;
 
-    *_Target = Target;
+    status = STATUS_NO_MEMORY;
+    Size = sizeof("data/scsi/target/XXXX") + 1;
+    Target->TargetPath = __TargetAllocate(Size);
+    if (Target->TargetPath == NULL)
+        goto fail4;
 
-    Verbose("Target[%d] : Created (%s)\n", TargetId, Target);
-    Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
+    status = RtlStringCbPrintfA(Target->TargetPath,
+                                Size,
+                                "data/scsi/target/%u",
+                                TargetId);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    status = GranterCreate(Target, &Target->Granter);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
+    status = BlockRingCreate(Target, &Target->BlockRing);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
+    status = ThreadCreate(TargetBackendThread,
+                          Target,
+                          &Target->BackendThread);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
+    InitializeListHead(&Target->Fresh);
+    InitializeListHead(&Target->Prepared);
+    InitializeListHead(&Target->Submitted);
+    InitializeListHead(&Target->Shutdown);
+
+    ExInitializeNPagedLookasideList(&Target->RequestList,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    sizeof(XENVBD_REQUEST),
+                                    REQUEST_POOL_TAG,
+                                    0);
+    ExInitializeNPagedLookasideList(&Target->SegmentList,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    sizeof(XENVBD_SEGMENT),
+                                    SEGMENT_POOL_TAG,
+                                    0);
+    ExInitializeNPagedLookasideList(&Target->IndirectList,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    sizeof(XENVBD_INDIRECT),
+                                    INDIRECT_POOL_TAG,
+                                    0);
+
+    status = TargetD3ToD0(Target);
+    if (!NT_SUCCESS(status))
+        goto fail9;
+
+    Verbose("[%u] <=====\n", TargetId);
+    *_Target = Target;
     return STATUS_SUCCESS;
 
+fail9:
+    Error("fail9\n");
+
+    ExDeleteNPagedLookasideList(&Target->RequestList);
+    ExDeleteNPagedLookasideList(&Target->SegmentList);
+    ExDeleteNPagedLookasideList(&Target->IndirectList);
+
+    RtlZeroMemory(&Target->Fresh, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Prepared, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Submitted, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Shutdown, sizeof(LIST_ENTRY));
+
+    ThreadAlert(Target->BackendThread);
+    ThreadJoin(Target->BackendThread);
+    Target->BackendThread = NULL;
+fail8:
+    Error("fail8\n");
+    BlockRingDestroy(Target->BlockRing);
+    Target->BlockRing = NULL;
+fail7:
+    Error("fail7\n");
+    GranterDestroy(Target->Granter);
+    Target->Granter = NULL;
+fail6:
+    Error("fail6\n");
+fail5:
+    Error("fail5\n");
+    __TargetFree(Target->TargetPath);
+    Target->TargetPath = NULL;
+fail4:
+    Error("fail4\n");
 fail3:
-    Error("Fail3\n");
-    FrontendDestroy(Target->Frontend);
-    Target->Frontend = NULL;
-
+    Error("fail3\n");
+    __TargetFree(Target->Path);
+    Target->Path = NULL;
 fail2:
-    Error("Fail2\n");
-    __LookasideTerm(&Target->IndirectList);
-    __LookasideTerm(&Target->SegmentList);
-    __LookasideTerm(&Target->RequestList);
+    Error("fail2\n");
+    RtlZeroMemory(&Target->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+    RtlZeroMemory(&Target->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
+    RtlZeroMemory(&Target->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE));
+
+    Target->Adapter         = NULL;
+    Target->DeviceObject    = NULL; // filled in later
+    Target->DevicePnpState  = 0;
+    Target->DevicePowerState = 0;
+    Target->DeviceId        = 0;
+    Target->TargetId        = 0;
+    Target->State           = 0;
+    Target->BackendId       = 0;
+    RtlZeroMemory(&Target->QueueLock, sizeof(KSPIN_LOCK));
+    RtlZeroMemory(&Target->StateLock, sizeof(KSPIN_LOCK));
+
+    ASSERT(IsZeroMemory(Target, sizeof(XENVBD_TARGET)));
     __TargetFree(Target);
-
 fail1:
-    Error("Fail1 (%08x)\n", Status);
-    return Status;
+    Error("fail1 %08x\n", status);
+    return status;
 }
 
 VOID
 TargetDestroy(
-    __in PXENVBD_TARGET    Target
+    IN  PXENVBD_TARGET  Target
     )
 {
-    const ULONG         TargetId = TargetGetTargetId(Target);
-    PVOID               Objects[3];
-    PKWAIT_BLOCK        WaitBlock;
+    ASSERT(IsListEmpty(&Target->Fresh));
+    ASSERT(IsListEmpty(&Target->Prepared));
+    ASSERT(IsListEmpty(&Target->Submitted));
+    ASSERT(IsListEmpty(&Target->Shutdown));
 
-    Trace("Target[%d] @ (%d) =====>\n", TargetId, KeGetCurrentIrql());
-    Verbose("Target[%d] : Destroying\n", TargetId);
+    ExDeleteNPagedLookasideList(&Target->RequestList);
+    ExDeleteNPagedLookasideList(&Target->SegmentList);
+    ExDeleteNPagedLookasideList(&Target->IndirectList);
 
-    ASSERT3U(Target->Signature, ==, TARGET_SIGNATURE);
+    RtlZeroMemory(&Target->Fresh, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Prepared, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Submitted, sizeof(LIST_ENTRY));
+    RtlZeroMemory(&Target->Shutdown, sizeof(LIST_ENTRY));
 
-    TargetD0ToD3(Target);
+    ThreadAlert(Target->BackendThread);
+    ThreadJoin(Target->BackendThread);
+    Target->BackendThread = NULL;
 
-    Verbose("Target[%d] : RequestListUsed %d\n", TargetId, 
Target->RequestList.Used);
-    Objects[0] = &Target->RequestList.Empty;
-    Objects[1] = &Target->SegmentList.Empty;
-    Objects[2] = &Target->IndirectList.Empty;
+    BlockRingDestroy(Target->BlockRing);
+    Target->BlockRing = NULL;
 
-    WaitBlock = (PKWAIT_BLOCK)__TargetAlloc(sizeof(KWAIT_BLOCK) * 
ARRAYSIZE(Objects));
-    if (WaitBlock == NULL) {
-        ULONG   Index;
+    GranterDestroy(Target->Granter);
+    Target->Granter = NULL;
 
-        Error("Unable to allocate resources for KWAIT_BLOCK\n");
+    __TargetFree(Target->BackendPath);
+    Target->BackendPath = NULL;
 
-        for (Index = 0; Index < ARRAYSIZE(Objects); Index++)
-            KeWaitForSingleObject(Objects[Index],
-                                  Executive,
-                                  KernelMode,
-                                  FALSE,
-                                  NULL);
-    } else {
-        KeWaitForMultipleObjects(ARRAYSIZE(Objects),
-                                 Objects,
-                                 WaitAll,
-                                 Executive,
-                                 KernelMode,
-                                 FALSE,
-                                 NULL,
-                                 WaitBlock);
-#pragma prefast(suppress:6102)
-        __TargetFree(WaitBlock);
-    }
+    __TargetFree(Target->TargetPath);
+    Target->TargetPath = NULL;
 
-    ASSERT3U(TargetGetDevicePnpState(Target), ==, Deleted);
+    __TargetFree(Target->Path);
+    Target->Path = NULL;
 
-    FrontendDestroy(Target->Frontend);
-    Target->Frontend = NULL;
+    RtlZeroMemory(&Target->DebugInterface, sizeof(XENBUS_DEBUG_INTERFACE));
+    RtlZeroMemory(&Target->StoreInterface, sizeof(XENBUS_STORE_INTERFACE));
+    RtlZeroMemory(&Target->SuspendInterface, sizeof(XENBUS_SUSPEND_INTERFACE));
 
-    __LookasideTerm(&Target->IndirectList);
-    __LookasideTerm(&Target->SegmentList);
-    __LookasideTerm(&Target->RequestList);
+    Target->Adapter         = NULL;
+    Target->DeviceObject    = NULL; // filled in later
+    Target->DevicePnpState  = 0;
+    Target->DevicePowerState = 0;
+    Target->DeviceId        = 0;
+    Target->TargetId        = 0;
+    Target->State           = 0;
+    Target->BackendId       = 0;
+    RtlZeroMemory(&Target->QueueLock, sizeof(KSPIN_LOCK));
+    RtlZeroMemory(&Target->StateLock, sizeof(KSPIN_LOCK));
 
-    ASSERT3U(Target->Signature, ==, TARGET_SIGNATURE);
-    RtlZeroMemory(Target, sizeof(XENVBD_TARGET));
+    ASSERT(IsZeroMemory(Target, sizeof(XENVBD_TARGET)));
     __TargetFree(Target);
-
-    Verbose("Target[%d] : Destroyed\n", TargetId);
-    Trace("Target[%d] @ (%d) <=====\n", TargetId, KeGetCurrentIrql());
 }
diff --git a/src/xenvbd/target.h b/src/xenvbd/target.h
index 86f57fd..43660dd 100644
--- a/src/xenvbd/target.h
+++ b/src/xenvbd/target.h
@@ -36,197 +36,117 @@
 
 typedef struct _XENVBD_TARGET XENVBD_TARGET, *PXENVBD_TARGET;
 
-#include "adapter.h"
-#include "srbext.h"
 #include "types.h"
-#include <debug_interface.h>
-
-extern VOID
-TargetDebugCallback(
-    __in PXENVBD_TARGET             Target,
-    __in PXENBUS_DEBUG_INTERFACE Debug
-    );
-
-// Creation/Deletion
-__checkReturn
-extern NTSTATUS
-TargetCreate(
-    __in PXENVBD_ADAPTER             Adapter,
-    __in __nullterminated PCHAR  DeviceId,
-    OUT PXENVBD_TARGET*         _Target
-    );
-
-extern VOID
-TargetDestroy(
-    __in PXENVBD_TARGET             Target
-    );
-
-__checkReturn
-extern NTSTATUS
-TargetD3ToD0(
-    __in PXENVBD_TARGET             Target
-    );
-
-extern VOID
-TargetD0ToD3(
-    __in PXENVBD_TARGET             Target
-    );
-
-// PnP States
-extern VOID
-TargetSetMissing(
-    __in PXENVBD_TARGET             Target,
-    __in __nullterminated const CHAR* Reason
-    );
+#include "srbext.h"
+#include "adapter.h"
+#include "granter.h"
 
-__checkReturn
-extern BOOLEAN
-TargetIsMissing(
-    __in PXENVBD_TARGET             Target
+#define TARGET_GET_PROPERTY(_name, _type)       \
+extern _type                                    \
+TargetGet ## _name ## (                         \
+    IN  PXENVBD_TARGET  Target                  \
     );
 
-extern const CHAR*
-TargetMissingReason(
-    __in PXENVBD_TARGET            Target
-    );
+TARGET_GET_PROPERTY(DeviceId, ULONG)
+TARGET_GET_PROPERTY(TargetId, ULONG)
+TARGET_GET_PROPERTY(DeviceObject, PDEVICE_OBJECT)
+TARGET_GET_PROPERTY(Missing, BOOLEAN)
+TARGET_GET_PROPERTY(DevicePnpState, DEVICE_PNP_STATE)
+TARGET_GET_PROPERTY(Adapter, PXENVBD_ADAPTER)
+TARGET_GET_PROPERTY(Granter, PXENVBD_GRANTER)
+TARGET_GET_PROPERTY(Path, PCHAR)
+TARGET_GET_PROPERTY(BackendPath, PCHAR)
+TARGET_GET_PROPERTY(BackendId, USHORT)
+TARGET_GET_PROPERTY(Removable, BOOLEAN)
 
-__checkReturn
-extern BOOLEAN
-TargetIsEmulatedUnplugged(
-    __in PXENVBD_TARGET             Target
-    );
+#undef TARGET_GET_PROPERTY
 
 extern VOID
 TargetSetDevicePnpState(
-    __in PXENVBD_TARGET             Target,
-    __in DEVICE_PNP_STATE        State
-    );
-
-__checkReturn
-extern DEVICE_PNP_STATE
-TargetGetDevicePnpState(
-    __in PXENVBD_TARGET             Target
-    );
-
-// Query Methods
-extern ULONG
-TargetGetTargetId(
-    __in PXENVBD_TARGET             Target
-    );
-
-extern ULONG
-TargetGetDeviceId(
-    __in PXENVBD_TARGET             Target
-    );
-
-__checkReturn
-extern PDEVICE_OBJECT
-TargetGetDeviceObject(
-    __in PXENVBD_TARGET             Target
+    IN  PXENVBD_TARGET      Target,
+    IN  DEVICE_PNP_STATE    State
     );
 
 extern VOID
 TargetSetDeviceObject(
-    __in PXENVBD_TARGET             Target,
-    __in PDEVICE_OBJECT          DeviceObject
-    );
-
-__checkReturn
-extern BOOLEAN
-TargetIsPaused(
-    __in PXENVBD_TARGET             Target
-    );
-
-__checkReturn
-extern ULONG
-TargetOutstandingReqs(
-    __in PXENVBD_TARGET             Target
+    IN  PXENVBD_TARGET  Target,
+    IN  PDEVICE_OBJECT  DeviceObject
     );
 
-__checkReturn
-extern PXENVBD_ADAPTER
-TargetGetAdapter( 
-    __in PXENVBD_TARGET             Target
+extern VOID
+TargetSetMissing(
+    IN  PXENVBD_TARGET  Target,
+    IN  const CHAR*     Reason
     );
 
-extern ULONG
-TargetSectorSize(
-    __in PXENVBD_TARGET             Target
+extern NTSTATUS
+TargetCreate(
+    IN  PXENVBD_ADAPTER Adapter,
+    IN  PANSI_STRING    Device,
+    OUT PXENVBD_TARGET* _Target
     );
 
-// Queue-Related
 extern VOID
-TargetSubmitRequests(
-    __in PXENVBD_TARGET             Target
+TargetDestroy(
+    IN  PXENVBD_TARGET  Target
     );
 
-extern VOID
-TargetCompleteResponse(
-    __in PXENVBD_TARGET             Target,
-    __in ULONG                   Tag,
-    __in SHORT                   Status
+extern NTSTATUS
+TargetD3ToD0(
+    IN  PXENVBD_TARGET  Target
     );
 
 extern VOID
-TargetPreResume(
-    __in PXENVBD_TARGET             Target
+TargetD0ToD3(
+    IN  PXENVBD_TARGET  Target
     );
 
-extern VOID
-TargetPostResume(
-    __in PXENVBD_TARGET             Target
+extern NTSTATUS
+TargetDispatchPnp(
+    IN  PXENVBD_TARGET  Target,
+    IN  PDEVICE_OBJECT  DeviceObject,
+    IN  PIRP            Irp
     );
 
-// StorPort Methods
 extern VOID
 TargetReset(
     IN  PXENVBD_TARGET  Target
     );
 
 extern VOID
-TargetPrepareSrb(
+TargetFlush(
     IN  PXENVBD_TARGET  Target,
     IN  PXENVBD_SRBEXT  SrbExt
     );
 
 extern VOID
-TargetStartSrb(
+TargetShutdown(
     IN  PXENVBD_TARGET  Target,
     IN  PXENVBD_SRBEXT  SrbExt
     );
 
 extern VOID
-TargetFlush(
+TargetPrepareSrb(
     IN  PXENVBD_TARGET  Target,
     IN  PXENVBD_SRBEXT  SrbExt
     );
 
 extern VOID
-TargetShutdown(
+TargetStartSrb(
     IN  PXENVBD_TARGET  Target,
     IN  PXENVBD_SRBEXT  SrbExt
     );
 
 extern VOID
-TargetSrbPnp(
-    __in PXENVBD_TARGET             Target,
-    __in PSCSI_PNP_REQUEST_BLOCK Srb
-    );
-
-// PnP Handler
-__checkReturn
-extern NTSTATUS
-TargetDispatchPnp(
-    __in PXENVBD_TARGET             Target,
-    __in PDEVICE_OBJECT          DeviceObject,
-    __in PIRP                    Irp
+TargetSubmitRequests(
+    IN  PXENVBD_TARGET  Target
     );
 
-__drv_maxIRQL(DISPATCH_LEVEL)
 extern VOID
-TargetIssueDeviceEject(
-    __in PXENVBD_TARGET             Target,
-    __in __nullterminated const CHAR* Reason
+TargetCompleteResponse(
+    IN  PXENVBD_TARGET  Target,
+    IN  ULONG64         Id,
+    IN  SHORT           Status
     );
 
 #endif // _XENVBD_TARGET_H
diff --git a/vs2012/xenvbd/xenvbd.vcxproj b/vs2012/xenvbd/xenvbd.vcxproj
index 04aff7c..993310d 100644
--- a/vs2012/xenvbd/xenvbd.vcxproj
+++ b/vs2012/xenvbd/xenvbd.vcxproj
@@ -76,12 +76,8 @@
                <ClCompile Include="../../src/xenvbd/driver.c" />
                <ClCompile Include="../../src/xenvbd/registry.c" />
                <ClCompile Include="../../src/xenvbd/adapter.c" />
-               <ClCompile Include="../../src/xenvbd/frontend.c" />
                <ClCompile Include="../../src/xenvbd/target.c" />
-               <ClCompile Include="../../src/xenvbd/pdoinquiry.c" />
-               <ClCompile Include="../../src/xenvbd/queue.c" />
                <ClCompile Include="../../src/xenvbd/thread.c" />
-               <ClCompile Include="../../src/xenvbd/notifier.c" />
                <ClCompile Include="../../src/xenvbd/blockring.c" />
                <ClCompile Include="../../src/xenvbd/granter.c" />
        </ItemGroup>
diff --git a/vs2013/xenvbd/xenvbd.vcxproj b/vs2013/xenvbd/xenvbd.vcxproj
index 4dc5bb5..19d5a40 100644
--- a/vs2013/xenvbd/xenvbd.vcxproj
+++ b/vs2013/xenvbd/xenvbd.vcxproj
@@ -104,12 +104,8 @@
     <ClCompile Include="../../src/xenvbd/driver.c" />
     <ClCompile Include="../../src/xenvbd/registry.c" />
     <ClCompile Include="../../src/xenvbd/adapter.c" />
-    <ClCompile Include="../../src/xenvbd/frontend.c" />
     <ClCompile Include="../../src/xenvbd/target.c" />
-    <ClCompile Include="../../src/xenvbd/pdoinquiry.c" />
-    <ClCompile Include="../../src/xenvbd/queue.c" />
     <ClCompile Include="../../src/xenvbd/thread.c" />
-    <ClCompile Include="../../src/xenvbd/notifier.c" />
     <ClCompile Include="../../src/xenvbd/blockring.c" />
     <ClCompile Include="../../src/xenvbd/granter.c" />
   </ItemGroup>
diff --git a/vs2015/xenvbd/xenvbd.vcxproj b/vs2015/xenvbd/xenvbd.vcxproj
index 4ae5159..f93ed7d 100644
--- a/vs2015/xenvbd/xenvbd.vcxproj
+++ b/vs2015/xenvbd/xenvbd.vcxproj
@@ -68,12 +68,8 @@
     <ClCompile Include="../../src/xenvbd/driver.c" />
     <ClCompile Include="../../src/xenvbd/registry.c" />
     <ClCompile Include="../../src/xenvbd/adapter.c" />
-    <ClCompile Include="../../src/xenvbd/frontend.c" />
     <ClCompile Include="../../src/xenvbd/target.c" />
-    <ClCompile Include="../../src/xenvbd/pdoinquiry.c" />
-    <ClCompile Include="../../src/xenvbd/queue.c" />
     <ClCompile Include="../../src/xenvbd/thread.c" />
-    <ClCompile Include="../../src/xenvbd/notifier.c" />
     <ClCompile Include="../../src/xenvbd/blockring.c" />
     <ClCompile Include="../../src/xenvbd/granter.c" />
   </ItemGroup>
-- 
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®.