win-pvdrivers

changeset 831:d0130ea66500

Move xenvbd to xenvbd_scsiport and make new storport driver.
Boot, hibernate, and dump appear to be working.
No performance optimisation yet so it won't be any faster than scsiport
author James Harper <james.harper@bendigoit.com.au>
date Sat Jan 22 15:47:16 2011 +1100 (2011-01-22)
parents 28b96b05fa36
children 4db4fd1c87fb
files xenvbd/sources xenvbd/xenvbd.c xenvbd/xenvbd.h xenvbd/xenvbd_scsiport.c xenvbd/xenvbd_scsiport.h xenvbd/xenvbd_storport.c xenvbd/xenvbd_storport.h
line diff
     1.1 --- a/xenvbd/sources	Thu Jan 13 11:21:18 2011 +1100
     1.2 +++ b/xenvbd/sources	Sat Jan 22 15:47:16 2011 +1100
     1.3 @@ -3,6 +3,11 @@
     1.4  !UNDEF KMDF_VERSION_MAJOR
     1.5  TARGETNAME=xenvbd
     1.6  TARGETTYPE=DRIVER
     1.7 +!IF "$(DDK_TARGET_OS)" == "Win2K" || "$(DDK_TARGET_OS)" == "WinXP"
     1.8  TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\scsiport.lib
     1.9 +SOURCES=xenvbd.rc xenvbd_scsiport.c
    1.10 +!ELSE
    1.11 +TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\storport.lib
    1.12 +SOURCES=xenvbd.rc xenvbd_storport.c
    1.13 +!ENDIF
    1.14  NTTARGETFILES=$(NTTARGETFILES) $(OBJ_PATH)\$(O)\$(TARGETNAME).inf
    1.15 -SOURCES=xenvbd.rc xenvbd.c
     2.1 --- a/xenvbd/xenvbd.c	Thu Jan 13 11:21:18 2011 +1100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,1745 +0,0 @@
     2.4 -/*
     2.5 -PV Drivers for Windows Xen HVM Domains
     2.6 -Copyright (C) 2007 James Harper
     2.7 -
     2.8 -This program is free software; you can redistribute it and/or
     2.9 -modify it under the terms of the GNU General Public License
    2.10 -as published by the Free Software Foundation; either version 2
    2.11 -of the License, or (at your option) any later version.
    2.12 -
    2.13 -This program is distributed in the hope that it will be useful,
    2.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 -GNU General Public License for more details.
    2.17 -
    2.18 -You should have received a copy of the GNU General Public License
    2.19 -along with this program; if not, write to the Free Software
    2.20 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    2.21 -*/
    2.22 -
    2.23 -#define INITGUID
    2.24 -#include "xenvbd.h"
    2.25 -#include <io/blkif.h>
    2.26 -#include <scsi.h>
    2.27 -#include <ntddscsi.h>
    2.28 -#include <ntdddisk.h>
    2.29 -#include <stdlib.h>
    2.30 -#include <xen_public.h>
    2.31 -#include <io/xenbus.h>
    2.32 -#include <io/protocols.h>
    2.33 -
    2.34 -#pragma warning(disable: 4127)
    2.35 -
    2.36 -#if defined(__x86_64__)
    2.37 -  #define LongLongToPtr(x) (PVOID)(x)
    2.38 -#else
    2.39 -  #define LongLongToPtr(x) UlongToPtr(x)
    2.40 -#endif
    2.41 -
    2.42 -/* Not really necessary but keeps PREfast happy */
    2.43 -DRIVER_INITIALIZE DriverEntry;
    2.44 -
    2.45 -static BOOLEAN dump_mode = FALSE;
    2.46 -#define DUMP_MODE_ERROR_LIMIT 64
    2.47 -static ULONG dump_mode_errors = 0;
    2.48 -
    2.49 -CHAR scsi_device_manufacturer[8];
    2.50 -CHAR scsi_disk_model[16];
    2.51 -CHAR scsi_cdrom_model[16];
    2.52 -
    2.53 -ULONGLONG parse_numeric_string(PCHAR string)
    2.54 -{
    2.55 -  ULONGLONG val = 0;
    2.56 -  while (*string != 0)
    2.57 -  {
    2.58 -    val = val * 10 + (*string - '0');
    2.59 -    string++;
    2.60 -  }
    2.61 -  return val;
    2.62 -}
    2.63 -
    2.64 -static blkif_shadow_t *
    2.65 -get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
    2.66 -{
    2.67 -  if (xvdd->shadow_free == 0)
    2.68 -  {
    2.69 -    KdPrint((__DRIVER_NAME "     No more shadow entries\n"));
    2.70 -    return NULL;
    2.71 -  }
    2.72 -  xvdd->shadow_free--;
    2.73 -  if (xvdd->shadow_free < xvdd->shadow_min_free)
    2.74 -    xvdd->shadow_min_free = xvdd->shadow_free;
    2.75 -  return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
    2.76 -}
    2.77 -
    2.78 -static VOID
    2.79 -put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
    2.80 -{
    2.81 -  xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
    2.82 -  shadow->srb = NULL;
    2.83 -  xvdd->shadow_free++;
    2.84 -}
    2.85 -
    2.86 -static blkif_response_t *
    2.87 -XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
    2.88 -{
    2.89 -  blkif_other_response_t *rep;
    2.90 -  if (!xvdd->use_other)
    2.91 -    return RING_GET_RESPONSE(&xvdd->ring, i);
    2.92 -  rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
    2.93 -  xvdd->tmp_rep.id = rep->id;
    2.94 -  xvdd->tmp_rep.operation = rep->operation;
    2.95 -  xvdd->tmp_rep.status = rep->status;
    2.96 -  return &xvdd->tmp_rep;
    2.97 -}
    2.98 -
    2.99 -static VOID
   2.100 -XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
   2.101 -{
   2.102 -  blkif_other_request_t *other_req;
   2.103 -
   2.104 -  if (!xvdd->use_other)
   2.105 -  {
   2.106 -    *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
   2.107 -  }
   2.108 -  else
   2.109 -  {  
   2.110 -    other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
   2.111 -    other_req->operation = req->operation;
   2.112 -    other_req->nr_segments = req->nr_segments;
   2.113 -    other_req->handle = req->handle;
   2.114 -    other_req->id = req->id;
   2.115 -    other_req->sector_number = req->sector_number;
   2.116 -    memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
   2.117 -  }
   2.118 -  xvdd->ring.req_prod_pvt++;
   2.119 -}
   2.120 -
   2.121 -static ULONG
   2.122 -XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
   2.123 -{
   2.124 -  ULONG i;
   2.125 -  PUCHAR ptr;
   2.126 -  USHORT type;
   2.127 -  PCHAR setting, value, value2;
   2.128 -  ULONG qemu_protocol_version = 0;
   2.129 -  BOOLEAN qemu_hide_filter = FALSE;
   2.130 -  ULONG qemu_hide_flags_value = 0;
   2.131 -
   2.132 -  xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   2.133 -  xvdd->sring = NULL;
   2.134 -  xvdd->event_channel = 0;
   2.135 -  
   2.136 -  xvdd->inactive = TRUE;  
   2.137 -  ptr = xvdd->device_base;
   2.138 -  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   2.139 -  {
   2.140 -    switch(type)
   2.141 -    {
   2.142 -    case XEN_INIT_TYPE_RING: /* frontend ring */
   2.143 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   2.144 -      if (strcmp(setting, "ring-ref") == 0)
   2.145 -      {
   2.146 -        xvdd->sring = (blkif_sring_t *)value;
   2.147 -        FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
   2.148 -        /* this bit is for when we have to take over an existing ring on a crash dump */
   2.149 -        xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
   2.150 -        xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
   2.151 -      }
   2.152 -      break;
   2.153 -    case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   2.154 -    case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
   2.155 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
   2.156 -      if (strcmp(setting, "event-channel") == 0)
   2.157 -      {
   2.158 -        /* cheat here - save the state of the ring in the topmost bits of the event-channel */
   2.159 -        xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
   2.160 -        xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
   2.161 -        if (PtrToUlong(value) & 0x80000000)
   2.162 -        {
   2.163 -          xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
   2.164 -          KdPrint((__DRIVER_NAME "     cached_use_other = %d\n", xvdd->cached_use_other));
   2.165 -        }
   2.166 -      }
   2.167 -      break;
   2.168 -    case XEN_INIT_TYPE_READ_STRING_BACK:
   2.169 -    case XEN_INIT_TYPE_READ_STRING_FRONT:
   2.170 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   2.171 -      if (strcmp(setting, "sectors") == 0)
   2.172 -        xvdd->total_sectors = parse_numeric_string(value);
   2.173 -      else if (strcmp(setting, "sector-size") == 0)
   2.174 -        xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
   2.175 -      else if (strcmp(setting, "device-type") == 0)
   2.176 -      {
   2.177 -        if (strcmp(value, "disk") == 0)
   2.178 -        {
   2.179 -          KdPrint((__DRIVER_NAME "     device-type = Disk\n"));    
   2.180 -          xvdd->device_type = XENVBD_DEVICETYPE_DISK;
   2.181 -        }
   2.182 -        else if (strcmp(value, "cdrom") == 0)
   2.183 -        {
   2.184 -          KdPrint((__DRIVER_NAME "     device-type = CDROM\n"));    
   2.185 -          xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
   2.186 -        }
   2.187 -        else
   2.188 -        {
   2.189 -          KdPrint((__DRIVER_NAME "     device-type = %s (This probably won't work!)\n", value));
   2.190 -          xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   2.191 -        }
   2.192 -      }
   2.193 -      else if (strcmp(setting, "mode") == 0)
   2.194 -      {
   2.195 -        if (strncmp(value, "r", 1) == 0)
   2.196 -        {
   2.197 -          KdPrint((__DRIVER_NAME "     mode = r\n"));    
   2.198 -          xvdd->device_mode = XENVBD_DEVICEMODE_READ;
   2.199 -        }
   2.200 -        else if (strncmp(value, "w", 1) == 0)
   2.201 -        {
   2.202 -          KdPrint((__DRIVER_NAME "     mode = w\n"));    
   2.203 -          xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
   2.204 -        }
   2.205 -        else
   2.206 -        {
   2.207 -          KdPrint((__DRIVER_NAME "     mode = unknown\n"));
   2.208 -          xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
   2.209 -        }
   2.210 -      }
   2.211 -      break;
   2.212 -    case XEN_INIT_TYPE_VECTORS:
   2.213 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   2.214 -      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   2.215 -        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   2.216 -      {
   2.217 -        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   2.218 -          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   2.219 -        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.220 -        return SP_RETURN_BAD_CONFIG;
   2.221 -      }
   2.222 -      else
   2.223 -        memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
   2.224 -      break;
   2.225 -    case XEN_INIT_TYPE_STATE_PTR:
   2.226 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   2.227 -      xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
   2.228 -      break;
   2.229 -    case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
   2.230 -      qemu_protocol_version = PtrToUlong(value);
   2.231 -      break;
   2.232 -    case XEN_INIT_TYPE_GRANT_ENTRIES:
   2.233 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - entries = %d\n", PtrToUlong(setting)));
   2.234 -      memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * sizeof(grant_ref_t));
   2.235 -      break;
   2.236 -    case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   2.237 -      qemu_hide_flags_value = PtrToUlong(value);
   2.238 -      KdPrint((__DRIVER_NAME "     qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
   2.239 -      break;
   2.240 -    case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
   2.241 -      qemu_hide_filter = TRUE;
   2.242 -      KdPrint((__DRIVER_NAME "     qemu_hide_filter = TRUE\n"));
   2.243 -      break;
   2.244 -    default:
   2.245 -      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   2.246 -      break;
   2.247 -    }
   2.248 -  }
   2.249 -  
   2.250 -  if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
   2.251 -    xvdd->inactive = FALSE;
   2.252 -  
   2.253 -  if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
   2.254 -      || xvdd->sring == NULL
   2.255 -      || xvdd->event_channel == 0
   2.256 -      || xvdd->total_sectors == 0
   2.257 -      || xvdd->bytes_per_sector == 0))
   2.258 -  {
   2.259 -    KdPrint((__DRIVER_NAME "     Missing settings\n"));
   2.260 -    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.261 -    return SP_RETURN_BAD_CONFIG;
   2.262 -  }
   2.263 -
   2.264 -  if (xvdd->inactive)
   2.265 -    KdPrint((__DRIVER_NAME "     Device is inactive\n"));
   2.266 -  else
   2.267 -  {
   2.268 -    if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
   2.269 -    {
   2.270 -      /* CD/DVD drives must have bytes_per_sector = 2048. */
   2.271 -      xvdd->bytes_per_sector = 2048;
   2.272 -    }
   2.273 -
   2.274 -    /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
   2.275 -    xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
   2.276 -
   2.277 -    xvdd->shadow_free = 0;
   2.278 -    memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
   2.279 -    for (i = 0; i < SHADOW_ENTRIES; i++)
   2.280 -    {
   2.281 -      xvdd->shadows[i].req.id = i;
   2.282 -      put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
   2.283 -    }
   2.284 -  }
   2.285 -  
   2.286 -  return SP_RETURN_FOUND;
   2.287 -}
   2.288 -
   2.289 -static __inline ULONG
   2.290 -decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
   2.291 -{
   2.292 -  switch (srb->Cdb[0])
   2.293 -  {
   2.294 -  case SCSIOP_READ:
   2.295 -  case SCSIOP_WRITE:
   2.296 -    return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
   2.297 -  case SCSIOP_READ16:
   2.298 -  case SCSIOP_WRITE16:
   2.299 -    return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];    
   2.300 -  default:
   2.301 -    return 0;
   2.302 -  }
   2.303 -}
   2.304 -
   2.305 -static __inline ULONGLONG
   2.306 -decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
   2.307 -{
   2.308 -  ULONGLONG sector;
   2.309 -  
   2.310 -  switch (srb->Cdb[0])
   2.311 -  {
   2.312 -  case SCSIOP_READ:
   2.313 -  case SCSIOP_WRITE:
   2.314 -    sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
   2.315 -    break;
   2.316 -  case SCSIOP_READ16:
   2.317 -  case SCSIOP_WRITE16:
   2.318 -    sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
   2.319 -           | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
   2.320 -           | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
   2.321 -           | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
   2.322 -    //KdPrint((__DRIVER_NAME "     sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
   2.323 -    break;
   2.324 -  default:
   2.325 -    sector = 0;
   2.326 -    break;
   2.327 -  }
   2.328 -  return sector;
   2.329 -}
   2.330 -
   2.331 -static __inline BOOLEAN
   2.332 -decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
   2.333 -{
   2.334 -  switch (srb->Cdb[0])
   2.335 -  {
   2.336 -  case SCSIOP_READ:
   2.337 -  case SCSIOP_READ16:
   2.338 -    return TRUE;
   2.339 -  case SCSIOP_WRITE:
   2.340 -  case SCSIOP_WRITE16:
   2.341 -    return FALSE;
   2.342 -  default:
   2.343 -    return FALSE;
   2.344 -  }
   2.345 -}
   2.346 -
   2.347 -ULONG max_dump_mode_blocks = 0;
   2.348 -ULONG max_dump_mode_length = 0;
   2.349 -
   2.350 -static VOID
   2.351 -XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   2.352 -{
   2.353 -  srb_list_entry_t *list_entry = srb->SrbExtension;
   2.354 -  list_entry->srb = srb;
   2.355 -  InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)list_entry);
   2.356 -}
   2.357 -
   2.358 -static VOID
   2.359 -XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
   2.360 -{
   2.361 -  PSCSI_REQUEST_BLOCK srb;
   2.362 -  srb_list_entry_t *srb_entry;
   2.363 -  ULONGLONG sector_number;
   2.364 -  ULONG block_count;
   2.365 -  blkif_shadow_t *shadow;
   2.366 -  ULONG remaining, offset, length;
   2.367 -  grant_ref_t gref;
   2.368 -  PUCHAR ptr;
   2.369 -  int notify;
   2.370 -  int i;
   2.371 -
   2.372 -  //FUNCTION_ENTER();
   2.373 -
   2.374 -  if (xvdd->aligned_buffer_in_use)
   2.375 -    return;
   2.376 -
   2.377 -  while(xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
   2.378 -  {
   2.379 -    srb = srb_entry->srb;
   2.380 -    block_count = decode_cdb_length(srb);;
   2.381 -    block_count *= xvdd->bytes_per_sector / 512;
   2.382 -    sector_number = decode_cdb_sector(srb);
   2.383 -    sector_number *= xvdd->bytes_per_sector / 512;
   2.384 -    
   2.385 -    /* look for pending writes that overlap this one */
   2.386 -    /* we get warnings from drbd if we don't */
   2.387 -    for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
   2.388 -    {
   2.389 -      PSCSI_REQUEST_BLOCK srb2;
   2.390 -      ULONGLONG sector_number2;
   2.391 -      ULONG block_count2;
   2.392 -      
   2.393 -      srb2 = xvdd->shadows[i].srb;
   2.394 -      if (!srb2)
   2.395 -        continue;
   2.396 -      if (decode_cdb_is_read(srb2))
   2.397 -        continue;
   2.398 -      block_count2 = decode_cdb_length(srb2);;
   2.399 -      block_count2 *= xvdd->bytes_per_sector / 512;
   2.400 -      sector_number2 = decode_cdb_sector(srb2);
   2.401 -      sector_number2 *= xvdd->bytes_per_sector / 512;
   2.402 -      
   2.403 -      if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
   2.404 -        continue;
   2.405 -      if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
   2.406 -        continue;
   2.407 -
   2.408 -#if 0
   2.409 -      /* check if the data being written is identical to the data in the pipe */
   2.410 -      {
   2.411 -        PUCHAR buf, buf2;
   2.412 -        ULONG byte_count;
   2.413 -        int j;
   2.414 -
   2.415 -        buf = (PUCHAR)srb->DataBuffer + (max(sector_number, sector_number2) - sector_number) * xvdd->bytes_per_sector;
   2.416 -        buf2 = (PUCHAR)srb2->DataBuffer + (max(sector_number, sector_number2) - sector_number2) * xvdd->bytes_per_sector;
   2.417 -        byte_count = (ULONG)(min(sector_number + block_count, sector_number2 + block_count2) - max(sector_number, sector_number2)) * xvdd->bytes_per_sector;
   2.418 -        for (j = 0; j < (int)byte_count; j++)
   2.419 -        {
   2.420 -          if (buf[j] != buf2[j])
   2.421 -            break;
   2.422 -        }
   2.423 -      }
   2.424 -#endif
   2.425 -
   2.426 -      KdPrint((__DRIVER_NAME "     Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
   2.427 -        sector_number, block_count, sector_number2, block_count2));
   2.428 -      /* put the srb back at the start of the queue */
   2.429 -      InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   2.430 -      return; /* stall the queue */
   2.431 -    }
   2.432 -
   2.433 -    remaining = block_count * 512;
   2.434 -    shadow = get_shadow_from_freelist(xvdd);
   2.435 -    ASSERT(shadow);
   2.436 -    ASSERT(!shadow->aligned_buffer_in_use);
   2.437 -    ASSERT(!shadow->srb);
   2.438 -    shadow->req.sector_number = sector_number;
   2.439 -    shadow->req.handle = 0;
   2.440 -    shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
   2.441 -    shadow->req.nr_segments = 0;
   2.442 -    shadow->srb = srb;
   2.443 -
   2.444 -    if ((ULONG_PTR)srb->DataBuffer & 511)
   2.445 -    {
   2.446 -      if (dump_mode)
   2.447 -        KdPrint((__DRIVER_NAME "     unaligned dump mode buffer = %d bytes\n", block_count * 512));
   2.448 -      ASSERT(!dump_mode || block_count * 512 < BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE);
   2.449 -      xvdd->aligned_buffer_in_use = TRUE;
   2.450 -      ptr = xvdd->aligned_buffer;
   2.451 -      if (!decode_cdb_is_read(srb))
   2.452 -        memcpy(ptr, srb->DataBuffer, block_count * 512);
   2.453 -      shadow->aligned_buffer_in_use = TRUE;
   2.454 -    }
   2.455 -    else
   2.456 -    {
   2.457 -      ptr = srb->DataBuffer;
   2.458 -      shadow->aligned_buffer_in_use = FALSE;
   2.459 -    }
   2.460 -
   2.461 -    if (dump_mode && block_count > max_dump_mode_blocks)
   2.462 -    {
   2.463 -      max_dump_mode_blocks = block_count;
   2.464 -      KdPrint((__DRIVER_NAME "     max_dump_mode_blocks = %d\n", max_dump_mode_blocks));
   2.465 -    }
   2.466 -    if (dump_mode && srb->DataTransferLength > max_dump_mode_length)
   2.467 -    {
   2.468 -      max_dump_mode_length = srb->DataTransferLength;
   2.469 -      KdPrint((__DRIVER_NAME "     max_dump_mode_length = %d\n", max_dump_mode_length));
   2.470 -    }
   2.471 -
   2.472 -    //KdPrint((__DRIVER_NAME "     sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
   2.473 -    //KdPrint((__DRIVER_NAME "     SrbExtension = %p\n", srb->SrbExtension));
   2.474 -    //KdPrint((__DRIVER_NAME "     DataBuffer   = %p\n", srb->DataBuffer));
   2.475 -
   2.476 -    //KdPrint((__DRIVER_NAME "     sector_number = %d\n", (ULONG)shadow->req.sector_number));
   2.477 -    //KdPrint((__DRIVER_NAME "     handle = %d\n", shadow->req.handle));
   2.478 -    //KdPrint((__DRIVER_NAME "     operation = %d\n", shadow->req.operation));
   2.479 -    
   2.480 -    while (remaining > 0)
   2.481 -    {
   2.482 -      PHYSICAL_ADDRESS physical_address = MmGetPhysicalAddress(ptr);
   2.483 -      
   2.484 -      if (dump_mode)
   2.485 -      {
   2.486 -        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   2.487 -                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE,
   2.488 -                 xvdd->dump_grant_refs[shadow->req.nr_segments], (ULONG)'XPDO');
   2.489 -      }
   2.490 -      else
   2.491 -      {
   2.492 -        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   2.493 -                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XVBD');
   2.494 -      }
   2.495 -      if (gref == INVALID_GRANT_REF)
   2.496 -      {
   2.497 -        ULONG i;
   2.498 -        for (i = 0; i < shadow->req.nr_segments; i++)
   2.499 -        {
   2.500 -          xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
   2.501 -            shadow->req.seg[i].gref, FALSE, (ULONG)'XVBD');
   2.502 -        }
   2.503 -        if (shadow->aligned_buffer_in_use)
   2.504 -        {
   2.505 -          shadow->aligned_buffer_in_use = FALSE;
   2.506 -          xvdd->aligned_buffer_in_use = FALSE;
   2.507 -        }
   2.508 -        /* put the srb back at the start of the queue */
   2.509 -        InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   2.510 -        put_shadow_on_freelist(xvdd, shadow);
   2.511 -        KdPrint((__DRIVER_NAME "     Out of gref's. Deferring\n"));
   2.512 -        return;
   2.513 -      }
   2.514 -      offset = physical_address.LowPart & (PAGE_SIZE - 1);
   2.515 -      length = min(PAGE_SIZE - offset, remaining);
   2.516 -      ASSERT((offset & 511) == 0);
   2.517 -      ASSERT((length & 511) == 0);
   2.518 -      ASSERT(offset + length <= PAGE_SIZE);
   2.519 -      shadow->req.seg[shadow->req.nr_segments].gref = gref;
   2.520 -      shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
   2.521 -      shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
   2.522 -      remaining -= length;
   2.523 -      ptr += length;
   2.524 -      shadow->req.nr_segments++;
   2.525 -    }
   2.526 -
   2.527 -    //KdPrint((__DRIVER_NAME "     nr_segments = %d\n", shadow->req.nr_segments));
   2.528 -
   2.529 -    XenVbd_PutRequest(xvdd, &shadow->req);
   2.530 -
   2.531 -    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   2.532 -    if (notify)
   2.533 -    {
   2.534 -      //KdPrint((__DRIVER_NAME "     Notifying\n"));
   2.535 -      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   2.536 -    }
   2.537 -  }
   2.538 -  if (xvdd->shadow_free && !xvdd->aligned_buffer_in_use)
   2.539 -  {
   2.540 -    ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
   2.541 -  }
   2.542 -  //FUNCTION_EXIT();
   2.543 -}
   2.544 -
   2.545 -static ULONG DDKAPI
   2.546 -XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
   2.547 -{
   2.548 -//  PACCESS_RANGE AccessRange;
   2.549 -  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   2.550 -  ULONG status;
   2.551 -//  PXENPCI_XEN_DEVICE_DATA XenDeviceData;
   2.552 -  PACCESS_RANGE access_range;
   2.553 -
   2.554 -  UNREFERENCED_PARAMETER(HwContext);
   2.555 -  UNREFERENCED_PARAMETER(BusInformation);
   2.556 -  UNREFERENCED_PARAMETER(ArgumentString);
   2.557 -
   2.558 -  FUNCTION_ENTER(); 
   2.559 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   2.560 -  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
   2.561 -
   2.562 -  RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
   2.563 -  *Again = FALSE;
   2.564 -
   2.565 -  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
   2.566 -  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
   2.567 -
   2.568 -  KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));    
   2.569 -  if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
   2.570 -  {
   2.571 -    return SP_RETURN_BAD_CONFIG;
   2.572 -  }
   2.573 -
   2.574 -  access_range = &((*(ConfigInfo->AccessRanges))[0]);
   2.575 -  KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
   2.576 -    access_range->RangeStart.LowPart, access_range->RangeLength));
   2.577 -  xvdd->device_base = ScsiPortGetDeviceBase(
   2.578 -    DeviceExtension,
   2.579 -    ConfigInfo->AdapterInterfaceType,
   2.580 -    ConfigInfo->SystemIoBusNumber,
   2.581 -    access_range->RangeStart,
   2.582 -    access_range->RangeLength,
   2.583 -    !access_range->RangeInMemory);
   2.584 -  if (!xvdd->device_base)
   2.585 -  {
   2.586 -    KdPrint((__DRIVER_NAME "     Invalid config\n"));
   2.587 -    FUNCTION_EXIT(); 
   2.588 -    return SP_RETURN_BAD_CONFIG;
   2.589 -  }
   2.590 -  
   2.591 -  status = XenVbd_InitFromConfig(xvdd);
   2.592 -  if (status != SP_RETURN_FOUND)
   2.593 -  {
   2.594 -    FUNCTION_EXIT();
   2.595 -    return status;
   2.596 -  }
   2.597 -
   2.598 -  xvdd->aligned_buffer_in_use = FALSE;
   2.599 -  /* align the buffer to PAGE_SIZE */
   2.600 -  xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
   2.601 -  KdPrint((__DRIVER_NAME "     aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
   2.602 -  KdPrint((__DRIVER_NAME "     aligned_buffer = %p\n", xvdd->aligned_buffer));
   2.603 -
   2.604 -  if (!dump_mode)
   2.605 -  {
   2.606 -    ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
   2.607 -    ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
   2.608 -    //ConfigInfo->ScatterGather = TRUE;
   2.609 -  }
   2.610 -  else
   2.611 -  {
   2.612 -    ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE;
   2.613 -    ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE - 1;
   2.614 -    //ConfigInfo->ScatterGather = FALSE;
   2.615 -  }
   2.616 -  KdPrint((__DRIVER_NAME "     ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength));
   2.617 -  KdPrint((__DRIVER_NAME "     ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks));
   2.618 -  ConfigInfo->ScatterGather = FALSE;
   2.619 -  ConfigInfo->AlignmentMask = 0;
   2.620 -  ConfigInfo->NumberOfBuses = 1;
   2.621 -  ConfigInfo->InitiatorBusId[0] = 1;
   2.622 -  ConfigInfo->MaximumNumberOfLogicalUnits = 1;
   2.623 -  ConfigInfo->MaximumNumberOfTargets = 2;
   2.624 -  ConfigInfo->BufferAccessScsiPortControlled = FALSE;
   2.625 -  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
   2.626 -  {
   2.627 -    ConfigInfo->Master = TRUE;
   2.628 -    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
   2.629 -    ConfigInfo->Dma32BitAddresses = FALSE;
   2.630 -    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
   2.631 -  }
   2.632 -  else
   2.633 -  {
   2.634 -    ConfigInfo->Master = TRUE;
   2.635 -    ConfigInfo->Dma32BitAddresses = TRUE;
   2.636 -    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
   2.637 -  }
   2.638 -
   2.639 -  FUNCTION_EXIT();
   2.640 -
   2.641 -  return SP_RETURN_FOUND;
   2.642 -}
   2.643 -
   2.644 -static VOID
   2.645 -XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
   2.646 -{
   2.647 -  blkif_request_t *req;
   2.648 -  int notify;
   2.649 -
   2.650 -  xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
   2.651 -  RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
   2.652 -  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   2.653 -  req->operation = 0xff;
   2.654 -  xvdd->ring.req_prod_pvt++;
   2.655 -  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   2.656 -  req->operation = 0xff;
   2.657 -  xvdd->ring.req_prod_pvt++;
   2.658 -
   2.659 -  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   2.660 -  if (notify)
   2.661 -    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   2.662 -}
   2.663 -
   2.664 -static BOOLEAN
   2.665 -XenVbd_HwScsiInitialize(PVOID DeviceExtension)
   2.666 -{
   2.667 -  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   2.668 -  
   2.669 -  FUNCTION_ENTER();
   2.670 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   2.671 -  KdPrint((__DRIVER_NAME "     dump_mode = %d\n", dump_mode));
   2.672 -
   2.673 -  if (!xvdd->inactive)
   2.674 -  {
   2.675 -    if (!dump_mode)
   2.676 -    {
   2.677 -      XenVbd_StartRingDetection(xvdd);
   2.678 -    }
   2.679 -    else
   2.680 -    {
   2.681 -      if (xvdd->cached_use_other)
   2.682 -      {
   2.683 -        xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   2.684 -        xvdd->use_other = TRUE;
   2.685 -      }
   2.686 -      xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
   2.687 -    }
   2.688 -    InitializeListHead(&xvdd->srb_list);
   2.689 -  }
   2.690 -  FUNCTION_EXIT();
   2.691 -
   2.692 -  return TRUE;
   2.693 -}
   2.694 -
   2.695 -static ULONG
   2.696 -XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   2.697 -{
   2.698 -  PMODE_PARAMETER_HEADER parameter_header = NULL;
   2.699 -  PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
   2.700 -  PMODE_PARAMETER_BLOCK param_block;
   2.701 -  PMODE_FORMAT_PAGE format_page;
   2.702 -  ULONG offset = 0;
   2.703 -  UCHAR buffer[1024];
   2.704 -  BOOLEAN valid_page = FALSE;
   2.705 -  BOOLEAN cdb_llbaa;
   2.706 -  BOOLEAN cdb_dbd;
   2.707 -  UCHAR cdb_page_code;
   2.708 -  USHORT cdb_allocation_length;
   2.709 -
   2.710 -  UNREFERENCED_PARAMETER(xvdd);
   2.711 -
   2.712 -  RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
   2.713 -  RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
   2.714 -  offset = 0;
   2.715 -
   2.716 -  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.717 -  
   2.718 -  switch (srb->Cdb[0])
   2.719 -  {
   2.720 -  case SCSIOP_MODE_SENSE:
   2.721 -    cdb_llbaa = FALSE;
   2.722 -    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   2.723 -    cdb_page_code = srb->Cdb[2] & 0x3f;
   2.724 -    cdb_allocation_length = srb->Cdb[4];
   2.725 -    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   2.726 -      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   2.727 -    parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
   2.728 -    parameter_header->MediumType = 0;
   2.729 -    parameter_header->DeviceSpecificParameter = 0;
   2.730 -    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   2.731 -    {
   2.732 -      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   2.733 -      parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   2.734 -    }
   2.735 -    offset += sizeof(MODE_PARAMETER_HEADER);
   2.736 -    break;
   2.737 -  case SCSIOP_MODE_SENSE10:
   2.738 -    cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
   2.739 -    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   2.740 -    cdb_page_code = srb->Cdb[2] & 0x3f;
   2.741 -    cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
   2.742 -    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   2.743 -      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   2.744 -    parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
   2.745 -    parameter_header10->MediumType = 0;
   2.746 -    parameter_header10->DeviceSpecificParameter = 0;
   2.747 -    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   2.748 -    {
   2.749 -      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   2.750 -      parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   2.751 -    }
   2.752 -    offset += sizeof(MODE_PARAMETER_HEADER10);
   2.753 -    break;
   2.754 -  default:
   2.755 -    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
   2.756 -    return FALSE;
   2.757 -  }  
   2.758 -  
   2.759 -  if (!cdb_dbd)
   2.760 -  {
   2.761 -    param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
   2.762 -    if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
   2.763 -    {
   2.764 -      if (xvdd->total_sectors >> 32) 
   2.765 -      {
   2.766 -        param_block->DensityCode = 0xff;
   2.767 -        param_block->NumberOfBlocks[0] = 0xff;
   2.768 -        param_block->NumberOfBlocks[1] = 0xff;
   2.769 -        param_block->NumberOfBlocks[2] = 0xff;
   2.770 -      }
   2.771 -      else
   2.772 -      {
   2.773 -        param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
   2.774 -        param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
   2.775 -        param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
   2.776 -        param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
   2.777 -      }
   2.778 -      param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
   2.779 -      param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
   2.780 -      param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
   2.781 -    }
   2.782 -    offset += sizeof(MODE_PARAMETER_BLOCK);
   2.783 -  }
   2.784 -  switch (srb->Cdb[0])
   2.785 -  {
   2.786 -  case SCSIOP_MODE_SENSE:
   2.787 -    parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
   2.788 -    break;
   2.789 -  case SCSIOP_MODE_SENSE10:
   2.790 -    parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
   2.791 -    parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
   2.792 -    break;
   2.793 -  }
   2.794 -  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
   2.795 -  {
   2.796 -    valid_page = TRUE;
   2.797 -    format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
   2.798 -    format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
   2.799 -    format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
   2.800 -    /* 256 sectors per track */
   2.801 -    format_page->SectorsPerTrack[0] = 0x01;
   2.802 -    format_page->SectorsPerTrack[1] = 0x00;
   2.803 -    /* xxx bytes per sector */
   2.804 -    format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
   2.805 -    format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
   2.806 -    format_page->HardSectorFormating = TRUE;
   2.807 -    format_page->SoftSectorFormating = TRUE;
   2.808 -    offset += sizeof(MODE_FORMAT_PAGE);
   2.809 -  }
   2.810 -  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
   2.811 -  {
   2.812 -    PMODE_CACHING_PAGE caching_page;
   2.813 -    valid_page = TRUE;
   2.814 -    caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
   2.815 -    caching_page->PageCode = MODE_PAGE_CACHING;
   2.816 -    caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
   2.817 -    // caching_page-> // all zeros is just fine... maybe
   2.818 -    offset += sizeof(MODE_CACHING_PAGE);
   2.819 -  }
   2.820 -  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
   2.821 -  {
   2.822 -    PUCHAR medium_types_page;
   2.823 -    valid_page = TRUE;
   2.824 -    medium_types_page = &buffer[offset];
   2.825 -    medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
   2.826 -    medium_types_page[1] = 0x06;
   2.827 -    medium_types_page[2] = 0;
   2.828 -    medium_types_page[3] = 0;
   2.829 -    medium_types_page[4] = 0;
   2.830 -    medium_types_page[5] = 0;
   2.831 -    medium_types_page[6] = 0;
   2.832 -    medium_types_page[7] = 0;
   2.833 -    offset += 8;
   2.834 -  }
   2.835 -  switch (srb->Cdb[0])
   2.836 -  {
   2.837 -  case SCSIOP_MODE_SENSE:
   2.838 -    parameter_header->ModeDataLength = (UCHAR)(offset - 1);
   2.839 -    break;
   2.840 -  case SCSIOP_MODE_SENSE10:
   2.841 -    parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
   2.842 -    parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
   2.843 -    break;
   2.844 -  }
   2.845 -
   2.846 -  if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
   2.847 -  {
   2.848 -    srb->SrbStatus = SRB_STATUS_ERROR;
   2.849 -  }
   2.850 -  else if(offset < srb->DataTransferLength)
   2.851 -    srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
   2.852 -  else
   2.853 -    srb->SrbStatus = SRB_STATUS_SUCCESS;
   2.854 -  srb->DataTransferLength = min(srb->DataTransferLength, offset);
   2.855 -  srb->ScsiStatus = 0;
   2.856 -  memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
   2.857 -  
   2.858 -  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.859 -
   2.860 -  return TRUE;
   2.861 -}
   2.862 -
   2.863 -static VOID
   2.864 -XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
   2.865 -{
   2.866 -  PSENSE_DATA sd = srb->SenseInfoBuffer;
   2.867 - 
   2.868 -  UNREFERENCED_PARAMETER(xvdd);
   2.869 -  
   2.870 -  if (!srb->SenseInfoBuffer)
   2.871 -    return;
   2.872 -  
   2.873 -  sd->ErrorCode = 0x70;
   2.874 -  sd->Valid = 1;
   2.875 -  sd->SenseKey = sense_key;
   2.876 -  sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
   2.877 -  sd->AdditionalSenseCode = additional_sense_code;
   2.878 -  return;
   2.879 -}
   2.880 -
   2.881 -static VOID
   2.882 -XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   2.883 -{
   2.884 -  if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
   2.885 -    return;
   2.886 -  XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
   2.887 -  srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
   2.888 -}
   2.889 -
   2.890 -static BOOLEAN DDKAPI
   2.891 -XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
   2.892 -{
   2.893 -  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   2.894 -  PSCSI_REQUEST_BLOCK srb;
   2.895 -  RING_IDX i, rp;
   2.896 -  ULONG j;
   2.897 -  blkif_response_t *rep;
   2.898 -  int block_count;
   2.899 -  int more_to_do = TRUE;
   2.900 -  blkif_shadow_t *shadow;
   2.901 -  ULONG suspend_resume_state_pdo;
   2.902 -  BOOLEAN last_interrupt = FALSE;
   2.903 -  ULONG start_ring_detect_state = xvdd->ring_detect_state;
   2.904 -
   2.905 -  /* in dump mode I think we get called on a timer, not by an actual IRQ */
   2.906 -  if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
   2.907 -    return FALSE; /* interrupt was not for us */
   2.908 -    
   2.909 -  suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
   2.910 -  KeMemoryBarrier();
   2.911 -
   2.912 -  if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
   2.913 -  {
   2.914 -    FUNCTION_ENTER();
   2.915 -    switch (suspend_resume_state_pdo)
   2.916 -    {
   2.917 -      case SR_STATE_SUSPENDING:
   2.918 -        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_SUSPENDING\n"));
   2.919 -        break;
   2.920 -      case SR_STATE_RESUMING:
   2.921 -        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_RESUMING\n"));
   2.922 -        XenVbd_InitFromConfig(xvdd);
   2.923 -        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   2.924 -        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   2.925 -        break;
   2.926 -      case SR_STATE_RUNNING:
   2.927 -        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
   2.928 -        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   2.929 -        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   2.930 -        ScsiPortNotification(NextRequest, DeviceExtension);
   2.931 -      default:
   2.932 -        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
   2.933 -        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   2.934 -        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   2.935 -        break;
   2.936 -    }
   2.937 -    KeMemoryBarrier();
   2.938 -  }
   2.939 -
   2.940 -  if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
   2.941 -  {
   2.942 -    return last_interrupt;
   2.943 -  }
   2.944 -
   2.945 -  while (more_to_do)
   2.946 -  {
   2.947 -    rp = xvdd->ring.sring->rsp_prod;
   2.948 -    KeMemoryBarrier();
   2.949 -    for (i = xvdd->ring.rsp_cons; i < rp; i++)
   2.950 -    {
   2.951 -      rep = XenVbd_GetResponse(xvdd, i);
   2.952 -/*
   2.953 -* This code is to automatically detect if the backend is using the same
   2.954 -* bit width or a different bit width to us. Later versions of Xen do this
   2.955 -* via a xenstore value, but not all. That 0x0fffffff (notice
   2.956 -* that the msb is not actually set, so we don't have any problems with
   2.957 -* sign extending) is to signify the last entry on the right, which is
   2.958 -* different under 32 and 64 bits, and that is why we set it up there.
   2.959 -
   2.960 -* To do the detection, we put two initial entries on the ring, with an op
   2.961 -* of 0xff (which is invalid). The first entry is mostly okay, but the
   2.962 -* second will be grossly misaligned if the backend bit width is different,
   2.963 -* and we detect this and switch frontend structures.
   2.964 -*/
   2.965 -      switch (xvdd->ring_detect_state)
   2.966 -      {
   2.967 -      case RING_DETECT_STATE_NOT_STARTED:
   2.968 -        KdPrint((__DRIVER_NAME "     premature IRQ\n"));
   2.969 -        break;
   2.970 -      case RING_DETECT_STATE_DETECT1:
   2.971 -        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
   2.972 -        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
   2.973 -        xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
   2.974 -        break;
   2.975 -      case RING_DETECT_STATE_DETECT2:
   2.976 -        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
   2.977 -        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
   2.978 -        *xvdd->event_channel_ptr |= 0x80000000;
   2.979 -        if (rep->operation != 0xff)
   2.980 -        {
   2.981 -          KdPrint((__DRIVER_NAME "     switching to 'other' ring size\n"));
   2.982 -          xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   2.983 -          xvdd->use_other = TRUE;
   2.984 -          *xvdd->event_channel_ptr |= 0x40000000;
   2.985 -        }
   2.986 -        xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
   2.987 -        ScsiPortNotification(NextRequest, DeviceExtension);
   2.988 -        break;
   2.989 -      case RING_DETECT_STATE_COMPLETE:
   2.990 -        shadow = &xvdd->shadows[rep->id];
   2.991 -        srb = shadow->srb;
   2.992 -        ASSERT(srb != NULL);
   2.993 -        block_count = decode_cdb_length(srb);
   2.994 -        block_count *= xvdd->bytes_per_sector / 512;
   2.995 -        /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
   2.996 -        if (rep->status == BLKIF_RSP_OKAY || (dump_mode &&  dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
   2.997 -          srb->SrbStatus = SRB_STATUS_SUCCESS;
   2.998 -        else
   2.999 -        {
  2.1000 -          KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
  2.1001 -          if (decode_cdb_is_read(srb))
  2.1002 -            KdPrint((__DRIVER_NAME "     Operation = Read\n"));
  2.1003 -          else
  2.1004 -            KdPrint((__DRIVER_NAME "     Operation = Write\n"));
  2.1005 -          if (dump_mode)
  2.1006 -          {
  2.1007 -            KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
  2.1008 -            KdPrint((__DRIVER_NAME "     DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
  2.1009 -            KdPrint((__DRIVER_NAME "     Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
  2.1010 -            KdPrint((__DRIVER_NAME "     PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
  2.1011 -
  2.1012 -            for (j = 0; j < shadow->req.nr_segments; j++)
  2.1013 -            {
  2.1014 -              KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[j].gref));
  2.1015 -              KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[j].first_sect));
  2.1016 -              KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[j].last_sect));
  2.1017 -            }
  2.1018 -          }
  2.1019 -          srb->SrbStatus = SRB_STATUS_ERROR;
  2.1020 -          srb->ScsiStatus = 0x02;
  2.1021 -          xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
  2.1022 -          xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  2.1023 -          XenVbd_MakeAutoSense(xvdd, srb);
  2.1024 -        }
  2.1025 -        if (shadow->aligned_buffer_in_use)
  2.1026 -        {
  2.1027 -          ASSERT(xvdd->aligned_buffer_in_use);
  2.1028 -          xvdd->aligned_buffer_in_use = FALSE;
  2.1029 -          if (decode_cdb_is_read(srb))
  2.1030 -            memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
  2.1031 -//KdPrint((__DRIVER_NAME "     Completed use of buffer\n"));
  2.1032 -        }
  2.1033 -        
  2.1034 -#if 0
  2.1035 -if (xvdd->aligned_buffer_in_use)
  2.1036 -{
  2.1037 -KdPrint((__DRIVER_NAME "     Completed request while aligned buffer in use\n"));
  2.1038 -}
  2.1039 -#endif
  2.1040 -        for (j = 0; j < shadow->req.nr_segments; j++)
  2.1041 -        {
  2.1042 -          if (dump_mode)
  2.1043 -          {
  2.1044 -            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  2.1045 -              shadow->req.seg[j].gref, TRUE, (ULONG)'XPDO');
  2.1046 -          }
  2.1047 -          else
  2.1048 -          {
  2.1049 -            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  2.1050 -              shadow->req.seg[j].gref, FALSE, (ULONG)'XVBD');
  2.1051 -          }
  2.1052 -        }
  2.1053 -        shadow->aligned_buffer_in_use = FALSE;
  2.1054 -        shadow->srb = NULL;
  2.1055 -        put_shadow_on_freelist(xvdd, shadow);
  2.1056 -        //KdPrint((__DRIVER_NAME "     B RequestComplete srb = %p\n", srb));
  2.1057 -        ScsiPortNotification(RequestComplete, xvdd, srb);
  2.1058 -        break;
  2.1059 -      }
  2.1060 -    }
  2.1061 -
  2.1062 -    xvdd->ring.rsp_cons = i;
  2.1063 -    if (i != xvdd->ring.req_prod_pvt)
  2.1064 -    {
  2.1065 -      RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
  2.1066 -    }
  2.1067 -    else
  2.1068 -    {
  2.1069 -      xvdd->ring.sring->rsp_event = i + 1;
  2.1070 -      more_to_do = FALSE;
  2.1071 -    }
  2.1072 -  }
  2.1073 -
  2.1074 -  if (start_ring_detect_state == RING_DETECT_STATE_COMPLETE)
  2.1075 -    XenVbd_PutQueuedSrbsOnRing(xvdd);
  2.1076 -
  2.1077 -  if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
  2.1078 -  {
  2.1079 -    if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
  2.1080 -    {
  2.1081 -      /* all entries are purged from the list (or we are inactive). ready to suspend */
  2.1082 -      xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  2.1083 -      KeMemoryBarrier();
  2.1084 -      KdPrint((__DRIVER_NAME "     Set fdo state SR_STATE_SUSPENDING\n"));
  2.1085 -      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
  2.1086 -      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  2.1087 -    }
  2.1088 -    FUNCTION_EXIT();
  2.1089 -  }
  2.1090 -
  2.1091 -  return last_interrupt;
  2.1092 -}
  2.1093 -
  2.1094 -static BOOLEAN DDKAPI
  2.1095 -XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
  2.1096 -{
  2.1097 -  PUCHAR data_buffer;
  2.1098 -  //ULONG data_buffer_length;
  2.1099 -  PCDB cdb;
  2.1100 -  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  2.1101 -  ULONG data_transfer_length = srb->DataTransferLength;
  2.1102 -
  2.1103 -  if (xvdd->inactive)
  2.1104 -  {
  2.1105 -    KdPrint((__DRIVER_NAME "     Inactive srb->Function = %08X\n", srb->Function));
  2.1106 -    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  2.1107 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1108 -    ScsiPortNotification(NextRequest, DeviceExtension);
  2.1109 -    return TRUE;
  2.1110 -  }
  2.1111 -  
  2.1112 -  // If we haven't enumerated all the devices yet then just defer the request
  2.1113 -  if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
  2.1114 -  {
  2.1115 -    srb->SrbStatus = SRB_STATUS_BUSY;
  2.1116 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1117 -    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
  2.1118 -    return TRUE;
  2.1119 -  }
  2.1120 -
  2.1121 -  if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
  2.1122 -  {
  2.1123 -    KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Suspending/Resuming)\n"));
  2.1124 -    srb->SrbStatus = SRB_STATUS_BUSY;
  2.1125 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1126 -    KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Suspending/Resuming)\n"));
  2.1127 -    return TRUE;
  2.1128 -  }
  2.1129 -
  2.1130 -  if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
  2.1131 -  {
  2.1132 -    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  2.1133 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1134 -    ScsiPortNotification(NextRequest, DeviceExtension);
  2.1135 -    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
  2.1136 -    return TRUE;
  2.1137 -  }
  2.1138 -
  2.1139 -  switch (srb->Function)
  2.1140 -  {
  2.1141 -  case SRB_FUNCTION_EXECUTE_SCSI:
  2.1142 -    cdb = (PCDB)srb->Cdb;
  2.1143 -
  2.1144 -    switch(cdb->CDB6GENERIC.OperationCode)
  2.1145 -    {
  2.1146 -    case SCSIOP_TEST_UNIT_READY:
  2.1147 -      if (dump_mode)
  2.1148 -        KdPrint((__DRIVER_NAME "     Command = TEST_UNIT_READY\n"));
  2.1149 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1150 -      srb->ScsiStatus = 0;
  2.1151 -      break;
  2.1152 -    case SCSIOP_INQUIRY:
  2.1153 -      if (dump_mode)
  2.1154 -      {
  2.1155 -        //PHYSICAL_ADDRESS physical;
  2.1156 -        KdPrint((__DRIVER_NAME "     Command = INQUIRY\n"));
  2.1157 -        //KdPrint((__DRIVER_NAME "     srb->Databuffer = %p\n", srb->DataBuffer));
  2.1158 -        //physical = ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length);
  2.1159 -        //KdPrint((__DRIVER_NAME "     ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
  2.1160 -      }
  2.1161 -//      KdPrint((__DRIVER_NAME "     (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
  2.1162 -//      KdPrint((__DRIVER_NAME "     (Length = %d)\n", srb->DataTransferLength));
  2.1163 -      
  2.1164 -      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  2.1165 -      data_buffer = srb->DataBuffer;
  2.1166 -      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  2.1167 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1168 -      switch (xvdd->device_type)
  2.1169 -      {
  2.1170 -      case XENVBD_DEVICETYPE_DISK:
  2.1171 -        if ((srb->Cdb[1] & 1) == 0)
  2.1172 -        {
  2.1173 -          if (srb->Cdb[2])
  2.1174 -          {
  2.1175 -            srb->SrbStatus = SRB_STATUS_ERROR;
  2.1176 -          }
  2.1177 -          else
  2.1178 -          {
  2.1179 -            PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  2.1180 -            id->DeviceType = DIRECT_ACCESS_DEVICE;
  2.1181 -            id->Versions = 4; /* minimum that WHQL says we must support */
  2.1182 -            id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
  2.1183 -            id->HiSupport = 1; /* WHQL test says we should set this */
  2.1184 -            //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  2.1185 -            id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
  2.1186 -            id->CommandQueue = 1;
  2.1187 -            memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  2.1188 -            memcpy(id->ProductId, scsi_disk_model, 16); // product id
  2.1189 -            memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  2.1190 -            data_transfer_length = sizeof(INQUIRYDATA);
  2.1191 -          }
  2.1192 -        }
  2.1193 -        else
  2.1194 -        {
  2.1195 -          switch (srb->Cdb[2])
  2.1196 -          {
  2.1197 -          case VPD_SUPPORTED_PAGES: /* list of pages we support */
  2.1198 -            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  2.1199 -            data_buffer[1] = VPD_SUPPORTED_PAGES;
  2.1200 -            data_buffer[2] = 0x00;
  2.1201 -            data_buffer[3] = 2;
  2.1202 -            data_buffer[4] = 0x00;
  2.1203 -            data_buffer[5] = 0x80;
  2.1204 -            data_transfer_length = 6;
  2.1205 -            break;
  2.1206 -          case VPD_SERIAL_NUMBER: /* serial number */
  2.1207 -            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  2.1208 -            data_buffer[1] = VPD_SERIAL_NUMBER;
  2.1209 -            data_buffer[2] = 0x00;
  2.1210 -            data_buffer[3] = 8;
  2.1211 -            memset(&data_buffer[4], ' ', 8);
  2.1212 -            data_transfer_length = 12;
  2.1213 -            break;
  2.1214 -          case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
  2.1215 -            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  2.1216 -            data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
  2.1217 -            data_buffer[2] = 0x00;
  2.1218 -            data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
  2.1219 -            data_buffer[4] = 2; /* ASCII */
  2.1220 -            data_buffer[5] = 1; /* VendorId */
  2.1221 -            data_buffer[6] = 0;
  2.1222 -            data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
  2.1223 -            memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
  2.1224 -            data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
  2.1225 -            break;
  2.1226 -          default:
  2.1227 -            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  2.1228 -            srb->SrbStatus = SRB_STATUS_ERROR;
  2.1229 -            break;
  2.1230 -          }
  2.1231 -        }
  2.1232 -        break;
  2.1233 -      case XENVBD_DEVICETYPE_CDROM:
  2.1234 -        if ((srb->Cdb[1] & 1) == 0)
  2.1235 -        {
  2.1236 -          PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  2.1237 -          id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
  2.1238 -          id->RemovableMedia = 1;
  2.1239 -          id->Versions = 3;
  2.1240 -          id->ResponseDataFormat = 0;
  2.1241 -          id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  2.1242 -          id->CommandQueue = 1;
  2.1243 -          memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  2.1244 -          memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
  2.1245 -          memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  2.1246 -        }
  2.1247 -        else
  2.1248 -        {
  2.1249 -          switch (srb->Cdb[2])
  2.1250 -          {
  2.1251 -          case 0x00:
  2.1252 -            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  2.1253 -            data_buffer[1] = 0x00;
  2.1254 -            data_buffer[2] = 0x00;
  2.1255 -            data_buffer[3] = 2;
  2.1256 -            data_buffer[4] = 0x00;
  2.1257 -            data_buffer[5] = 0x80;
  2.1258 -            break;
  2.1259 -          case 0x80:
  2.1260 -            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  2.1261 -            data_buffer[1] = 0x80;
  2.1262 -            data_buffer[2] = 0x00;
  2.1263 -            data_buffer[3] = 8;
  2.1264 -            data_buffer[4] = 0x31;
  2.1265 -            data_buffer[5] = 0x32;
  2.1266 -            data_buffer[6] = 0x33;
  2.1267 -            data_buffer[7] = 0x34;
  2.1268 -            data_buffer[8] = 0x35;
  2.1269 -            data_buffer[9] = 0x36;
  2.1270 -            data_buffer[10] = 0x37;
  2.1271 -            data_buffer[11] = 0x38;
  2.1272 -            break;
  2.1273 -          default:
  2.1274 -            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  2.1275 -            srb->SrbStatus = SRB_STATUS_ERROR;
  2.1276 -            break;
  2.1277 -          }
  2.1278 -        }
  2.1279 -        break;
  2.1280 -      default:
  2.1281 -        //KdPrint((__DRIVER_NAME "     Unknown DeviceType %02x requested\n", xvdd->device_type));
  2.1282 -        srb->SrbStatus = SRB_STATUS_ERROR;
  2.1283 -        break;
  2.1284 -      }
  2.1285 -      break;
  2.1286 -    case SCSIOP_READ_CAPACITY:
  2.1287 -      if (dump_mode)
  2.1288 -        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  2.1289 -      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  2.1290 -      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  2.1291 -      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  2.1292 -      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  2.1293 -      data_buffer = srb->DataBuffer;
  2.1294 -      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  2.1295 -      if ((xvdd->total_sectors - 1) >> 32)
  2.1296 -      {
  2.1297 -        data_buffer[0] = 0xff;
  2.1298 -        data_buffer[1] = 0xff;
  2.1299 -        data_buffer[2] = 0xff;
  2.1300 -        data_buffer[3] = 0xff;
  2.1301 -      }
  2.1302 -      else
  2.1303 -      {
  2.1304 -        data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  2.1305 -        data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  2.1306 -        data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  2.1307 -        data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  2.1308 -      }
  2.1309 -      data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  2.1310 -      data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  2.1311 -      data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  2.1312 -      data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  2.1313 -      srb->ScsiStatus = 0;
  2.1314 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1315 -      break;
  2.1316 -    case SCSIOP_READ_CAPACITY16:
  2.1317 -      if (dump_mode)
  2.1318 -        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  2.1319 -      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  2.1320 -      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  2.1321 -      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  2.1322 -      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  2.1323 -      data_buffer = srb->DataBuffer;
  2.1324 -      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  2.1325 -      data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
  2.1326 -      data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
  2.1327 -      data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
  2.1328 -      data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
  2.1329 -      data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  2.1330 -      data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  2.1331 -      data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  2.1332 -      data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  2.1333 -      data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  2.1334 -      data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  2.1335 -      data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  2.1336 -      data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  2.1337 -      srb->ScsiStatus = 0;
  2.1338 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1339 -      break;
  2.1340 -    case SCSIOP_MODE_SENSE:
  2.1341 -    case SCSIOP_MODE_SENSE10:
  2.1342 -      if (dump_mode)
  2.1343 -        KdPrint((__DRIVER_NAME "     Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", srb->Cdb[1] & 0x08, srb->Cdb[2] & 0xC0, srb->Cdb[2] & 0x3F));
  2.1344 -      XenVbd_FillModePage(xvdd, srb);
  2.1345 -      break;
  2.1346 -    case SCSIOP_READ:
  2.1347 -    case SCSIOP_READ16:
  2.1348 -    case SCSIOP_WRITE:
  2.1349 -    case SCSIOP_WRITE16:
  2.1350 -      XenVbd_PutSrbOnList(xvdd, srb);
  2.1351 -      XenVbd_PutQueuedSrbsOnRing(xvdd);
  2.1352 -      break;
  2.1353 -    case SCSIOP_VERIFY:
  2.1354 -    case SCSIOP_VERIFY16:
  2.1355 -      // Should we do more here?
  2.1356 -      if (dump_mode)
  2.1357 -        KdPrint((__DRIVER_NAME "     Command = VERIFY\n"));
  2.1358 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1359 -      break;
  2.1360 -    case SCSIOP_REPORT_LUNS:
  2.1361 -      if (dump_mode)
  2.1362 -        KdPrint((__DRIVER_NAME "     Command = REPORT_LUNS\n"));
  2.1363 -      srb->SrbStatus = SRB_STATUS_SUCCESS;;
  2.1364 -      break;
  2.1365 -    case SCSIOP_REQUEST_SENSE:
  2.1366 -      if (dump_mode)
  2.1367 -        KdPrint((__DRIVER_NAME "     Command = REQUEST_SENSE\n"));
  2.1368 -      XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
  2.1369 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1370 -      break;      
  2.1371 -    case SCSIOP_READ_TOC:
  2.1372 -      if (dump_mode)
  2.1373 -        KdPrint((__DRIVER_NAME "     Command = READ_TOC\n"));
  2.1374 -      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  2.1375 -      data_buffer = srb->DataBuffer;
  2.1376 -//      DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
  2.1377 -/*
  2.1378 -#define READ_TOC_FORMAT_TOC         0x00
  2.1379 -#define READ_TOC_FORMAT_SESSION     0x01
  2.1380 -#define READ_TOC_FORMAT_FULL_TOC    0x02
  2.1381 -#define READ_TOC_FORMAT_PMA         0x03
  2.1382 -#define READ_TOC_FORMAT_ATIP        0x04
  2.1383 -*/
  2.1384 -//      KdPrint((__DRIVER_NAME "     Msf = %d\n", cdb->READ_TOC.Msf));
  2.1385 -//      KdPrint((__DRIVER_NAME "     LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
  2.1386 -//      KdPrint((__DRIVER_NAME "     Format2 = %d\n", cdb->READ_TOC.Format2));
  2.1387 -//      KdPrint((__DRIVER_NAME "     StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
  2.1388 -//      KdPrint((__DRIVER_NAME "     AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
  2.1389 -//      KdPrint((__DRIVER_NAME "     Control = %d\n", cdb->READ_TOC.Control));
  2.1390 -//      KdPrint((__DRIVER_NAME "     Format = %d\n", cdb->READ_TOC.Format));
  2.1391 -      switch (cdb->READ_TOC.Format2)
  2.1392 -      {
  2.1393 -      case READ_TOC_FORMAT_TOC:
  2.1394 -        data_buffer[0] = 0; // length MSB
  2.1395 -        data_buffer[1] = 10; // length LSB
  2.1396 -        data_buffer[2] = 1; // First Track
  2.1397 -        data_buffer[3] = 1; // Last Track
  2.1398 -        data_buffer[4] = 0; // Reserved
  2.1399 -        data_buffer[5] = 0x14; // current position data + uninterrupted data
  2.1400 -        data_buffer[6] = 1; // last complete track
  2.1401 -        data_buffer[7] = 0; // reserved
  2.1402 -        data_buffer[8] = 0; // MSB Block
  2.1403 -        data_buffer[9] = 0;
  2.1404 -        data_buffer[10] = 0;
  2.1405 -        data_buffer[11] = 0; // LSB Block
  2.1406 -        srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1407 -        break;
  2.1408 -      case READ_TOC_FORMAT_SESSION:
  2.1409 -      case READ_TOC_FORMAT_FULL_TOC:
  2.1410 -      case READ_TOC_FORMAT_PMA:
  2.1411 -      case READ_TOC_FORMAT_ATIP:
  2.1412 -        srb->SrbStatus = SRB_STATUS_ERROR;
  2.1413 -        break;
  2.1414 -      }
  2.1415 -      break;
  2.1416 -    case SCSIOP_START_STOP_UNIT:
  2.1417 -      KdPrint((__DRIVER_NAME "     Command = SCSIOP_START_STOP_UNIT\n"));
  2.1418 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1419 -      break;
  2.1420 -    case SCSIOP_RESERVE_UNIT:
  2.1421 -      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RESERVE_UNIT\n"));
  2.1422 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1423 -      break;
  2.1424 -    case SCSIOP_RELEASE_UNIT:
  2.1425 -      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RELEASE_UNIT\n"));
  2.1426 -      srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1427 -      break;
  2.1428 -    default:
  2.1429 -      KdPrint((__DRIVER_NAME "     Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
  2.1430 -      srb->SrbStatus = SRB_STATUS_ERROR;
  2.1431 -      break;
  2.1432 -    }
  2.1433 -    if (srb->SrbStatus == SRB_STATUS_ERROR)
  2.1434 -    {
  2.1435 -      KdPrint((__DRIVER_NAME "     EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
  2.1436 -      if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
  2.1437 -      {
  2.1438 -        xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
  2.1439 -        xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
  2.1440 -      }
  2.1441 -      srb->ScsiStatus = 0x02;
  2.1442 -      XenVbd_MakeAutoSense(xvdd, srb);
  2.1443 -      ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1444 -      if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1445 -      {
  2.1446 -        ScsiPortNotification(NextRequest, DeviceExtension);
  2.1447 -      }
  2.1448 -    }
  2.1449 -    else if (srb->SrbStatus != SRB_STATUS_PENDING)
  2.1450 -    {
  2.1451 -      if (srb->SrbStatus == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
  2.1452 -      {
  2.1453 -        srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  2.1454 -        srb->DataTransferLength = data_transfer_length;
  2.1455 -      }
  2.1456 -      xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
  2.1457 -      xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  2.1458 -      ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1459 -      if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1460 -      {
  2.1461 -        ScsiPortNotification(NextRequest, DeviceExtension);
  2.1462 -      }
  2.1463 -    }
  2.1464 -    break;
  2.1465 -  case SRB_FUNCTION_IO_CONTROL:
  2.1466 -    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_IO_CONTROL\n"));
  2.1467 -    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  2.1468 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1469 -    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1470 -    {
  2.1471 -      ScsiPortNotification(NextRequest, DeviceExtension);
  2.1472 -    }
  2.1473 -    break;
  2.1474 -  case SRB_FUNCTION_FLUSH:
  2.1475 -    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  2.1476 -    srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1477 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1478 -    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1479 -    {
  2.1480 -      ScsiPortNotification(NextRequest, DeviceExtension);
  2.1481 -    }
  2.1482 -    break;
  2.1483 -  case SRB_FUNCTION_SHUTDOWN:
  2.1484 -    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  2.1485 -    srb->SrbStatus = SRB_STATUS_SUCCESS;
  2.1486 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1487 -    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1488 -    {
  2.1489 -      ScsiPortNotification(NextRequest, DeviceExtension);
  2.1490 -    }
  2.1491 -    break;
  2.1492 -  default:
  2.1493 -    KdPrint((__DRIVER_NAME "     Unhandled srb->Function = %08X\n", srb->Function));
  2.1494 -    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  2.1495 -    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  2.1496 -    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1497 -    {
  2.1498 -      ScsiPortNotification(NextRequest, DeviceExtension);
  2.1499 -    }
  2.1500 -    break;
  2.1501 -  }
  2.1502 -
  2.1503 -  //FUNCTION_EXIT();
  2.1504 -  return TRUE;
  2.1505 -}
  2.1506 -
  2.1507 -static BOOLEAN
  2.1508 -XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
  2.1509 -{
  2.1510 -  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  2.1511 -
  2.1512 -  UNREFERENCED_PARAMETER(DeviceExtension);
  2.1513 -  UNREFERENCED_PARAMETER(PathId);
  2.1514 -
  2.1515 -  FUNCTION_ENTER();
  2.1516 -
  2.1517 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  2.1518 -  if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  2.1519 -  {
  2.1520 -    ScsiPortNotification(NextRequest, DeviceExtension);
  2.1521 -  }
  2.1522 -
  2.1523 -  FUNCTION_EXIT();
  2.1524 -
  2.1525 -
  2.1526 -  return TRUE;
  2.1527 -}
  2.1528 -
  2.1529 -static BOOLEAN
  2.1530 -XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
  2.1531 -{
  2.1532 -  UNREFERENCED_PARAMETER(DeviceExtension);
  2.1533 -  UNREFERENCED_PARAMETER(Context);
  2.1534 -  UNREFERENCED_PARAMETER(SaveState);
  2.1535 -
  2.1536 -  FUNCTION_ENTER();
  2.1537 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  2.1538 -
  2.1539 -  FUNCTION_EXIT();
  2.1540 -
  2.1541 -  return TRUE;
  2.1542 -}
  2.1543 -
  2.1544 -static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
  2.1545 -XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
  2.1546 -{
  2.1547 -  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  2.1548 -  SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
  2.1549 -  PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
  2.1550 -  //KIRQL OldIrql;
  2.1551 -
  2.1552 -  FUNCTION_ENTER();
  2.1553 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  2.1554 -  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
  2.1555 -
  2.1556 -  switch (ControlType)
  2.1557 -  {
  2.1558 -  case ScsiQuerySupportedControlTypes:
  2.1559 -    SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
  2.1560 -    KdPrint((__DRIVER_NAME "     ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
  2.1561 -    SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
  2.1562 -    SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
  2.1563 -    SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
  2.1564 -    break;
  2.1565 -  case ScsiStopAdapter:
  2.1566 -    KdPrint((__DRIVER_NAME "     ScsiStopAdapter\n"));
  2.1567 -    /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
  2.1568 -    break;
  2.1569 -  case ScsiRestartAdapter:
  2.1570 -    KdPrint((__DRIVER_NAME "     ScsiRestartAdapter\n"));
  2.1571 -    if (!xvdd->inactive)
  2.1572 -    {
  2.1573 -      if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
  2.1574 -        KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR) xvdd, 0, 0);
  2.1575 -      XenVbd_StartRingDetection(xvdd);
  2.1576 -    }
  2.1577 -    break;
  2.1578 -  case ScsiSetBootConfig:
  2.1579 -    KdPrint((__DRIVER_NAME "     ScsiSetBootConfig\n"));
  2.1580 -    break;
  2.1581 -  case ScsiSetRunningConfig:
  2.1582 -    KdPrint((__DRIVER_NAME "     ScsiSetRunningConfig\n"));
  2.1583 -    break;
  2.1584 -  default:
  2.1585 -    KdPrint((__DRIVER_NAME "     UNKNOWN\n"));
  2.1586 -    break;
  2.1587 -  }
  2.1588 -
  2.1589 -  FUNCTION_EXIT();
  2.1590 -  
  2.1591 -  return Status;
  2.1592 -}
  2.1593 -
  2.1594 -NTSTATUS
  2.1595 -DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  2.1596 -{
  2.1597 -  ULONG status;
  2.1598 -  HW_INITIALIZATION_DATA HwInitializationData;
  2.1599 -  PVOID driver_extension;
  2.1600 -  PUCHAR ptr;
  2.1601 -  OBJECT_ATTRIBUTES oa;
  2.1602 -  HANDLE service_handle;
  2.1603 -  UNICODE_STRING param_name;
  2.1604 -  HANDLE param_handle;
  2.1605 -  UNICODE_STRING value_name;
  2.1606 -  CHAR buf[256];
  2.1607 -  ULONG buf_len;
  2.1608 -  PKEY_VALUE_PARTIAL_INFORMATION kpv;
  2.1609 -  
  2.1610 -  FUNCTION_ENTER();
  2.1611 -  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  2.1612 -  KdPrint((__DRIVER_NAME "     DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
  2.1613 -
  2.1614 -  /* RegistryPath == NULL when we are invoked as a crash dump driver */
  2.1615 -  if (!RegistryPath)
  2.1616 -  {
  2.1617 -    dump_mode = TRUE;
  2.1618 -  }
  2.1619 -  
  2.1620 -  if (!dump_mode)
  2.1621 -  {
  2.1622 -    IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
  2.1623 -    ptr = driver_extension;
  2.1624 -    //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
  2.1625 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
  2.1626 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
  2.1627 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
  2.1628 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
  2.1629 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
  2.1630 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
  2.1631 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
  2.1632 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
  2.1633 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  2.1634 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  2.1635 -    __ADD_XEN_INIT_UCHAR(&ptr, 20);
  2.1636 -    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  2.1637 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
  2.1638 -    //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  2.1639 -    //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  2.1640 -    //__ADD_XEN_INIT_UCHAR(&ptr, 20);
  2.1641 -    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  2.1642 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
  2.1643 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
  2.1644 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
  2.1645 -    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  2.1646 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
  2.1647 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
  2.1648 -    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  2.1649 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
  2.1650 -    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
  2.1651 -    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  2.1652 -    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  2.1653 -    
  2.1654 -    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
  2.1655 -
  2.1656 -    InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  2.1657 -    status = ZwOpenKey(&service_handle, KEY_READ, &oa);
  2.1658 -    if(!NT_SUCCESS(status))
  2.1659 -    {
  2.1660 -      KdPrint((__DRIVER_NAME "     ZwOpenKey(Service) returned %08x\n", status));
  2.1661 -    }
  2.1662 -    else
  2.1663 -    {
  2.1664 -      RtlInitUnicodeString(&param_name, L"Parameters");
  2.1665 -      InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
  2.1666 -      status = ZwOpenKey(&param_handle, KEY_READ, &oa);
  2.1667 -      if(!NT_SUCCESS(status))
  2.1668 -      {
  2.1669 -        KdPrint((__DRIVER_NAME "     ZwOpenKey(Parameters) returned %08x\n", status));
  2.1670 -      }
  2.1671 -      else
  2.1672 -      {
  2.1673 -        kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
  2.1674 -        RtlFillMemory(scsi_device_manufacturer, 8, ' ');
  2.1675 -        RtlFillMemory(scsi_disk_model, 16, ' ');
  2.1676 -        RtlFillMemory(scsi_cdrom_model, 16, ' ');
  2.1677 -
  2.1678 -        RtlInitUnicodeString(&value_name, L"Manufacturer");
  2.1679 -        buf_len = 256;
  2.1680 -        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  2.1681 -        if(NT_SUCCESS(status))
  2.1682 -          wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
  2.1683 -        else
  2.1684 -          RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN     ");
  2.1685 -
  2.1686 -        RtlInitUnicodeString(&value_name, L"Disk_Model");
  2.1687 -        buf_len = 256;
  2.1688 -        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  2.1689 -        if(NT_SUCCESS(status))
  2.1690 -          wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  2.1691 -        else
  2.1692 -          RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK          ");
  2.1693 -
  2.1694 -        RtlInitUnicodeString(&value_name, L"CDROM_Model");
  2.1695 -        buf_len = 256;
  2.1696 -        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  2.1697 -        if(NT_SUCCESS(status))
  2.1698 -          wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  2.1699 -        else
  2.1700 -          RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM        ");
  2.1701 -        ZwClose(param_handle);
  2.1702 -      }
  2.1703 -      ZwClose(service_handle);
  2.1704 -    }
  2.1705 -  }
  2.1706 -  
  2.1707 -  RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
  2.1708 -
  2.1709 -  HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
  2.1710 -  HwInitializationData.AdapterInterfaceType = PNPBus;
  2.1711 -  if (!dump_mode)
  2.1712 -    HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
  2.1713 -  else
  2.1714 -    HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
  2.1715 -  HwInitializationData.SpecificLuExtensionSize = 0;
  2.1716 -  HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
  2.1717 -  HwInitializationData.NumberOfAccessRanges = 1;
  2.1718 -  HwInitializationData.MapBuffers = TRUE;
  2.1719 -  HwInitializationData.NeedPhysicalAddresses = FALSE;
  2.1720 -  HwInitializationData.TaggedQueuing = TRUE;
  2.1721 -  HwInitializationData.AutoRequestSense = TRUE;
  2.1722 -  HwInitializationData.MultipleRequestPerLu = TRUE;
  2.1723 -  HwInitializationData.ReceiveEvent = FALSE;
  2.1724 -  HwInitializationData.VendorIdLength = 0;
  2.1725 -  HwInitializationData.VendorId = NULL;
  2.1726 -  HwInitializationData.DeviceIdLength = 0;
  2.1727 -  HwInitializationData.DeviceId = NULL;
  2.1728 -
  2.1729 -  HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
  2.1730 -  HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
  2.1731 -  HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
  2.1732 -  HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
  2.1733 -  HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
  2.1734 -  HwInitializationData.HwDmaStarted = NULL;
  2.1735 -  HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
  2.1736 -  HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
  2.1737 -
  2.1738 -  status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
  2.1739 -  
  2.1740 -  if(!NT_SUCCESS(status))
  2.1741 -  {
  2.1742 -    KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
  2.1743 -  }
  2.1744 -
  2.1745 -  FUNCTION_EXIT();
  2.1746 -
  2.1747 -  return status;
  2.1748 -}
     3.1 --- a/xenvbd/xenvbd.h	Thu Jan 13 11:21:18 2011 +1100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,164 +0,0 @@
     3.4 -/*
     3.5 -PV Drivers for Windows Xen HVM Domains
     3.6 -Copyright (C) 2007 James Harper
     3.7 -
     3.8 -This program is free software; you can redistribute it and/or
     3.9 -modify it under the terms of the GNU General Public License
    3.10 -as published by the Free Software Foundation; either version 2
    3.11 -of the License, or (at your option) any later version.
    3.12 -
    3.13 -This program is distributed in the hope that it will be useful,
    3.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.16 -GNU General Public License for more details.
    3.17 -
    3.18 -You should have received a copy of the GNU General Public License
    3.19 -along with this program; if not, write to the Free Software
    3.20 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    3.21 -*/
    3.22 -
    3.23 -#if !defined(_XENVBD_H_)
    3.24 -#define _XENVBD_H_
    3.25 -
    3.26 -#define DDKAPI
    3.27 -
    3.28 -//#include <ntifs.h>
    3.29 -#include <ntddk.h>
    3.30 -#include <wdm.h>
    3.31 -#include <initguid.h>
    3.32 -#define NTSTRSAFE_LIB
    3.33 -#include <ntstrsafe.h>
    3.34 -
    3.35 -#include <ntdddisk.h>
    3.36 -#if (NTDDI_VERSION < NTDDI_WINXP) /* srb.h causes warnings under 2K for some reason */
    3.37 -#pragma warning(disable:4201) /* nameless struct/union */
    3.38 -#pragma warning(disable:4214) /* bit field types other than int */
    3.39 -#endif
    3.40 -#include <srb.h>
    3.41 -
    3.42 -#define __DRIVER_NAME "XenVbd"
    3.43 -
    3.44 -#include <xen_windows.h>
    3.45 -#include <memory.h>
    3.46 -//#include <grant_table.h>
    3.47 -#include <event_channel.h>
    3.48 -#include <hvm/params.h>
    3.49 -#include <hvm/hvm_op.h>
    3.50 -#include <xen_public.h>
    3.51 -#include <io/ring.h>
    3.52 -#include <io/blkif.h>
    3.53 -#include <io/xenbus.h>
    3.54 -
    3.55 -#define XENVBD_POOL_TAG (ULONG) 'XVBD'
    3.56 -
    3.57 -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    3.58 -#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
    3.59 -#define BLK_OTHER_RING_SIZE __RING_SIZE((blkif_other_sring_t *)0, PAGE_SIZE)
    3.60 -
    3.61 -#if defined(__x86_64__)
    3.62 -#pragma pack(push, 4)
    3.63 -#endif
    3.64 -struct blkif_other_request {
    3.65 -  uint8_t operation;
    3.66 -  uint8_t nr_segments;
    3.67 -  blkif_vdev_t handle;
    3.68 -  uint64_t id;
    3.69 -  blkif_sector_t sector_number;
    3.70 -  struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    3.71 -};
    3.72 -struct blkif_other_response {
    3.73 -  uint64_t id;
    3.74 -  uint8_t operation;
    3.75 -  int16_t status;
    3.76 -};
    3.77 -#if defined(__x86_64__)
    3.78 -#pragma pack(pop)
    3.79 -#endif
    3.80 -
    3.81 -typedef struct blkif_other_request blkif_other_request_t;
    3.82 -typedef struct blkif_other_response blkif_other_response_t;
    3.83 -DEFINE_RING_TYPES(blkif_other, struct blkif_other_request, struct blkif_other_response);
    3.84 -
    3.85 -typedef struct {
    3.86 -  LIST_ENTRY list_entry;
    3.87 -  PSCSI_REQUEST_BLOCK srb;
    3.88 -} srb_list_entry_t;
    3.89 -
    3.90 -typedef struct {
    3.91 -  blkif_request_t req;
    3.92 -  PSCSI_REQUEST_BLOCK srb;
    3.93 -  BOOLEAN aligned_buffer_in_use;
    3.94 -} blkif_shadow_t;
    3.95 -
    3.96 -#define MAX_SHADOW_ENTRIES 64
    3.97 -#define SHADOW_ENTRIES min(MAX_SHADOW_ENTRIES, min(BLK_RING_SIZE, BLK_OTHER_RING_SIZE))
    3.98 -
    3.99 -typedef enum {
   3.100 -  XENVBD_DEVICETYPE_UNKNOWN,
   3.101 -  XENVBD_DEVICETYPE_DISK,
   3.102 -  XENVBD_DEVICETYPE_CDROM,
   3.103 -  XENVBD_DEVICETYPE_CONTROLLER // Not yet used
   3.104 -} XENVBD_DEVICETYPE;
   3.105 -
   3.106 -typedef enum {
   3.107 -  XENVBD_DEVICEMODE_UNKNOWN,
   3.108 -  XENVBD_DEVICEMODE_READ,
   3.109 -  XENVBD_DEVICEMODE_WRITE
   3.110 -} XENVBD_DEVICEMODE;
   3.111 -
   3.112 -#define RING_DETECT_STATE_NOT_STARTED  0
   3.113 -#define RING_DETECT_STATE_DETECT1      1
   3.114 -#define RING_DETECT_STATE_DETECT2      2
   3.115 -#define RING_DETECT_STATE_COMPLETE     3
   3.116 -
   3.117 -struct
   3.118 -{
   3.119 -  BOOLEAN inactive;
   3.120 -  
   3.121 -  blkif_shadow_t shadows[MAX_SHADOW_ENTRIES];
   3.122 -  USHORT shadow_free_list[MAX_SHADOW_ENTRIES];
   3.123 -  USHORT shadow_free;
   3.124 -  USHORT shadow_min_free;
   3.125 -
   3.126 -  PUCHAR device_base;
   3.127 -
   3.128 -  blkif_sring_t *sring;
   3.129 -  evtchn_port_t event_channel;
   3.130 -  ULONG *event_channel_ptr;
   3.131 -  union {
   3.132 -    blkif_front_ring_t ring;
   3.133 -    blkif_other_front_ring_t other_ring;
   3.134 -  };
   3.135 -  int ring_detect_state;
   3.136 -  BOOLEAN use_other;
   3.137 -  BOOLEAN cached_use_other;
   3.138 -  UCHAR last_sense_key;
   3.139 -  UCHAR last_additional_sense_code;
   3.140 -  blkif_response_t tmp_rep;
   3.141 -  XENVBD_DEVICETYPE device_type;
   3.142 -  XENVBD_DEVICEMODE device_mode;
   3.143 -  ULONG bytes_per_sector;
   3.144 -  ULONGLONG total_sectors;
   3.145 -  XENPCI_VECTORS vectors;
   3.146 -  PXENPCI_DEVICE_STATE device_state;
   3.147 -  LIST_ENTRY srb_list;
   3.148 -  grant_ref_t dump_grant_refs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   3.149 -  BOOLEAN aligned_buffer_in_use;
   3.150 -  PVOID aligned_buffer;
   3.151 -/*  
   3.152 -  ULONGLONG interrupts;
   3.153 -  ULONGLONG aligned_requests;
   3.154 -  ULONGLONG aligned_bytes;
   3.155 -  ULONGLONG unaligned_requests;
   3.156 -  ULONGLONG unaligned_bytes;
   3.157 -*/
   3.158 -  #define BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE 1
   3.159 -  #define UNALIGNED_BUFFER_DATA_SIZE ((BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * PAGE_SIZE - 1)
   3.160 -  #define UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE ((BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE + 1) * PAGE_SIZE - 1)
   3.161 -  /* this has to be right at the end of DeviceExtension */
   3.162 -  /* can't allocate too much data in dump mode so size DeviceExtensionSize accordingly */
   3.163 -  UCHAR aligned_buffer_data[1];
   3.164 -} typedef XENVBD_DEVICE_DATA, *PXENVBD_DEVICE_DATA;
   3.165 -
   3.166 -#endif
   3.167 -
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xenvbd/xenvbd_scsiport.c	Sat Jan 22 15:47:16 2011 +1100
     4.3 @@ -0,0 +1,1744 @@
     4.4 +/*
     4.5 +PV Drivers for Windows Xen HVM Domains
     4.6 +Copyright (C) 2007 James Harper
     4.7 +
     4.8 +This program is free software; you can redistribute it and/or
     4.9 +modify it under the terms of the GNU General Public License
    4.10 +as published by the Free Software Foundation; either version 2
    4.11 +of the License, or (at your option) any later version.
    4.12 +
    4.13 +This program is distributed in the hope that it will be useful,
    4.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.16 +GNU General Public License for more details.
    4.17 +
    4.18 +You should have received a copy of the GNU General Public License
    4.19 +along with this program; if not, write to the Free Software
    4.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    4.21 +*/
    4.22 +
    4.23 +#define INITGUID
    4.24 +#include "xenvbd.h"
    4.25 +#include <io/blkif.h>
    4.26 +#include <scsi.h>
    4.27 +#include <ntddscsi.h>
    4.28 +#include <ntdddisk.h>
    4.29 +#include <stdlib.h>
    4.30 +#include <xen_public.h>
    4.31 +#include <io/xenbus.h>
    4.32 +#include <io/protocols.h>
    4.33 +
    4.34 +#pragma warning(disable: 4127)
    4.35 +
    4.36 +#if defined(__x86_64__)
    4.37 +  #define LongLongToPtr(x) (PVOID)(x)
    4.38 +#else
    4.39 +  #define LongLongToPtr(x) UlongToPtr(x)
    4.40 +#endif
    4.41 +
    4.42 +/* Not really necessary but keeps PREfast happy */
    4.43 +DRIVER_INITIALIZE DriverEntry;
    4.44 +
    4.45 +static BOOLEAN dump_mode = FALSE;
    4.46 +#define DUMP_MODE_ERROR_LIMIT 64
    4.47 +static ULONG dump_mode_errors = 0;
    4.48 +
    4.49 +CHAR scsi_device_manufacturer[8];
    4.50 +CHAR scsi_disk_model[16];
    4.51 +CHAR scsi_cdrom_model[16];
    4.52 +
    4.53 +ULONGLONG parse_numeric_string(PCHAR string)
    4.54 +{
    4.55 +  ULONGLONG val = 0;
    4.56 +  while (*string != 0)
    4.57 +  {
    4.58 +    val = val * 10 + (*string - '0');
    4.59 +    string++;
    4.60 +  }
    4.61 +  return val;
    4.62 +}
    4.63 +
    4.64 +static blkif_shadow_t *
    4.65 +get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
    4.66 +{
    4.67 +  if (xvdd->shadow_free == 0)
    4.68 +  {
    4.69 +    KdPrint((__DRIVER_NAME "     No more shadow entries\n"));
    4.70 +    return NULL;
    4.71 +  }
    4.72 +  xvdd->shadow_free--;
    4.73 +  if (xvdd->shadow_free < xvdd->shadow_min_free)
    4.74 +    xvdd->shadow_min_free = xvdd->shadow_free;
    4.75 +  return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
    4.76 +}
    4.77 +
    4.78 +static VOID
    4.79 +put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
    4.80 +{
    4.81 +  xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
    4.82 +  shadow->srb = NULL;
    4.83 +  xvdd->shadow_free++;
    4.84 +}
    4.85 +
    4.86 +static blkif_response_t *
    4.87 +XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
    4.88 +{
    4.89 +  blkif_other_response_t *rep;
    4.90 +  if (!xvdd->use_other)
    4.91 +    return RING_GET_RESPONSE(&xvdd->ring, i);
    4.92 +  rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
    4.93 +  xvdd->tmp_rep.id = rep->id;
    4.94 +  xvdd->tmp_rep.operation = rep->operation;
    4.95 +  xvdd->tmp_rep.status = rep->status;
    4.96 +  return &xvdd->tmp_rep;
    4.97 +}
    4.98 +
    4.99 +static VOID
   4.100 +XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
   4.101 +{
   4.102 +  blkif_other_request_t *other_req;
   4.103 +
   4.104 +  if (!xvdd->use_other)
   4.105 +  {
   4.106 +    *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
   4.107 +  }
   4.108 +  else
   4.109 +  {  
   4.110 +    other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
   4.111 +    other_req->operation = req->operation;
   4.112 +    other_req->nr_segments = req->nr_segments;
   4.113 +    other_req->handle = req->handle;
   4.114 +    other_req->id = req->id;
   4.115 +    other_req->sector_number = req->sector_number;
   4.116 +    memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
   4.117 +  }
   4.118 +  xvdd->ring.req_prod_pvt++;
   4.119 +}
   4.120 +
   4.121 +static ULONG
   4.122 +XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
   4.123 +{
   4.124 +  ULONG i;
   4.125 +  PUCHAR ptr;
   4.126 +  USHORT type;
   4.127 +  PCHAR setting, value, value2;
   4.128 +  ULONG qemu_protocol_version = 0;
   4.129 +  BOOLEAN qemu_hide_filter = FALSE;
   4.130 +  ULONG qemu_hide_flags_value = 0;
   4.131 +
   4.132 +  xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   4.133 +  xvdd->sring = NULL;
   4.134 +  xvdd->event_channel = 0;
   4.135 +  
   4.136 +  xvdd->inactive = TRUE;  
   4.137 +  ptr = xvdd->device_base;
   4.138 +  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   4.139 +  {
   4.140 +    switch(type)
   4.141 +    {
   4.142 +    case XEN_INIT_TYPE_RING: /* frontend ring */
   4.143 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   4.144 +      if (strcmp(setting, "ring-ref") == 0)
   4.145 +      {
   4.146 +        xvdd->sring = (blkif_sring_t *)value;
   4.147 +        FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
   4.148 +        /* this bit is for when we have to take over an existing ring on a crash dump */
   4.149 +        xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
   4.150 +        xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
   4.151 +      }
   4.152 +      break;
   4.153 +    case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   4.154 +    case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
   4.155 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
   4.156 +      if (strcmp(setting, "event-channel") == 0)
   4.157 +      {
   4.158 +        /* cheat here - save the state of the ring in the topmost bits of the event-channel */
   4.159 +        xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
   4.160 +        xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
   4.161 +        if (PtrToUlong(value) & 0x80000000)
   4.162 +        {
   4.163 +          xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
   4.164 +          KdPrint((__DRIVER_NAME "     cached_use_other = %d\n", xvdd->cached_use_other));
   4.165 +        }
   4.166 +      }
   4.167 +      break;
   4.168 +    case XEN_INIT_TYPE_READ_STRING_BACK:
   4.169 +    case XEN_INIT_TYPE_READ_STRING_FRONT:
   4.170 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   4.171 +      if (strcmp(setting, "sectors") == 0)
   4.172 +        xvdd->total_sectors = parse_numeric_string(value);
   4.173 +      else if (strcmp(setting, "sector-size") == 0)
   4.174 +        xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
   4.175 +      else if (strcmp(setting, "device-type") == 0)
   4.176 +      {
   4.177 +        if (strcmp(value, "disk") == 0)
   4.178 +        {
   4.179 +          KdPrint((__DRIVER_NAME "     device-type = Disk\n"));    
   4.180 +          xvdd->device_type = XENVBD_DEVICETYPE_DISK;
   4.181 +        }
   4.182 +        else if (strcmp(value, "cdrom") == 0)
   4.183 +        {
   4.184 +          KdPrint((__DRIVER_NAME "     device-type = CDROM\n"));    
   4.185 +          xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
   4.186 +        }
   4.187 +        else
   4.188 +        {
   4.189 +          KdPrint((__DRIVER_NAME "     device-type = %s (This probably won't work!)\n", value));
   4.190 +          xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   4.191 +        }
   4.192 +      }
   4.193 +      else if (strcmp(setting, "mode") == 0)
   4.194 +      {
   4.195 +        if (strncmp(value, "r", 1) == 0)
   4.196 +        {
   4.197 +          KdPrint((__DRIVER_NAME "     mode = r\n"));    
   4.198 +          xvdd->device_mode = XENVBD_DEVICEMODE_READ;
   4.199 +        }
   4.200 +        else if (strncmp(value, "w", 1) == 0)
   4.201 +        {
   4.202 +          KdPrint((__DRIVER_NAME "     mode = w\n"));    
   4.203 +          xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
   4.204 +        }
   4.205 +        else
   4.206 +        {
   4.207 +          KdPrint((__DRIVER_NAME "     mode = unknown\n"));
   4.208 +          xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
   4.209 +        }
   4.210 +      }
   4.211 +      break;
   4.212 +    case XEN_INIT_TYPE_VECTORS:
   4.213 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   4.214 +      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   4.215 +        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   4.216 +      {
   4.217 +        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   4.218 +          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   4.219 +        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.220 +        return SP_RETURN_BAD_CONFIG;
   4.221 +      }
   4.222 +      else
   4.223 +        memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
   4.224 +      break;
   4.225 +    case XEN_INIT_TYPE_STATE_PTR:
   4.226 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   4.227 +      xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
   4.228 +      break;
   4.229 +    case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
   4.230 +      qemu_protocol_version = PtrToUlong(value);
   4.231 +      break;
   4.232 +    case XEN_INIT_TYPE_GRANT_ENTRIES:
   4.233 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - entries = %d\n", PtrToUlong(setting)));
   4.234 +      memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * sizeof(grant_ref_t));
   4.235 +      break;
   4.236 +    case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   4.237 +      qemu_hide_flags_value = PtrToUlong(value);
   4.238 +      KdPrint((__DRIVER_NAME "     qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
   4.239 +      break;
   4.240 +    case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
   4.241 +      qemu_hide_filter = TRUE;
   4.242 +      KdPrint((__DRIVER_NAME "     qemu_hide_filter = TRUE\n"));
   4.243 +      break;
   4.244 +    default:
   4.245 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   4.246 +      break;
   4.247 +    }
   4.248 +  }
   4.249 +  
   4.250 +  if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
   4.251 +    xvdd->inactive = FALSE;
   4.252 +  
   4.253 +  if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
   4.254 +      || xvdd->sring == NULL
   4.255 +      || xvdd->event_channel == 0
   4.256 +      || xvdd->total_sectors == 0
   4.257 +      || xvdd->bytes_per_sector == 0))
   4.258 +  {
   4.259 +    KdPrint((__DRIVER_NAME "     Missing settings\n"));
   4.260 +    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.261 +    return SP_RETURN_BAD_CONFIG;
   4.262 +  }
   4.263 +
   4.264 +  if (xvdd->inactive)
   4.265 +    KdPrint((__DRIVER_NAME "     Device is inactive\n"));
   4.266 +  else
   4.267 +  {
   4.268 +    if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
   4.269 +    {
   4.270 +      /* CD/DVD drives must have bytes_per_sector = 2048. */
   4.271 +      xvdd->bytes_per_sector = 2048;
   4.272 +    }
   4.273 +
   4.274 +    /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
   4.275 +    xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
   4.276 +
   4.277 +    xvdd->shadow_free = 0;
   4.278 +    memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
   4.279 +    for (i = 0; i < SHADOW_ENTRIES; i++)
   4.280 +    {
   4.281 +      xvdd->shadows[i].req.id = i;
   4.282 +      put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
   4.283 +    }
   4.284 +  }
   4.285 +  
   4.286 +  return SP_RETURN_FOUND;
   4.287 +}
   4.288 +
   4.289 +static __inline ULONG
   4.290 +decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
   4.291 +{
   4.292 +  switch (srb->Cdb[0])
   4.293 +  {
   4.294 +  case SCSIOP_READ:
   4.295 +  case SCSIOP_WRITE:
   4.296 +    return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
   4.297 +  case SCSIOP_READ16:
   4.298 +  case SCSIOP_WRITE16:
   4.299 +    return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];    
   4.300 +  default:
   4.301 +    return 0;
   4.302 +  }
   4.303 +}
   4.304 +
   4.305 +static __inline ULONGLONG
   4.306 +decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
   4.307 +{
   4.308 +  ULONGLONG sector;
   4.309 +  
   4.310 +  switch (srb->Cdb[0])
   4.311 +  {
   4.312 +  case SCSIOP_READ:
   4.313 +  case SCSIOP_WRITE:
   4.314 +    sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
   4.315 +    break;
   4.316 +  case SCSIOP_READ16:
   4.317 +  case SCSIOP_WRITE16:
   4.318 +    sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
   4.319 +           | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
   4.320 +           | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
   4.321 +           | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
   4.322 +    //KdPrint((__DRIVER_NAME "     sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
   4.323 +    break;
   4.324 +  default:
   4.325 +    sector = 0;
   4.326 +    break;
   4.327 +  }
   4.328 +  return sector;
   4.329 +}
   4.330 +
   4.331 +static __inline BOOLEAN
   4.332 +decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
   4.333 +{
   4.334 +  switch (srb->Cdb[0])
   4.335 +  {
   4.336 +  case SCSIOP_READ:
   4.337 +  case SCSIOP_READ16:
   4.338 +    return TRUE;
   4.339 +  case SCSIOP_WRITE:
   4.340 +  case SCSIOP_WRITE16:
   4.341 +    return FALSE;
   4.342 +  default:
   4.343 +    return FALSE;
   4.344 +  }
   4.345 +}
   4.346 +
   4.347 +ULONG max_dump_mode_blocks = 0;
   4.348 +ULONG max_dump_mode_length = 0;
   4.349 +
   4.350 +static VOID
   4.351 +XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   4.352 +{
   4.353 +  srb_list_entry_t *list_entry = srb->SrbExtension;
   4.354 +  list_entry->srb = srb;
   4.355 +  InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)list_entry);
   4.356 +}
   4.357 +
   4.358 +static VOID
   4.359 +XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
   4.360 +{
   4.361 +  PSCSI_REQUEST_BLOCK srb;
   4.362 +  srb_list_entry_t *srb_entry;
   4.363 +  ULONGLONG sector_number;
   4.364 +  ULONG block_count;
   4.365 +  blkif_shadow_t *shadow;
   4.366 +  ULONG remaining, offset, length;
   4.367 +  grant_ref_t gref;
   4.368 +  PUCHAR ptr;
   4.369 +  int notify;
   4.370 +  int i;
   4.371 +
   4.372 +  //FUNCTION_ENTER();
   4.373 +
   4.374 +  while(!xvdd->aligned_buffer_in_use && xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
   4.375 +  {
   4.376 +    srb = srb_entry->srb;
   4.377 +    block_count = decode_cdb_length(srb);;
   4.378 +    block_count *= xvdd->bytes_per_sector / 512;
   4.379 +    sector_number = decode_cdb_sector(srb);
   4.380 +    sector_number *= xvdd->bytes_per_sector / 512;
   4.381 +    
   4.382 +    /* look for pending writes that overlap this one */
   4.383 +    /* we get warnings from drbd if we don't */
   4.384 +    for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
   4.385 +    {
   4.386 +      PSCSI_REQUEST_BLOCK srb2;
   4.387 +      ULONGLONG sector_number2;
   4.388 +      ULONG block_count2;
   4.389 +      
   4.390 +      srb2 = xvdd->shadows[i].srb;
   4.391 +      if (!srb2)
   4.392 +        continue;
   4.393 +      if (decode_cdb_is_read(srb2))
   4.394 +        continue;
   4.395 +      block_count2 = decode_cdb_length(srb2);;
   4.396 +      block_count2 *= xvdd->bytes_per_sector / 512;
   4.397 +      sector_number2 = decode_cdb_sector(srb2);
   4.398 +      sector_number2 *= xvdd->bytes_per_sector / 512;
   4.399 +      
   4.400 +      if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
   4.401 +        continue;
   4.402 +      if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
   4.403 +        continue;
   4.404 +
   4.405 +#if 0
   4.406 +      /* check if the data being written is identical to the data in the pipe */
   4.407 +      {
   4.408 +        PUCHAR buf, buf2;
   4.409 +        ULONG byte_count;
   4.410 +        int j;
   4.411 +
   4.412 +        buf = (PUCHAR)srb->DataBuffer + (max(sector_number, sector_number2) - sector_number) * xvdd->bytes_per_sector;
   4.413 +        buf2 = (PUCHAR)srb2->DataBuffer + (max(sector_number, sector_number2) - sector_number2) * xvdd->bytes_per_sector;
   4.414 +        byte_count = (ULONG)(min(sector_number + block_count, sector_number2 + block_count2) - max(sector_number, sector_number2)) * xvdd->bytes_per_sector;
   4.415 +        for (j = 0; j < (int)byte_count; j++)
   4.416 +        {
   4.417 +          if (buf[j] != buf2[j])
   4.418 +            break;
   4.419 +        }
   4.420 +      }
   4.421 +#endif
   4.422 +
   4.423 +      KdPrint((__DRIVER_NAME "     Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
   4.424 +        sector_number, block_count, sector_number2, block_count2));
   4.425 +      /* put the srb back at the start of the queue */
   4.426 +      InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   4.427 +      return; /* stall the queue */
   4.428 +    }
   4.429 +
   4.430 +    remaining = block_count * 512;
   4.431 +    shadow = get_shadow_from_freelist(xvdd);
   4.432 +    ASSERT(shadow);
   4.433 +    ASSERT(!shadow->aligned_buffer_in_use);
   4.434 +    ASSERT(!shadow->srb);
   4.435 +    shadow->req.sector_number = sector_number;
   4.436 +    shadow->req.handle = 0;
   4.437 +    shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
   4.438 +    shadow->req.nr_segments = 0;
   4.439 +    shadow->srb = srb;
   4.440 +
   4.441 +    if ((ULONG_PTR)srb->DataBuffer & 511)
   4.442 +    {
   4.443 +      if (dump_mode)
   4.444 +        KdPrint((__DRIVER_NAME "     unaligned dump mode buffer = %d bytes\n", block_count * 512));
   4.445 +      ASSERT(!dump_mode || block_count * 512 < BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE);
   4.446 +      xvdd->aligned_buffer_in_use = TRUE;
   4.447 +      ptr = xvdd->aligned_buffer;
   4.448 +      if (!decode_cdb_is_read(srb))
   4.449 +        memcpy(ptr, srb->DataBuffer, block_count * 512);
   4.450 +      shadow->aligned_buffer_in_use = TRUE;
   4.451 +    }
   4.452 +    else
   4.453 +    {
   4.454 +      ptr = srb->DataBuffer;
   4.455 +      shadow->aligned_buffer_in_use = FALSE;
   4.456 +    }
   4.457 +
   4.458 +    if (dump_mode && block_count > max_dump_mode_blocks)
   4.459 +    {
   4.460 +      max_dump_mode_blocks = block_count;
   4.461 +      KdPrint((__DRIVER_NAME "     max_dump_mode_blocks = %d\n", max_dump_mode_blocks));
   4.462 +    }
   4.463 +    if (dump_mode && srb->DataTransferLength > max_dump_mode_length)
   4.464 +    {
   4.465 +      max_dump_mode_length = srb->DataTransferLength;
   4.466 +      KdPrint((__DRIVER_NAME "     max_dump_mode_length = %d\n", max_dump_mode_length));
   4.467 +    }
   4.468 +
   4.469 +    //KdPrint((__DRIVER_NAME "     sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
   4.470 +    //KdPrint((__DRIVER_NAME "     SrbExtension = %p\n", srb->SrbExtension));
   4.471 +    //KdPrint((__DRIVER_NAME "     DataBuffer   = %p\n", srb->DataBuffer));
   4.472 +
   4.473 +    //KdPrint((__DRIVER_NAME "     sector_number = %d\n", (ULONG)shadow->req.sector_number));
   4.474 +    //KdPrint((__DRIVER_NAME "     handle = %d\n", shadow->req.handle));
   4.475 +    //KdPrint((__DRIVER_NAME "     operation = %d\n", shadow->req.operation));
   4.476 +    
   4.477 +    while (remaining > 0)
   4.478 +    {
   4.479 +      PHYSICAL_ADDRESS physical_address = MmGetPhysicalAddress(ptr);
   4.480 +      
   4.481 +      if (dump_mode)
   4.482 +      {
   4.483 +        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   4.484 +                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE,
   4.485 +                 xvdd->dump_grant_refs[shadow->req.nr_segments], (ULONG)'XPDO');
   4.486 +      }
   4.487 +      else
   4.488 +      {
   4.489 +        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   4.490 +                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XVBD');
   4.491 +      }
   4.492 +      if (gref == INVALID_GRANT_REF)
   4.493 +      {
   4.494 +        ULONG i;
   4.495 +        for (i = 0; i < shadow->req.nr_segments; i++)
   4.496 +        {
   4.497 +          xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
   4.498 +            shadow->req.seg[i].gref, FALSE, (ULONG)'XVBD');
   4.499 +        }
   4.500 +        if (shadow->aligned_buffer_in_use)
   4.501 +        {
   4.502 +          shadow->aligned_buffer_in_use = FALSE;
   4.503 +          xvdd->aligned_buffer_in_use = FALSE;
   4.504 +        }
   4.505 +        /* put the srb back at the start of the queue */
   4.506 +        InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   4.507 +        put_shadow_on_freelist(xvdd, shadow);
   4.508 +        KdPrint((__DRIVER_NAME "     Out of gref's. Deferring\n"));
   4.509 +        return;
   4.510 +      }
   4.511 +      offset = physical_address.LowPart & (PAGE_SIZE - 1);
   4.512 +      length = min(PAGE_SIZE - offset, remaining);
   4.513 +      ASSERT((offset & 511) == 0);
   4.514 +      ASSERT((length & 511) == 0);
   4.515 +      ASSERT(offset + length <= PAGE_SIZE);
   4.516 +      shadow->req.seg[shadow->req.nr_segments].gref = gref;
   4.517 +      shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
   4.518 +      shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
   4.519 +      remaining -= length;
   4.520 +      ptr += length;
   4.521 +      shadow->req.nr_segments++;
   4.522 +    }
   4.523 +
   4.524 +    //KdPrint((__DRIVER_NAME "     nr_segments = %d\n", shadow->req.nr_segments));
   4.525 +
   4.526 +    XenVbd_PutRequest(xvdd, &shadow->req);
   4.527 +
   4.528 +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   4.529 +    if (notify)
   4.530 +    {
   4.531 +      //KdPrint((__DRIVER_NAME "     Notifying\n"));
   4.532 +      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   4.533 +    }
   4.534 +  }
   4.535 +  if (xvdd->shadow_free && !xvdd->aligned_buffer_in_use)
   4.536 +  {
   4.537 +    ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
   4.538 +  }
   4.539 +  //FUNCTION_EXIT();
   4.540 +}
   4.541 +
   4.542 +static ULONG DDKAPI
   4.543 +XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
   4.544 +{
   4.545 +//  PACCESS_RANGE AccessRange;
   4.546 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   4.547 +  ULONG status;
   4.548 +//  PXENPCI_XEN_DEVICE_DATA XenDeviceData;
   4.549 +  PACCESS_RANGE access_range;
   4.550 +
   4.551 +  UNREFERENCED_PARAMETER(HwContext);
   4.552 +  UNREFERENCED_PARAMETER(BusInformation);
   4.553 +  UNREFERENCED_PARAMETER(ArgumentString);
   4.554 +
   4.555 +  FUNCTION_ENTER(); 
   4.556 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   4.557 +  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
   4.558 +
   4.559 +  RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
   4.560 +  *Again = FALSE;
   4.561 +
   4.562 +  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
   4.563 +  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
   4.564 +
   4.565 +  KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));    
   4.566 +  if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
   4.567 +  {
   4.568 +    return SP_RETURN_BAD_CONFIG;
   4.569 +  }
   4.570 +
   4.571 +  access_range = &((*(ConfigInfo->AccessRanges))[0]);
   4.572 +  KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
   4.573 +    access_range->RangeStart.LowPart, access_range->RangeLength));
   4.574 +  xvdd->device_base = ScsiPortGetDeviceBase(
   4.575 +    DeviceExtension,
   4.576 +    ConfigInfo->AdapterInterfaceType,
   4.577 +    ConfigInfo->SystemIoBusNumber,
   4.578 +    access_range->RangeStart,
   4.579 +    access_range->RangeLength,
   4.580 +    !access_range->RangeInMemory);
   4.581 +  if (!xvdd->device_base)
   4.582 +  {
   4.583 +    KdPrint((__DRIVER_NAME "     Invalid config\n"));
   4.584 +    FUNCTION_EXIT(); 
   4.585 +    return SP_RETURN_BAD_CONFIG;
   4.586 +  }
   4.587 +  
   4.588 +  status = XenVbd_InitFromConfig(xvdd);
   4.589 +  if (status != SP_RETURN_FOUND)
   4.590 +  {
   4.591 +    FUNCTION_EXIT();
   4.592 +    return status;
   4.593 +  }
   4.594 +
   4.595 +  xvdd->aligned_buffer_in_use = FALSE;
   4.596 +  /* align the buffer to PAGE_SIZE */
   4.597 +  xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
   4.598 +  KdPrint((__DRIVER_NAME "     aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
   4.599 +  KdPrint((__DRIVER_NAME "     aligned_buffer = %p\n", xvdd->aligned_buffer));
   4.600 +
   4.601 +  if (!dump_mode)
   4.602 +  {
   4.603 +    ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
   4.604 +    ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
   4.605 +    //ConfigInfo->ScatterGather = TRUE;
   4.606 +  }
   4.607 +  else
   4.608 +  {
   4.609 +    ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE;
   4.610 +    ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE - 1;
   4.611 +    //ConfigInfo->ScatterGather = FALSE;
   4.612 +  }
   4.613 +  KdPrint((__DRIVER_NAME "     ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength));
   4.614 +  KdPrint((__DRIVER_NAME "     ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks));
   4.615 +  ConfigInfo->ScatterGather = FALSE;
   4.616 +  ConfigInfo->AlignmentMask = 0;
   4.617 +  ConfigInfo->NumberOfBuses = 1;
   4.618 +  ConfigInfo->InitiatorBusId[0] = 1;
   4.619 +  ConfigInfo->MaximumNumberOfLogicalUnits = 1;
   4.620 +  ConfigInfo->MaximumNumberOfTargets = 2;
   4.621 +  KdPrint((__DRIVER_NAME "     ConfigInfo->CachesData was initialised to %d\n", ConfigInfo->CachesData));
   4.622 +  ConfigInfo->CachesData = FALSE;
   4.623 +  ConfigInfo->BufferAccessScsiPortControlled = FALSE;
   4.624 +  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
   4.625 +  {
   4.626 +    ConfigInfo->Master = TRUE;
   4.627 +    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
   4.628 +    ConfigInfo->Dma32BitAddresses = FALSE;
   4.629 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
   4.630 +  }
   4.631 +  else
   4.632 +  {
   4.633 +    ConfigInfo->Master = TRUE;
   4.634 +    ConfigInfo->Dma32BitAddresses = TRUE;
   4.635 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
   4.636 +  }
   4.637 +
   4.638 +  FUNCTION_EXIT();
   4.639 +
   4.640 +  return SP_RETURN_FOUND;
   4.641 +}
   4.642 +
   4.643 +static VOID
   4.644 +XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
   4.645 +{
   4.646 +  blkif_request_t *req;
   4.647 +  int notify;
   4.648 +
   4.649 +  xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
   4.650 +  RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
   4.651 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   4.652 +  req->operation = 0xff;
   4.653 +  xvdd->ring.req_prod_pvt++;
   4.654 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   4.655 +  req->operation = 0xff;
   4.656 +  xvdd->ring.req_prod_pvt++;
   4.657 +
   4.658 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   4.659 +  if (notify)
   4.660 +    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   4.661 +}
   4.662 +
   4.663 +static BOOLEAN
   4.664 +XenVbd_HwScsiInitialize(PVOID DeviceExtension)
   4.665 +{
   4.666 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   4.667 +  
   4.668 +  FUNCTION_ENTER();
   4.669 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   4.670 +  KdPrint((__DRIVER_NAME "     dump_mode = %d\n", dump_mode));
   4.671 +
   4.672 +  if (!xvdd->inactive)
   4.673 +  {
   4.674 +    if (!dump_mode)
   4.675 +    {
   4.676 +      XenVbd_StartRingDetection(xvdd);
   4.677 +    }
   4.678 +    else
   4.679 +    {
   4.680 +      if (xvdd->cached_use_other)
   4.681 +      {
   4.682 +        xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   4.683 +        xvdd->use_other = TRUE;
   4.684 +      }
   4.685 +      xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
   4.686 +    }
   4.687 +    InitializeListHead(&xvdd->srb_list);
   4.688 +  }
   4.689 +  FUNCTION_EXIT();
   4.690 +
   4.691 +  return TRUE;
   4.692 +}
   4.693 +
   4.694 +static ULONG
   4.695 +XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   4.696 +{
   4.697 +  PMODE_PARAMETER_HEADER parameter_header = NULL;
   4.698 +  PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
   4.699 +  PMODE_PARAMETER_BLOCK param_block;
   4.700 +  PMODE_FORMAT_PAGE format_page;
   4.701 +  ULONG offset = 0;
   4.702 +  UCHAR buffer[1024];
   4.703 +  BOOLEAN valid_page = FALSE;
   4.704 +  BOOLEAN cdb_llbaa;
   4.705 +  BOOLEAN cdb_dbd;
   4.706 +  UCHAR cdb_page_code;
   4.707 +  USHORT cdb_allocation_length;
   4.708 +
   4.709 +  UNREFERENCED_PARAMETER(xvdd);
   4.710 +
   4.711 +  RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
   4.712 +  RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
   4.713 +  offset = 0;
   4.714 +
   4.715 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   4.716 +  
   4.717 +  switch (srb->Cdb[0])
   4.718 +  {
   4.719 +  case SCSIOP_MODE_SENSE:
   4.720 +    cdb_llbaa = FALSE;
   4.721 +    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   4.722 +    cdb_page_code = srb->Cdb[2] & 0x3f;
   4.723 +    cdb_allocation_length = srb->Cdb[4];
   4.724 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   4.725 +      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   4.726 +    parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
   4.727 +    parameter_header->MediumType = 0;
   4.728 +    parameter_header->DeviceSpecificParameter = 0;
   4.729 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   4.730 +    {
   4.731 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   4.732 +      parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   4.733 +    }
   4.734 +    offset += sizeof(MODE_PARAMETER_HEADER);
   4.735 +    break;
   4.736 +  case SCSIOP_MODE_SENSE10:
   4.737 +    cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
   4.738 +    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   4.739 +    cdb_page_code = srb->Cdb[2] & 0x3f;
   4.740 +    cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
   4.741 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   4.742 +      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   4.743 +    parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
   4.744 +    parameter_header10->MediumType = 0;
   4.745 +    parameter_header10->DeviceSpecificParameter = 0;
   4.746 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   4.747 +    {
   4.748 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   4.749 +      parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   4.750 +    }
   4.751 +    offset += sizeof(MODE_PARAMETER_HEADER10);
   4.752 +    break;
   4.753 +  default:
   4.754 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
   4.755 +    return FALSE;
   4.756 +  }  
   4.757 +  
   4.758 +  if (!cdb_dbd)
   4.759 +  {
   4.760 +    param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
   4.761 +    if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
   4.762 +    {
   4.763 +      if (xvdd->total_sectors >> 32) 
   4.764 +      {
   4.765 +        param_block->DensityCode = 0xff;
   4.766 +        param_block->NumberOfBlocks[0] = 0xff;
   4.767 +        param_block->NumberOfBlocks[1] = 0xff;
   4.768 +        param_block->NumberOfBlocks[2] = 0xff;
   4.769 +      }
   4.770 +      else
   4.771 +      {
   4.772 +        param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
   4.773 +        param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
   4.774 +        param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
   4.775 +        param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
   4.776 +      }
   4.777 +      param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
   4.778 +      param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
   4.779 +      param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
   4.780 +    }
   4.781 +    offset += sizeof(MODE_PARAMETER_BLOCK);
   4.782 +  }
   4.783 +  switch (srb->Cdb[0])
   4.784 +  {
   4.785 +  case SCSIOP_MODE_SENSE:
   4.786 +    parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
   4.787 +    break;
   4.788 +  case SCSIOP_MODE_SENSE10:
   4.789 +    parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
   4.790 +    parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
   4.791 +    break;
   4.792 +  }
   4.793 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
   4.794 +  {
   4.795 +    valid_page = TRUE;
   4.796 +    format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
   4.797 +    format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
   4.798 +    format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
   4.799 +    /* 256 sectors per track */
   4.800 +    format_page->SectorsPerTrack[0] = 0x01;
   4.801 +    format_page->SectorsPerTrack[1] = 0x00;
   4.802 +    /* xxx bytes per sector */
   4.803 +    format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
   4.804 +    format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
   4.805 +    format_page->HardSectorFormating = TRUE;
   4.806 +    format_page->SoftSectorFormating = TRUE;
   4.807 +    offset += sizeof(MODE_FORMAT_PAGE);
   4.808 +  }
   4.809 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
   4.810 +  {
   4.811 +    PMODE_CACHING_PAGE caching_page;
   4.812 +    valid_page = TRUE;
   4.813 +    caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
   4.814 +    caching_page->PageCode = MODE_PAGE_CACHING;
   4.815 +    caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
   4.816 +    // caching_page-> // all zeros is just fine... maybe
   4.817 +    offset += sizeof(MODE_CACHING_PAGE);
   4.818 +  }
   4.819 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
   4.820 +  {
   4.821 +    PUCHAR medium_types_page;
   4.822 +    valid_page = TRUE;
   4.823 +    medium_types_page = &buffer[offset];
   4.824 +    medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
   4.825 +    medium_types_page[1] = 0x06;
   4.826 +    medium_types_page[2] = 0;
   4.827 +    medium_types_page[3] = 0;
   4.828 +    medium_types_page[4] = 0;
   4.829 +    medium_types_page[5] = 0;
   4.830 +    medium_types_page[6] = 0;
   4.831 +    medium_types_page[7] = 0;
   4.832 +    offset += 8;
   4.833 +  }
   4.834 +  switch (srb->Cdb[0])
   4.835 +  {
   4.836 +  case SCSIOP_MODE_SENSE:
   4.837 +    parameter_header->ModeDataLength = (UCHAR)(offset - 1);
   4.838 +    break;
   4.839 +  case SCSIOP_MODE_SENSE10:
   4.840 +    parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
   4.841 +    parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
   4.842 +    break;
   4.843 +  }
   4.844 +
   4.845 +  if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
   4.846 +  {
   4.847 +    srb->SrbStatus = SRB_STATUS_ERROR;
   4.848 +  }
   4.849 +  else if(offset < srb->DataTransferLength)
   4.850 +    srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
   4.851 +  else
   4.852 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
   4.853 +  srb->DataTransferLength = min(srb->DataTransferLength, offset);
   4.854 +  srb->ScsiStatus = 0;
   4.855 +  memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
   4.856 +  
   4.857 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   4.858 +
   4.859 +  return TRUE;
   4.860 +}
   4.861 +
   4.862 +static VOID
   4.863 +XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
   4.864 +{
   4.865 +  PSENSE_DATA sd = srb->SenseInfoBuffer;
   4.866 + 
   4.867 +  UNREFERENCED_PARAMETER(xvdd);
   4.868 +  
   4.869 +  if (!srb->SenseInfoBuffer)
   4.870 +    return;
   4.871 +  
   4.872 +  sd->ErrorCode = 0x70;
   4.873 +  sd->Valid = 1;
   4.874 +  sd->SenseKey = sense_key;
   4.875 +  sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
   4.876 +  sd->AdditionalSenseCode = additional_sense_code;
   4.877 +  return;
   4.878 +}
   4.879 +
   4.880 +static VOID
   4.881 +XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   4.882 +{
   4.883 +  if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
   4.884 +    return;
   4.885 +  XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
   4.886 +  srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
   4.887 +}
   4.888 +
   4.889 +static BOOLEAN DDKAPI
   4.890 +XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
   4.891 +{
   4.892 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   4.893 +  PSCSI_REQUEST_BLOCK srb;
   4.894 +  RING_IDX i, rp;
   4.895 +  ULONG j;
   4.896 +  blkif_response_t *rep;
   4.897 +  int block_count;
   4.898 +  int more_to_do = TRUE;
   4.899 +  blkif_shadow_t *shadow;
   4.900 +  ULONG suspend_resume_state_pdo;
   4.901 +  BOOLEAN last_interrupt = FALSE;
   4.902 +  ULONG start_ring_detect_state = xvdd->ring_detect_state;
   4.903 +
   4.904 +  /* in dump mode I think we get called on a timer, not by an actual IRQ */
   4.905 +  if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
   4.906 +    return FALSE; /* interrupt was not for us */
   4.907 +
   4.908 +  suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
   4.909 +  KeMemoryBarrier();
   4.910 +
   4.911 +  if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
   4.912 +  {
   4.913 +    FUNCTION_ENTER();
   4.914 +    switch (suspend_resume_state_pdo)
   4.915 +    {
   4.916 +      case SR_STATE_SUSPENDING:
   4.917 +        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_SUSPENDING\n"));
   4.918 +        break;
   4.919 +      case SR_STATE_RESUMING:
   4.920 +        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_RESUMING\n"));
   4.921 +        XenVbd_InitFromConfig(xvdd);
   4.922 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   4.923 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   4.924 +        break;
   4.925 +      case SR_STATE_RUNNING:
   4.926 +        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
   4.927 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   4.928 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   4.929 +        ScsiPortNotification(NextRequest, DeviceExtension);
   4.930 +      default:
   4.931 +        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
   4.932 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
   4.933 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
   4.934 +        break;
   4.935 +    }
   4.936 +    KeMemoryBarrier();
   4.937 +  }
   4.938 +
   4.939 +  if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
   4.940 +  {
   4.941 +    return last_interrupt;
   4.942 +  }
   4.943 +
   4.944 +  while (more_to_do)
   4.945 +  {
   4.946 +    rp = xvdd->ring.sring->rsp_prod;
   4.947 +    KeMemoryBarrier();
   4.948 +    for (i = xvdd->ring.rsp_cons; i < rp; i++)
   4.949 +    {
   4.950 +      rep = XenVbd_GetResponse(xvdd, i);
   4.951 +/*
   4.952 +* This code is to automatically detect if the backend is using the same
   4.953 +* bit width or a different bit width to us. Later versions of Xen do this
   4.954 +* via a xenstore value, but not all. That 0x0fffffff (notice
   4.955 +* that the msb is not actually set, so we don't have any problems with
   4.956 +* sign extending) is to signify the last entry on the right, which is
   4.957 +* different under 32 and 64 bits, and that is why we set it up there.
   4.958 +
   4.959 +* To do the detection, we put two initial entries on the ring, with an op
   4.960 +* of 0xff (which is invalid). The first entry is mostly okay, but the
   4.961 +* second will be grossly misaligned if the backend bit width is different,
   4.962 +* and we detect this and switch frontend structures.
   4.963 +*/
   4.964 +      switch (xvdd->ring_detect_state)
   4.965 +      {
   4.966 +      case RING_DETECT_STATE_NOT_STARTED:
   4.967 +        KdPrint((__DRIVER_NAME "     premature IRQ\n"));
   4.968 +        break;
   4.969 +      case RING_DETECT_STATE_DETECT1:
   4.970 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
   4.971 +        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
   4.972 +        xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
   4.973 +        break;
   4.974 +      case RING_DETECT_STATE_DETECT2:
   4.975 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
   4.976 +        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
   4.977 +        *xvdd->event_channel_ptr |= 0x80000000;
   4.978 +        if (rep->operation != 0xff)
   4.979 +        {
   4.980 +          KdPrint((__DRIVER_NAME "     switching to 'other' ring size\n"));
   4.981 +          xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   4.982 +          xvdd->use_other = TRUE;
   4.983 +          *xvdd->event_channel_ptr |= 0x40000000;
   4.984 +        }
   4.985 +        xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
   4.986 +        ScsiPortNotification(NextRequest, DeviceExtension);
   4.987 +        break;
   4.988 +      case RING_DETECT_STATE_COMPLETE:
   4.989 +        shadow = &xvdd->shadows[rep->id];
   4.990 +        srb = shadow->srb;
   4.991 +        ASSERT(srb != NULL);
   4.992 +        block_count = decode_cdb_length(srb);
   4.993 +        block_count *= xvdd->bytes_per_sector / 512;
   4.994 +        /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
   4.995 +        if (rep->status == BLKIF_RSP_OKAY || (dump_mode &&  dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
   4.996 +          srb->SrbStatus = SRB_STATUS_SUCCESS;
   4.997 +        else
   4.998 +        {
   4.999 +          KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
  4.1000 +          if (decode_cdb_is_read(srb))
  4.1001 +            KdPrint((__DRIVER_NAME "     Operation = Read\n"));
  4.1002 +          else
  4.1003 +            KdPrint((__DRIVER_NAME "     Operation = Write\n"));
  4.1004 +          if (dump_mode)
  4.1005 +          {
  4.1006 +            KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
  4.1007 +            KdPrint((__DRIVER_NAME "     DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
  4.1008 +            KdPrint((__DRIVER_NAME "     Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
  4.1009 +            KdPrint((__DRIVER_NAME "     PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
  4.1010 +
  4.1011 +            for (j = 0; j < shadow->req.nr_segments; j++)
  4.1012 +            {
  4.1013 +              KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[j].gref));
  4.1014 +              KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[j].first_sect));
  4.1015 +              KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[j].last_sect));
  4.1016 +            }
  4.1017 +          }
  4.1018 +          srb->SrbStatus = SRB_STATUS_ERROR;
  4.1019 +          srb->ScsiStatus = 0x02;
  4.1020 +          xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
  4.1021 +          xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  4.1022 +          XenVbd_MakeAutoSense(xvdd, srb);
  4.1023 +        }
  4.1024 +        if (shadow->aligned_buffer_in_use)
  4.1025 +        {
  4.1026 +          ASSERT(xvdd->aligned_buffer_in_use);
  4.1027 +          xvdd->aligned_buffer_in_use = FALSE;
  4.1028 +          if (decode_cdb_is_read(srb))
  4.1029 +            memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
  4.1030 +//KdPrint((__DRIVER_NAME "     Completed use of buffer\n"));
  4.1031 +        }
  4.1032 +        
  4.1033 +#if 0
  4.1034 +if (xvdd->aligned_buffer_in_use)
  4.1035 +{
  4.1036 +KdPrint((__DRIVER_NAME "     Completed request while aligned buffer in use\n"));
  4.1037 +}
  4.1038 +#endif
  4.1039 +        for (j = 0; j < shadow->req.nr_segments; j++)
  4.1040 +        {
  4.1041 +          if (dump_mode)
  4.1042 +          {
  4.1043 +            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  4.1044 +              shadow->req.seg[j].gref, TRUE, (ULONG)'XPDO');
  4.1045 +          }
  4.1046 +          else
  4.1047 +          {
  4.1048 +            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  4.1049 +              shadow->req.seg[j].gref, FALSE, (ULONG)'XVBD');
  4.1050 +          }
  4.1051 +        }
  4.1052 +        shadow->aligned_buffer_in_use = FALSE;
  4.1053 +        shadow->srb = NULL;
  4.1054 +        put_shadow_on_freelist(xvdd, shadow);
  4.1055 +        //KdPrint((__DRIVER_NAME "     B RequestComplete srb = %p\n", srb));
  4.1056 +        ScsiPortNotification(RequestComplete, xvdd, srb);
  4.1057 +        break;
  4.1058 +      }
  4.1059 +    }
  4.1060 +
  4.1061 +    xvdd->ring.rsp_cons = i;
  4.1062 +    if (i != xvdd->ring.req_prod_pvt)
  4.1063 +    {
  4.1064 +      RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
  4.1065 +    }
  4.1066 +    else
  4.1067 +    {
  4.1068 +      xvdd->ring.sring->rsp_event = i + 1;
  4.1069 +      more_to_do = FALSE;
  4.1070 +    }
  4.1071 +  }
  4.1072 +
  4.1073 +  if (start_ring_detect_state == RING_DETECT_STATE_COMPLETE)
  4.1074 +    XenVbd_PutQueuedSrbsOnRing(xvdd);
  4.1075 +
  4.1076 +  if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
  4.1077 +  {
  4.1078 +    if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
  4.1079 +    {
  4.1080 +      /* all entries are purged from the list (or we are inactive). ready to suspend */
  4.1081 +      xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  4.1082 +      KeMemoryBarrier();
  4.1083 +      KdPrint((__DRIVER_NAME "     Set fdo state SR_STATE_SUSPENDING\n"));
  4.1084 +      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
  4.1085 +      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  4.1086 +    }
  4.1087 +    FUNCTION_EXIT();
  4.1088 +  }
  4.1089 +
  4.1090 +  return last_interrupt;
  4.1091 +}
  4.1092 +
  4.1093 +static BOOLEAN DDKAPI
  4.1094 +XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
  4.1095 +{
  4.1096 +  PUCHAR data_buffer;
  4.1097 +  //ULONG data_buffer_length;
  4.1098 +  PCDB cdb;
  4.1099 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  4.1100 +  ULONG data_transfer_length = srb->DataTransferLength;
  4.1101 +
  4.1102 +  if (xvdd->inactive)
  4.1103 +  {
  4.1104 +    KdPrint((__DRIVER_NAME "     Inactive srb->Function = %08X\n", srb->Function));
  4.1105 +    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  4.1106 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1107 +    ScsiPortNotification(NextRequest, DeviceExtension);
  4.1108 +    return TRUE;
  4.1109 +  }
  4.1110 +  
  4.1111 +  // If we haven't enumerated all the devices yet then just defer the request
  4.1112 +  if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
  4.1113 +  {
  4.1114 +    srb->SrbStatus = SRB_STATUS_BUSY;
  4.1115 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1116 +    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
  4.1117 +    return TRUE;
  4.1118 +  }
  4.1119 +
  4.1120 +  if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
  4.1121 +  {
  4.1122 +    KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Suspending/Resuming)\n"));
  4.1123 +    srb->SrbStatus = SRB_STATUS_BUSY;
  4.1124 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1125 +    KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Suspending/Resuming)\n"));
  4.1126 +    return TRUE;
  4.1127 +  }
  4.1128 +
  4.1129 +  if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
  4.1130 +  {
  4.1131 +    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  4.1132 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1133 +    ScsiPortNotification(NextRequest, DeviceExtension);
  4.1134 +    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
  4.1135 +    return TRUE;
  4.1136 +  }
  4.1137 +
  4.1138 +  switch (srb->Function)
  4.1139 +  {
  4.1140 +  case SRB_FUNCTION_EXECUTE_SCSI:
  4.1141 +    cdb = (PCDB)srb->Cdb;
  4.1142 +
  4.1143 +    switch(cdb->CDB6GENERIC.OperationCode)
  4.1144 +    {
  4.1145 +    case SCSIOP_TEST_UNIT_READY:
  4.1146 +      if (dump_mode)
  4.1147 +        KdPrint((__DRIVER_NAME "     Command = TEST_UNIT_READY\n"));
  4.1148 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1149 +      srb->ScsiStatus = 0;
  4.1150 +      break;
  4.1151 +    case SCSIOP_INQUIRY:
  4.1152 +      if (dump_mode)
  4.1153 +      {
  4.1154 +        //PHYSICAL_ADDRESS physical;
  4.1155 +        KdPrint((__DRIVER_NAME "     Command = INQUIRY\n"));
  4.1156 +        //KdPrint((__DRIVER_NAME "     srb->Databuffer = %p\n", srb->DataBuffer));
  4.1157 +        //physical = ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length);
  4.1158 +        //KdPrint((__DRIVER_NAME "     ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
  4.1159 +      }
  4.1160 +//      KdPrint((__DRIVER_NAME "     (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
  4.1161 +//      KdPrint((__DRIVER_NAME "     (Length = %d)\n", srb->DataTransferLength));
  4.1162 +      
  4.1163 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  4.1164 +      data_buffer = srb->DataBuffer;
  4.1165 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  4.1166 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1167 +      switch (xvdd->device_type)
  4.1168 +      {
  4.1169 +      case XENVBD_DEVICETYPE_DISK:
  4.1170 +        if ((srb->Cdb[1] & 1) == 0)
  4.1171 +        {
  4.1172 +          if (srb->Cdb[2])
  4.1173 +          {
  4.1174 +            srb->SrbStatus = SRB_STATUS_ERROR;
  4.1175 +          }
  4.1176 +          else
  4.1177 +          {
  4.1178 +            PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  4.1179 +            id->DeviceType = DIRECT_ACCESS_DEVICE;
  4.1180 +            id->Versions = 4; /* minimum that WHQL says we must support */
  4.1181 +            id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
  4.1182 +            id->HiSupport = 1; /* WHQL test says we should set this */
  4.1183 +            //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  4.1184 +            id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
  4.1185 +            id->CommandQueue = 1;
  4.1186 +            memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  4.1187 +            memcpy(id->ProductId, scsi_disk_model, 16); // product id
  4.1188 +            memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  4.1189 +            data_transfer_length = sizeof(INQUIRYDATA);
  4.1190 +          }
  4.1191 +        }
  4.1192 +        else
  4.1193 +        {
  4.1194 +          switch (srb->Cdb[2])
  4.1195 +          {
  4.1196 +          case VPD_SUPPORTED_PAGES: /* list of pages we support */
  4.1197 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  4.1198 +            data_buffer[1] = VPD_SUPPORTED_PAGES;
  4.1199 +            data_buffer[2] = 0x00;
  4.1200 +            data_buffer[3] = 2;
  4.1201 +            data_buffer[4] = 0x00;
  4.1202 +            data_buffer[5] = 0x80;
  4.1203 +            data_transfer_length = 6;
  4.1204 +            break;
  4.1205 +          case VPD_SERIAL_NUMBER: /* serial number */
  4.1206 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  4.1207 +            data_buffer[1] = VPD_SERIAL_NUMBER;
  4.1208 +            data_buffer[2] = 0x00;
  4.1209 +            data_buffer[3] = 8;
  4.1210 +            memset(&data_buffer[4], ' ', 8);
  4.1211 +            data_transfer_length = 12;
  4.1212 +            break;
  4.1213 +          case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
  4.1214 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  4.1215 +            data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
  4.1216 +            data_buffer[2] = 0x00;
  4.1217 +            data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
  4.1218 +            data_buffer[4] = 2; /* ASCII */
  4.1219 +            data_buffer[5] = 1; /* VendorId */
  4.1220 +            data_buffer[6] = 0;
  4.1221 +            data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
  4.1222 +            memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
  4.1223 +            data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
  4.1224 +            break;
  4.1225 +          default:
  4.1226 +            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  4.1227 +            srb->SrbStatus = SRB_STATUS_ERROR;
  4.1228 +            break;
  4.1229 +          }
  4.1230 +        }
  4.1231 +        break;
  4.1232 +      case XENVBD_DEVICETYPE_CDROM:
  4.1233 +        if ((srb->Cdb[1] & 1) == 0)
  4.1234 +        {
  4.1235 +          PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  4.1236 +          id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
  4.1237 +          id->RemovableMedia = 1;
  4.1238 +          id->Versions = 3;
  4.1239 +          id->ResponseDataFormat = 0;
  4.1240 +          id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  4.1241 +          id->CommandQueue = 1;
  4.1242 +          memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  4.1243 +          memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
  4.1244 +          memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  4.1245 +        }
  4.1246 +        else
  4.1247 +        {
  4.1248 +          switch (srb->Cdb[2])
  4.1249 +          {
  4.1250 +          case 0x00:
  4.1251 +            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  4.1252 +            data_buffer[1] = 0x00;
  4.1253 +            data_buffer[2] = 0x00;
  4.1254 +            data_buffer[3] = 2;
  4.1255 +            data_buffer[4] = 0x00;
  4.1256 +            data_buffer[5] = 0x80;
  4.1257 +            break;
  4.1258 +          case 0x80:
  4.1259 +            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  4.1260 +            data_buffer[1] = 0x80;
  4.1261 +            data_buffer[2] = 0x00;
  4.1262 +            data_buffer[3] = 8;
  4.1263 +            data_buffer[4] = 0x31;
  4.1264 +            data_buffer[5] = 0x32;
  4.1265 +            data_buffer[6] = 0x33;
  4.1266 +            data_buffer[7] = 0x34;
  4.1267 +            data_buffer[8] = 0x35;
  4.1268 +            data_buffer[9] = 0x36;
  4.1269 +            data_buffer[10] = 0x37;
  4.1270 +            data_buffer[11] = 0x38;
  4.1271 +            break;
  4.1272 +          default:
  4.1273 +            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  4.1274 +            srb->SrbStatus = SRB_STATUS_ERROR;
  4.1275 +            break;
  4.1276 +          }
  4.1277 +        }
  4.1278 +        break;
  4.1279 +      default:
  4.1280 +        //KdPrint((__DRIVER_NAME "     Unknown DeviceType %02x requested\n", xvdd->device_type));
  4.1281 +        srb->SrbStatus = SRB_STATUS_ERROR;
  4.1282 +        break;
  4.1283 +      }
  4.1284 +      break;
  4.1285 +    case SCSIOP_READ_CAPACITY:
  4.1286 +      if (dump_mode)
  4.1287 +        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  4.1288 +      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  4.1289 +      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  4.1290 +      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  4.1291 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  4.1292 +      data_buffer = srb->DataBuffer;
  4.1293 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  4.1294 +      if ((xvdd->total_sectors - 1) >> 32)
  4.1295 +      {
  4.1296 +        data_buffer[0] = 0xff;
  4.1297 +        data_buffer[1] = 0xff;
  4.1298 +        data_buffer[2] = 0xff;
  4.1299 +        data_buffer[3] = 0xff;
  4.1300 +      }
  4.1301 +      else
  4.1302 +      {
  4.1303 +        data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  4.1304 +        data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  4.1305 +        data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  4.1306 +        data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  4.1307 +      }
  4.1308 +      data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  4.1309 +      data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  4.1310 +      data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  4.1311 +      data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  4.1312 +      srb->ScsiStatus = 0;
  4.1313 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1314 +      break;
  4.1315 +    case SCSIOP_READ_CAPACITY16:
  4.1316 +      if (dump_mode)
  4.1317 +        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  4.1318 +      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  4.1319 +      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  4.1320 +      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  4.1321 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  4.1322 +      data_buffer = srb->DataBuffer;
  4.1323 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  4.1324 +      data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
  4.1325 +      data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
  4.1326 +      data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
  4.1327 +      data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
  4.1328 +      data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  4.1329 +      data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  4.1330 +      data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  4.1331 +      data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  4.1332 +      data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  4.1333 +      data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  4.1334 +      data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  4.1335 +      data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  4.1336 +      srb->ScsiStatus = 0;
  4.1337 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1338 +      break;
  4.1339 +    case SCSIOP_MODE_SENSE:
  4.1340 +    case SCSIOP_MODE_SENSE10:
  4.1341 +      if (dump_mode)
  4.1342 +        KdPrint((__DRIVER_NAME "     Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", srb->Cdb[1] & 0x08, srb->Cdb[2] & 0xC0, srb->Cdb[2] & 0x3F));
  4.1343 +      XenVbd_FillModePage(xvdd, srb);
  4.1344 +      break;
  4.1345 +    case SCSIOP_READ:
  4.1346 +    case SCSIOP_READ16:
  4.1347 +    case SCSIOP_WRITE:
  4.1348 +    case SCSIOP_WRITE16:
  4.1349 +      XenVbd_PutSrbOnList(xvdd, srb);
  4.1350 +      XenVbd_PutQueuedSrbsOnRing(xvdd);
  4.1351 +      break;
  4.1352 +    case SCSIOP_VERIFY:
  4.1353 +    case SCSIOP_VERIFY16:
  4.1354 +      // Should we do more here?
  4.1355 +      if (dump_mode)
  4.1356 +        KdPrint((__DRIVER_NAME "     Command = VERIFY\n"));
  4.1357 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1358 +      break;
  4.1359 +    case SCSIOP_REPORT_LUNS:
  4.1360 +      if (dump_mode)
  4.1361 +        KdPrint((__DRIVER_NAME "     Command = REPORT_LUNS\n"));
  4.1362 +      srb->SrbStatus = SRB_STATUS_SUCCESS;;
  4.1363 +      break;
  4.1364 +    case SCSIOP_REQUEST_SENSE:
  4.1365 +      if (dump_mode)
  4.1366 +        KdPrint((__DRIVER_NAME "     Command = REQUEST_SENSE\n"));
  4.1367 +      XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
  4.1368 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1369 +      break;      
  4.1370 +    case SCSIOP_READ_TOC:
  4.1371 +      if (dump_mode)
  4.1372 +        KdPrint((__DRIVER_NAME "     Command = READ_TOC\n"));
  4.1373 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  4.1374 +      data_buffer = srb->DataBuffer;
  4.1375 +//      DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
  4.1376 +/*
  4.1377 +#define READ_TOC_FORMAT_TOC         0x00
  4.1378 +#define READ_TOC_FORMAT_SESSION     0x01
  4.1379 +#define READ_TOC_FORMAT_FULL_TOC    0x02
  4.1380 +#define READ_TOC_FORMAT_PMA         0x03
  4.1381 +#define READ_TOC_FORMAT_ATIP        0x04
  4.1382 +*/
  4.1383 +//      KdPrint((__DRIVER_NAME "     Msf = %d\n", cdb->READ_TOC.Msf));
  4.1384 +//      KdPrint((__DRIVER_NAME "     LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
  4.1385 +//      KdPrint((__DRIVER_NAME "     Format2 = %d\n", cdb->READ_TOC.Format2));
  4.1386 +//      KdPrint((__DRIVER_NAME "     StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
  4.1387 +//      KdPrint((__DRIVER_NAME "     AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
  4.1388 +//      KdPrint((__DRIVER_NAME "     Control = %d\n", cdb->READ_TOC.Control));
  4.1389 +//      KdPrint((__DRIVER_NAME "     Format = %d\n", cdb->READ_TOC.Format));
  4.1390 +      switch (cdb->READ_TOC.Format2)
  4.1391 +      {
  4.1392 +      case READ_TOC_FORMAT_TOC:
  4.1393 +        data_buffer[0] = 0; // length MSB
  4.1394 +        data_buffer[1] = 10; // length LSB
  4.1395 +        data_buffer[2] = 1; // First Track
  4.1396 +        data_buffer[3] = 1; // Last Track
  4.1397 +        data_buffer[4] = 0; // Reserved
  4.1398 +        data_buffer[5] = 0x14; // current position data + uninterrupted data
  4.1399 +        data_buffer[6] = 1; // last complete track
  4.1400 +        data_buffer[7] = 0; // reserved
  4.1401 +        data_buffer[8] = 0; // MSB Block
  4.1402 +        data_buffer[9] = 0;
  4.1403 +        data_buffer[10] = 0;
  4.1404 +        data_buffer[11] = 0; // LSB Block
  4.1405 +        srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1406 +        break;
  4.1407 +      case READ_TOC_FORMAT_SESSION:
  4.1408 +      case READ_TOC_FORMAT_FULL_TOC:
  4.1409 +      case READ_TOC_FORMAT_PMA:
  4.1410 +      case READ_TOC_FORMAT_ATIP:
  4.1411 +        srb->SrbStatus = SRB_STATUS_ERROR;
  4.1412 +        break;
  4.1413 +      }
  4.1414 +      break;
  4.1415 +    case SCSIOP_START_STOP_UNIT:
  4.1416 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_START_STOP_UNIT\n"));
  4.1417 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1418 +      break;
  4.1419 +    case SCSIOP_RESERVE_UNIT:
  4.1420 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RESERVE_UNIT\n"));
  4.1421 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1422 +      break;
  4.1423 +    case SCSIOP_RELEASE_UNIT:
  4.1424 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RELEASE_UNIT\n"));
  4.1425 +      srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1426 +      break;
  4.1427 +    default:
  4.1428 +      KdPrint((__DRIVER_NAME "     Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
  4.1429 +      srb->SrbStatus = SRB_STATUS_ERROR;
  4.1430 +      break;
  4.1431 +    }
  4.1432 +    if (srb->SrbStatus == SRB_STATUS_ERROR)
  4.1433 +    {
  4.1434 +      KdPrint((__DRIVER_NAME "     EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
  4.1435 +      if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
  4.1436 +      {
  4.1437 +        xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
  4.1438 +        xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
  4.1439 +      }
  4.1440 +      srb->ScsiStatus = 0x02;
  4.1441 +      XenVbd_MakeAutoSense(xvdd, srb);
  4.1442 +      ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1443 +      if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1444 +      {
  4.1445 +        ScsiPortNotification(NextRequest, DeviceExtension);
  4.1446 +      }
  4.1447 +    }
  4.1448 +    else if (srb->SrbStatus != SRB_STATUS_PENDING)
  4.1449 +    {
  4.1450 +      if (srb->SrbStatus == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
  4.1451 +      {
  4.1452 +        srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  4.1453 +        srb->DataTransferLength = data_transfer_length;
  4.1454 +      }
  4.1455 +      xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
  4.1456 +      xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  4.1457 +      ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1458 +      if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1459 +      {
  4.1460 +        ScsiPortNotification(NextRequest, DeviceExtension);
  4.1461 +      }
  4.1462 +    }
  4.1463 +    break;
  4.1464 +  case SRB_FUNCTION_IO_CONTROL:
  4.1465 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_IO_CONTROL\n"));
  4.1466 +    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  4.1467 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1468 +    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1469 +    {
  4.1470 +      ScsiPortNotification(NextRequest, DeviceExtension);
  4.1471 +    }
  4.1472 +    break;
  4.1473 +  case SRB_FUNCTION_FLUSH:
  4.1474 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  4.1475 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1476 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1477 +    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1478 +    {
  4.1479 +      ScsiPortNotification(NextRequest, DeviceExtension);
  4.1480 +    }
  4.1481 +    break;
  4.1482 +  case SRB_FUNCTION_SHUTDOWN:
  4.1483 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  4.1484 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  4.1485 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1486 +    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1487 +    {
  4.1488 +      ScsiPortNotification(NextRequest, DeviceExtension);
  4.1489 +    }
  4.1490 +    break;
  4.1491 +  default:
  4.1492 +    KdPrint((__DRIVER_NAME "     Unhandled srb->Function = %08X\n", srb->Function));
  4.1493 +    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  4.1494 +    ScsiPortNotification(RequestComplete, DeviceExtension, srb);
  4.1495 +    if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1496 +    {
  4.1497 +      ScsiPortNotification(NextRequest, DeviceExtension);
  4.1498 +    }
  4.1499 +    break;
  4.1500 +  }
  4.1501 +
  4.1502 +  //FUNCTION_EXIT();
  4.1503 +  return TRUE;
  4.1504 +}
  4.1505 +
  4.1506 +static BOOLEAN
  4.1507 +XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
  4.1508 +{
  4.1509 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  4.1510 +
  4.1511 +  UNREFERENCED_PARAMETER(DeviceExtension);
  4.1512 +  UNREFERENCED_PARAMETER(PathId);
  4.1513 +
  4.1514 +  FUNCTION_ENTER();
  4.1515 +
  4.1516 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  4.1517 +  if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
  4.1518 +  {
  4.1519 +    ScsiPortNotification(NextRequest, DeviceExtension);
  4.1520 +  }
  4.1521 +
  4.1522 +  FUNCTION_EXIT();
  4.1523 +
  4.1524 +
  4.1525 +  return TRUE;
  4.1526 +}
  4.1527 +
  4.1528 +static BOOLEAN
  4.1529 +XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
  4.1530 +{
  4.1531 +  UNREFERENCED_PARAMETER(DeviceExtension);
  4.1532 +  UNREFERENCED_PARAMETER(Context);
  4.1533 +  UNREFERENCED_PARAMETER(SaveState);
  4.1534 +
  4.1535 +  FUNCTION_ENTER();
  4.1536 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  4.1537 +
  4.1538 +  FUNCTION_EXIT();
  4.1539 +
  4.1540 +  return TRUE;
  4.1541 +}
  4.1542 +
  4.1543 +static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
  4.1544 +XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
  4.1545 +{
  4.1546 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  4.1547 +  SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
  4.1548 +  PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
  4.1549 +  //KIRQL OldIrql;
  4.1550 +
  4.1551 +  FUNCTION_ENTER();
  4.1552 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  4.1553 +  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
  4.1554 +
  4.1555 +  switch (ControlType)
  4.1556 +  {
  4.1557 +  case ScsiQuerySupportedControlTypes:
  4.1558 +    SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
  4.1559 +    KdPrint((__DRIVER_NAME "     ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
  4.1560 +    SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
  4.1561 +    SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
  4.1562 +    SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
  4.1563 +    break;
  4.1564 +  case ScsiStopAdapter:
  4.1565 +    KdPrint((__DRIVER_NAME "     ScsiStopAdapter\n"));
  4.1566 +    /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
  4.1567 +    break;
  4.1568 +  case ScsiRestartAdapter:
  4.1569 +    KdPrint((__DRIVER_NAME "     ScsiRestartAdapter\n"));
  4.1570 +    if (!xvdd->inactive)
  4.1571 +    {
  4.1572 +      if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
  4.1573 +        KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR) xvdd, 0, 0);
  4.1574 +      XenVbd_StartRingDetection(xvdd);
  4.1575 +    }
  4.1576 +    break;
  4.1577 +  case ScsiSetBootConfig:
  4.1578 +    KdPrint((__DRIVER_NAME "     ScsiSetBootConfig\n"));
  4.1579 +    break;
  4.1580 +  case ScsiSetRunningConfig:
  4.1581 +    KdPrint((__DRIVER_NAME "     ScsiSetRunningConfig\n"));
  4.1582 +    break;
  4.1583 +  default:
  4.1584 +    KdPrint((__DRIVER_NAME "     UNKNOWN\n"));
  4.1585 +    break;
  4.1586 +  }
  4.1587 +
  4.1588 +  FUNCTION_EXIT();
  4.1589 +  
  4.1590 +  return Status;
  4.1591 +}
  4.1592 +
  4.1593 +NTSTATUS
  4.1594 +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  4.1595 +{
  4.1596 +  ULONG status;
  4.1597 +  HW_INITIALIZATION_DATA HwInitializationData;
  4.1598 +  PVOID driver_extension;
  4.1599 +  PUCHAR ptr;
  4.1600 +  OBJECT_ATTRIBUTES oa;
  4.1601 +  HANDLE service_handle;
  4.1602 +  UNICODE_STRING param_name;
  4.1603 +  HANDLE param_handle;
  4.1604 +  UNICODE_STRING value_name;
  4.1605 +  CHAR buf[256];
  4.1606 +  ULONG buf_len;
  4.1607 +  PKEY_VALUE_PARTIAL_INFORMATION kpv;
  4.1608 +  
  4.1609 +  FUNCTION_ENTER();
  4.1610 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  4.1611 +  KdPrint((__DRIVER_NAME "     DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
  4.1612 +
  4.1613 +  /* RegistryPath == NULL when we are invoked as a crash dump driver */
  4.1614 +  if (!RegistryPath)
  4.1615 +  {
  4.1616 +    dump_mode = TRUE;
  4.1617 +  }
  4.1618 +  
  4.1619 +  if (!dump_mode)
  4.1620 +  {
  4.1621 +    IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
  4.1622 +    ptr = driver_extension;
  4.1623 +    //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
  4.1624 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
  4.1625 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
  4.1626 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
  4.1627 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
  4.1628 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
  4.1629 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
  4.1630 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
  4.1631 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
  4.1632 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  4.1633 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  4.1634 +    __ADD_XEN_INIT_UCHAR(&ptr, 20);
  4.1635 +    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  4.1636 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
  4.1637 +    //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  4.1638 +    //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
  4.1639 +    //__ADD_XEN_INIT_UCHAR(&ptr, 20);
  4.1640 +    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  4.1641 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
  4.1642 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
  4.1643 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
  4.1644 +    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  4.1645 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
  4.1646 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
  4.1647 +    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  4.1648 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
  4.1649 +    __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
  4.1650 +    __ADD_XEN_INIT_UCHAR(&ptr, 50);
  4.1651 +    __ADD_XEN_INIT_UCHAR(&ptr, 0);
  4.1652 +    
  4.1653 +    ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
  4.1654 +
  4.1655 +    InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  4.1656 +    status = ZwOpenKey(&service_handle, KEY_READ, &oa);
  4.1657 +    if(!NT_SUCCESS(status))
  4.1658 +    {
  4.1659 +      KdPrint((__DRIVER_NAME "     ZwOpenKey(Service) returned %08x\n", status));
  4.1660 +    }
  4.1661 +    else
  4.1662 +    {
  4.1663 +      RtlInitUnicodeString(&param_name, L"Parameters");
  4.1664 +      InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
  4.1665 +      status = ZwOpenKey(&param_handle, KEY_READ, &oa);
  4.1666 +      if(!NT_SUCCESS(status))
  4.1667 +      {
  4.1668 +        KdPrint((__DRIVER_NAME "     ZwOpenKey(Parameters) returned %08x\n", status));
  4.1669 +      }
  4.1670 +      else
  4.1671 +      {
  4.1672 +        kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
  4.1673 +        RtlFillMemory(scsi_device_manufacturer, 8, ' ');
  4.1674 +        RtlFillMemory(scsi_disk_model, 16, ' ');
  4.1675 +        RtlFillMemory(scsi_cdrom_model, 16, ' ');
  4.1676 +
  4.1677 +        RtlInitUnicodeString(&value_name, L"Manufacturer");
  4.1678 +        buf_len = 256;
  4.1679 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  4.1680 +        if(NT_SUCCESS(status))
  4.1681 +          wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
  4.1682 +        else
  4.1683 +          RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN     ");
  4.1684 +
  4.1685 +        RtlInitUnicodeString(&value_name, L"Disk_Model");
  4.1686 +        buf_len = 256;
  4.1687 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  4.1688 +        if(NT_SUCCESS(status))
  4.1689 +          wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  4.1690 +        else
  4.1691 +          RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK          ");
  4.1692 +
  4.1693 +        RtlInitUnicodeString(&value_name, L"CDROM_Model");
  4.1694 +        buf_len = 256;
  4.1695 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  4.1696 +        if(NT_SUCCESS(status))
  4.1697 +          wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  4.1698 +        else
  4.1699 +          RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM        ");
  4.1700 +        ZwClose(param_handle);
  4.1701 +      }
  4.1702 +      ZwClose(service_handle);
  4.1703 +    }
  4.1704 +  }
  4.1705 +  
  4.1706 +  RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
  4.1707 +
  4.1708 +  HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
  4.1709 +  HwInitializationData.AdapterInterfaceType = PNPBus;
  4.1710 +  if (!dump_mode)
  4.1711 +    HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
  4.1712 +  else
  4.1713 +    HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
  4.1714 +  HwInitializationData.SpecificLuExtensionSize = 0;
  4.1715 +  HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
  4.1716 +  HwInitializationData.NumberOfAccessRanges = 1;
  4.1717 +  HwInitializationData.MapBuffers = TRUE;
  4.1718 +  HwInitializationData.NeedPhysicalAddresses = FALSE;
  4.1719 +  HwInitializationData.TaggedQueuing = TRUE;
  4.1720 +  HwInitializationData.AutoRequestSense = TRUE;
  4.1721 +  HwInitializationData.MultipleRequestPerLu = TRUE;
  4.1722 +  HwInitializationData.ReceiveEvent = FALSE;
  4.1723 +  HwInitializationData.VendorIdLength = 0;
  4.1724 +  HwInitializationData.VendorId = NULL;
  4.1725 +  HwInitializationData.DeviceIdLength = 0;
  4.1726 +  HwInitializationData.DeviceId = NULL;
  4.1727 +
  4.1728 +  HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
  4.1729 +  HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
  4.1730 +  HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
  4.1731 +  HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
  4.1732 +  HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
  4.1733 +  HwInitializationData.HwDmaStarted = NULL;
  4.1734 +  HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
  4.1735 +  HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
  4.1736 +
  4.1737 +  status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
  4.1738 +  
  4.1739 +  if(!NT_SUCCESS(status))
  4.1740 +  {
  4.1741 +    KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
  4.1742 +  }
  4.1743 +
  4.1744 +  FUNCTION_EXIT();
  4.1745 +
  4.1746 +  return status;
  4.1747 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xenvbd/xenvbd_scsiport.h	Sat Jan 22 15:47:16 2011 +1100
     5.3 @@ -0,0 +1,164 @@
     5.4 +/*
     5.5 +PV Drivers for Windows Xen HVM Domains
     5.6 +Copyright (C) 2007 James Harper
     5.7 +
     5.8 +This program is free software; you can redistribute it and/or
     5.9 +modify it under the terms of the GNU General Public License
    5.10 +as published by the Free Software Foundation; either version 2
    5.11 +of the License, or (at your option) any later version.
    5.12 +
    5.13 +This program is distributed in the hope that it will be useful,
    5.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.16 +GNU General Public License for more details.
    5.17 +
    5.18 +You should have received a copy of the GNU General Public License
    5.19 +along with this program; if not, write to the Free Software
    5.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    5.21 +*/
    5.22 +
    5.23 +#if !defined(_XENVBD_H_)
    5.24 +#define _XENVBD_H_
    5.25 +
    5.26 +#define DDKAPI
    5.27 +
    5.28 +//#include <ntifs.h>
    5.29 +#include <ntddk.h>
    5.30 +#include <wdm.h>
    5.31 +#include <initguid.h>
    5.32 +#define NTSTRSAFE_LIB
    5.33 +#include <ntstrsafe.h>
    5.34 +
    5.35 +#include <ntdddisk.h>
    5.36 +#if (NTDDI_VERSION < NTDDI_WINXP) /* srb.h causes warnings under 2K for some reason */
    5.37 +#pragma warning(disable:4201) /* nameless struct/union */
    5.38 +#pragma warning(disable:4214) /* bit field types other than int */
    5.39 +#endif
    5.40 +#include <srb.h>
    5.41 +
    5.42 +#define __DRIVER_NAME "XenVbd"
    5.43 +
    5.44 +#include <xen_windows.h>
    5.45 +#include <memory.h>
    5.46 +//#include <grant_table.h>
    5.47 +#include <event_channel.h>
    5.48 +#include <hvm/params.h>
    5.49 +#include <hvm/hvm_op.h>
    5.50 +#include <xen_public.h>
    5.51 +#include <io/ring.h>
    5.52 +#include <io/blkif.h>
    5.53 +#include <io/xenbus.h>
    5.54 +
    5.55 +#define XENVBD_POOL_TAG (ULONG) 'XVBD'
    5.56 +
    5.57 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    5.58 +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
    5.59 +#define BLK_OTHER_RING_SIZE __RING_SIZE((blkif_other_sring_t *)0, PAGE_SIZE)
    5.60 +
    5.61 +#if defined(__x86_64__)
    5.62 +#pragma pack(push, 4)
    5.63 +#endif
    5.64 +struct blkif_other_request {
    5.65 +  uint8_t operation;
    5.66 +  uint8_t nr_segments;
    5.67 +  blkif_vdev_t handle;
    5.68 +  uint64_t id;
    5.69 +  blkif_sector_t sector_number;
    5.70 +  struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    5.71 +};
    5.72 +struct blkif_other_response {
    5.73 +  uint64_t id;
    5.74 +  uint8_t operation;
    5.75 +  int16_t status;
    5.76 +};
    5.77 +#if defined(__x86_64__)
    5.78 +#pragma pack(pop)
    5.79 +#endif
    5.80 +
    5.81 +typedef struct blkif_other_request blkif_other_request_t;
    5.82 +typedef struct blkif_other_response blkif_other_response_t;
    5.83 +DEFINE_RING_TYPES(blkif_other, struct blkif_other_request, struct blkif_other_response);
    5.84 +
    5.85 +typedef struct {
    5.86 +  LIST_ENTRY list_entry;
    5.87 +  PSCSI_REQUEST_BLOCK srb;
    5.88 +} srb_list_entry_t;
    5.89 +
    5.90 +typedef struct {
    5.91 +  blkif_request_t req;
    5.92 +  PSCSI_REQUEST_BLOCK srb;
    5.93 +  BOOLEAN aligned_buffer_in_use;
    5.94 +} blkif_shadow_t;
    5.95 +
    5.96 +#define MAX_SHADOW_ENTRIES 64
    5.97 +#define SHADOW_ENTRIES min(MAX_SHADOW_ENTRIES, min(BLK_RING_SIZE, BLK_OTHER_RING_SIZE))
    5.98 +
    5.99 +typedef enum {
   5.100 +  XENVBD_DEVICETYPE_UNKNOWN,
   5.101 +  XENVBD_DEVICETYPE_DISK,
   5.102 +  XENVBD_DEVICETYPE_CDROM,
   5.103 +  XENVBD_DEVICETYPE_CONTROLLER // Not yet used
   5.104 +} XENVBD_DEVICETYPE;
   5.105 +
   5.106 +typedef enum {
   5.107 +  XENVBD_DEVICEMODE_UNKNOWN,
   5.108 +  XENVBD_DEVICEMODE_READ,
   5.109 +  XENVBD_DEVICEMODE_WRITE
   5.110 +} XENVBD_DEVICEMODE;
   5.111 +
   5.112 +#define RING_DETECT_STATE_NOT_STARTED  0
   5.113 +#define RING_DETECT_STATE_DETECT1      1
   5.114 +#define RING_DETECT_STATE_DETECT2      2
   5.115 +#define RING_DETECT_STATE_COMPLETE     3
   5.116 +
   5.117 +struct
   5.118 +{
   5.119 +  BOOLEAN inactive;
   5.120 +  
   5.121 +  blkif_shadow_t shadows[MAX_SHADOW_ENTRIES];
   5.122 +  USHORT shadow_free_list[MAX_SHADOW_ENTRIES];
   5.123 +  USHORT shadow_free;
   5.124 +  USHORT shadow_min_free;
   5.125 +
   5.126 +  PUCHAR device_base;
   5.127 +
   5.128 +  blkif_sring_t *sring;
   5.129 +  evtchn_port_t event_channel;
   5.130 +  ULONG *event_channel_ptr;
   5.131 +  union {
   5.132 +    blkif_front_ring_t ring;
   5.133 +    blkif_other_front_ring_t other_ring;
   5.134 +  };
   5.135 +  int ring_detect_state;
   5.136 +  BOOLEAN use_other;
   5.137 +  BOOLEAN cached_use_other;
   5.138 +  UCHAR last_sense_key;
   5.139 +  UCHAR last_additional_sense_code;
   5.140 +  blkif_response_t tmp_rep;
   5.141 +  XENVBD_DEVICETYPE device_type;
   5.142 +  XENVBD_DEVICEMODE device_mode;
   5.143 +  ULONG bytes_per_sector;
   5.144 +  ULONGLONG total_sectors;
   5.145 +  XENPCI_VECTORS vectors;
   5.146 +  PXENPCI_DEVICE_STATE device_state;
   5.147 +  LIST_ENTRY srb_list;
   5.148 +  grant_ref_t dump_grant_refs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   5.149 +  BOOLEAN aligned_buffer_in_use;
   5.150 +  PVOID aligned_buffer;
   5.151 +/*  
   5.152 +  ULONGLONG interrupts;
   5.153 +  ULONGLONG aligned_requests;
   5.154 +  ULONGLONG aligned_bytes;
   5.155 +  ULONGLONG unaligned_requests;
   5.156 +  ULONGLONG unaligned_bytes;
   5.157 +*/
   5.158 +  #define BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE 1
   5.159 +  #define UNALIGNED_BUFFER_DATA_SIZE ((BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * PAGE_SIZE - 1)
   5.160 +  #define UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE ((BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE + 1) * PAGE_SIZE - 1)
   5.161 +  /* this has to be right at the end of DeviceExtension */
   5.162 +  /* can't allocate too much data in dump mode so size DeviceExtensionSize accordingly */
   5.163 +  UCHAR aligned_buffer_data[1];
   5.164 +} typedef XENVBD_DEVICE_DATA, *PXENVBD_DEVICE_DATA;
   5.165 +
   5.166 +#endif
   5.167 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xenvbd/xenvbd_storport.c	Sat Jan 22 15:47:16 2011 +1100
     6.3 @@ -0,0 +1,1922 @@
     6.4 +/*
     6.5 +PV Drivers for Windows Xen HVM Domains
     6.6 +Copyright (C) 2007 James Harper
     6.7 +
     6.8 +This program is free software; you can redistribute it and/or
     6.9 +modify it under the terms of the GNU General Public License
    6.10 +as published by the Free Software Foundation; either version 2
    6.11 +of the License, or (at your option) any later version.
    6.12 +
    6.13 +This program is distributed in the hope that it will be useful,
    6.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 +GNU General Public License for more details.
    6.17 +
    6.18 +You should have received a copy of the GNU General Public License
    6.19 +along with this program; if not, write to the Free Software
    6.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    6.21 +*/
    6.22 +
    6.23 +#define INITGUID
    6.24 +#include "xenvbd_storport.h"
    6.25 +
    6.26 +#pragma warning(disable: 4127)
    6.27 +
    6.28 +#if defined(__x86_64__)
    6.29 +  #define LongLongToPtr(x) (PVOID)(x)
    6.30 +#else
    6.31 +  #define LongLongToPtr(x) UlongToPtr(x)
    6.32 +#endif
    6.33 +
    6.34 +/* Not really necessary but keeps PREfast happy */
    6.35 +DRIVER_INITIALIZE DriverEntry;
    6.36 +static BOOLEAN XenVbd_HandleEvent(PVOID DeviceExtension);
    6.37 +
    6.38 +static BOOLEAN dump_mode = FALSE;
    6.39 +#define DUMP_MODE_ERROR_LIMIT 64
    6.40 +static ULONG dump_mode_errors = 0;
    6.41 +
    6.42 +CHAR scsi_device_manufacturer[8];
    6.43 +CHAR scsi_disk_model[16];
    6.44 +CHAR scsi_cdrom_model[16];
    6.45 +
    6.46 +ULONGLONG parse_numeric_string(PCHAR string)
    6.47 +{
    6.48 +  ULONGLONG val = 0;
    6.49 +  while (*string != 0)
    6.50 +  {
    6.51 +    val = val * 10 + (*string - '0');
    6.52 +    string++;
    6.53 +  }
    6.54 +  return val;
    6.55 +}
    6.56 +
    6.57 +static blkif_shadow_t *
    6.58 +get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
    6.59 +{
    6.60 +  if (xvdd->shadow_free == 0)
    6.61 +  {
    6.62 +    KdPrint((__DRIVER_NAME "     No more shadow entries\n"));
    6.63 +    return NULL;
    6.64 +  }
    6.65 +  xvdd->shadow_free--;
    6.66 +  if (xvdd->shadow_free < xvdd->shadow_min_free)
    6.67 +    xvdd->shadow_min_free = xvdd->shadow_free;
    6.68 +  return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
    6.69 +}
    6.70 +
    6.71 +static VOID
    6.72 +put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
    6.73 +{
    6.74 +  xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
    6.75 +  shadow->srb = NULL;
    6.76 +  xvdd->shadow_free++;
    6.77 +}
    6.78 +
    6.79 +static blkif_response_t *
    6.80 +XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
    6.81 +{
    6.82 +  blkif_other_response_t *rep;
    6.83 +  if (!xvdd->use_other)
    6.84 +    return RING_GET_RESPONSE(&xvdd->ring, i);
    6.85 +  rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
    6.86 +  xvdd->tmp_rep.id = rep->id;
    6.87 +  xvdd->tmp_rep.operation = rep->operation;
    6.88 +  xvdd->tmp_rep.status = rep->status;
    6.89 +  return &xvdd->tmp_rep;
    6.90 +}
    6.91 +
    6.92 +static VOID
    6.93 +XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
    6.94 +{
    6.95 +  blkif_other_request_t *other_req;
    6.96 +
    6.97 +  if (!xvdd->use_other)
    6.98 +  {
    6.99 +    *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
   6.100 +  }
   6.101 +  else
   6.102 +  {  
   6.103 +    other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
   6.104 +    other_req->operation = req->operation;
   6.105 +    other_req->nr_segments = req->nr_segments;
   6.106 +    other_req->handle = req->handle;
   6.107 +    other_req->id = req->id;
   6.108 +    other_req->sector_number = req->sector_number;
   6.109 +    memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
   6.110 +  }
   6.111 +  xvdd->ring.req_prod_pvt++;
   6.112 +}
   6.113 +
   6.114 +static ULONG
   6.115 +XenVbd_InitConfig(PXENVBD_DEVICE_DATA xvdd)
   6.116 +{
   6.117 +  ULONG status;
   6.118 +  PUCHAR ptr;
   6.119 +  USHORT type;
   6.120 +  PCHAR setting, value, value2;
   6.121 +
   6.122 +  FUNCTION_ENTER();
   6.123 +  /* first read the default config items */
   6.124 +  ptr = xvdd->device_base;
   6.125 +  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   6.126 +  {
   6.127 +    switch(type)
   6.128 +    {
   6.129 +    case XEN_INIT_TYPE_VECTORS:
   6.130 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   6.131 +      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   6.132 +        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   6.133 +      {
   6.134 +        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   6.135 +          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   6.136 +        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.137 +        return SP_RETURN_BAD_CONFIG;
   6.138 +      }
   6.139 +      else
   6.140 +        memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
   6.141 +      break;
   6.142 +    default:
   6.143 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   6.144 +      break;
   6.145 +    }
   6.146 +  }
   6.147 +
   6.148 +  /* then set up all the configuration requests */
   6.149 +  ptr = xvdd->device_base;
   6.150 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
   6.151 +  #pragma warning(suppress:4054)
   6.152 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_DPC, "event-channel", (PVOID)XenVbd_HandleEvent, xvdd);
   6.153 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
   6.154 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
   6.155 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
   6.156 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
   6.157 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
   6.158 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
   6.159 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   6.160 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
   6.161 +  __ADD_XEN_INIT_UCHAR(&ptr, 20);
   6.162 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   6.163 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
   6.164 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   6.165 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
   6.166 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   6.167 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
   6.168 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   6.169 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   6.170 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
   6.171 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   6.172 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
   6.173 +  __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
   6.174 +  __ADD_XEN_INIT_UCHAR(&ptr, 50);
   6.175 +  __ADD_XEN_INIT_UCHAR(&ptr, 0);
   6.176 +  ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
   6.177 +
   6.178 +  /* then configure */
   6.179 +  status = xvdd->vectors.XenPci_XenConfigDevice(xvdd->vectors.context);
   6.180 +  if (!NT_SUCCESS(status))
   6.181 +  {
   6.182 +    KdPrint(("Failed to complete device configuration (%08x)\n", status));
   6.183 +    FUNCTION_EXIT();
   6.184 +    return SP_RETURN_BAD_CONFIG;
   6.185 +  }
   6.186 +  FUNCTION_EXIT();
   6.187 +  return SP_RETURN_FOUND;
   6.188 +}
   6.189 +
   6.190 +static ULONG
   6.191 +XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
   6.192 +{
   6.193 +  ULONG i;
   6.194 +  PUCHAR ptr;
   6.195 +  USHORT type;
   6.196 +  PCHAR setting, value, value2;
   6.197 +  ULONG qemu_protocol_version = 0;
   6.198 +  BOOLEAN qemu_hide_filter = FALSE;
   6.199 +  ULONG qemu_hide_flags_value = 0;
   6.200 +
   6.201 +  FUNCTION_ENTER();
   6.202 +  
   6.203 +  xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   6.204 +  xvdd->sring = NULL;
   6.205 +  xvdd->event_channel = 0;
   6.206 +  
   6.207 +  xvdd->inactive = TRUE;  
   6.208 +  
   6.209 +  ptr = xvdd->device_base;
   6.210 +  while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
   6.211 +  {
   6.212 +    switch(type)
   6.213 +    {
   6.214 +    case XEN_INIT_TYPE_VECTORS:
   6.215 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   6.216 +      if (dump_mode)
   6.217 +      {
   6.218 +        if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   6.219 +          ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   6.220 +        {
   6.221 +          KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   6.222 +            ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   6.223 +          KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   6.224 +          return SP_RETURN_BAD_CONFIG;
   6.225 +        }
   6.226 +        else
   6.227 +          memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
   6.228 +      }
   6.229 +      break;
   6.230 +    case XEN_INIT_TYPE_RING: /* frontend ring */
   6.231 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   6.232 +      if (strcmp(setting, "ring-ref") == 0)
   6.233 +      {
   6.234 +        xvdd->sring = (blkif_sring_t *)value;
   6.235 +        FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
   6.236 +        /* this bit is for when we have to take over an existing ring on a crash dump */
   6.237 +        xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
   6.238 +        xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
   6.239 +      }
   6.240 +      break;
   6.241 +    case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
   6.242 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
   6.243 +      if (strcmp(setting, "event-channel") == 0)
   6.244 +      {
   6.245 +        /* cheat here - save the state of the ring in the topmost bits of the event-channel */
   6.246 +        xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
   6.247 +        xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
   6.248 +        if (PtrToUlong(value) & 0x80000000)
   6.249 +        {
   6.250 +          xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
   6.251 +          KdPrint((__DRIVER_NAME "     cached_use_other = %d\n", xvdd->cached_use_other));
   6.252 +        }
   6.253 +      }
   6.254 +      break;
   6.255 +    case XEN_INIT_TYPE_READ_STRING_BACK:
   6.256 +    case XEN_INIT_TYPE_READ_STRING_FRONT:
   6.257 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   6.258 +      if (strcmp(setting, "sectors") == 0)
   6.259 +        xvdd->total_sectors = parse_numeric_string(value);
   6.260 +      else if (strcmp(setting, "sector-size") == 0)
   6.261 +        xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
   6.262 +      else if (strcmp(setting, "device-type") == 0)
   6.263 +      {
   6.264 +        if (strcmp(value, "disk") == 0)
   6.265 +        {
   6.266 +          KdPrint((__DRIVER_NAME "     device-type = Disk\n"));    
   6.267 +          xvdd->device_type = XENVBD_DEVICETYPE_DISK;
   6.268 +        }
   6.269 +        else if (strcmp(value, "cdrom") == 0)
   6.270 +        {
   6.271 +          KdPrint((__DRIVER_NAME "     device-type = CDROM\n"));    
   6.272 +          xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
   6.273 +        }
   6.274 +        else
   6.275 +        {
   6.276 +          KdPrint((__DRIVER_NAME "     device-type = %s (This probably won't work!)\n", value));
   6.277 +          xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   6.278 +        }
   6.279 +      }
   6.280 +      else if (strcmp(setting, "mode") == 0)
   6.281 +      {
   6.282 +        if (strncmp(value, "r", 1) == 0)
   6.283 +        {
   6.284 +          KdPrint((__DRIVER_NAME "     mode = r\n"));    
   6.285 +          xvdd->device_mode = XENVBD_DEVICEMODE_READ;
   6.286 +        }
   6.287 +        else if (strncmp(value, "w", 1) == 0)
   6.288 +        {
   6.289 +          KdPrint((__DRIVER_NAME "     mode = w\n"));    
   6.290 +          xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
   6.291 +        }
   6.292 +        else
   6.293 +        {
   6.294 +          KdPrint((__DRIVER_NAME "     mode = unknown\n"));
   6.295 +          xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
   6.296 +        }
   6.297 +      }
   6.298 +      break;
   6.299 +    case XEN_INIT_TYPE_GRANT_ENTRIES:
   6.300 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - entries = %d\n", PtrToUlong(setting)));
   6.301 +      memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * sizeof(grant_ref_t));
   6.302 +      break;
   6.303 +    case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
   6.304 +      qemu_protocol_version = PtrToUlong(value);
   6.305 +      break;
   6.306 +    case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
   6.307 +      qemu_hide_flags_value = PtrToUlong(value);
   6.308 +      KdPrint((__DRIVER_NAME "     qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
   6.309 +      break;
   6.310 +    case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
   6.311 +      qemu_hide_filter = TRUE;
   6.312 +      KdPrint((__DRIVER_NAME "     qemu_hide_filter = TRUE\n"));
   6.313 +      break;
   6.314 +    case XEN_INIT_TYPE_STATE_PTR:
   6.315 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
   6.316 +      xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
   6.317 +      break;
   6.318 +    default:
   6.319 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   6.320 +      break;
   6.321 +    }
   6.322 +  }
   6.323 +
   6.324 +  if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
   6.325 +    xvdd->inactive = FALSE;
   6.326 +  
   6.327 +  if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
   6.328 +      || xvdd->sring == NULL
   6.329 +      || xvdd->event_channel == 0
   6.330 +      || xvdd->total_sectors == 0
   6.331 +      || xvdd->bytes_per_sector == 0))
   6.332 +  {
   6.333 +    KdPrint((__DRIVER_NAME "     Missing settings\n"));
   6.334 +    FUNCTION_EXIT();
   6.335 +    return SP_RETURN_BAD_CONFIG;
   6.336 +  }
   6.337 +
   6.338 +  if (xvdd->inactive)
   6.339 +    KdPrint((__DRIVER_NAME "     Device is inactive\n"));
   6.340 +  else
   6.341 +  {
   6.342 +    if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
   6.343 +    {
   6.344 +      /* CD/DVD drives must have bytes_per_sector = 2048. */
   6.345 +      xvdd->bytes_per_sector = 2048;
   6.346 +    }
   6.347 +
   6.348 +    /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
   6.349 +    xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
   6.350 +
   6.351 +    xvdd->shadow_free = 0;
   6.352 +    memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
   6.353 +    for (i = 0; i < SHADOW_ENTRIES; i++)
   6.354 +    {
   6.355 +      xvdd->shadows[i].req.id = i;
   6.356 +      put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
   6.357 +    }
   6.358 +  }
   6.359 +
   6.360 +  FUNCTION_EXIT();
   6.361 +  return SP_RETURN_FOUND;
   6.362 +}
   6.363 +
   6.364 +static __inline ULONG
   6.365 +decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
   6.366 +{
   6.367 +  switch (srb->Cdb[0])
   6.368 +  {
   6.369 +  case SCSIOP_READ:
   6.370 +  case SCSIOP_WRITE:
   6.371 +    return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
   6.372 +  case SCSIOP_READ16:
   6.373 +  case SCSIOP_WRITE16:
   6.374 +    return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];    
   6.375 +  default:
   6.376 +    return 0;
   6.377 +  }
   6.378 +}
   6.379 +
   6.380 +static __inline ULONGLONG
   6.381 +decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
   6.382 +{
   6.383 +  ULONGLONG sector;
   6.384 +  
   6.385 +  switch (srb->Cdb[0])
   6.386 +  {
   6.387 +  case SCSIOP_READ:
   6.388 +  case SCSIOP_WRITE:
   6.389 +    sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
   6.390 +    break;
   6.391 +  case SCSIOP_READ16:
   6.392 +  case SCSIOP_WRITE16:
   6.393 +    sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
   6.394 +           | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
   6.395 +           | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
   6.396 +           | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
   6.397 +    //KdPrint((__DRIVER_NAME "     sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
   6.398 +    break;
   6.399 +  default:
   6.400 +    sector = 0;
   6.401 +    break;
   6.402 +  }
   6.403 +  return sector;
   6.404 +}
   6.405 +
   6.406 +static __inline BOOLEAN
   6.407 +decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
   6.408 +{
   6.409 +  switch (srb->Cdb[0])
   6.410 +  {
   6.411 +  case SCSIOP_READ:
   6.412 +  case SCSIOP_READ16:
   6.413 +    return TRUE;
   6.414 +  case SCSIOP_WRITE:
   6.415 +  case SCSIOP_WRITE16:
   6.416 +    return FALSE;
   6.417 +  default:
   6.418 +    return FALSE;
   6.419 +  }
   6.420 +}
   6.421 +
   6.422 +ULONG max_dump_mode_blocks = 0;
   6.423 +ULONG max_dump_mode_length = 0;
   6.424 +
   6.425 +static VOID
   6.426 +XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   6.427 +{
   6.428 +  srb_list_entry_t *list_entry = srb->SrbExtension;
   6.429 +  list_entry->srb = srb;
   6.430 +  InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)list_entry);
   6.431 +}
   6.432 +
   6.433 +static VOID
   6.434 +XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
   6.435 +{
   6.436 +  PSCSI_REQUEST_BLOCK srb;
   6.437 +  srb_list_entry_t *srb_entry;
   6.438 +  ULONGLONG sector_number;
   6.439 +  ULONG block_count;
   6.440 +  blkif_shadow_t *shadow;
   6.441 +  ULONG remaining, offset, length;
   6.442 +  grant_ref_t gref;
   6.443 +  PUCHAR ptr;
   6.444 +  int notify;
   6.445 +  int i;
   6.446 +  PVOID system_address;
   6.447 +
   6.448 +  //if (dump_mode) FUNCTION_ENTER();
   6.449 +
   6.450 +  while(!xvdd->aligned_buffer_in_use && xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
   6.451 +  {
   6.452 +    srb = srb_entry->srb;
   6.453 +    //if (dump_mode) KdPrint((__DRIVER_NAME "     srb = %p\n", srb));
   6.454 +    if (!dump_mode)
   6.455 +    {
   6.456 +      if (StorPortGetSystemAddress(xvdd, srb, &system_address) != STOR_STATUS_SUCCESS)
   6.457 +      {
   6.458 +        KdPrint((__DRIVER_NAME "     Failed to map DataBuffer\n"));
   6.459 +        srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   6.460 +        StorPortNotification(RequestComplete, xvdd, srb);
   6.461 +        continue;
   6.462 +      }
   6.463 +    }
   6.464 +    else
   6.465 +    {
   6.466 +      //KdPrint((__DRIVER_NAME "     DataBuffer = %p\n", srb->DataBuffer));
   6.467 +      system_address = srb->DataBuffer;
   6.468 +    }
   6.469 +    block_count = decode_cdb_length(srb);
   6.470 +    block_count *= xvdd->bytes_per_sector / 512;
   6.471 +    sector_number = decode_cdb_sector(srb);
   6.472 +    sector_number *= xvdd->bytes_per_sector / 512;
   6.473 +
   6.474 +    //if (dump_mode) KdPrint((__DRIVER_NAME "     sector_number = %I64d, block_count = %d, bytes_per_sector = %d, DataTransferLength = %d\n", sector_number, block_count, xvdd->bytes_per_sector, srb->DataTransferLength));
   6.475 +    ASSERT(block_count * xvdd->bytes_per_sector == srb->DataTransferLength);
   6.476 +    
   6.477 +    /* look for pending writes that overlap this one */
   6.478 +    /* we get warnings from drbd if we don't */
   6.479 +    for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
   6.480 +    {
   6.481 +      PSCSI_REQUEST_BLOCK srb2;
   6.482 +      ULONGLONG sector_number2;
   6.483 +      ULONG block_count2;
   6.484 +      
   6.485 +      srb2 = xvdd->shadows[i].srb;
   6.486 +      if (!srb2)
   6.487 +        continue;
   6.488 +      if (decode_cdb_is_read(srb2))
   6.489 +        continue;
   6.490 +      block_count2 = decode_cdb_length(srb2);;
   6.491 +      block_count2 *= xvdd->bytes_per_sector / 512;
   6.492 +      sector_number2 = decode_cdb_sector(srb2);
   6.493 +      sector_number2 *= xvdd->bytes_per_sector / 512;
   6.494 +      
   6.495 +      if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
   6.496 +        continue;
   6.497 +      if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
   6.498 +        continue;
   6.499 +
   6.500 +      KdPrint((__DRIVER_NAME "     Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
   6.501 +        sector_number, block_count, sector_number2, block_count2));
   6.502 +      /* put the srb back at the start of the queue */
   6.503 +      InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   6.504 +      return; /* stall the queue */
   6.505 +    }
   6.506 +
   6.507 +    remaining = block_count * 512;
   6.508 +    shadow = get_shadow_from_freelist(xvdd);
   6.509 +    ASSERT(shadow);
   6.510 +    ASSERT(!shadow->aligned_buffer_in_use);
   6.511 +    ASSERT(!shadow->srb);
   6.512 +    shadow->req.sector_number = sector_number;
   6.513 +    shadow->req.handle = 0;
   6.514 +    shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
   6.515 +    shadow->req.nr_segments = 0;
   6.516 +    shadow->srb = srb;
   6.517 +    shadow->system_address = system_address;
   6.518 +
   6.519 +    if (!dump_mode)
   6.520 +    {
   6.521 +      if ((ULONG_PTR)shadow->system_address & 511)
   6.522 +      {
   6.523 +        xvdd->aligned_buffer_in_use = TRUE;
   6.524 +        ptr = xvdd->aligned_buffer;
   6.525 +        if (!decode_cdb_is_read(srb))
   6.526 +          memcpy(ptr, shadow->system_address, block_count * 512);
   6.527 +        shadow->aligned_buffer_in_use = TRUE;
   6.528 +      }
   6.529 +      else
   6.530 +      {
   6.531 +        ptr = shadow->system_address;
   6.532 +        shadow->aligned_buffer_in_use = FALSE;
   6.533 +      }
   6.534 +    }
   6.535 +    else
   6.536 +    {
   6.537 +      ASSERT(!((ULONG_PTR)shadow->system_address & 511));
   6.538 +      ptr = srb->DataBuffer;
   6.539 +      shadow->aligned_buffer_in_use = FALSE;
   6.540 +      if (block_count > max_dump_mode_blocks)
   6.541 +      {
   6.542 +        max_dump_mode_blocks = block_count;
   6.543 +        KdPrint((__DRIVER_NAME "     max_dump_mode_blocks = %d\n", max_dump_mode_blocks));
   6.544 +      }
   6.545 +      if (srb->DataTransferLength > max_dump_mode_length)
   6.546 +      {
   6.547 +        max_dump_mode_length = srb->DataTransferLength;
   6.548 +        KdPrint((__DRIVER_NAME "     max_dump_mode_length = %d\n", max_dump_mode_length));
   6.549 +      }
   6.550 +    }
   6.551 +
   6.552 +    //KdPrint((__DRIVER_NAME "     sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
   6.553 +    //KdPrint((__DRIVER_NAME "     DataBuffer   = %p\n", srb->DataBuffer));
   6.554 +    //KdPrint((__DRIVER_NAME "     system_address   = %p\n", shadow->system_address));
   6.555 +
   6.556 +    //KdPrint((__DRIVER_NAME "     handle = %d\n", shadow->req.handle));
   6.557 +    //KdPrint((__DRIVER_NAME "     operation = %d\n", shadow->req.operation));
   6.558 +    
   6.559 +    while (remaining > 0)
   6.560 +    {
   6.561 +      PHYSICAL_ADDRESS physical_address;
   6.562 +
   6.563 +      if (!dump_mode)
   6.564 +      {
   6.565 +        physical_address = MmGetPhysicalAddress(ptr);
   6.566 +        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   6.567 +                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'XVBD');
   6.568 +      }
   6.569 +      else
   6.570 +      {
   6.571 +        ULONG length;       
   6.572 +        physical_address.QuadPart = 0;
   6.573 +        physical_address = StorPortGetPhysicalAddress(xvdd, srb, ptr, &length);
   6.574 +        //KdPrint((__DRIVER_NAME "     pfn = %08x, length = %d\n", (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), length));
   6.575 +        gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
   6.576 +                 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE,
   6.577 +                 xvdd->dump_grant_refs[shadow->req.nr_segments], (ULONG)'XPDO');
   6.578 +      }
   6.579 +      if (gref == INVALID_GRANT_REF)
   6.580 +      {
   6.581 +        ULONG i;
   6.582 +        for (i = 0; i < shadow->req.nr_segments; i++)
   6.583 +        {
   6.584 +          xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
   6.585 +            shadow->req.seg[i].gref, FALSE, (ULONG)'XVBD');
   6.586 +        }
   6.587 +        if (shadow->aligned_buffer_in_use)
   6.588 +        {
   6.589 +          shadow->aligned_buffer_in_use = FALSE;
   6.590 +          xvdd->aligned_buffer_in_use = FALSE;
   6.591 +        }
   6.592 +        /* put the srb back at the start of the queue */
   6.593 +        InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
   6.594 +        put_shadow_on_freelist(xvdd, shadow);
   6.595 +        KdPrint((__DRIVER_NAME "     Out of gref's. Deferring\n"));
   6.596 +        return;
   6.597 +      }
   6.598 +      offset = physical_address.LowPart & (PAGE_SIZE - 1);
   6.599 +      length = min(PAGE_SIZE - offset, remaining);
   6.600 +      //if (dump_mode) KdPrint((__DRIVER_NAME "     length = %d\n", length));
   6.601 +      //if (dump_mode) KdPrint((__DRIVER_NAME "     offset = %d\n", length));
   6.602 +      ASSERT((offset & 511) == 0);
   6.603 +      ASSERT((length & 511) == 0);
   6.604 +      ASSERT(offset + length <= PAGE_SIZE);
   6.605 +      shadow->req.seg[shadow->req.nr_segments].gref = gref;
   6.606 +      shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
   6.607 +      shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
   6.608 +      //if (dump_mode) KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[shadow->req.nr_segments].gref));
   6.609 +      //if (dump_mode) KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[shadow->req.nr_segments].first_sect));
   6.610 +      //if (dump_mode) KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[shadow->req.nr_segments].last_sect));
   6.611 +      remaining -= length;
   6.612 +      ptr += length;
   6.613 +      shadow->req.nr_segments++;
   6.614 +    }
   6.615 +
   6.616 +    //KdPrint((__DRIVER_NAME "     nr_segments = %d\n", shadow->req.nr_segments));
   6.617 +
   6.618 +    XenVbd_PutRequest(xvdd, &shadow->req);
   6.619 +
   6.620 +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   6.621 +    if (notify)
   6.622 +    {
   6.623 +      //KdPrint((__DRIVER_NAME "     Notifying\n"));
   6.624 +      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   6.625 +    }
   6.626 +  }
   6.627 +  //if (dump_mode) FUNCTION_EXIT();
   6.628 +}
   6.629 +
   6.630 +static ULONG
   6.631 +XenVbd_VirtualHwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PVOID LowerDevice, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
   6.632 +{
   6.633 +//  PACCESS_RANGE AccessRange;
   6.634 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   6.635 +  ULONG status;
   6.636 +//  PXENPCI_XEN_DEVICE_DATA XenDeviceData;
   6.637 +  PACCESS_RANGE access_range;
   6.638 +
   6.639 +  UNREFERENCED_PARAMETER(HwContext);
   6.640 +  UNREFERENCED_PARAMETER(BusInformation);
   6.641 +  UNREFERENCED_PARAMETER(LowerDevice);
   6.642 +  UNREFERENCED_PARAMETER(ArgumentString);
   6.643 +
   6.644 +  FUNCTION_ENTER(); 
   6.645 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   6.646 +  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
   6.647 +
   6.648 +  RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
   6.649 +  *Again = FALSE;
   6.650 +
   6.651 +  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
   6.652 +  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
   6.653 +
   6.654 +  if (!dump_mode)
   6.655 +  {
   6.656 +    KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));    
   6.657 +    if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
   6.658 +    {
   6.659 +      return SP_RETURN_BAD_CONFIG;
   6.660 +    }
   6.661 +
   6.662 +    access_range = &((*(ConfigInfo->AccessRanges))[0]);
   6.663 +    KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
   6.664 +      access_range->RangeStart.LowPart, access_range->RangeLength));
   6.665 +    xvdd->device_base = StorPortGetDeviceBase(
   6.666 +      DeviceExtension,
   6.667 +      PNPBus, //AdapterInterfaceType,
   6.668 +      ConfigInfo->SystemIoBusNumber,
   6.669 +      access_range->RangeStart,
   6.670 +      access_range->RangeLength,
   6.671 +      !access_range->RangeInMemory);
   6.672 +    if (!xvdd->device_base)
   6.673 +    {
   6.674 +      KdPrint((__DRIVER_NAME "     StorPortGetDeviceBase failed\n"));
   6.675 +      FUNCTION_EXIT(); 
   6.676 +      return SP_RETURN_BAD_CONFIG;
   6.677 +    }
   6.678 +    status = XenVbd_InitConfig(xvdd);
   6.679 +    if (status != SP_RETURN_FOUND)
   6.680 +    {
   6.681 +      FUNCTION_EXIT();
   6.682 +      return status;
   6.683 +    }
   6.684 +  }
   6.685 +  else
   6.686 +  {
   6.687 +    xvdd->device_base = ConfigInfo->Reserved;
   6.688 +  }
   6.689 +  
   6.690 +  status = XenVbd_InitFromConfig(xvdd);
   6.691 +  if (status != SP_RETURN_FOUND)
   6.692 +  {
   6.693 +    FUNCTION_EXIT();
   6.694 +    return status;
   6.695 +  }
   6.696 +
   6.697 +  xvdd->aligned_buffer_in_use = FALSE;
   6.698 +  /* align the buffer to PAGE_SIZE */
   6.699 +  xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
   6.700 +  KdPrint((__DRIVER_NAME "     aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
   6.701 +  KdPrint((__DRIVER_NAME "     aligned_buffer = %p\n", xvdd->aligned_buffer));
   6.702 +
   6.703 +  ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
   6.704 +  ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
   6.705 +  KdPrint((__DRIVER_NAME "     ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength));
   6.706 +  KdPrint((__DRIVER_NAME "     ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks));
   6.707 +  if (!dump_mode)
   6.708 +  {
   6.709 +    ConfigInfo->VirtualDevice = TRUE;
   6.710 +  }
   6.711 +  else
   6.712 +  {
   6.713 +    ConfigInfo->VirtualDevice = FALSE;
   6.714 +  }
   6.715 +  
   6.716 +  KdPrint((__DRIVER_NAME "     ConfigInfo->VirtualDevice = %d\n", ConfigInfo->VirtualDevice));
   6.717 +  ConfigInfo->ScatterGather = TRUE;
   6.718 +  ConfigInfo->Master = TRUE;
   6.719 +  ConfigInfo->CachesData = FALSE;
   6.720 +  ConfigInfo->MapBuffers = STOR_MAP_ALL_BUFFERS;
   6.721 +  KdPrint((__DRIVER_NAME "     ConfigInfo->NeedPhysicalAddresses = %d\n", ConfigInfo->NeedPhysicalAddresses));
   6.722 +  ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
   6.723 +  ConfigInfo->AlignmentMask = 0;
   6.724 +  ConfigInfo->NumberOfBuses = 1;
   6.725 +  ConfigInfo->InitiatorBusId[0] = 1;
   6.726 +  ConfigInfo->MaximumNumberOfLogicalUnits = 1;
   6.727 +  ConfigInfo->MaximumNumberOfTargets = 2;
   6.728 +  //ConfigInfo->BufferAccessScsiPortControlled = FALSE;
   6.729 +  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
   6.730 +  {
   6.731 +    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
   6.732 +    //ConfigInfo->Dma32BitAddresses = FALSE;
   6.733 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
   6.734 +  }
   6.735 +  else
   6.736 +  {
   6.737 +    //ConfigInfo->Dma32BitAddresses = TRUE;
   6.738 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
   6.739 +  }
   6.740 +
   6.741 +  FUNCTION_EXIT();
   6.742 +
   6.743 +  return SP_RETURN_FOUND;
   6.744 +}
   6.745 +
   6.746 +static ULONG
   6.747 +XenVbd_HwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
   6.748 +{
   6.749 +  ULONG status;
   6.750 +  
   6.751 +  FUNCTION_ENTER();
   6.752 +  status = XenVbd_VirtualHwStorFindAdapter(DeviceExtension, HwContext, BusInformation, NULL, ArgumentString, ConfigInfo, Again);
   6.753 +  FUNCTION_EXIT();
   6.754 +  return status;
   6.755 +}
   6.756 +
   6.757 +//do this in StartIo instead to prevent races with the driver initialisation
   6.758 +static VOID
   6.759 +XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
   6.760 +{
   6.761 +  blkif_request_t *req;
   6.762 +  int notify;
   6.763 +
   6.764 +  xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
   6.765 +  RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
   6.766 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   6.767 +  req->operation = 0xff;
   6.768 +  xvdd->ring.req_prod_pvt++;
   6.769 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   6.770 +  req->operation = 0xff;
   6.771 +  xvdd->ring.req_prod_pvt++;
   6.772 +
   6.773 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   6.774 +  if (notify)
   6.775 +    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   6.776 +}
   6.777 +
   6.778 +static BOOLEAN
   6.779 +XenVbd_HwStorInitialize(PVOID DeviceExtension)
   6.780 +{
   6.781 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   6.782 +  
   6.783 +  FUNCTION_ENTER();
   6.784 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   6.785 +  KdPrint((__DRIVER_NAME "     dump_mode = %d\n", dump_mode));
   6.786 +
   6.787 +  if (!xvdd->inactive)
   6.788 +  {
   6.789 +    if (dump_mode)
   6.790 +    {
   6.791 +      if (xvdd->cached_use_other)
   6.792 +      {
   6.793 +        xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   6.794 +        xvdd->use_other = TRUE;
   6.795 +      }
   6.796 +      xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
   6.797 +    }
   6.798 +    InitializeListHead(&xvdd->srb_list);
   6.799 +  }
   6.800 +  FUNCTION_EXIT();
   6.801 +
   6.802 +  return TRUE;
   6.803 +}
   6.804 +
   6.805 +static ULONG
   6.806 +XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   6.807 +{
   6.808 +  PMODE_PARAMETER_HEADER parameter_header = NULL;
   6.809 +  PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
   6.810 +  PMODE_PARAMETER_BLOCK param_block;
   6.811 +  PMODE_FORMAT_PAGE format_page;
   6.812 +  ULONG offset = 0;
   6.813 +  UCHAR buffer[1024];
   6.814 +  BOOLEAN valid_page = FALSE;
   6.815 +  BOOLEAN cdb_llbaa;
   6.816 +  BOOLEAN cdb_dbd;
   6.817 +  UCHAR cdb_page_code;
   6.818 +  USHORT cdb_allocation_length;
   6.819 +
   6.820 +  UNREFERENCED_PARAMETER(xvdd);
   6.821 +
   6.822 +  RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
   6.823 +  RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
   6.824 +  offset = 0;
   6.825 +
   6.826 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   6.827 +  
   6.828 +  switch (srb->Cdb[0])
   6.829 +  {
   6.830 +  case SCSIOP_MODE_SENSE:
   6.831 +    cdb_llbaa = FALSE;
   6.832 +    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   6.833 +    cdb_page_code = srb->Cdb[2] & 0x3f;
   6.834 +    cdb_allocation_length = srb->Cdb[4];
   6.835 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   6.836 +      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   6.837 +    parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
   6.838 +    parameter_header->MediumType = 0;
   6.839 +    parameter_header->DeviceSpecificParameter = 0;
   6.840 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   6.841 +    {
   6.842 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   6.843 +      parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   6.844 +    }
   6.845 +    offset += sizeof(MODE_PARAMETER_HEADER);
   6.846 +    break;
   6.847 +  case SCSIOP_MODE_SENSE10:
   6.848 +    cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
   6.849 +    cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
   6.850 +    cdb_page_code = srb->Cdb[2] & 0x3f;
   6.851 +    cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
   6.852 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
   6.853 +      cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
   6.854 +    parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
   6.855 +    parameter_header10->MediumType = 0;
   6.856 +    parameter_header10->DeviceSpecificParameter = 0;
   6.857 +    if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
   6.858 +    {
   6.859 +      KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
   6.860 +      parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
   6.861 +    }
   6.862 +    offset += sizeof(MODE_PARAMETER_HEADER10);
   6.863 +    break;
   6.864 +  default:
   6.865 +    KdPrint((__DRIVER_NAME "     SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
   6.866 +    return FALSE;
   6.867 +  }  
   6.868 +  
   6.869 +  if (!cdb_dbd)
   6.870 +  {
   6.871 +    param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
   6.872 +    if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
   6.873 +    {
   6.874 +      if (xvdd->total_sectors >> 32) 
   6.875 +      {
   6.876 +        param_block->DensityCode = 0xff;
   6.877 +        param_block->NumberOfBlocks[0] = 0xff;
   6.878 +        param_block->NumberOfBlocks[1] = 0xff;
   6.879 +        param_block->NumberOfBlocks[2] = 0xff;
   6.880 +      }
   6.881 +      else
   6.882 +      {
   6.883 +        param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
   6.884 +        param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
   6.885 +        param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
   6.886 +        param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
   6.887 +      }
   6.888 +      param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
   6.889 +      param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
   6.890 +      param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
   6.891 +    }
   6.892 +    offset += sizeof(MODE_PARAMETER_BLOCK);
   6.893 +  }
   6.894 +  switch (srb->Cdb[0])
   6.895 +  {
   6.896 +  case SCSIOP_MODE_SENSE:
   6.897 +    parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
   6.898 +    break;
   6.899 +  case SCSIOP_MODE_SENSE10:
   6.900 +    parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
   6.901 +    parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
   6.902 +    break;
   6.903 +  }
   6.904 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
   6.905 +  {
   6.906 +    valid_page = TRUE;
   6.907 +    format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
   6.908 +    format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
   6.909 +    format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
   6.910 +    /* 256 sectors per track */
   6.911 +    format_page->SectorsPerTrack[0] = 0x01;
   6.912 +    format_page->SectorsPerTrack[1] = 0x00;
   6.913 +    /* xxx bytes per sector */
   6.914 +    format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
   6.915 +    format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
   6.916 +    format_page->HardSectorFormating = TRUE;
   6.917 +    format_page->SoftSectorFormating = TRUE;
   6.918 +    offset += sizeof(MODE_FORMAT_PAGE);
   6.919 +  }
   6.920 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
   6.921 +  {
   6.922 +    PMODE_CACHING_PAGE caching_page;
   6.923 +    valid_page = TRUE;
   6.924 +    caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
   6.925 +    caching_page->PageCode = MODE_PAGE_CACHING;
   6.926 +    caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
   6.927 +    // caching_page-> // all zeros is just fine... maybe
   6.928 +    offset += sizeof(MODE_CACHING_PAGE);
   6.929 +  }
   6.930 +  if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
   6.931 +  {
   6.932 +    PUCHAR medium_types_page;
   6.933 +    valid_page = TRUE;
   6.934 +    medium_types_page = &buffer[offset];
   6.935 +    medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
   6.936 +    medium_types_page[1] = 0x06;
   6.937 +    medium_types_page[2] = 0;
   6.938 +    medium_types_page[3] = 0;
   6.939 +    medium_types_page[4] = 0;
   6.940 +    medium_types_page[5] = 0;
   6.941 +    medium_types_page[6] = 0;
   6.942 +    medium_types_page[7] = 0;
   6.943 +    offset += 8;
   6.944 +  }
   6.945 +  switch (srb->Cdb[0])
   6.946 +  {
   6.947 +  case SCSIOP_MODE_SENSE:
   6.948 +    parameter_header->ModeDataLength = (UCHAR)(offset - 1);
   6.949 +    break;
   6.950 +  case SCSIOP_MODE_SENSE10:
   6.951 +    parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
   6.952 +    parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
   6.953 +    break;
   6.954 +  }
   6.955 +
   6.956 +  if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
   6.957 +  {
   6.958 +    srb->SrbStatus = SRB_STATUS_ERROR;
   6.959 +  }
   6.960 +  else if(offset < srb->DataTransferLength)
   6.961 +    srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
   6.962 +  else
   6.963 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
   6.964 +  srb->DataTransferLength = min(srb->DataTransferLength, offset);
   6.965 +  srb->ScsiStatus = 0;
   6.966 +  memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
   6.967 +  
   6.968 +  //FUNCTION_EXIT();
   6.969 +
   6.970 +  return TRUE;
   6.971 +}
   6.972 +
   6.973 +static ULONG
   6.974 +XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
   6.975 +{
   6.976 +  PSENSE_DATA sd = srb->SenseInfoBuffer;
   6.977 + 
   6.978 +  UNREFERENCED_PARAMETER(xvdd);
   6.979 +  
   6.980 +  if (!srb->SenseInfoBuffer)
   6.981 +    return 0;
   6.982 +  
   6.983 +  sd->ErrorCode = 0x70;
   6.984 +  sd->Valid = 1;
   6.985 +  sd->SenseKey = sense_key;
   6.986 +  sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
   6.987 +  sd->AdditionalSenseCode = additional_sense_code;
   6.988 +  return sizeof(SENSE_DATA);
   6.989 +}
   6.990 +
   6.991 +static VOID
   6.992 +XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
   6.993 +{
   6.994 +  if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
   6.995 +    return;
   6.996 +  XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
   6.997 +  srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
   6.998 +}
   6.999 +
  6.1000 +static BOOLEAN
  6.1001 +XenVbd_HandleEventSynchronised(PVOID DeviceExtension, PVOID context)
  6.1002 +{
  6.1003 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
  6.1004 +  PSCSI_REQUEST_BLOCK srb;
  6.1005 +  RING_IDX i, rp;
  6.1006 +  ULONG j;
  6.1007 +  blkif_response_t *rep;
  6.1008 +  int block_count;
  6.1009 +  int more_to_do = TRUE;
  6.1010 +  blkif_shadow_t *shadow;
  6.1011 +  ULONG suspend_resume_state_pdo;
  6.1012 +
  6.1013 +  UNREFERENCED_PARAMETER(context);
  6.1014 +  
  6.1015 +  //if (dump_mode) FUNCTION_ENTER();
  6.1016 +
  6.1017 +  suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
  6.1018 +  KeMemoryBarrier();
  6.1019 +
  6.1020 +  if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
  6.1021 +  {
  6.1022 +    //FUNCTION_ENTER();
  6.1023 +    switch (suspend_resume_state_pdo)
  6.1024 +    {
  6.1025 +      case SR_STATE_SUSPENDING:
  6.1026 +        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_SUSPENDING\n"));
  6.1027 +        break;
  6.1028 +      case SR_STATE_RESUMING:
  6.1029 +        KdPrint((__DRIVER_NAME "     New pdo state SR_STATE_RESUMING\n"));
  6.1030 +        XenVbd_InitFromConfig(xvdd);
  6.1031 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  6.1032 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  6.1033 +        break;
  6.1034 +      case SR_STATE_RUNNING:
  6.1035 +        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
  6.1036 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  6.1037 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  6.1038 +      default:
  6.1039 +        KdPrint((__DRIVER_NAME "     New pdo state %d\n", suspend_resume_state_pdo));
  6.1040 +        xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  6.1041 +        xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  6.1042 +        break;
  6.1043 +    }
  6.1044 +    KeMemoryBarrier();
  6.1045 +  }
  6.1046 +
  6.1047 +  if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
  6.1048 +  {
  6.1049 +    return TRUE;
  6.1050 +  }
  6.1051 +
  6.1052 +  while (more_to_do)
  6.1053 +  {
  6.1054 +    rp = xvdd->ring.sring->rsp_prod;
  6.1055 +    KeMemoryBarrier();
  6.1056 +    for (i = xvdd->ring.rsp_cons; i < rp; i++)
  6.1057 +    {
  6.1058 +      rep = XenVbd_GetResponse(xvdd, i);
  6.1059 +/*
  6.1060 +* This code is to automatically detect if the backend is using the same
  6.1061 +* bit width or a different bit width to us. Later versions of Xen do this
  6.1062 +* via a xenstore value, but not all. That 0x0fffffff (notice
  6.1063 +* that the msb is not actually set, so we don't have any problems with
  6.1064 +* sign extending) is to signify the last entry on the right, which is
  6.1065 +* different under 32 and 64 bits, and that is why we set it up there.
  6.1066 +
  6.1067 +* To do the detection, we put two initial entries on the ring, with an op
  6.1068 +* of 0xff (which is invalid). The first entry is mostly okay, but the
  6.1069 +* second will be grossly misaligned if the backend bit width is different,
  6.1070 +* and we detect this and switch frontend structures.
  6.1071 +*/
  6.1072 +      switch (xvdd->ring_detect_state)
  6.1073 +      {
  6.1074 +      case RING_DETECT_STATE_NOT_STARTED:
  6.1075 +        KdPrint((__DRIVER_NAME "     premature IRQ\n"));
  6.1076 +        break;
  6.1077 +      case RING_DETECT_STATE_DETECT1:
  6.1078 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
  6.1079 +        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
  6.1080 +        xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
  6.1081 +        break;
  6.1082 +      case RING_DETECT_STATE_DETECT2:
  6.1083 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, index = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, i, rep->operation, rep->id, rep->status));
  6.1084 +        KdPrint((__DRIVER_NAME "     req_prod = %d, rsp_prod = %d, rsp_cons = %d\n", xvdd->sring->req_prod, xvdd->sring->rsp_prod, xvdd->ring.rsp_cons));
  6.1085 +        *xvdd->event_channel_ptr |= 0x80000000;
  6.1086 +        if (rep->operation != 0xff)
  6.1087 +        {
  6.1088 +          KdPrint((__DRIVER_NAME "     switching to 'other' ring size\n"));
  6.1089 +          xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
  6.1090 +          xvdd->use_other = TRUE;
  6.1091 +          *xvdd->event_channel_ptr |= 0x40000000;
  6.1092 +        }
  6.1093 +        xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
  6.1094 +        break;
  6.1095 +      case RING_DETECT_STATE_COMPLETE:
  6.1096 +        shadow = &xvdd->shadows[rep->id];
  6.1097 +        srb = shadow->srb;
  6.1098 +        //KdPrint((__DRIVER_NAME "     srb = %p\n", srb));
  6.1099 +        ASSERT(srb != NULL);
  6.1100 +        block_count = decode_cdb_length(srb);
  6.1101 +        block_count *= xvdd->bytes_per_sector / 512;
  6.1102 +        /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
  6.1103 +        if (rep->status == BLKIF_RSP_OKAY || (dump_mode &&  dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
  6.1104 +          srb->SrbStatus = SRB_STATUS_SUCCESS;
  6.1105 +        else
  6.1106 +        {
  6.1107 +          KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
  6.1108 +          if (decode_cdb_is_read(srb))
  6.1109 +            KdPrint((__DRIVER_NAME "     Operation = Read\n"));
  6.1110 +          else
  6.1111 +            KdPrint((__DRIVER_NAME "     Operation = Write\n"));
  6.1112 +          if (!dump_mode)
  6.1113 +          {
  6.1114 +            KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
  6.1115 +            KdPrint((__DRIVER_NAME "     DataBuffer = %p\n", srb->DataBuffer));
  6.1116 +            KdPrint((__DRIVER_NAME "     Physical = %08x%08x\n", MmGetPhysicalAddress(shadow->system_address).HighPart, MmGetPhysicalAddress(shadow->system_address).LowPart));
  6.1117 +            KdPrint((__DRIVER_NAME "     PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(shadow->system_address).QuadPart >> PAGE_SHIFT)));
  6.1118 +
  6.1119 +            for (j = 0; j < shadow->req.nr_segments; j++)
  6.1120 +            {
  6.1121 +              KdPrint((__DRIVER_NAME "     gref = %d\n", shadow->req.seg[j].gref));
  6.1122 +              KdPrint((__DRIVER_NAME "     first_sect = %d\n", shadow->req.seg[j].first_sect));
  6.1123 +              KdPrint((__DRIVER_NAME "     last_sect = %d\n", shadow->req.seg[j].last_sect));
  6.1124 +            }
  6.1125 +          }
  6.1126 +          srb->SrbStatus = SRB_STATUS_ERROR;
  6.1127 +          srb->ScsiStatus = 0x02;
  6.1128 +          xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
  6.1129 +          xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  6.1130 +          XenVbd_MakeAutoSense(xvdd, srb);
  6.1131 +        }
  6.1132 +        if (shadow->aligned_buffer_in_use)
  6.1133 +        {
  6.1134 +          ASSERT(xvdd->aligned_buffer_in_use);
  6.1135 +          xvdd->aligned_buffer_in_use = FALSE;
  6.1136 +          if (decode_cdb_is_read(srb))
  6.1137 +            memcpy(shadow->system_address, xvdd->aligned_buffer, block_count * 512);
  6.1138 +        }
  6.1139 +        
  6.1140 +        for (j = 0; j < shadow->req.nr_segments; j++)
  6.1141 +        {
  6.1142 +          if (dump_mode)
  6.1143 +          {
  6.1144 +            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  6.1145 +              shadow->req.seg[j].gref, TRUE, (ULONG)'XPDO');
  6.1146 +          }
  6.1147 +          else
  6.1148 +          {
  6.1149 +            xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
  6.1150 +              shadow->req.seg[j].gref, FALSE, (ULONG)'XVBD');
  6.1151 +          }
  6.1152 +        }
  6.1153 +        shadow->aligned_buffer_in_use = FALSE;
  6.1154 +        shadow->srb = NULL;
  6.1155 +        put_shadow_on_freelist(xvdd, shadow);
  6.1156 +        //if (dump_mode) KdPrint((__DRIVER_NAME "     srb = %p\n", srb));
  6.1157 +        StorPortNotification(RequestComplete, xvdd, srb);
  6.1158 +        break;
  6.1159 +      }
  6.1160 +    }
  6.1161 +
  6.1162 +    xvdd->ring.rsp_cons = i;
  6.1163 +    if (i != xvdd->ring.req_prod_pvt)
  6.1164 +    {
  6.1165 +      RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
  6.1166 +    }
  6.1167 +    else
  6.1168 +    {
  6.1169 +      xvdd->ring.sring->rsp_event = i + 1;
  6.1170 +      more_to_do = FALSE;
  6.1171 +    }
  6.1172 +  }
  6.1173 +
  6.1174 +  //if (start_ring_detect_state == RING_DETECT_STATE_COMPLETE)
  6.1175 +  XenVbd_PutQueuedSrbsOnRing(xvdd);
  6.1176 +
  6.1177 +  if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
  6.1178 +  {
  6.1179 +    if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
  6.1180 +    {
  6.1181 +      /* all entries are purged from the list (or we are inactive). ready to suspend */
  6.1182 +      xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
  6.1183 +      KeMemoryBarrier();
  6.1184 +      KdPrint((__DRIVER_NAME "     Set fdo state SR_STATE_SUSPENDING\n"));
  6.1185 +      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
  6.1186 +      xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
  6.1187 +    }
  6.1188 +  }
  6.1189 +  //if (dump_mode) FUNCTION_EXIT();
  6.1190 +
  6.1191 +  return TRUE;
  6.1192 +}
  6.1193 +
  6.1194 +static BOOLEAN
  6.1195 +XenVbd_HandleEvent(PVOID DeviceExtension)
  6.1196 +{
  6.1197 +  BOOLEAN retval;
  6.1198 +  
  6.1199 +  //if (dump_mode) FUNCTION_ENTER();
  6.1200 +  retval = StorPortSynchronizeAccess(DeviceExtension, XenVbd_HandleEventSynchronised, NULL);
  6.1201 +  //if (dump_mode) FUNCTION_EXIT();
  6.1202 +  return retval;
  6.1203 +}
  6.1204 +
  6.1205 +/* this is only used during hiber and dump */
  6.1206 +static BOOLEAN
  6.1207 +XenVbd_HwStorInterrupt(PVOID DeviceExtension)
  6.1208 +{
  6.1209 +  BOOLEAN retval;
  6.1210 +  
  6.1211 +  //FUNCTION_ENTER();
  6.1212 +  retval = XenVbd_HandleEventSynchronised(DeviceExtension, NULL);
  6.1213 +  //FUNCTION_EXIT();
  6.1214 +  return retval;
  6.1215 +}
  6.1216 +
  6.1217 +static BOOLEAN
  6.1218 +XenVbd_HwStorStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
  6.1219 +{
  6.1220 +  PUCHAR data_buffer;
  6.1221 +  PSCSI_PNP_REQUEST_BLOCK sprb;
  6.1222 +  PMINIPORT_DUMP_POINTERS dump_pointers;
  6.1223 +  PCDB cdb;
  6.1224 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  6.1225 +  ULONG data_transfer_length;
  6.1226 +  UCHAR srb_status = SRB_STATUS_PENDING;
  6.1227 +
  6.1228 +  //if (dump_mode) FUNCTION_ENTER();
  6.1229 +  //if (dump_mode) KdPrint((__DRIVER_NAME "     srb = %p\n", srb));
  6.1230 +
  6.1231 +  data_transfer_length = srb->DataTransferLength;
  6.1232 +  
  6.1233 +  if (xvdd->inactive)
  6.1234 +  {
  6.1235 +    KdPrint((__DRIVER_NAME "     Inactive srb->Function = %08X\n", srb->Function));
  6.1236 +    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  6.1237 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1238 +    return TRUE;
  6.1239 +  }
  6.1240 +
  6.1241 +  if (xvdd->ring_detect_state == RING_DETECT_STATE_NOT_STARTED)
  6.1242 +  {
  6.1243 +    XenVbd_StartRingDetection(DeviceExtension);
  6.1244 +  }
  6.1245 +
  6.1246 +  // If we haven't enumerated all the devices yet then just defer the request
  6.1247 +  if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
  6.1248 +  {
  6.1249 +    srb->SrbStatus = SRB_STATUS_BUSY;
  6.1250 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1251 +    KdPrint((__DRIVER_NAME " --- HwStorStartIo (Still figuring out ring)\n"));
  6.1252 +    return TRUE;
  6.1253 +  }
  6.1254 +
  6.1255 +  if (!dump_mode && xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
  6.1256 +  {
  6.1257 +    KdPrint((__DRIVER_NAME " --> HwStorStartIo (Suspending/Resuming)\n"));
  6.1258 +    srb->SrbStatus = SRB_STATUS_BUSY;
  6.1259 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1260 +    KdPrint((__DRIVER_NAME " <-- HwStorStartIo (Suspending/Resuming)\n"));
  6.1261 +    return TRUE;
  6.1262 +  }
  6.1263 +
  6.1264 +  if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
  6.1265 +  {
  6.1266 +    srb->SrbStatus = SRB_STATUS_NO_DEVICE;
  6.1267 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1268 +    KdPrint((__DRIVER_NAME " --- HwStorStartIo (Out of bounds - PathId = %d, TargetId = %d, Lun = %d)\n", srb->PathId, srb->TargetId, srb->Lun));
  6.1269 +    return TRUE;
  6.1270 +  }
  6.1271 +
  6.1272 +  switch (srb->Function)
  6.1273 +  {
  6.1274 +  case SRB_FUNCTION_EXECUTE_SCSI:
  6.1275 +    cdb = (PCDB)srb->Cdb;
  6.1276 +
  6.1277 +    switch(cdb->CDB6GENERIC.OperationCode)
  6.1278 +    {
  6.1279 +    case SCSIOP_TEST_UNIT_READY:
  6.1280 +      if (dump_mode)
  6.1281 +        KdPrint((__DRIVER_NAME "     Command = TEST_UNIT_READY\n"));
  6.1282 +      srb_status = SRB_STATUS_SUCCESS;
  6.1283 +      srb->ScsiStatus = 0;
  6.1284 +      break;
  6.1285 +    case SCSIOP_INQUIRY:
  6.1286 +      if (dump_mode)
  6.1287 +        KdPrint((__DRIVER_NAME "     Command = INQUIRY\n"));
  6.1288 +//      KdPrint((__DRIVER_NAME "     (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
  6.1289 +//      KdPrint((__DRIVER_NAME "     (Length = %d)\n", srb->DataTransferLength));
  6.1290 +      
  6.1291 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  6.1292 +      data_buffer = srb->DataBuffer;
  6.1293 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  6.1294 +      srb_status = SRB_STATUS_SUCCESS;
  6.1295 +      switch (xvdd->device_type)
  6.1296 +      {
  6.1297 +      case XENVBD_DEVICETYPE_DISK:
  6.1298 +        if ((srb->Cdb[1] & 1) == 0)
  6.1299 +        {
  6.1300 +          if (srb->Cdb[2])
  6.1301 +          {
  6.1302 +            srb_status = SRB_STATUS_ERROR;
  6.1303 +          }
  6.1304 +          else
  6.1305 +          {
  6.1306 +            PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  6.1307 +            id->DeviceType = DIRECT_ACCESS_DEVICE;
  6.1308 +            id->Versions = 4; /* minimum that WHQL says we must support */
  6.1309 +            id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
  6.1310 +            id->HiSupport = 1; /* WHQL test says we should set this */
  6.1311 +            //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  6.1312 +            id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
  6.1313 +            id->CommandQueue = 1;
  6.1314 +            memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  6.1315 +            memcpy(id->ProductId, scsi_disk_model, 16); // product id
  6.1316 +            memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  6.1317 +            data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
  6.1318 +          }
  6.1319 +        }
  6.1320 +        else
  6.1321 +        {
  6.1322 +          switch (srb->Cdb[2])
  6.1323 +          {
  6.1324 +          case VPD_SUPPORTED_PAGES: /* list of pages we support */
  6.1325 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  6.1326 +            data_buffer[1] = VPD_SUPPORTED_PAGES;
  6.1327 +            data_buffer[2] = 0x00;
  6.1328 +            data_buffer[3] = 2;
  6.1329 +            data_buffer[4] = 0x00;
  6.1330 +            data_buffer[5] = 0x80;
  6.1331 +            data_transfer_length = 6;
  6.1332 +            break;
  6.1333 +          case VPD_SERIAL_NUMBER: /* serial number */
  6.1334 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  6.1335 +            data_buffer[1] = VPD_SERIAL_NUMBER;
  6.1336 +            data_buffer[2] = 0x00;
  6.1337 +            data_buffer[3] = 8;
  6.1338 +            memset(&data_buffer[4], ' ', 8);
  6.1339 +            data_transfer_length = 12;
  6.1340 +            break;
  6.1341 +          case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
  6.1342 +            data_buffer[0] = DIRECT_ACCESS_DEVICE;
  6.1343 +            data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
  6.1344 +            data_buffer[2] = 0x00;
  6.1345 +            data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
  6.1346 +            data_buffer[4] = 2; /* ASCII */
  6.1347 +            data_buffer[5] = 1; /* VendorId */
  6.1348 +            data_buffer[6] = 0;
  6.1349 +            data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
  6.1350 +            memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
  6.1351 +            data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
  6.1352 +            break;
  6.1353 +          default:
  6.1354 +            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  6.1355 +            srb_status = SRB_STATUS_ERROR;
  6.1356 +            break;
  6.1357 +          }
  6.1358 +        }
  6.1359 +        break;
  6.1360 +      case XENVBD_DEVICETYPE_CDROM:
  6.1361 +        if ((srb->Cdb[1] & 1) == 0)
  6.1362 +        {
  6.1363 +          PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
  6.1364 +          id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
  6.1365 +          id->RemovableMedia = 1;
  6.1366 +          id->Versions = 3;
  6.1367 +          id->ResponseDataFormat = 0;
  6.1368 +          id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
  6.1369 +          id->CommandQueue = 1;
  6.1370 +          memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
  6.1371 +          memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
  6.1372 +          memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
  6.1373 +          data_transfer_length = sizeof(INQUIRYDATA);
  6.1374 +        }
  6.1375 +        else
  6.1376 +        {
  6.1377 +          switch (srb->Cdb[2])
  6.1378 +          {
  6.1379 +          case 0x00:
  6.1380 +            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  6.1381 +            data_buffer[1] = 0x00;
  6.1382 +            data_buffer[2] = 0x00;
  6.1383 +            data_buffer[3] = 2;
  6.1384 +            data_buffer[4] = 0x00;
  6.1385 +            data_buffer[5] = 0x80;
  6.1386 +            data_transfer_length = 6;
  6.1387 +            break;
  6.1388 +          case 0x80:
  6.1389 +            data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
  6.1390 +            data_buffer[1] = 0x80;
  6.1391 +            data_buffer[2] = 0x00;
  6.1392 +            data_buffer[3] = 8;
  6.1393 +            data_buffer[4] = 0x31;
  6.1394 +            data_buffer[5] = 0x32;
  6.1395 +            data_buffer[6] = 0x33;
  6.1396 +            data_buffer[7] = 0x34;
  6.1397 +            data_buffer[8] = 0x35;
  6.1398 +            data_buffer[9] = 0x36;
  6.1399 +            data_buffer[10] = 0x37;
  6.1400 +            data_buffer[11] = 0x38;
  6.1401 +            data_transfer_length = 12;
  6.1402 +            break;
  6.1403 +          default:
  6.1404 +            //KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", srb->Cdb[2]));
  6.1405 +            srb_status = SRB_STATUS_ERROR;
  6.1406 +            break;
  6.1407 +          }
  6.1408 +        }
  6.1409 +        break;
  6.1410 +      default:
  6.1411 +        //KdPrint((__DRIVER_NAME "     Unknown DeviceType %02x requested\n", xvdd->device_type));
  6.1412 +        srb_status = SRB_STATUS_ERROR;
  6.1413 +        break;
  6.1414 +      }
  6.1415 +      break;
  6.1416 +    case SCSIOP_READ_CAPACITY:
  6.1417 +      if (dump_mode)
  6.1418 +        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  6.1419 +      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  6.1420 +      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  6.1421 +      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  6.1422 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  6.1423 +      data_buffer = srb->DataBuffer;
  6.1424 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  6.1425 +      if ((xvdd->total_sectors - 1) >> 32)
  6.1426 +      {
  6.1427 +        data_buffer[0] = 0xff;
  6.1428 +        data_buffer[1] = 0xff;
  6.1429 +        data_buffer[2] = 0xff;
  6.1430 +        data_buffer[3] = 0xff;
  6.1431 +      }
  6.1432 +      else
  6.1433 +      {
  6.1434 +        data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  6.1435 +        data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  6.1436 +        data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  6.1437 +        data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  6.1438 +      }
  6.1439 +      data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  6.1440 +      data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  6.1441 +      data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  6.1442 +      data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  6.1443 +      data_transfer_length = 8;
  6.1444 +      srb->ScsiStatus = 0;
  6.1445 +      srb_status = SRB_STATUS_SUCCESS;
  6.1446 +      break;
  6.1447 +    case SCSIOP_READ_CAPACITY16:
  6.1448 +      if (dump_mode)
  6.1449 +        KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
  6.1450 +      //KdPrint((__DRIVER_NAME "       LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
  6.1451 +      //KdPrint((__DRIVER_NAME "       LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
  6.1452 +      //KdPrint((__DRIVER_NAME "       PMI = %d\n", srb->Cdb[8] & 1));
  6.1453 +      //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
  6.1454 +      data_buffer = srb->DataBuffer;
  6.1455 +      RtlZeroMemory(data_buffer, srb->DataTransferLength);
  6.1456 +      data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
  6.1457 +      data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
  6.1458 +      data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
  6.1459 +      data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
  6.1460 +      data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
  6.1461 +      data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
  6.1462 +      data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
  6.1463 +      data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
  6.1464 +      data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
  6.1465 +      data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
  6.1466 +      data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
  6.1467 +      data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
  6.1468 +      data_transfer_length = 12;
  6.1469 +      srb->ScsiStatus = 0;
  6.1470 +      srb_status = SRB_STATUS_SUCCESS;
  6.1471 +      break;
  6.1472 +    case SCSIOP_MODE_SENSE:
  6.1473 +    case SCSIOP_MODE_SENSE10:
  6.1474 +      if (dump_mode)
  6.1475 +        KdPrint((__DRIVER_NAME "     Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", srb->Cdb[1] & 0x08, srb->Cdb[2] & 0xC0, srb->Cdb[2] & 0x3F));
  6.1476 +      data_transfer_length = XenVbd_FillModePage(xvdd, srb);
  6.1477 +      srb_status = SRB_STATUS_SUCCESS;
  6.1478 +      break;
  6.1479 +    case SCSIOP_READ:
  6.1480 +    case SCSIOP_READ16:
  6.1481 +    case SCSIOP_WRITE:
  6.1482 +    case SCSIOP_WRITE16:
  6.1483 +      //KdPrint((__DRIVER_NAME "     srb = %p\n", srb));  
  6.1484 +      XenVbd_PutSrbOnList(xvdd, srb);
  6.1485 +      XenVbd_PutQueuedSrbsOnRing(xvdd);
  6.1486 +      break;
  6.1487 +    case SCSIOP_VERIFY:
  6.1488 +    case SCSIOP_VERIFY16:
  6.1489 +      // Should we do more here?
  6.1490 +      if (dump_mode)
  6.1491 +        KdPrint((__DRIVER_NAME "     Command = VERIFY\n"));
  6.1492 +      srb_status = SRB_STATUS_SUCCESS;
  6.1493 +      break;
  6.1494 +#if 0
  6.1495 +    case SCSIOP_REPORT_LUNS:
  6.1496 +      if (dump_mode)
  6.1497 +        KdPrint((__DRIVER_NAME "     Command = REPORT_LUNS\n"));
  6.1498 +      switch (srb->Cdb[1])
  6.1499 +      {
  6.1500 +      }
  6.1501 +      srb_status = SRB_STATUS_SUCCESS;;
  6.1502 +      break;
  6.1503 +#endif
  6.1504 +    case SCSIOP_REQUEST_SENSE:
  6.1505 +      if (dump_mode)
  6.1506 +        KdPrint((__DRIVER_NAME "     Command = REQUEST_SENSE\n"));
  6.1507 +      data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
  6.1508 +      srb_status = SRB_STATUS_SUCCESS;
  6.1509 +      break;      
  6.1510 +    case SCSIOP_READ_TOC:
  6.1511 +      if (dump_mode)
  6.1512 +        KdPrint((__DRIVER_NAME "     Command = READ_TOC\n"));
  6.1513 +      data_buffer = srb->DataBuffer;
  6.1514 +/*
  6.1515 +#define READ_TOC_FORMAT_TOC         0x00
  6.1516 +#define READ_TOC_FORMAT_SESSION     0x01
  6.1517 +#define READ_TOC_FORMAT_FULL_TOC    0x02
  6.1518 +#define READ_TOC_FORMAT_PMA         0x03
  6.1519 +#define READ_TOC_FORMAT_ATIP        0x04
  6.1520 +*/
  6.1521 +//      KdPrint((__DRIVER_NAME "     Msf = %d\n", cdb->READ_TOC.Msf));
  6.1522 +//      KdPrint((__DRIVER_NAME "     LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
  6.1523 +//      KdPrint((__DRIVER_NAME "     Format2 = %d\n", cdb->READ_TOC.Format2));
  6.1524 +//      KdPrint((__DRIVER_NAME "     StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
  6.1525 +//      KdPrint((__DRIVER_NAME "     AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
  6.1526 +//      KdPrint((__DRIVER_NAME "     Control = %d\n", cdb->READ_TOC.Control));
  6.1527 +//      KdPrint((__DRIVER_NAME "     Format = %d\n", cdb->READ_TOC.Format));
  6.1528 +      switch (cdb->READ_TOC.Format2)
  6.1529 +      {
  6.1530 +      case READ_TOC_FORMAT_TOC:
  6.1531 +        data_buffer[0] = 0; // length MSB
  6.1532 +        data_buffer[1] = 10; // length LSB
  6.1533 +        data_buffer[2] = 1; // First Track
  6.1534 +        data_buffer[3] = 1; // Last Track
  6.1535 +        data_buffer[4] = 0; // Reserved
  6.1536 +        data_buffer[5] = 0x14; // current position data + uninterrupted data
  6.1537 +        data_buffer[6] = 1; // last complete track
  6.1538 +        data_buffer[7] = 0; // reserved
  6.1539 +        data_buffer[8] = 0; // MSB Block
  6.1540 +        data_buffer[9] = 0;
  6.1541 +        data_buffer[10] = 0;
  6.1542 +        data_buffer[11] = 0; // LSB Block
  6.1543 +        data_transfer_length = 12;
  6.1544 +        srb_status = SRB_STATUS_SUCCESS;
  6.1545 +        break;
  6.1546 +      case READ_TOC_FORMAT_SESSION:
  6.1547 +      case READ_TOC_FORMAT_FULL_TOC:
  6.1548 +      case READ_TOC_FORMAT_PMA:
  6.1549 +      case READ_TOC_FORMAT_ATIP:
  6.1550 +        srb_status = SRB_STATUS_ERROR;
  6.1551 +        break;
  6.1552 +      default:
  6.1553 +        srb_status = SRB_STATUS_ERROR;
  6.1554 +        break;
  6.1555 +      }
  6.1556 +      break;
  6.1557 +    case SCSIOP_START_STOP_UNIT:
  6.1558 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_START_STOP_UNIT\n"));
  6.1559 +      srb_status = SRB_STATUS_SUCCESS;
  6.1560 +      break;
  6.1561 +    case SCSIOP_RESERVE_UNIT:
  6.1562 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RESERVE_UNIT\n"));
  6.1563 +      srb_status = SRB_STATUS_SUCCESS;
  6.1564 +      break;
  6.1565 +    case SCSIOP_RELEASE_UNIT:
  6.1566 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_RELEASE_UNIT\n"));
  6.1567 +      srb_status = SRB_STATUS_SUCCESS;
  6.1568 +      break;
  6.1569 +    default:
  6.1570 +      KdPrint((__DRIVER_NAME "     Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
  6.1571 +      srb_status = SRB_STATUS_ERROR;
  6.1572 +      break;
  6.1573 +    }
  6.1574 +    if (srb_status == SRB_STATUS_ERROR)
  6.1575 +    {
  6.1576 +      KdPrint((__DRIVER_NAME "     EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
  6.1577 +      if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
  6.1578 +      {
  6.1579 +        xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
  6.1580 +        xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
  6.1581 +      }
  6.1582 +      srb->SrbStatus = srb_status;
  6.1583 +      srb->ScsiStatus = 0x02;
  6.1584 +      XenVbd_MakeAutoSense(xvdd, srb);
  6.1585 +      StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1586 +    }
  6.1587 +    else if (srb_status != SRB_STATUS_PENDING)
  6.1588 +    {
  6.1589 +      if (data_transfer_length > srb->DataTransferLength)
  6.1590 +        KdPrint((__DRIVER_NAME "     data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength));
  6.1591 +      
  6.1592 +      if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
  6.1593 +      {
  6.1594 +        srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
  6.1595 +        srb->DataTransferLength = data_transfer_length;
  6.1596 +      }
  6.1597 +      else
  6.1598 +      {
  6.1599 +        srb->SrbStatus = srb_status;
  6.1600 +      }
  6.1601 +      xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
  6.1602 +      xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
  6.1603 +      StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1604 +    }
  6.1605 +    break;
  6.1606 +  case SRB_FUNCTION_IO_CONTROL:
  6.1607 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_IO_CONTROL\n"));
  6.1608 +    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  6.1609 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1610 +    break;
  6.1611 +  case SRB_FUNCTION_FLUSH:
  6.1612 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  6.1613 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  6.1614 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1615 +    break;
  6.1616 +  case SRB_FUNCTION_PNP:
  6.1617 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_PNP\n"));
  6.1618 +    sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
  6.1619 +    switch (sprb->PnPAction)
  6.1620 +    {
  6.1621 +    case StorStartDevice:
  6.1622 +      KdPrint((__DRIVER_NAME "      StorStartDevice\n"));
  6.1623 +      break;
  6.1624 +    case StorRemoveDevice:
  6.1625 +      KdPrint((__DRIVER_NAME "      StorRemoveDevice\n"));
  6.1626 +      break;
  6.1627 +    case StorStopDevice:
  6.1628 +      KdPrint((__DRIVER_NAME "      StorStopDevice\n"));
  6.1629 +      break;
  6.1630 +    case StorQueryCapabilities:
  6.1631 +      KdPrint((__DRIVER_NAME "      StorQueryCapabilities\n"));
  6.1632 +      break;
  6.1633 +    case StorFilterResourceRequirements:
  6.1634 +      KdPrint((__DRIVER_NAME "      StorFilterResourceRequirements\n"));
  6.1635 +      break;
  6.1636 +    default:
  6.1637 +      KdPrint((__DRIVER_NAME "      Stor%d\n", sprb->PnPAction));
  6.1638 +      break;
  6.1639 +    }
  6.1640 +    KdPrint((__DRIVER_NAME "      SrbPnPFlags = %08x\n", sprb->SrbPnPFlags));
  6.1641 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  6.1642 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1643 +    break;
  6.1644 +  case SRB_FUNCTION_DUMP_POINTERS:
  6.1645 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_DUMP_POINTERS\n"));
  6.1646 +    KdPrint((__DRIVER_NAME "     DataTransferLength = %d\n", srb->DataTransferLength));
  6.1647 +    //RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
  6.1648 +    dump_pointers = srb->DataBuffer;
  6.1649 +    KdPrint((__DRIVER_NAME "      Version = %d\n", dump_pointers->Version));
  6.1650 +    KdPrint((__DRIVER_NAME "      Size = %d\n", dump_pointers->Size));
  6.1651 +    KdPrint((__DRIVER_NAME "      DriverName = %S\n", dump_pointers->DriverName));
  6.1652 +    KdPrint((__DRIVER_NAME "      AdapterObject = %p\n", dump_pointers->AdapterObject));
  6.1653 +    KdPrint((__DRIVER_NAME "      MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
  6.1654 +    KdPrint((__DRIVER_NAME "      CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
  6.1655 +    KdPrint((__DRIVER_NAME "      MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
  6.1656 +    KdPrint((__DRIVER_NAME "      SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
  6.1657 +    KdPrint((__DRIVER_NAME "      AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
  6.1658 +    KdPrint((__DRIVER_NAME "      MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
  6.1659 +    KdPrint((__DRIVER_NAME "      NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
  6.1660 +    KdPrint((__DRIVER_NAME "      AlignmentMask = %d\n", dump_pointers->AlignmentMask));
  6.1661 +    KdPrint((__DRIVER_NAME "      NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
  6.1662 +    KdPrint((__DRIVER_NAME "      NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
  6.1663 +    KdPrint((__DRIVER_NAME "      Master = %d\n", dump_pointers->Master));
  6.1664 +    KdPrint((__DRIVER_NAME "      MapBuffers = %d\n", dump_pointers->MapBuffers));
  6.1665 +    KdPrint((__DRIVER_NAME "      MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
  6.1666 +
  6.1667 +    dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
  6.1668 +    dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
  6.1669 +    RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
  6.1670 +    dump_pointers->AdapterObject = NULL;
  6.1671 +    dump_pointers->MappedRegisterBase = 0;
  6.1672 +    dump_pointers->CommonBufferSize = 0;
  6.1673 +    dump_pointers->MiniportPrivateDumpData = (PVOID)xvdd->device_base;
  6.1674 +    //dump_pointers->SystemIoBusNumber = 0;
  6.1675 +    dump_pointers->AdapterInterfaceType = Internal;
  6.1676 +    dump_pointers->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;;
  6.1677 +    dump_pointers->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
  6.1678 +    dump_pointers->AlignmentMask = 0;
  6.1679 +    dump_pointers->NumberOfAccessRanges = 1;
  6.1680 +    dump_pointers->NumberOfBuses = 1;
  6.1681 +    dump_pointers->Master = TRUE;
  6.1682 +    dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
  6.1683 +    dump_pointers->MaximumNumberOfTargets = 2;
  6.1684 +
  6.1685 +    KdPrint((__DRIVER_NAME "      Version = %d\n", dump_pointers->Version));
  6.1686 +    KdPrint((__DRIVER_NAME "      Size = %d\n", dump_pointers->Size));
  6.1687 +    KdPrint((__DRIVER_NAME "      DriverName = %S\n", dump_pointers->DriverName));
  6.1688 +    KdPrint((__DRIVER_NAME "      AdapterObject = %p\n", dump_pointers->AdapterObject));
  6.1689 +    KdPrint((__DRIVER_NAME "      MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
  6.1690 +    KdPrint((__DRIVER_NAME "      CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
  6.1691 +    KdPrint((__DRIVER_NAME "      MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
  6.1692 +    KdPrint((__DRIVER_NAME "      SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
  6.1693 +    KdPrint((__DRIVER_NAME "      AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
  6.1694 +    KdPrint((__DRIVER_NAME "      MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
  6.1695 +    KdPrint((__DRIVER_NAME "      NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
  6.1696 +    KdPrint((__DRIVER_NAME "      AlignmentMask = %d\n", dump_pointers->AlignmentMask));
  6.1697 +    KdPrint((__DRIVER_NAME "      NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
  6.1698 +    KdPrint((__DRIVER_NAME "      NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
  6.1699 +    KdPrint((__DRIVER_NAME "      Master = %d\n", dump_pointers->Master));
  6.1700 +    KdPrint((__DRIVER_NAME "      MapBuffers = %d\n", dump_pointers->MapBuffers));
  6.1701 +    KdPrint((__DRIVER_NAME "      MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
  6.1702 +
  6.1703 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  6.1704 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1705 +    break;
  6.1706 +  case SRB_FUNCTION_SHUTDOWN:
  6.1707 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
  6.1708 +    srb->SrbStatus = SRB_STATUS_SUCCESS;
  6.1709 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1710 +    break;
  6.1711 +  default:
  6.1712 +    KdPrint((__DRIVER_NAME "     Unhandled srb->Function = %08X\n", srb->Function));
  6.1713 +    srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  6.1714 +    StorPortNotification(RequestComplete, DeviceExtension, srb);
  6.1715 +    break;
  6.1716 +  }
  6.1717 +
  6.1718 +  //if (dump_mode) FUNCTION_EXIT();
  6.1719 +  return TRUE;
  6.1720 +}
  6.1721 +
  6.1722 +static BOOLEAN
  6.1723 +XenVbd_HwStorResetBus(PVOID DeviceExtension, ULONG PathId)
  6.1724 +{
  6.1725 +  //PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  6.1726 +
  6.1727 +  UNREFERENCED_PARAMETER(DeviceExtension);
  6.1728 +  UNREFERENCED_PARAMETER(PathId);
  6.1729 +
  6.1730 +  FUNCTION_ENTER();
  6.1731 +
  6.1732 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  6.1733 +
  6.1734 +  FUNCTION_EXIT();
  6.1735 +
  6.1736 +
  6.1737 +  return TRUE;
  6.1738 +}
  6.1739 +
  6.1740 +static SCSI_ADAPTER_CONTROL_STATUS
  6.1741 +XenVbd_HwStorAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
  6.1742 +{
  6.1743 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
  6.1744 +  SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
  6.1745 +  PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
  6.1746 +  //KIRQL OldIrql;
  6.1747 +
  6.1748 +  FUNCTION_ENTER();
  6.1749 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  6.1750 +  KdPrint((__DRIVER_NAME "     xvdd = %p\n", xvdd));
  6.1751 +
  6.1752 +  switch (ControlType)
  6.1753 +  {
  6.1754 +  case ScsiQuerySupportedControlTypes:
  6.1755 +    SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
  6.1756 +    KdPrint((__DRIVER_NAME "     ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
  6.1757 +    SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
  6.1758 +    SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
  6.1759 +    SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
  6.1760 +    break;
  6.1761 +  case ScsiStopAdapter:
  6.1762 +    KdPrint((__DRIVER_NAME "     ScsiStopAdapter\n"));
  6.1763 +    /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
  6.1764 +    break;
  6.1765 +  case ScsiRestartAdapter:
  6.1766 +    KdPrint((__DRIVER_NAME "     ScsiRestartAdapter\n"));
  6.1767 +    if (!xvdd->inactive)
  6.1768 +    {
  6.1769 +/*
  6.1770 +      if (XenVbd_InitConfig(xvdd) != SP_RETURN_FOUND)
  6.1771 +        KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR)xvdd, 0, 0);
  6.1772 +*/
  6.1773 +      if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
  6.1774 +        KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR)xvdd, 0, 0);
  6.1775 +      xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED;
  6.1776 +      //XenVbd_StartRingDetection(xvdd);
  6.1777 +    }
  6.1778 +    break;
  6.1779 +  case ScsiSetBootConfig:
  6.1780 +    KdPrint((__DRIVER_NAME "     ScsiSetBootConfig\n"));
  6.1781 +    break;
  6.1782 +  case ScsiSetRunningConfig:
  6.1783 +    KdPrint((__DRIVER_NAME "     ScsiSetRunningConfig\n"));
  6.1784 +    break;
  6.1785 +  default:
  6.1786 +    KdPrint((__DRIVER_NAME "     UNKNOWN\n"));
  6.1787 +    break;
  6.1788 +  }
  6.1789 +
  6.1790 +  FUNCTION_EXIT();
  6.1791 +  
  6.1792 +  return Status;
  6.1793 +}
  6.1794 +
  6.1795 +NTSTATUS
  6.1796 +DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  6.1797 +{
  6.1798 +  ULONG status;
  6.1799 +  VIRTUAL_HW_INITIALIZATION_DATA VHwInitializationData;
  6.1800 +  HW_INITIALIZATION_DATA HwInitializationData;
  6.1801 +  //PVOID driver_extension;
  6.1802 +  //PUCHAR ptr;
  6.1803 +  OBJECT_ATTRIBUTES oa;
  6.1804 +  HANDLE service_handle;
  6.1805 +  UNICODE_STRING param_name;
  6.1806 +  HANDLE param_handle;
  6.1807 +  UNICODE_STRING value_name;
  6.1808 +  CHAR buf[256];
  6.1809 +  ULONG buf_len;
  6.1810 +  PKEY_VALUE_PARTIAL_INFORMATION kpv;
  6.1811 +  
  6.1812 +  FUNCTION_ENTER();
  6.1813 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  6.1814 +  KdPrint((__DRIVER_NAME "     DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
  6.1815 +
  6.1816 +  /* RegistryPath == NULL when we are invoked as a crash dump driver */
  6.1817 +  if (!RegistryPath)
  6.1818 +  {
  6.1819 +    dump_mode = TRUE;
  6.1820 +  }
  6.1821 +  
  6.1822 +  if (!dump_mode)
  6.1823 +  {
  6.1824 +    InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  6.1825 +    status = ZwOpenKey(&service_handle, KEY_READ, &oa);
  6.1826 +    if(!NT_SUCCESS(status))
  6.1827 +    {
  6.1828 +      KdPrint((__DRIVER_NAME "     ZwOpenKey(Service) returned %08x\n", status));
  6.1829 +    }
  6.1830 +    else
  6.1831 +    {
  6.1832 +      RtlInitUnicodeString(&param_name, L"Parameters");
  6.1833 +      InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
  6.1834 +      status = ZwOpenKey(&param_handle, KEY_READ, &oa);
  6.1835 +      if(!NT_SUCCESS(status))
  6.1836 +      {
  6.1837 +        KdPrint((__DRIVER_NAME "     ZwOpenKey(Parameters) returned %08x\n", status));
  6.1838 +      }
  6.1839 +      else
  6.1840 +      {
  6.1841 +        kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
  6.1842 +        RtlFillMemory(scsi_device_manufacturer, 8, ' ');
  6.1843 +        RtlFillMemory(scsi_disk_model, 16, ' ');
  6.1844 +        RtlFillMemory(scsi_cdrom_model, 16, ' ');
  6.1845 +
  6.1846 +        RtlInitUnicodeString(&value_name, L"Manufacturer");
  6.1847 +        buf_len = 256;
  6.1848 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  6.1849 +        if(NT_SUCCESS(status))
  6.1850 +          wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
  6.1851 +        else
  6.1852 +          RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN     ");
  6.1853 +
  6.1854 +        RtlInitUnicodeString(&value_name, L"Disk_Model");
  6.1855 +        buf_len = 256;
  6.1856 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  6.1857 +        if(NT_SUCCESS(status))
  6.1858 +          wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  6.1859 +        else
  6.1860 +          RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK          ");
  6.1861 +
  6.1862 +        RtlInitUnicodeString(&value_name, L"CDROM_Model");
  6.1863 +        buf_len = 256;
  6.1864 +        status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
  6.1865 +        if(NT_SUCCESS(status))
  6.1866 +          wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
  6.1867 +        else
  6.1868 +          RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM        ");
  6.1869 +        ZwClose(param_handle);
  6.1870 +      }
  6.1871 +      ZwClose(service_handle);
  6.1872 +    }  
  6.1873 +    RtlZeroMemory(&VHwInitializationData, sizeof(VIRTUAL_HW_INITIALIZATION_DATA));
  6.1874 +    VHwInitializationData.HwInitializationDataSize = sizeof(VIRTUAL_HW_INITIALIZATION_DATA);
  6.1875 +    VHwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* maybe should be internal? */
  6.1876 +    VHwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
  6.1877 +    VHwInitializationData.SpecificLuExtensionSize = 0;
  6.1878 +    VHwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
  6.1879 +    VHwInitializationData.NumberOfAccessRanges = 1;
  6.1880 +    VHwInitializationData.MapBuffers = STOR_MAP_ALL_BUFFERS;
  6.1881 +    //VHwInitializationData.NeedPhysicalAddresses  = TRUE;
  6.1882 +    VHwInitializationData.TaggedQueuing = TRUE;
  6.1883 +    VHwInitializationData.AutoRequestSense = TRUE;
  6.1884 +    VHwInitializationData.MultipleRequestPerLu = TRUE;
  6.1885 +    VHwInitializationData.ReceiveEvent = TRUE;
  6.1886 +    VHwInitializationData.PortVersionFlags = 0;
  6.1887 +    VHwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
  6.1888 +    VHwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
  6.1889 +    VHwInitializationData.HwFindAdapter = XenVbd_VirtualHwStorFindAdapter;
  6.1890 +    VHwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
  6.1891 +    VHwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
  6.1892 +    status = StorPortInitialize(DriverObject, RegistryPath, (PHW_INITIALIZATION_DATA)&VHwInitializationData, NULL);
  6.1893 +  }
  6.1894 +  else
  6.1895 +  {
  6.1896 +    RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
  6.1897 +    HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
  6.1898 +    HwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* not Internal */
  6.1899 +    HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
  6.1900 +    HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
  6.1901 +    HwInitializationData.NumberOfAccessRanges = 1;
  6.1902 +    HwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
  6.1903 +    HwInitializationData.NeedPhysicalAddresses  = TRUE;
  6.1904 +    HwInitializationData.TaggedQueuing = FALSE;
  6.1905 +    HwInitializationData.AutoRequestSense = TRUE;
  6.1906 +    HwInitializationData.MultipleRequestPerLu = FALSE;
  6.1907 +    HwInitializationData.ReceiveEvent = TRUE;
  6.1908 +    HwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
  6.1909 +    HwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
  6.1910 +    HwInitializationData.HwFindAdapter = XenVbd_HwStorFindAdapter;
  6.1911 +    HwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
  6.1912 +    HwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
  6.1913 +    HwInitializationData.HwInterrupt = XenVbd_HwStorInterrupt;
  6.1914 +    status = StorPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
  6.1915 +  }
  6.1916 +  
  6.1917 +  if(!NT_SUCCESS(status))
  6.1918 +  {
  6.1919 +    KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
  6.1920 +  }
  6.1921 +
  6.1922 +  FUNCTION_EXIT();
  6.1923 +
  6.1924 +  return status;
  6.1925 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xenvbd/xenvbd_storport.h	Sat Jan 22 15:47:16 2011 +1100
     7.3 @@ -0,0 +1,159 @@
     7.4 +/*
     7.5 +PV Drivers for Windows Xen HVM Domains
     7.6 +Copyright (C) 2007 James Harper
     7.7 +
     7.8 +This program is free software; you can redistribute it and/or
     7.9 +modify it under the terms of the GNU General Public License
    7.10 +as published by the Free Software Foundation; either version 2
    7.11 +of the License, or (at your option) any later version.
    7.12 +
    7.13 +This program is distributed in the hope that it will be useful,
    7.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.16 +GNU General Public License for more details.
    7.17 +
    7.18 +You should have received a copy of the GNU General Public License
    7.19 +along with this program; if not, write to the Free Software
    7.20 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    7.21 +*/
    7.22 +
    7.23 +#if !defined(_XENVBD_H_)
    7.24 +#define _XENVBD_H_
    7.25 +
    7.26 +#include <ntddk.h>
    7.27 +#include <wdm.h>
    7.28 +#include <initguid.h>
    7.29 +#define NTSTRSAFE_LIB
    7.30 +#include <ntstrsafe.h>
    7.31 +#include <storport.h>
    7.32 +#include <ntddscsi.h>
    7.33 +#include <ntdddisk.h>
    7.34 +#include <stdlib.h>
    7.35 +
    7.36 +#define __DRIVER_NAME "XenVbd"
    7.37 +
    7.38 +#include <xen_windows.h>
    7.39 +#include <xen_public.h>
    7.40 +#include <io/protocols.h>
    7.41 +#include <memory.h>
    7.42 +#include <event_channel.h>
    7.43 +#include <hvm/params.h>
    7.44 +#include <hvm/hvm_op.h>
    7.45 +#include <io/ring.h>
    7.46 +#include <io/blkif.h>
    7.47 +#include <io/xenbus.h>
    7.48 +
    7.49 +#define XENVBD_POOL_TAG (ULONG) 'XVBD'
    7.50 +
    7.51 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    7.52 +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
    7.53 +#define BLK_OTHER_RING_SIZE __RING_SIZE((blkif_other_sring_t *)0, PAGE_SIZE)
    7.54 +
    7.55 +#if defined(__x86_64__)
    7.56 +#pragma pack(push, 4)
    7.57 +#endif
    7.58 +struct blkif_other_request {
    7.59 +  uint8_t operation;
    7.60 +  uint8_t nr_segments;
    7.61 +  blkif_vdev_t handle;
    7.62 +  uint64_t id;
    7.63 +  blkif_sector_t sector_number;
    7.64 +  struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    7.65 +};
    7.66 +struct blkif_other_response {
    7.67 +  uint64_t id;
    7.68 +  uint8_t operation;
    7.69 +  int16_t status;
    7.70 +};
    7.71 +#if defined(__x86_64__)
    7.72 +#pragma pack(pop)
    7.73 +#endif
    7.74 +
    7.75 +typedef struct blkif_other_request blkif_other_request_t;
    7.76 +typedef struct blkif_other_response blkif_other_response_t;
    7.77 +DEFINE_RING_TYPES(blkif_other, struct blkif_other_request, struct blkif_other_response);
    7.78 +
    7.79 +typedef struct {
    7.80 +  LIST_ENTRY list_entry;
    7.81 +  PSCSI_REQUEST_BLOCK srb;
    7.82 +} srb_list_entry_t;
    7.83 +
    7.84 +typedef struct {
    7.85 +  blkif_request_t req;
    7.86 +  PSCSI_REQUEST_BLOCK srb;
    7.87 +  PVOID system_address;
    7.88 +  BOOLEAN aligned_buffer_in_use;
    7.89 +} blkif_shadow_t;
    7.90 +
    7.91 +#define MAX_SHADOW_ENTRIES 64
    7.92 +#define SHADOW_ENTRIES min(MAX_SHADOW_ENTRIES, min(BLK_RING_SIZE, BLK_OTHER_RING_SIZE))
    7.93 +
    7.94 +typedef enum {
    7.95 +  XENVBD_DEVICETYPE_UNKNOWN,
    7.96 +  XENVBD_DEVICETYPE_DISK,
    7.97 +  XENVBD_DEVICETYPE_CDROM,
    7.98 +  XENVBD_DEVICETYPE_CONTROLLER // Not yet used
    7.99 +} XENVBD_DEVICETYPE;
   7.100 +
   7.101 +typedef enum {
   7.102 +  XENVBD_DEVICEMODE_UNKNOWN,
   7.103 +  XENVBD_DEVICEMODE_READ,
   7.104 +  XENVBD_DEVICEMODE_WRITE
   7.105 +} XENVBD_DEVICEMODE;
   7.106 +
   7.107 +#define RING_DETECT_STATE_NOT_STARTED  0
   7.108 +#define RING_DETECT_STATE_DETECT1      1
   7.109 +#define RING_DETECT_STATE_DETECT2      2
   7.110 +#define RING_DETECT_STATE_COMPLETE     3
   7.111 +
   7.112 +struct
   7.113 +{
   7.114 +  BOOLEAN inactive;
   7.115 +  
   7.116 +  blkif_shadow_t shadows[MAX_SHADOW_ENTRIES];
   7.117 +  USHORT shadow_free_list[MAX_SHADOW_ENTRIES];
   7.118 +  USHORT shadow_free;
   7.119 +  USHORT shadow_min_free;
   7.120 +
   7.121 +  PUCHAR device_base;
   7.122 +
   7.123 +  blkif_sring_t *sring;
   7.124 +  evtchn_port_t event_channel;
   7.125 +  ULONG *event_channel_ptr;
   7.126 +  union {
   7.127 +    blkif_front_ring_t ring;
   7.128 +    blkif_other_front_ring_t other_ring;
   7.129 +  };
   7.130 +  int ring_detect_state;
   7.131 +  BOOLEAN use_other;
   7.132 +  BOOLEAN cached_use_other;
   7.133 +  UCHAR last_sense_key;
   7.134 +  UCHAR last_additional_sense_code;
   7.135 +  blkif_response_t tmp_rep;
   7.136 +  XENVBD_DEVICETYPE device_type;
   7.137 +  XENVBD_DEVICEMODE device_mode;
   7.138 +  ULONG bytes_per_sector;
   7.139 +  ULONGLONG total_sectors;
   7.140 +  XENPCI_VECTORS vectors;
   7.141 +  PXENPCI_DEVICE_STATE device_state;
   7.142 +  LIST_ENTRY srb_list;
   7.143 +  grant_ref_t dump_grant_refs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   7.144 +  BOOLEAN aligned_buffer_in_use;
   7.145 +  PVOID aligned_buffer;
   7.146 +/*  
   7.147 +  ULONGLONG interrupts;
   7.148 +  ULONGLONG aligned_requests;
   7.149 +  ULONGLONG aligned_bytes;
   7.150 +  ULONGLONG unaligned_requests;
   7.151 +  ULONGLONG unaligned_bytes;
   7.152 +*/
   7.153 +  #define BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE 1
   7.154 +  #define UNALIGNED_BUFFER_DATA_SIZE ((BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) * PAGE_SIZE - 1)
   7.155 +  #define UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE ((BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE + 1) * PAGE_SIZE - 1)
   7.156 +  /* this has to be right at the end of DeviceExtension */
   7.157 +  /* can't allocate too much data in dump mode so size DeviceExtensionSize accordingly */
   7.158 +  UCHAR aligned_buffer_data[1];
   7.159 +} typedef XENVBD_DEVICE_DATA, *PXENVBD_DEVICE_DATA;
   7.160 +
   7.161 +#endif
   7.162 +