win-pvdrivers

changeset 280:3ee7c3e5036d wdm

Fixed the handling of misaligned scsiport buffers when the buffer is > PAGE_SIZE. Added scsiport.c which I had forgotten. Activated sysrq handler again.
author James Harper <james.harper@bendigoit.com.au>
date Mon May 26 11:55:43 2008 +1000 (2008-05-26)
parents 685399b9adb0
children 31bf6b16a106
files common.inc xenpci/xenpci_fdo.c xenvbd/scsiport.c xenvbd/xenvbd.h
line diff
     1.1 --- a/common.inc	Fri May 23 23:53:02 2008 +1000
     1.2 +++ b/common.inc	Mon May 26 11:55:43 2008 +1000
     1.3 @@ -1,4 +1,4 @@
     1.4 -VERSION=0.9.1.0
     1.5 +VERSION=0.9.1.1
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7  MSC_WARNING_LEVEL=/W4
     1.8  INCLUDES = ..\common\include;..\common\include\public
     2.1 --- a/xenpci/xenpci_fdo.c	Fri May 23 23:53:02 2008 +1000
     2.2 +++ b/xenpci/xenpci_fdo.c	Mon May 26 11:55:43 2008 +1000
     2.3 @@ -26,8 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fi
     2.4  #define BALLOON_PATH "memory/target"
     2.5  
     2.6  static VOID
     2.7 -XenBus_SysrqHandler(char *Path, PVOID Data);
     2.8 -static VOID
     2.9  XenBus_BalloonHandler(char *Path, PVOID Data);
    2.10  
    2.11  /*
    2.12 @@ -421,7 +419,7 @@ XenPci_BeginSuspend(PXENPCI_DEVICE_DATA 
    2.13  }
    2.14  
    2.15  static void
    2.16 -XenBus_ShutdownHandler(char *path, PVOID context)
    2.17 +XenPci_ShutdownHandler(char *path, PVOID context)
    2.18  {
    2.19    PXENPCI_DEVICE_DATA xpdd = (PXENPCI_DEVICE_DATA)context;
    2.20    char *res;
    2.21 @@ -471,6 +469,56 @@ XenBus_ShutdownHandler(char *path, PVOID
    2.22  }
    2.23  
    2.24  static VOID
    2.25 +XenPci_SysrqHandler(char *path, PVOID context)
    2.26 +{
    2.27 +  PXENPCI_DEVICE_DATA xpdd = context;
    2.28 +  char *value;
    2.29 +  char letter;
    2.30 +  char *res;
    2.31 +
    2.32 +  UNREFERENCED_PARAMETER(path);
    2.33 +
    2.34 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
    2.35 +
    2.36 +  XenBus_Read(xpdd, XBT_NIL, SYSRQ_PATH, &value);
    2.37 +
    2.38 +  KdPrint((__DRIVER_NAME "     SysRq Value = %s\n", value));
    2.39 +
    2.40 +  if (value != NULL && strlen(value) != 0)
    2.41 +  {
    2.42 +    letter = *value;
    2.43 +    res = XenBus_Write(xpdd, XBT_NIL, SYSRQ_PATH, "");
    2.44 +    if (res)
    2.45 +    {
    2.46 +      KdPrint(("Error writing sysrq path\n"));
    2.47 +      XenPci_FreeMem(res);
    2.48 +      return;
    2.49 +    }
    2.50 +  }
    2.51 +  else
    2.52 +  {
    2.53 +    letter = 0;
    2.54 +  }
    2.55 +
    2.56 +  if (value != NULL)
    2.57 +  {
    2.58 +    XenPci_FreeMem(value);
    2.59 +  }
    2.60 +
    2.61 +  switch (letter)
    2.62 +  {
    2.63 +  case 'B':
    2.64 +    KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
    2.65 +    break;
    2.66 +  default:
    2.67 +    KdPrint(("     Unhandled sysrq letter %c\n", letter));
    2.68 +    break;
    2.69 +  }
    2.70 +
    2.71 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
    2.72 +}
    2.73 +
    2.74 +static VOID
    2.75  XenPci_DeviceWatchHandler(char *path, PVOID context)
    2.76  {
    2.77    char **bits;
    2.78 @@ -512,10 +560,10 @@ XenPci_Pnp_StartDeviceCallback(PDEVICE_O
    2.79  
    2.80    XenBus_Init(xpdd);
    2.81  
    2.82 -  //response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenBus_SysrqHandler, xpdd);
    2.83 -  //KdPrint((__DRIVER_NAME "     sysrqwatch response = '%s'\n", response)); 
    2.84 +  response = XenBus_AddWatch(xpdd, XBT_NIL, SYSRQ_PATH, XenPci_SysrqHandler, xpdd);
    2.85 +  KdPrint((__DRIVER_NAME "     sysrqwatch response = '%s'\n", response)); 
    2.86    
    2.87 -  response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, xpdd);
    2.88 +  response = XenBus_AddWatch(xpdd, XBT_NIL, SHUTDOWN_PATH, XenPci_ShutdownHandler, xpdd);
    2.89    KdPrint((__DRIVER_NAME "     shutdown watch response = '%s'\n", response)); 
    2.90  
    2.91    response = XenBus_AddWatch(xpdd, XBT_NIL, "device", XenPci_DeviceWatchHandler, xpdd);
    2.92 @@ -1241,63 +1289,6 @@ XenBus_BalloonHandler(char *Path, PVOID 
    2.93    KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
    2.94  }
    2.95  
    2.96 -static VOID
    2.97 -XenBus_SysrqHandler(char *Path, PVOID Data)
    2.98 -{
    2.99 -  WDFDEVICE Device = Data;
   2.100 -  char *Value;
   2.101 -  xenbus_transaction_t xbt;
   2.102 -  int retry;
   2.103 -  char letter;
   2.104 -  char *res;
   2.105 -
   2.106 -  UNREFERENCED_PARAMETER(Path);
   2.107 -
   2.108 -  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   2.109 -
   2.110 -  XenBus_StartTransaction(Device, &xbt);
   2.111 -
   2.112 -  XenBus_Read(Device, XBT_NIL, SYSRQ_PATH, &Value);
   2.113 -
   2.114 -  KdPrint((__DRIVER_NAME "     SysRq Value = %s\n", Value));
   2.115 -
   2.116 -  if (Value != NULL && strlen(Value) != 0)
   2.117 -  {
   2.118 -    letter = *Value;
   2.119 -    res = XenBus_Write(Device, XBT_NIL, SYSRQ_PATH, "");
   2.120 -    if (res)
   2.121 -    {
   2.122 -      KdPrint(("Error writing sysrq path\n"));
   2.123 -      XenPci_FreeMem(res);
   2.124 -      XenBus_EndTransaction(Device, xbt, 0, &retry);
   2.125 -      return;
   2.126 -    }
   2.127 -  }
   2.128 -  else
   2.129 -  {
   2.130 -    letter = 0;
   2.131 -  }
   2.132 -
   2.133 -  XenBus_EndTransaction(Device, xbt, 0, &retry);
   2.134 -
   2.135 -  if (Value != NULL)
   2.136 -  {
   2.137 -    XenPci_FreeMem(Value);
   2.138 -  }
   2.139 -
   2.140 -  switch (letter)
   2.141 -  {
   2.142 -  case 'B':
   2.143 -    KeBugCheckEx(('X' << 16)|('E' << 8)|('N'), 0x00000001, 0x00000000, 0x00000000, 0x00000000);
   2.144 -    break;
   2.145 -  default:
   2.146 -    KdPrint(("     Unhandled sysrq letter %c\n", letter));
   2.147 -    break;
   2.148 -  }
   2.149 -
   2.150 -  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   2.151 -}
   2.152 -
   2.153  static NTSTATUS
   2.154  XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
   2.155  {
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xenvbd/scsiport.c	Mon May 26 11:55:43 2008 +1000
     3.3 @@ -0,0 +1,958 @@
     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 +#include "xenvbd.h"
    3.24 +#include <io/blkif.h>
    3.25 +#include <scsi.h>
    3.26 +#include <ntddscsi.h>
    3.27 +#include <ntdddisk.h>
    3.28 +#include <stdlib.h>
    3.29 +#include <xen_public.h>
    3.30 +#include <io/xenbus.h>
    3.31 +#include <io/protocols.h>
    3.32 +
    3.33 +#pragma warning(disable: 4127)
    3.34 +
    3.35 +static blkif_shadow_t *
    3.36 +get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
    3.37 +{
    3.38 +  if (xvdd->shadow_free == 0)
    3.39 +  {
    3.40 +    KdPrint((__DRIVER_NAME "     No more shadow entries\n"));    
    3.41 +    return NULL;
    3.42 +  }
    3.43 +  xvdd->shadow_free--;
    3.44 +  return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
    3.45 +}
    3.46 +
    3.47 +static VOID
    3.48 +put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
    3.49 +{
    3.50 +  xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
    3.51 +  shadow->srb = NULL;
    3.52 +  xvdd->shadow_free++;
    3.53 +}
    3.54 +
    3.55 +static grant_ref_t
    3.56 +get_grant_from_freelist(PXENVBD_DEVICE_DATA xvdd)
    3.57 +{
    3.58 +  if (xvdd->grant_free == 0)
    3.59 +  {
    3.60 +    KdPrint((__DRIVER_NAME "     No more grant refs\n"));    
    3.61 +    return (grant_ref_t)0x0FFFFFFF;
    3.62 +  }
    3.63 +  xvdd->grant_free--;
    3.64 +  return xvdd->grant_free_list[xvdd->grant_free];
    3.65 +}
    3.66 +
    3.67 +static VOID
    3.68 +put_grant_on_freelist(PXENVBD_DEVICE_DATA xvdd, grant_ref_t grant)
    3.69 +{
    3.70 +  xvdd->grant_free_list[xvdd->grant_free] = grant;
    3.71 +  xvdd->grant_free++;
    3.72 +}
    3.73 +
    3.74 +static blkif_response_t *
    3.75 +XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
    3.76 +{
    3.77 +  blkif_other_response_t *rep;
    3.78 +  if (!xvdd->use_other)
    3.79 +    return RING_GET_RESPONSE(&xvdd->ring, i);
    3.80 +  rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
    3.81 +  xvdd->tmp_rep.id = rep->id;
    3.82 +  xvdd->tmp_rep.operation = rep->operation;
    3.83 +  xvdd->tmp_rep.status = rep->status;
    3.84 +  return &xvdd->tmp_rep;
    3.85 +}
    3.86 +
    3.87 +static ULONG
    3.88 +XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
    3.89 +{
    3.90 +  ULONG i;
    3.91 +//  PACCESS_RANGE AccessRange;
    3.92 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
    3.93 +//  ULONG status;
    3.94 +//  PXENPCI_XEN_DEVICE_DATA XenDeviceData;
    3.95 +  PACCESS_RANGE access_range;
    3.96 +  PUCHAR ptr;
    3.97 +  USHORT type;
    3.98 +  PCHAR setting, value;
    3.99 +  blkif_sring_t *sring;
   3.100 +
   3.101 +  UNREFERENCED_PARAMETER(HwContext);
   3.102 +  UNREFERENCED_PARAMETER(BusInformation);
   3.103 +  UNREFERENCED_PARAMETER(ArgumentString);
   3.104 +
   3.105 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));  
   3.106 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.107 +
   3.108 +  *Again = FALSE;
   3.109 +
   3.110 +  KdPrint((__DRIVER_NAME "     BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
   3.111 +  KdPrint((__DRIVER_NAME "     BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
   3.112 +
   3.113 +  if (ConfigInfo->NumberOfAccessRanges != 1)
   3.114 +  {
   3.115 +    KdPrint((__DRIVER_NAME "     NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));    
   3.116 +    return SP_RETURN_BAD_CONFIG;
   3.117 +  }
   3.118 +
   3.119 +  access_range = &((*(ConfigInfo->AccessRanges))[0]);
   3.120 +
   3.121 +  KdPrint((__DRIVER_NAME "     RangeStart = %08x, RangeLength = %08x\n",
   3.122 +    access_range->RangeStart.LowPart, access_range->RangeLength));
   3.123 +
   3.124 +  ptr = ScsiPortGetDeviceBase(
   3.125 +    DeviceExtension,
   3.126 +    ConfigInfo->AdapterInterfaceType,
   3.127 +    ConfigInfo->SystemIoBusNumber,
   3.128 +    access_range->RangeStart,
   3.129 +    access_range->RangeLength,
   3.130 +    !access_range->RangeInMemory);
   3.131 +  //ptr = MmMapIoSpace(access_range->RangeStart, access_range->RangeLength, MmCached);
   3.132 +  if (ptr == NULL)
   3.133 +  {
   3.134 +    KdPrint((__DRIVER_NAME "     Unable to map range\n"));
   3.135 +    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));  
   3.136 +    return SP_RETURN_BAD_CONFIG;
   3.137 +  }
   3.138 +
   3.139 +  xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   3.140 +  sring = NULL;
   3.141 +  xvdd->event_channel = 0;
   3.142 +  while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value)) != XEN_INIT_TYPE_END)
   3.143 +  {
   3.144 +    switch(type)
   3.145 +    {
   3.146 +    case XEN_INIT_TYPE_RING: /* frontend ring */
   3.147 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
   3.148 +      if (strcmp(setting, "ring-ref") == 0)
   3.149 +      {
   3.150 +        sring = (blkif_sring_t *)value;
   3.151 +        FRONT_RING_INIT(&xvdd->ring, sring, PAGE_SIZE);
   3.152 +      }
   3.153 +      break;
   3.154 +    case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
   3.155 +    case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
   3.156 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
   3.157 +      if (strcmp(setting, "event-channel") == 0)
   3.158 +      {
   3.159 +        xvdd->event_channel = PtrToUlong(value);
   3.160 +      }
   3.161 +      break;
   3.162 +    case XEN_INIT_TYPE_READ_STRING_BACK:
   3.163 +    case XEN_INIT_TYPE_READ_STRING_FRONT:
   3.164 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
   3.165 +      if (strcmp(setting, "sectors") == 0)
   3.166 +        xvdd->total_sectors = atoi(value);
   3.167 +      else if (strcmp(setting, "sector-size") == 0)
   3.168 +        xvdd->bytes_per_sector = atoi(value);
   3.169 +      else if (strcmp(setting, "device-type") == 0)
   3.170 +      {
   3.171 +        if (strcmp(value, "disk") == 0)
   3.172 +        {
   3.173 +          KdPrint((__DRIVER_NAME "     device-type = Disk\n"));    
   3.174 +          xvdd->device_type = XENVBD_DEVICETYPE_DISK;
   3.175 +        }
   3.176 +        else if (strcmp(value, "cdrom") == 0)
   3.177 +        {
   3.178 +          KdPrint((__DRIVER_NAME "     device-type = CDROM\n"));    
   3.179 +          xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
   3.180 +        }
   3.181 +        else
   3.182 +        {
   3.183 +          KdPrint((__DRIVER_NAME "     device-type = %s (This probably won't work!)\n", value));
   3.184 +          xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
   3.185 +        }
   3.186 +      }
   3.187 +      break;
   3.188 +    case XEN_INIT_TYPE_VECTORS:
   3.189 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_VECTORS\n"));
   3.190 +      if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
   3.191 +        ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
   3.192 +      {
   3.193 +        KdPrint((__DRIVER_NAME "     vectors mismatch (magic = %08x, length = %d)\n",
   3.194 +          ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
   3.195 +        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.196 +        return SP_RETURN_BAD_CONFIG;
   3.197 +      }
   3.198 +      else
   3.199 +        memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
   3.200 +      break;
   3.201 +    case XEN_INIT_TYPE_GRANT_ENTRIES:
   3.202 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
   3.203 +      if (PtrToUlong(setting) != GRANT_ENTRIES)
   3.204 +      {
   3.205 +        KdPrint((__DRIVER_NAME "     grant entries mismatch\n"));
   3.206 +        KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.207 +        return SP_RETURN_BAD_CONFIG;
   3.208 +      }
   3.209 +      else
   3.210 +      {
   3.211 +        memcpy(&xvdd->grant_free_list, value, sizeof(ULONG) * PtrToUlong(setting));
   3.212 +        xvdd->grant_free = GRANT_ENTRIES;
   3.213 +      }
   3.214 +      break;
   3.215 +    default:
   3.216 +      KdPrint((__DRIVER_NAME "     XEN_INIT_TYPE_%d\n", type));
   3.217 +      break;
   3.218 +    }
   3.219 +  }
   3.220 +  if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
   3.221 +    || sring == NULL
   3.222 +    || xvdd->event_channel == 0)
   3.223 +  {
   3.224 +    KdPrint((__DRIVER_NAME "     Missing settings\n"));
   3.225 +    KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.226 +    return SP_RETURN_BAD_CONFIG;
   3.227 +  }
   3.228 +  ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
   3.229 +  ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
   3.230 +  ConfigInfo->ScatterGather = TRUE;
   3.231 +  ConfigInfo->AlignmentMask = 0;
   3.232 +  ConfigInfo->NumberOfBuses = 1;
   3.233 +  ConfigInfo->InitiatorBusId[0] = 1;
   3.234 +  ConfigInfo->MaximumNumberOfLogicalUnits = 1;
   3.235 +  ConfigInfo->MaximumNumberOfTargets = 2;
   3.236 +  ConfigInfo->BufferAccessScsiPortControlled = TRUE;
   3.237 +  if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
   3.238 +  {
   3.239 +    ConfigInfo->Master = TRUE;
   3.240 +    ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
   3.241 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses supported\n"));
   3.242 +  }
   3.243 +  else
   3.244 +  {
   3.245 +    ConfigInfo->Master = FALSE;
   3.246 +    KdPrint((__DRIVER_NAME "     Dma64BitAddresses not supported\n"));
   3.247 +  }
   3.248 +
   3.249 +  xvdd->ring_detect_state = 0;
   3.250 +
   3.251 +  xvdd->shadow_free = 0;
   3.252 +  memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
   3.253 +  for (i = 0; i < SHADOW_ENTRIES; i++)
   3.254 +  {
   3.255 +    xvdd->shadows[i].req.id = i;
   3.256 +    put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
   3.257 +  }
   3.258 +
   3.259 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));  
   3.260 +
   3.261 +  return SP_RETURN_FOUND;
   3.262 +}
   3.263 +
   3.264 +static BOOLEAN
   3.265 +XenVbd_HwScsiInitialize(PVOID DeviceExtension)
   3.266 +{
   3.267 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   3.268 +  blkif_request_t *req;
   3.269 +  int i;
   3.270 +  int notify;
   3.271 +  
   3.272 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.273 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.274 +
   3.275 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   3.276 +  KdPrint((__DRIVER_NAME "     A\n"));
   3.277 +  req->operation = 0xff;
   3.278 +  req->nr_segments = 0;
   3.279 +  for (i = 0; i < req->nr_segments; i++)
   3.280 +  {
   3.281 +    req->seg[i].gref = 0xffffffff;
   3.282 +    req->seg[i].first_sect = 0xff;
   3.283 +    req->seg[i].last_sect = 0xff;
   3.284 +  }
   3.285 +  xvdd->ring.req_prod_pvt++;
   3.286 +
   3.287 +  KdPrint((__DRIVER_NAME "     B\n"));
   3.288 + 
   3.289 +  req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
   3.290 +  KdPrint((__DRIVER_NAME "     C\n"));
   3.291 +  req->operation = 0xff;
   3.292 +  req->nr_segments = 0;
   3.293 +  for (i = 0; i < req->nr_segments; i++)
   3.294 +  {
   3.295 +    req->seg[i].gref = 0xffffffff;
   3.296 +    req->seg[i].first_sect = 0xff;
   3.297 +    req->seg[i].last_sect = 0xff;
   3.298 +  }
   3.299 +  xvdd->ring.req_prod_pvt++;
   3.300 +
   3.301 +  KdPrint((__DRIVER_NAME "     D\n"));
   3.302 +
   3.303 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   3.304 +  KdPrint((__DRIVER_NAME "     E\n"));
   3.305 +  if (notify)
   3.306 +    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   3.307 +
   3.308 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.309 +
   3.310 +  return TRUE;
   3.311 +}
   3.312 +
   3.313 +static VOID
   3.314 +XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
   3.315 +{
   3.316 +  blkif_other_request_t *other_req;
   3.317 +
   3.318 +  if (!xvdd->use_other)
   3.319 +  {
   3.320 +    *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
   3.321 +  }
   3.322 +  else
   3.323 +  {  
   3.324 +    other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
   3.325 +    other_req->operation = req->operation;
   3.326 +    other_req->nr_segments = req->nr_segments;
   3.327 +    other_req->handle = req->handle;
   3.328 +    other_req->id = req->id;
   3.329 +    other_req->sector_number = req->sector_number;
   3.330 +    memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
   3.331 +  }
   3.332 +  xvdd->ring.req_prod_pvt++;
   3.333 +}
   3.334 +
   3.335 +static VOID
   3.336 +XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
   3.337 +{
   3.338 +  int block_count;
   3.339 +  blkif_shadow_t *shadow;
   3.340 +  PHYSICAL_ADDRESS physical_address;
   3.341 +  ULONG pfn;
   3.342 +  ULONG remaining, offset, length;
   3.343 +  PUCHAR ptr;
   3.344 +  int notify;
   3.345 +
   3.346 +// can use SRB_STATUS_BUSY to push the SRB back to windows...
   3.347 +
   3.348 +//  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.349 +
   3.350 +  shadow = get_shadow_from_freelist(xvdd);
   3.351 +  shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
   3.352 +  block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
   3.353 +  shadow->req.handle = 0;
   3.354 +  shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
   3.355 +  shadow->req.nr_segments = 0;
   3.356 +  shadow->offset = srb_offset;
   3.357 +  shadow->length = block_count * xvdd->bytes_per_sector;
   3.358 +  shadow->srb = srb;
   3.359 +
   3.360 +  //KdPrint((__DRIVER_NAME "     sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
   3.361 +  //KdPrint((__DRIVER_NAME "     SrbExtension = %p\n", srb->SrbExtension));
   3.362 +  //KdPrint((__DRIVER_NAME "     DataBuffer   = %p\n", srb->DataBuffer));
   3.363 +
   3.364 +  if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
   3.365 +  {
   3.366 +    shadow->req.sector_number += srb_offset / xvdd->bytes_per_sector;
   3.367 +    shadow->length = min(shadow->length - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
   3.368 +    //KdPrint((__DRIVER_NAME "     (Put) id = %d, DataBuffer = %p, SrbExtension = %p, total length = %d, offset = %d, length = %d, sector = %d\n", (ULONG)shadow->req.id, srb->DataBuffer, srb->SrbExtension, block_count * xvdd->bytes_per_sector, shadow->offset, shadow->length, shadow->req.sector_number));
   3.369 +    if (srb->Cdb[0] == SCSIOP_WRITE)
   3.370 +    {
   3.371 +      memcpy(srb->SrbExtension, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
   3.372 +      //KdPrint((__DRIVER_NAME "     (WR) memcpy(%p, %p, %d)\n", srb->SrbExtension, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length));
   3.373 +    }
   3.374 +    else
   3.375 +    {
   3.376 +      RtlZeroMemory(srb->SrbExtension, shadow->length);
   3.377 +    }
   3.378 +    ptr = srb->SrbExtension;
   3.379 +  }
   3.380 +  else
   3.381 +  {
   3.382 +    ptr = srb->DataBuffer;
   3.383 +  }
   3.384 +
   3.385 +  remaining = shadow->length;  
   3.386 +  while (remaining > 0)
   3.387 +  {
   3.388 +    physical_address = MmGetPhysicalAddress(ptr);
   3.389 +    //KdPrint((__DRIVER_NAME "     ptr = %p, physical = %08x:%08x\n", ptr, physical_address.HighPart, physical_address.LowPart));
   3.390 +    pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
   3.391 +    shadow->req.seg[shadow->req.nr_segments].gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, get_grant_from_freelist(xvdd));
   3.392 +    offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
   3.393 +    ASSERT((offset & 511) == 0);
   3.394 +    length = min(PAGE_SIZE - offset, remaining);
   3.395 +    shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
   3.396 +    shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
   3.397 +    //KdPrint((__DRIVER_NAME "     length = %d, remaining = %d, pfn = %08x, offset = %d, first = %d, last = %d\n",
   3.398 +    //  length, remaining, pfn, offset, shadow->req.seg[shadow->req.nr_segments].first_sect, shadow->req.seg[shadow->req.nr_segments].last_sect));
   3.399 +    remaining -= length;
   3.400 +    ptr += length;
   3.401 +    shadow->req.nr_segments++;
   3.402 +  }
   3.403 +    
   3.404 +  XenVbd_PutRequest(xvdd, &shadow->req);
   3.405 +
   3.406 +  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
   3.407 +  if (notify)
   3.408 +    xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
   3.409 +
   3.410 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.411 +}
   3.412 +
   3.413 +static ULONG
   3.414 +XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
   3.415 +{
   3.416 +  //PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
   3.417 +
   3.418 +  UNREFERENCED_PARAMETER(DeviceData);
   3.419 +  UNREFERENCED_PARAMETER(DataBuffer);
   3.420 +  UNREFERENCED_PARAMETER(BufferLength);
   3.421 +  UNREFERENCED_PARAMETER(Offset);
   3.422 +
   3.423 +  switch (PageCode)
   3.424 +  {
   3.425 +/*
   3.426 +  case MODE_PAGE_RIGID_GEOMETRY:
   3.427 +    if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
   3.428 +    {
   3.429 +    KdPrint((__DRIVER_NAME "     MODE_PAGE_RIGID_GEOMETRY\n"));
   3.430 +    if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
   3.431 +      return 1;
   3.432 +    ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
   3.433 +    memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
   3.434 +    ModeRigidGeometry->PageCode = PageCode;
   3.435 +    ModeRigidGeometry->PageSavable = 0;
   3.436 +    ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
   3.437 +    ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
   3.438 +    ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
   3.439 +    ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
   3.440 +    ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
   3.441 +    //ModeRigidGeometry->LandZoneCyclinder = 0;
   3.442 +    ModeRigidGeometry->RoataionRate[0] = 0x05;
   3.443 +    ModeRigidGeometry->RoataionRate[0] = 0x39;
   3.444 +    *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
   3.445 +    }
   3.446 +    break;
   3.447 +*/
   3.448 +  case MODE_PAGE_FAULT_REPORTING:
   3.449 +    break;
   3.450 +  default:
   3.451 +    break;
   3.452 +  }
   3.453 +  return 0;
   3.454 +}
   3.455 +
   3.456 +static BOOLEAN
   3.457 +XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
   3.458 +{
   3.459 +  PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
   3.460 +  PSCSI_REQUEST_BLOCK srb;
   3.461 +  RING_IDX i, rp;
   3.462 +  int j;
   3.463 +  blkif_response_t *rep;
   3.464 +  int block_count;
   3.465 +  int more_to_do = TRUE;
   3.466 +  blkif_shadow_t *shadow;
   3.467 +  ULONG offset;
   3.468 +
   3.469 +  //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.470 +
   3.471 +  while (more_to_do)
   3.472 +  {
   3.473 +    rp = xvdd->ring.sring->rsp_prod;
   3.474 +    KeMemoryBarrier();
   3.475 +    for (i = xvdd->ring.rsp_cons; i != rp; i++)
   3.476 +    {
   3.477 +      rep = XenVbd_GetResponse(xvdd, i);
   3.478 +/*
   3.479 +* This code is to automatically detect if the backend is using the same
   3.480 +* bit width or a different bit width to us. Later versions of Xen do this
   3.481 +* via a xenstore value, but not all. That 0x0fffffff (notice
   3.482 +* that the msb is not actually set, so we don't have any problems with
   3.483 +* sign extending) is to signify the last entry on the right, which is
   3.484 +* different under 32 and 64 bits, and that is why we set it up there.
   3.485 +
   3.486 +* To do the detection, we put two initial entries on the ring, with an op
   3.487 +* of 0xff (which is invalid). The first entry is mostly okay, but the
   3.488 +* second will be grossly misaligned if the backend bit width is different,
   3.489 +* and we detect this and switch frontend structures.
   3.490 +*/
   3.491 +      switch (xvdd->ring_detect_state)
   3.492 +      {
   3.493 +      case 0:
   3.494 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
   3.495 +        xvdd->ring_detect_state = 1;
   3.496 +        break;
   3.497 +      case 1:
   3.498 +        KdPrint((__DRIVER_NAME "     ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
   3.499 +        if (rep->operation != 0xff)
   3.500 +        {
   3.501 +          xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
   3.502 +          xvdd->use_other = TRUE;
   3.503 +        }
   3.504 +        xvdd->ring_detect_state = 2;
   3.505 +        ScsiPortNotification(NextRequest, xvdd);
   3.506 +        break;
   3.507 +      case 2:
   3.508 +        shadow = &xvdd->shadows[rep->id];
   3.509 +        srb = shadow->srb;
   3.510 +        ASSERT(srb != NULL);
   3.511 +        block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
   3.512 +
   3.513 +        if (rep->status == BLKIF_RSP_OKAY)
   3.514 +          srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.515 +        else
   3.516 +        {
   3.517 +          KdPrint((__DRIVER_NAME "     Xen Operation returned error\n"));
   3.518 +          if (srb->Cdb[0] == SCSIOP_READ)
   3.519 +            KdPrint((__DRIVER_NAME "     Operation = Read\n"));
   3.520 +          else
   3.521 +            KdPrint((__DRIVER_NAME "     Operation = Write\n"));     
   3.522 +          KdPrint((__DRIVER_NAME "     Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
   3.523 +          srb->SrbStatus = SRB_STATUS_ERROR;
   3.524 +        }
   3.525 +        for (j = 0; j < shadow->req.nr_segments; j++)
   3.526 +        {
   3.527 +          xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
   3.528 +          put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
   3.529 +        }
   3.530 +
   3.531 +        if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
   3.532 +        {
   3.533 +          if (srb->Cdb[0] == SCSIOP_READ)
   3.534 +          {
   3.535 +            memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, srb->SrbExtension, shadow->length);
   3.536 +            //KdPrint((__DRIVER_NAME "     (RD) memcpy(%p, %p, %d)\n", ((PUCHAR)srb->DataBuffer) + shadow->offset, srb->SrbExtension, shadow->length));
   3.537 +          }
   3.538 +          //KdPrint((__DRIVER_NAME "     (Get) id = %d, DataBuffer = %p, SrbExtension = %p, total length = %d, offset = %d, length = %d\n", (ULONG)shadow->req.id, srb->DataBuffer, srb->SrbExtension, block_count * xvdd->bytes_per_sector, shadow->offset, shadow->length));
   3.539 +          offset = shadow->offset + shadow->length;
   3.540 +          put_shadow_on_freelist(xvdd, shadow);
   3.541 +          if (offset == block_count * xvdd->bytes_per_sector)
   3.542 +          {
   3.543 +            ScsiPortNotification(RequestComplete, xvdd, srb);
   3.544 +            ScsiPortNotification(NextRequest, xvdd);
   3.545 +          }
   3.546 +          else
   3.547 +          {
   3.548 +            XenVbd_PutSrbOnRing(xvdd, srb, offset);
   3.549 +          }
   3.550 +        }
   3.551 +        else
   3.552 +        {
   3.553 +          put_shadow_on_freelist(xvdd, shadow);
   3.554 +          ScsiPortNotification(RequestComplete, xvdd, srb);
   3.555 +          ScsiPortNotification(NextRequest, xvdd);
   3.556 +        }
   3.557 +      }
   3.558 +    }
   3.559 +
   3.560 +    xvdd->ring.rsp_cons = i;
   3.561 +    if (i != xvdd->ring.req_prod_pvt)
   3.562 +    {
   3.563 +      RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
   3.564 +    }
   3.565 +    else
   3.566 +    {
   3.567 +      xvdd->ring.sring->rsp_event = i + 1;
   3.568 +      more_to_do = FALSE;
   3.569 +    }
   3.570 +  }
   3.571 +
   3.572 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.573 +  
   3.574 +  return FALSE; /* we just don't know... */
   3.575 +}
   3.576 +
   3.577 +
   3.578 +static BOOLEAN
   3.579 +XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
   3.580 +{
   3.581 +  PUCHAR DataBuffer;
   3.582 +  PCDB cdb;
   3.583 +  PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
   3.584 +  unsigned int i;
   3.585 +
   3.586 +  //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
   3.587 +
   3.588 +  // If we haven't enumerated all the devices yet then just defer the request
   3.589 +  // A timer will issue a NextRequest to get things started again...
   3.590 +  if (xvdd->ring_detect_state < 2)
   3.591 +  {
   3.592 +    Srb->SrbStatus = SRB_STATUS_BUSY;
   3.593 +    ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.594 +    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
   3.595 +    return TRUE;
   3.596 +  }
   3.597 +
   3.598 +  if (Srb->PathId != 0 || Srb->TargetId != 0)
   3.599 +  {
   3.600 +    Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
   3.601 +    ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.602 +    ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.603 +    KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
   3.604 +    return TRUE;
   3.605 +  }
   3.606 +
   3.607 +  switch (Srb->Function)
   3.608 +  {
   3.609 +  case SRB_FUNCTION_EXECUTE_SCSI:
   3.610 +    cdb = (PCDB)Srb->Cdb;
   3.611 +//    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_EXECUTE_SCSI\n"));
   3.612 +
   3.613 +    switch(cdb->CDB6GENERIC.OperationCode)
   3.614 +    {
   3.615 +    case SCSIOP_TEST_UNIT_READY:
   3.616 +//      KdPrint((__DRIVER_NAME "     Command = TEST_UNIT_READY\n"));
   3.617 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.618 +      Srb->ScsiStatus = 0;
   3.619 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.620 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.621 +      break;
   3.622 +    case SCSIOP_INQUIRY:
   3.623 +      KdPrint((__DRIVER_NAME "     Command = INQUIRY\n"));
   3.624 +      KdPrint((__DRIVER_NAME "     (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
   3.625 +      KdPrint((__DRIVER_NAME "     (Length = %d)\n", Srb->DataTransferLength));
   3.626 +      KdPrint((__DRIVER_NAME "     (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
   3.627 +      DataBuffer = Srb->DataBuffer;
   3.628 +      RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
   3.629 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.630 +      switch (xvdd->device_type)
   3.631 +      {
   3.632 +      case XENVBD_DEVICETYPE_DISK:
   3.633 +        if ((Srb->Cdb[1] & 1) == 0)
   3.634 +        {
   3.635 +          DataBuffer[0] = DIRECT_ACCESS_DEVICE;
   3.636 +          DataBuffer[1] = 0x00; // not removable
   3.637 +          DataBuffer[3] = 32;
   3.638 +          memcpy(DataBuffer + 8, "XEN     ", 8); // vendor id
   3.639 +          memcpy(DataBuffer + 16, "PV VBD          ", 16); // product id
   3.640 +          memcpy(DataBuffer + 32, "0000", 4); // product revision level
   3.641 +        }
   3.642 +        else
   3.643 +        {
   3.644 +          switch (Srb->Cdb[2])
   3.645 +          {
   3.646 +          case 0x00:
   3.647 +            DataBuffer[0] = DIRECT_ACCESS_DEVICE;
   3.648 +            DataBuffer[1] = 0x00;
   3.649 +            DataBuffer[2] = 0x00;
   3.650 +            DataBuffer[3] = 2;
   3.651 +            DataBuffer[4] = 0x00;
   3.652 +            DataBuffer[5] = 0x80;
   3.653 +            break;
   3.654 +          case 0x80:
   3.655 +            DataBuffer[0] = DIRECT_ACCESS_DEVICE;
   3.656 +            DataBuffer[1] = 0x80;
   3.657 +            DataBuffer[2] = 0x00;
   3.658 +            DataBuffer[3] = 8;
   3.659 +            DataBuffer[4] = 0x31;
   3.660 +            DataBuffer[5] = 0x32;
   3.661 +            DataBuffer[6] = 0x33;
   3.662 +            DataBuffer[7] = 0x34;
   3.663 +            DataBuffer[8] = 0x35;
   3.664 +            DataBuffer[9] = 0x36;
   3.665 +            DataBuffer[10] = 0x37;
   3.666 +            DataBuffer[11] = 0x38;
   3.667 +            break;
   3.668 +          default:
   3.669 +            KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", Srb->Cdb[2]));
   3.670 +            Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.671 +            break;
   3.672 +          }
   3.673 +        }
   3.674 +        break;
   3.675 +      case XENVBD_DEVICETYPE_CDROM:
   3.676 +        if ((Srb->Cdb[1] & 1) == 0)
   3.677 +        {
   3.678 +          DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
   3.679 +          DataBuffer[1] = 0x01; // removable
   3.680 +          DataBuffer[3] = 32;
   3.681 +          memcpy(DataBuffer + 8, "XEN     ", 8); // vendor id
   3.682 +          memcpy(DataBuffer + 16, "PV VBD          ", 16); // product id
   3.683 +          memcpy(DataBuffer + 32, "0000", 4); // product revision level
   3.684 +        }
   3.685 +        else
   3.686 +        {
   3.687 +          switch (Srb->Cdb[2])
   3.688 +          {
   3.689 +          case 0x00:
   3.690 +            DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
   3.691 +            DataBuffer[1] = 0x00;
   3.692 +            DataBuffer[2] = 0x00;
   3.693 +            DataBuffer[3] = 2;
   3.694 +            DataBuffer[4] = 0x00;
   3.695 +            DataBuffer[5] = 0x80;
   3.696 +            break;
   3.697 +          case 0x80:
   3.698 +            DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
   3.699 +            DataBuffer[1] = 0x80;
   3.700 +            DataBuffer[2] = 0x00;
   3.701 +            DataBuffer[3] = 8;
   3.702 +            DataBuffer[4] = 0x31;
   3.703 +            DataBuffer[5] = 0x32;
   3.704 +            DataBuffer[6] = 0x33;
   3.705 +            DataBuffer[7] = 0x34;
   3.706 +            DataBuffer[8] = 0x35;
   3.707 +            DataBuffer[9] = 0x36;
   3.708 +            DataBuffer[10] = 0x37;
   3.709 +            DataBuffer[11] = 0x38;
   3.710 +            break;
   3.711 +          default:
   3.712 +            KdPrint((__DRIVER_NAME "     Unknown Page %02x requested\n", Srb->Cdb[2]));
   3.713 +            Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.714 +            break;
   3.715 +          }
   3.716 +        }
   3.717 +        break;
   3.718 +      default:
   3.719 +        KdPrint((__DRIVER_NAME "     Unknown DeviceType %02x requested\n", xvdd->device_type));
   3.720 +        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.721 +        break;
   3.722 +      }
   3.723 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.724 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.725 +      break;
   3.726 +    case SCSIOP_READ_CAPACITY:
   3.727 +      //KdPrint((__DRIVER_NAME "     Command = READ_CAPACITY\n"));
   3.728 +      DataBuffer = Srb->DataBuffer;
   3.729 +      RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
   3.730 +      DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
   3.731 +      DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
   3.732 +      DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
   3.733 +      DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
   3.734 +      DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
   3.735 +      DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
   3.736 +      DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
   3.737 +      DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
   3.738 +      Srb->ScsiStatus = 0;
   3.739 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.740 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.741 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.742 +      break;
   3.743 +    case SCSIOP_MODE_SENSE:
   3.744 +      //KdPrint((__DRIVER_NAME "     Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x10, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
   3.745 +      //KdPrint((__DRIVER_NAME "     Length = %d\n", Srb->DataTransferLength));
   3.746 +
   3.747 +      Srb->ScsiStatus = 0;
   3.748 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.749 +      Srb->DataTransferLength = 0;
   3.750 +      DataBuffer = Srb->DataBuffer;
   3.751 +      RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
   3.752 +      switch(cdb->MODE_SENSE.PageCode)
   3.753 +      {
   3.754 +      case MODE_SENSE_RETURN_ALL:
   3.755 +        //Ptr = (UCHAR *)Srb->DataBuffer;
   3.756 +        for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
   3.757 +        {
   3.758 +          if (XenVbd_FillModePage(xvdd, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
   3.759 +          {
   3.760 +            break;
   3.761 +          }
   3.762 +        }
   3.763 +        break;
   3.764 +      default:
   3.765 +        XenVbd_FillModePage(xvdd, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
   3.766 +        break;
   3.767 +      }
   3.768 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.769 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.770 +      break;
   3.771 +    case SCSIOP_WRITE:
   3.772 +    case SCSIOP_READ:
   3.773 +      //KdPrint((__DRIVER_NAME "     Command = READ/WRITE\n"));
   3.774 +      XenVbd_PutSrbOnRing(xvdd, Srb, 0);
   3.775 +      if (!xvdd->shadow_free)
   3.776 +        ScsiPortNotification(NextRequest, DeviceExtension);
   3.777 +      break;
   3.778 +    case SCSIOP_VERIFY:
   3.779 +      // Should we do more here?
   3.780 +      KdPrint((__DRIVER_NAME "     Command = VERIFY\n"));
   3.781 +      Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
   3.782 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);      
   3.783 +      ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
   3.784 +      break;
   3.785 +    case SCSIOP_REPORT_LUNS:
   3.786 +      KdPrint((__DRIVER_NAME "     Command = REPORT_LUNS\n"));
   3.787 +      Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
   3.788 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.789 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.790 +      break;
   3.791 +    case SCSIOP_READ_TOC:
   3.792 +      DataBuffer = Srb->DataBuffer;
   3.793 +//      DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
   3.794 +/*
   3.795 +#define READ_TOC_FORMAT_TOC         0x00
   3.796 +#define READ_TOC_FORMAT_SESSION     0x01
   3.797 +#define READ_TOC_FORMAT_FULL_TOC    0x02
   3.798 +#define READ_TOC_FORMAT_PMA         0x03
   3.799 +#define READ_TOC_FORMAT_ATIP        0x04
   3.800 +*/
   3.801 +      KdPrint((__DRIVER_NAME "     Command = READ_TOC\n"));
   3.802 +      KdPrint((__DRIVER_NAME "     Msf = %d\n", cdb->READ_TOC.Msf));
   3.803 +      KdPrint((__DRIVER_NAME "     LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
   3.804 +      KdPrint((__DRIVER_NAME "     Format2 = %d\n", cdb->READ_TOC.Format2));
   3.805 +      KdPrint((__DRIVER_NAME "     StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
   3.806 +      KdPrint((__DRIVER_NAME "     AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
   3.807 +      KdPrint((__DRIVER_NAME "     Control = %d\n", cdb->READ_TOC.Control));
   3.808 +      KdPrint((__DRIVER_NAME "     Format = %d\n", cdb->READ_TOC.Format));
   3.809 +      switch (cdb->READ_TOC.Format2)
   3.810 +      {
   3.811 +      case READ_TOC_FORMAT_TOC:
   3.812 +        DataBuffer[0] = 0; // length MSB
   3.813 +        DataBuffer[1] = 10; // length LSB
   3.814 +        DataBuffer[2] = 1; // First Track
   3.815 +        DataBuffer[3] = 1; // Last Track
   3.816 +        DataBuffer[4] = 0; // Reserved
   3.817 +        DataBuffer[5] = 0x14; // current position data + uninterrupted data
   3.818 +        DataBuffer[6] = 1; // last complete track
   3.819 +        DataBuffer[7] = 0; // reserved
   3.820 +        DataBuffer[8] = 0; // MSB Block
   3.821 +        DataBuffer[9] = 0;
   3.822 +        DataBuffer[10] = 0;
   3.823 +        DataBuffer[11] = 0; // LSB Block
   3.824 +        Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.825 +        break;
   3.826 +      case READ_TOC_FORMAT_SESSION:
   3.827 +      case READ_TOC_FORMAT_FULL_TOC:
   3.828 +      case READ_TOC_FORMAT_PMA:
   3.829 +      case READ_TOC_FORMAT_ATIP:
   3.830 +        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.831 +        break;
   3.832 +      }
   3.833 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.834 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.835 +      break;
   3.836 +    case SCSIOP_START_STOP_UNIT:
   3.837 +      KdPrint((__DRIVER_NAME "     Command = SCSIOP_START_STOP_UNIT\n"));
   3.838 +      Srb->SrbStatus = SRB_STATUS_SUCCESS;
   3.839 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.840 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.841 +      break;
   3.842 +    default:
   3.843 +      KdPrint((__DRIVER_NAME "     Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
   3.844 +      Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.845 +      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.846 +      ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.847 +      break;
   3.848 +    }
   3.849 +    break;
   3.850 +  case SRB_FUNCTION_IO_CONTROL:
   3.851 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_IO_CONTROL\n"));
   3.852 +    Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.853 +    ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.854 +    ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.855 +    break;
   3.856 +  case SRB_FUNCTION_FLUSH:
   3.857 +    KdPrint((__DRIVER_NAME "     SRB_FUNCTION_FLUSH\n"));
   3.858 +    Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.859 +    ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.860 +    ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.861 +    break;
   3.862 +  default:
   3.863 +    KdPrint((__DRIVER_NAME "     Unhandled Srb->Function = %08X\n", Srb->Function));
   3.864 +    Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
   3.865 +    ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
   3.866 +    ScsiPortNotification(NextRequest, DeviceExtension, NULL);
   3.867 +    break;
   3.868 +  }
   3.869 +
   3.870 +  //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.871 +  return TRUE;
   3.872 +}
   3.873 +
   3.874 +static BOOLEAN
   3.875 +XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
   3.876 +{
   3.877 +  UNREFERENCED_PARAMETER(DeviceExtension);
   3.878 +  UNREFERENCED_PARAMETER(PathId);
   3.879 +
   3.880 +  KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
   3.881 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.882 +
   3.883 +  KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
   3.884 +
   3.885 +  return TRUE;
   3.886 +}
   3.887 +
   3.888 +static BOOLEAN
   3.889 +XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
   3.890 +{
   3.891 +  UNREFERENCED_PARAMETER(DeviceExtension);
   3.892 +  UNREFERENCED_PARAMETER(Context);
   3.893 +  UNREFERENCED_PARAMETER(SaveState);
   3.894 +
   3.895 +  KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
   3.896 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.897 +
   3.898 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.899 +
   3.900 +  return TRUE;
   3.901 +}
   3.902 +
   3.903 +static SCSI_ADAPTER_CONTROL_STATUS
   3.904 +XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
   3.905 +{
   3.906 +  SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
   3.907 +  PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
   3.908 +  //KIRQL OldIrql;
   3.909 +
   3.910 +  UNREFERENCED_PARAMETER(DeviceExtension);
   3.911 +
   3.912 +  KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
   3.913 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.914 +
   3.915 +  switch (ControlType)
   3.916 +  {
   3.917 +  case ScsiQuerySupportedControlTypes:
   3.918 +    SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
   3.919 +    KdPrint((__DRIVER_NAME "     ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
   3.920 +    SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
   3.921 +    SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
   3.922 +    break;
   3.923 +  case ScsiStopAdapter:
   3.924 +    KdPrint((__DRIVER_NAME "     ScsiStopAdapter\n"));
   3.925 +    /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
   3.926 +    break;
   3.927 +  case ScsiRestartAdapter:
   3.928 +    KdPrint((__DRIVER_NAME "     ScsiRestartAdapter\n"));
   3.929 +    break;
   3.930 +  case ScsiSetBootConfig:
   3.931 +    KdPrint((__DRIVER_NAME "     ScsiSetBootConfig\n"));
   3.932 +    break;
   3.933 +  case ScsiSetRunningConfig:
   3.934 +    KdPrint((__DRIVER_NAME "     ScsiSetRunningConfig\n"));
   3.935 +    break;
   3.936 +  default:
   3.937 +    KdPrint((__DRIVER_NAME "     UNKNOWN\n"));
   3.938 +    break;
   3.939 +  }
   3.940 +
   3.941 +  KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
   3.942 +
   3.943 +  return Status;
   3.944 +}
   3.945 +
   3.946 +VOID
   3.947 +XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
   3.948 +{
   3.949 +  KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
   3.950 +  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
   3.951 +
   3.952 +  HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
   3.953 +  HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
   3.954 +  HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
   3.955 +  HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
   3.956 +  HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
   3.957 +  HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
   3.958 +  HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
   3.959 +
   3.960 +  KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
   3.961 +}
     4.1 --- a/xenvbd/xenvbd.h	Fri May 23 23:53:02 2008 +1000
     4.2 +++ b/xenvbd/xenvbd.h	Mon May 26 11:55:43 2008 +1000
     4.3 @@ -44,7 +44,7 @@ Foundation, Inc., 51 Franklin Street, Fi
     4.4  
     4.5  #define XENVBD_POOL_TAG (ULONG) 'XVBD'
     4.6  
     4.7 -#define UNALIGNED_DOUBLE_BUFFER_SIZE (PAGE_SIZE * 2)
     4.8 +#define UNALIGNED_DOUBLE_BUFFER_SIZE (PAGE_SIZE * 1)
     4.9  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    4.10  #define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
    4.11  #define BLK_OTHER_RING_SIZE __RING_SIZE((blkif_other_sring_t *)0, PAGE_SIZE)
    4.12 @@ -75,7 +75,9 @@ DEFINE_RING_TYPES(blkif_other, struct bl
    4.13  
    4.14  typedef struct {
    4.15    blkif_request_t req;
    4.16 -  PSCSI_REQUEST_BLOCK Srb;
    4.17 +  PSCSI_REQUEST_BLOCK srb;
    4.18 +  ULONG offset;
    4.19 +  ULONG length;
    4.20  } blkif_shadow_t;
    4.21  
    4.22  #define SHADOW_ENTRIES 32