win-pvdrivers

annotate xenvbd/xenvbd_storport.c @ 979:8f483a2b2991

Fix up PREfast warnings
author James Harper <james.harper@bendigoit.com.au>
date Sun Apr 15 19:47:10 2012 +1000 (2012-04-15)
parents 941699790045
children e9011a1ba5bb d9da5f8f7431
rev   line source
james@831 1 /*
james@831 2 PV Drivers for Windows Xen HVM Domains
james@831 3 Copyright (C) 2007 James Harper
james@831 4
james@831 5 This program is free software; you can redistribute it and/or
james@831 6 modify it under the terms of the GNU General Public License
james@831 7 as published by the Free Software Foundation; either version 2
james@831 8 of the License, or (at your option) any later version.
james@831 9
james@831 10 This program is distributed in the hope that it will be useful,
james@831 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@831 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@831 13 GNU General Public License for more details.
james@831 14
james@831 15 You should have received a copy of the GNU General Public License
james@831 16 along with this program; if not, write to the Free Software
james@831 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@831 18 */
james@831 19
james@831 20 #define INITGUID
james@831 21 #include "xenvbd_storport.h"
james@831 22
james@831 23 #pragma warning(disable: 4127)
james@831 24
james@831 25 #if defined(__x86_64__)
james@831 26 #define LongLongToPtr(x) (PVOID)(x)
james@831 27 #else
james@831 28 #define LongLongToPtr(x) UlongToPtr(x)
james@831 29 #endif
james@831 30
james@831 31 /* Not really necessary but keeps PREfast happy */
james@831 32 DRIVER_INITIALIZE DriverEntry;
james@831 33 static BOOLEAN XenVbd_HandleEvent(PVOID DeviceExtension);
james@831 34
james@831 35 static BOOLEAN dump_mode = FALSE;
james@831 36 #define DUMP_MODE_ERROR_LIMIT 64
james@831 37 static ULONG dump_mode_errors = 0;
james@831 38
james@831 39 CHAR scsi_device_manufacturer[8];
james@831 40 CHAR scsi_disk_model[16];
james@831 41 CHAR scsi_cdrom_model[16];
james@831 42
james@831 43 ULONGLONG parse_numeric_string(PCHAR string)
james@831 44 {
james@831 45 ULONGLONG val = 0;
james@831 46 while (*string != 0)
james@831 47 {
james@831 48 val = val * 10 + (*string - '0');
james@831 49 string++;
james@831 50 }
james@831 51 return val;
james@831 52 }
james@831 53
james@831 54 static blkif_shadow_t *
james@831 55 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
james@831 56 {
james@831 57 if (xvdd->shadow_free == 0)
james@831 58 {
james@831 59 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
james@831 60 return NULL;
james@831 61 }
james@831 62 xvdd->shadow_free--;
james@831 63 if (xvdd->shadow_free < xvdd->shadow_min_free)
james@831 64 xvdd->shadow_min_free = xvdd->shadow_free;
james@831 65 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
james@831 66 }
james@831 67
james@831 68 static VOID
james@831 69 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
james@831 70 {
james@889 71 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)(shadow->req.id & SHADOW_ID_ID_MASK);
james@831 72 shadow->srb = NULL;
james@889 73 shadow->reset = FALSE;
james@831 74 xvdd->shadow_free++;
james@831 75 }
james@831 76
james@831 77 static blkif_response_t *
james@831 78 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
james@831 79 {
james@831 80 blkif_other_response_t *rep;
james@831 81 if (!xvdd->use_other)
james@831 82 return RING_GET_RESPONSE(&xvdd->ring, i);
james@831 83 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
james@831 84 xvdd->tmp_rep.id = rep->id;
james@831 85 xvdd->tmp_rep.operation = rep->operation;
james@831 86 xvdd->tmp_rep.status = rep->status;
james@831 87 return &xvdd->tmp_rep;
james@831 88 }
james@831 89
james@831 90 static VOID
james@831 91 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
james@831 92 {
james@831 93 blkif_other_request_t *other_req;
james@831 94
james@831 95 if (!xvdd->use_other)
james@831 96 {
james@831 97 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
james@831 98 }
james@831 99 else
james@831 100 {
james@831 101 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
james@831 102 other_req->operation = req->operation;
james@831 103 other_req->nr_segments = req->nr_segments;
james@831 104 other_req->handle = req->handle;
james@831 105 other_req->id = req->id;
james@831 106 other_req->sector_number = req->sector_number;
james@831 107 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
james@831 108 }
james@831 109 xvdd->ring.req_prod_pvt++;
james@831 110 }
james@831 111
james@831 112 static ULONG
james@831 113 XenVbd_InitConfig(PXENVBD_DEVICE_DATA xvdd)
james@831 114 {
james@831 115 ULONG status;
james@831 116 PUCHAR ptr;
james@831 117 USHORT type;
james@831 118 PCHAR setting, value, value2;
james@831 119
james@831 120 FUNCTION_ENTER();
james@831 121 /* first read the default config items */
james@831 122 ptr = xvdd->device_base;
james@831 123 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@831 124 {
james@831 125 switch(type)
james@831 126 {
james@831 127 case XEN_INIT_TYPE_VECTORS:
james@831 128 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
james@831 129 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
james@831 130 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
james@831 131 {
james@831 132 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
james@831 133 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
james@831 134 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@831 135 return SP_RETURN_BAD_CONFIG;
james@831 136 }
james@831 137 else
james@831 138 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
james@831 139 break;
james@831 140 default:
james@831 141 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
james@831 142 break;
james@831 143 }
james@831 144 }
james@831 145
james@831 146 /* then set up all the configuration requests */
james@831 147 ptr = xvdd->device_base;
james@831 148 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
james@831 149 #pragma warning(suppress:4054)
james@831 150 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_DPC, "event-channel", (PVOID)XenVbd_HandleEvent, xvdd);
james@831 151 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
james@831 152 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
james@831 153 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
james@831 154 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
james@831 155 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
james@845 156 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialised);
james@831 157 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
james@831 158 __ADD_XEN_INIT_UCHAR(&ptr, 20);
james@831 159 __ADD_XEN_INIT_UCHAR(&ptr, 0);
james@831 160 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
james@845 161 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
james@845 162 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
james@845 163 __ADD_XEN_INIT_UCHAR(&ptr, 20);
james@831 164 __ADD_XEN_INIT_UCHAR(&ptr, 0);
james@831 165 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
james@831 166 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
james@831 167 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
james@831 168 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@831 169 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
james@831 170 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
james@831 171 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@831 172 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
james@831 173 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
james@831 174 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@831 175 __ADD_XEN_INIT_UCHAR(&ptr, 0);
james@831 176 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@831 177
james@831 178 /* then configure */
james@831 179 status = xvdd->vectors.XenPci_XenConfigDevice(xvdd->vectors.context);
james@831 180 if (!NT_SUCCESS(status))
james@831 181 {
james@947 182 xvdd->inactive = TRUE;
james@831 183 KdPrint(("Failed to complete device configuration (%08x)\n", status));
james@831 184 FUNCTION_EXIT();
james@831 185 return SP_RETURN_BAD_CONFIG;
james@831 186 }
james@831 187 FUNCTION_EXIT();
james@831 188 return SP_RETURN_FOUND;
james@831 189 }
james@831 190
james@831 191 static ULONG
james@831 192 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
james@831 193 {
james@831 194 ULONG i;
james@831 195 PUCHAR ptr;
james@831 196 USHORT type;
james@831 197 PCHAR setting, value, value2;
james@831 198 ULONG qemu_protocol_version = 0;
james@831 199 BOOLEAN qemu_hide_filter = FALSE;
james@831 200 ULONG qemu_hide_flags_value = 0;
james@831 201
james@831 202 FUNCTION_ENTER();
james@831 203
james@831 204 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
james@831 205 xvdd->sring = NULL;
james@831 206 xvdd->event_channel = 0;
james@831 207
james@831 208 xvdd->inactive = TRUE;
james@831 209
james@831 210 ptr = xvdd->device_base;
james@831 211 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@831 212 {
james@831 213 switch(type)
james@831 214 {
james@831 215 case XEN_INIT_TYPE_VECTORS:
james@831 216 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
james@831 217 if (dump_mode)
james@831 218 {
james@831 219 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
james@831 220 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
james@831 221 {
james@831 222 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
james@831 223 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
james@831 224 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
james@831 225 return SP_RETURN_BAD_CONFIG;
james@831 226 }
james@831 227 else
james@831 228 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
james@831 229 }
james@831 230 break;
james@831 231 case XEN_INIT_TYPE_RING: /* frontend ring */
james@831 232 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
james@831 233 if (strcmp(setting, "ring-ref") == 0)
james@831 234 {
james@831 235 xvdd->sring = (blkif_sring_t *)value;
james@831 236 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
james@831 237 /* this bit is for when we have to take over an existing ring on a crash dump */
james@831 238 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
james@831 239 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
james@831 240 }
james@831 241 break;
james@831 242 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
james@841 243 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d (%08x)\n", setting, PtrToUlong(value) & 0x3FFFFFFF, PtrToUlong(value)));
james@831 244 if (strcmp(setting, "event-channel") == 0)
james@831 245 {
james@831 246 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
james@831 247 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
james@831 248 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
james@831 249 if (PtrToUlong(value) & 0x80000000)
james@831 250 {
james@831 251 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
james@831 252 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
james@831 253 }
james@831 254 }
james@831 255 break;
james@831 256 case XEN_INIT_TYPE_READ_STRING_BACK:
james@831 257 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@831 258 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@831 259 if (strcmp(setting, "sectors") == 0)
james@831 260 xvdd->total_sectors = parse_numeric_string(value);
james@831 261 else if (strcmp(setting, "sector-size") == 0)
james@831 262 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
james@831 263 else if (strcmp(setting, "device-type") == 0)
james@831 264 {
james@831 265 if (strcmp(value, "disk") == 0)
james@831 266 {
james@831 267 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
james@831 268 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
james@831 269 }
james@831 270 else if (strcmp(value, "cdrom") == 0)
james@831 271 {
james@831 272 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
james@831 273 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
james@831 274 }
james@831 275 else
james@831 276 {
james@831 277 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
james@831 278 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
james@831 279 }
james@831 280 }
james@831 281 else if (strcmp(setting, "mode") == 0)
james@831 282 {
james@831 283 if (strncmp(value, "r", 1) == 0)
james@831 284 {
james@831 285 KdPrint((__DRIVER_NAME " mode = r\n"));
james@831 286 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
james@831 287 }
james@831 288 else if (strncmp(value, "w", 1) == 0)
james@831 289 {
james@831 290 KdPrint((__DRIVER_NAME " mode = w\n"));
james@831 291 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
james@831 292 }
james@831 293 else
james@831 294 {
james@831 295 KdPrint((__DRIVER_NAME " mode = unknown\n"));
james@831 296 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
james@831 297 }
james@831 298 }
james@831 299 break;
james@831 300 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
james@831 301 qemu_protocol_version = PtrToUlong(value);
james@831 302 break;
james@831 303 case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
james@831 304 qemu_hide_flags_value = PtrToUlong(value);
james@831 305 KdPrint((__DRIVER_NAME " qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
james@831 306 break;
james@831 307 case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
james@831 308 qemu_hide_filter = TRUE;
james@831 309 KdPrint((__DRIVER_NAME " qemu_hide_filter = TRUE\n"));
james@831 310 break;
james@831 311 case XEN_INIT_TYPE_STATE_PTR:
james@831 312 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
james@831 313 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
james@831 314 break;
james@831 315 default:
james@831 316 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
james@831 317 break;
james@831 318 }
james@831 319 }
james@831 320
james@831 321 if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
james@831 322 xvdd->inactive = FALSE;
james@831 323
james@831 324 if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
james@831 325 || xvdd->sring == NULL
james@831 326 || xvdd->event_channel == 0
james@831 327 || xvdd->total_sectors == 0
james@831 328 || xvdd->bytes_per_sector == 0))
james@831 329 {
james@831 330 KdPrint((__DRIVER_NAME " Missing settings\n"));
james@831 331 FUNCTION_EXIT();
james@831 332 return SP_RETURN_BAD_CONFIG;
james@831 333 }
james@831 334
james@831 335 if (xvdd->inactive)
james@831 336 KdPrint((__DRIVER_NAME " Device is inactive\n"));
james@831 337 else
james@831 338 {
james@831 339 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
james@831 340 {
james@831 341 /* CD/DVD drives must have bytes_per_sector = 2048. */
james@831 342 xvdd->bytes_per_sector = 2048;
james@831 343 }
james@831 344
james@831 345 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
james@831 346 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
james@831 347
james@831 348 xvdd->shadow_free = 0;
james@831 349 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
james@831 350 for (i = 0; i < SHADOW_ENTRIES; i++)
james@831 351 {
james@831 352 xvdd->shadows[i].req.id = i;
james@889 353 /* make sure leftover real requests's are never confused with dump mode requests */
james@889 354 if (dump_mode)
james@889 355 xvdd->shadows[i].req.id |= SHADOW_ID_DUMP_FLAG;
james@831 356 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
james@831 357 }
james@831 358 }
james@831 359
james@831 360 FUNCTION_EXIT();
james@831 361 return SP_RETURN_FOUND;
james@831 362 }
james@831 363
james@831 364 static __inline ULONG
james@831 365 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
james@831 366 {
james@831 367 switch (srb->Cdb[0])
james@831 368 {
james@831 369 case SCSIOP_READ:
james@831 370 case SCSIOP_WRITE:
james@831 371 return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
james@831 372 case SCSIOP_READ16:
james@831 373 case SCSIOP_WRITE16:
james@831 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];
james@831 375 default:
james@831 376 return 0;
james@831 377 }
james@831 378 }
james@831 379
james@831 380 static __inline ULONGLONG
james@831 381 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
james@831 382 {
james@831 383 ULONGLONG sector;
james@831 384
james@831 385 switch (srb->Cdb[0])
james@831 386 {
james@831 387 case SCSIOP_READ:
james@831 388 case SCSIOP_WRITE:
james@831 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];
james@831 390 break;
james@831 391 case SCSIOP_READ16:
james@831 392 case SCSIOP_WRITE16:
james@831 393 sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
james@831 394 | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
james@831 395 | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
james@831 396 | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
james@831 397 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
james@831 398 break;
james@831 399 default:
james@831 400 sector = 0;
james@831 401 break;
james@831 402 }
james@831 403 return sector;
james@831 404 }
james@831 405
james@831 406 static __inline BOOLEAN
james@831 407 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
james@831 408 {
james@831 409 switch (srb->Cdb[0])
james@831 410 {
james@831 411 case SCSIOP_READ:
james@831 412 case SCSIOP_READ16:
james@831 413 return TRUE;
james@831 414 case SCSIOP_WRITE:
james@831 415 case SCSIOP_WRITE16:
james@831 416 return FALSE;
james@831 417 default:
james@831 418 return FALSE;
james@831 419 }
james@831 420 }
james@831 421
james@831 422 static VOID
james@831 423 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
james@831 424 {
james@841 425 srb_list_entry_t *srb_entry = srb->SrbExtension;
james@841 426 srb_entry->srb = srb;
james@841 427 if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI)
james@841 428 {
james@841 429 srb_entry->outstanding_requests = 0;
james@841 430 srb_entry->length = srb->DataTransferLength;
james@841 431 srb_entry->offset = 0;
james@841 432 srb_entry->error = FALSE;
james@841 433 }
james@841 434 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
james@831 435 }
james@831 436
james@831 437 static VOID
james@831 438 XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
james@831 439 {
james@831 440 PSCSI_REQUEST_BLOCK srb;
james@831 441 srb_list_entry_t *srb_entry;
james@831 442 ULONGLONG sector_number;
james@831 443 ULONG block_count;
james@831 444 blkif_shadow_t *shadow;
james@831 445 ULONG remaining, offset, length;
james@831 446 grant_ref_t gref;
james@831 447 PUCHAR ptr;
james@831 448 int notify;
james@831 449 int i;
james@831 450 PVOID system_address;
james@831 451
james@831 452 //if (dump_mode) FUNCTION_ENTER();
james@831 453
james@831 454 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)
james@831 455 {
james@831 456 srb = srb_entry->srb;
james@841 457 ASSERT(srb);
james@841 458 if (srb->Function != SRB_FUNCTION_EXECUTE_SCSI)
james@841 459 {
james@841 460 KdPrint((__DRIVER_NAME " SRB_FUNCTION_%02x retrieved from ring\n", srb->Function));
james@841 461 if (xvdd->shadow_free != SHADOW_ENTRIES)
james@841 462 {
james@841 463 KdPrint((__DRIVER_NAME " busy\n"));
james@841 464 /* put it back at the end of the list just in case something is queued that needs to be processed */
james@841 465 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
james@841 466 break; /* stall the queue until it's all empty */
james@841 467 }
james@841 468 else
james@841 469 {
james@841 470 KdPrint((__DRIVER_NAME " completing\n"));
james@841 471 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@841 472 StorPortNotification(RequestComplete, xvdd, srb);
james@841 473 continue;
james@841 474 }
james@841 475 }
james@841 476
james@831 477 if (!dump_mode)
james@831 478 {
james@831 479 if (StorPortGetSystemAddress(xvdd, srb, &system_address) != STOR_STATUS_SUCCESS)
james@831 480 {
james@831 481 KdPrint((__DRIVER_NAME " Failed to map DataBuffer\n"));
james@864 482 srb->SrbStatus = SRB_STATUS_BUSY;
james@831 483 StorPortNotification(RequestComplete, xvdd, srb);
james@831 484 continue;
james@831 485 }
james@841 486 system_address = (PUCHAR)system_address + srb_entry->offset;
james@831 487 }
james@831 488 else
james@831 489 {
james@831 490 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
james@841 491 system_address = (PUCHAR)srb->DataBuffer + srb_entry->offset;
james@831 492 }
james@831 493 block_count = decode_cdb_length(srb);
james@831 494 block_count *= xvdd->bytes_per_sector / 512;
james@831 495 sector_number = decode_cdb_sector(srb);
james@831 496 sector_number *= xvdd->bytes_per_sector / 512;
james@831 497
james@831 498 ASSERT(block_count * xvdd->bytes_per_sector == srb->DataTransferLength);
james@831 499
james@841 500 //KdPrint((__DRIVER_NAME " srb sector_number = %d, block_count = %d\n", (ULONG)sector_number, block_count));
james@841 501
james@841 502 sector_number += srb_entry->offset / 512;
james@841 503 block_count -= srb_entry->offset / 512;
james@841 504
james@831 505 /* look for pending writes that overlap this one */
james@831 506 /* we get warnings from drbd if we don't */
james@841 507 if (srb_entry->offset == 0)
james@831 508 {
james@841 509 for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
james@841 510 {
james@841 511 PSCSI_REQUEST_BLOCK srb2;
james@841 512 ULONGLONG sector_number2;
james@841 513 ULONG block_count2;
james@841 514
james@841 515 srb2 = xvdd->shadows[i].srb;
james@841 516 if (!srb2)
james@841 517 continue;
james@841 518 if (decode_cdb_is_read(srb2))
james@841 519 continue;
james@841 520 block_count2 = decode_cdb_length(srb2);;
james@841 521 block_count2 *= xvdd->bytes_per_sector / 512;
james@841 522 sector_number2 = decode_cdb_sector(srb2);
james@841 523 sector_number2 *= xvdd->bytes_per_sector / 512;
james@841 524
james@841 525 if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
james@841 526 continue;
james@841 527 if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
james@841 528 continue;
james@831 529
james@841 530 KdPrint((__DRIVER_NAME " Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
james@841 531 sector_number, block_count, sector_number2, block_count2));
james@841 532 /* put the srb back at the start of the queue */
james@841 533 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
james@841 534 break; /* stall the queue */
james@841 535 }
james@841 536 if (i != MAX_SHADOW_ENTRIES)
james@841 537 {
james@841 538 break; /* stall the queue but submit any outstanding requests */
james@841 539 }
james@831 540 }
james@841 541
james@831 542 shadow = get_shadow_from_freelist(xvdd);
james@839 543 if (!shadow)
james@839 544 {
james@839 545 /* put the srb back at the start of the queue */
james@839 546 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
james@841 547 break; /* stall the queue but submit any outstanding requests */
james@839 548 }
james@831 549 ASSERT(!shadow->aligned_buffer_in_use);
james@831 550 ASSERT(!shadow->srb);
james@831 551 shadow->req.sector_number = sector_number;
james@831 552 shadow->req.handle = 0;
james@831 553 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
james@831 554 shadow->req.nr_segments = 0;
james@831 555 shadow->srb = srb;
james@841 556 shadow->length = 0;
james@831 557 shadow->system_address = system_address;
james@889 558 shadow->reset = FALSE;
james@831 559
james@831 560 if (!dump_mode)
james@831 561 {
james@831 562 if ((ULONG_PTR)shadow->system_address & 511)
james@831 563 {
james@831 564 xvdd->aligned_buffer_in_use = TRUE;
james@898 565 /* limit to aligned_buffer_size */
james@898 566 block_count = min(block_count, xvdd->aligned_buffer_size / 512);
james@841 567 ptr = (PUCHAR)xvdd->aligned_buffer;
james@831 568 if (!decode_cdb_is_read(srb))
james@831 569 memcpy(ptr, shadow->system_address, block_count * 512);
james@831 570 shadow->aligned_buffer_in_use = TRUE;
james@831 571 }
james@831 572 else
james@831 573 {
james@841 574 ptr = (PUCHAR)shadow->system_address;
james@831 575 shadow->aligned_buffer_in_use = FALSE;
james@831 576 }
james@831 577 }
james@831 578 else
james@831 579 {
james@831 580 ASSERT(!((ULONG_PTR)shadow->system_address & 511));
james@841 581 ptr = shadow->system_address;
james@831 582 shadow->aligned_buffer_in_use = FALSE;
james@831 583 }
james@831 584
james@841 585 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)sector_number, block_count));
james@831 586 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
james@831 587 //KdPrint((__DRIVER_NAME " system_address = %p\n", shadow->system_address));
james@841 588 //KdPrint((__DRIVER_NAME " offset = %d, length = %d\n", srb_entry->offset, srb_entry->length));
james@841 589 //KdPrint((__DRIVER_NAME " ptr = %p\n", ptr));
james@831 590
james@831 591 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
james@831 592 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
james@831 593
james@841 594 remaining = block_count * 512;
james@841 595 while (remaining > 0 && shadow->req.nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST)
james@831 596 {
james@831 597 PHYSICAL_ADDRESS physical_address;
james@831 598
james@831 599 if (!dump_mode)
james@831 600 {
james@831 601 physical_address = MmGetPhysicalAddress(ptr);
james@831 602 }
james@831 603 else
james@831 604 {
james@831 605 ULONG length;
james@831 606 physical_address = StorPortGetPhysicalAddress(xvdd, srb, ptr, &length);
james@831 607 }
james@976 608 gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context,
james@841 609 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, xvdd->grant_tag);
james@831 610 if (gref == INVALID_GRANT_REF)
james@831 611 {
james@831 612 ULONG i;
james@831 613 for (i = 0; i < shadow->req.nr_segments; i++)
james@831 614 {
james@831 615 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
james@841 616 shadow->req.seg[i].gref, FALSE, xvdd->grant_tag);
james@831 617 }
james@831 618 if (shadow->aligned_buffer_in_use)
james@831 619 {
james@831 620 shadow->aligned_buffer_in_use = FALSE;
james@831 621 xvdd->aligned_buffer_in_use = FALSE;
james@831 622 }
james@831 623 /* put the srb back at the start of the queue */
james@831 624 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
james@831 625 put_shadow_on_freelist(xvdd, shadow);
james@831 626 KdPrint((__DRIVER_NAME " Out of gref's. Deferring\n"));
james@841 627 break; /* stall the queue but submit any outstanding requests */
james@831 628 }
james@831 629 offset = physical_address.LowPart & (PAGE_SIZE - 1);
james@831 630 length = min(PAGE_SIZE - offset, remaining);
james@831 631 //if (dump_mode) KdPrint((__DRIVER_NAME " length = %d\n", length));
james@831 632 //if (dump_mode) KdPrint((__DRIVER_NAME " offset = %d\n", length));
james@831 633 ASSERT((offset & 511) == 0);
james@831 634 ASSERT((length & 511) == 0);
james@831 635 ASSERT(offset + length <= PAGE_SIZE);
james@831 636 shadow->req.seg[shadow->req.nr_segments].gref = gref;
james@841 637 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset / 512);
james@841 638 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) / 512) - 1);
james@831 639 //if (dump_mode) KdPrint((__DRIVER_NAME " gref = %d\n", shadow->req.seg[shadow->req.nr_segments].gref));
james@831 640 //if (dump_mode) KdPrint((__DRIVER_NAME " first_sect = %d\n", shadow->req.seg[shadow->req.nr_segments].first_sect));
james@831 641 //if (dump_mode) KdPrint((__DRIVER_NAME " last_sect = %d\n", shadow->req.seg[shadow->req.nr_segments].last_sect));
james@831 642 remaining -= length;
james@831 643 ptr += length;
james@841 644 shadow->length += length;
james@831 645 shadow->req.nr_segments++;
james@831 646 }
james@841 647 srb_entry->offset += shadow->length;
james@841 648 srb_entry->outstanding_requests++;
james@841 649 //KdPrint((__DRIVER_NAME " outstanding_requests = %p\n", srb_entry->outstanding_requests));
james@841 650 //KdPrint((__DRIVER_NAME " offset = %d, length = %d\n", srb_entry->offset, srb_entry->length));
james@841 651 //KdPrint((__DRIVER_NAME " ptr = %p\n", ptr));
james@841 652 if (srb_entry->offset < srb_entry->length)
james@841 653 {
james@841 654 if (dump_mode) KdPrint((__DRIVER_NAME " inserting back into list\n"));
james@841 655 /* put the srb back at the start of the queue to continue on the next request */
james@841 656 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
james@841 657 }
james@831 658
james@831 659 XenVbd_PutRequest(xvdd, &shadow->req);
james@831 660 }
james@841 661 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
james@841 662 if (notify)
james@841 663 {
james@841 664 //KdPrint((__DRIVER_NAME " Notifying\n"));
james@841 665 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
james@841 666 }
james@841 667
james@831 668 //if (dump_mode) FUNCTION_EXIT();
james@831 669 }
james@831 670
james@831 671 static ULONG
james@831 672 XenVbd_VirtualHwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PVOID LowerDevice, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
james@831 673 {
james@831 674 // PACCESS_RANGE AccessRange;
james@831 675 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@831 676 ULONG status;
james@831 677 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
james@831 678 PACCESS_RANGE access_range;
james@831 679
james@831 680 UNREFERENCED_PARAMETER(HwContext);
james@831 681 UNREFERENCED_PARAMETER(BusInformation);
james@831 682 UNREFERENCED_PARAMETER(LowerDevice);
james@831 683 UNREFERENCED_PARAMETER(ArgumentString);
james@831 684
james@831 685 FUNCTION_ENTER();
james@831 686 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@831 687 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
james@831 688
james@831 689 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
james@831 690 *Again = FALSE;
james@831 691
james@831 692 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
james@831 693 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
james@831 694
james@831 695 if (!dump_mode)
james@831 696 {
james@831 697 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
james@831 698 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
james@831 699 {
james@831 700 return SP_RETURN_BAD_CONFIG;
james@831 701 }
james@831 702
james@831 703 access_range = &((*(ConfigInfo->AccessRanges))[0]);
james@831 704 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
james@831 705 access_range->RangeStart.LowPart, access_range->RangeLength));
james@831 706 xvdd->device_base = StorPortGetDeviceBase(
james@831 707 DeviceExtension,
james@831 708 PNPBus, //AdapterInterfaceType,
james@831 709 ConfigInfo->SystemIoBusNumber,
james@831 710 access_range->RangeStart,
james@831 711 access_range->RangeLength,
james@831 712 !access_range->RangeInMemory);
james@831 713 if (!xvdd->device_base)
james@831 714 {
james@831 715 KdPrint((__DRIVER_NAME " StorPortGetDeviceBase failed\n"));
james@831 716 FUNCTION_EXIT();
james@831 717 return SP_RETURN_BAD_CONFIG;
james@831 718 }
james@831 719 status = XenVbd_InitConfig(xvdd);
james@831 720 if (status != SP_RETURN_FOUND)
james@831 721 {
james@947 722 /* set inactive here so StartIo is harmless - we still get called with a PNP remove (or similar) */
james@947 723 xvdd->inactive = TRUE;
james@831 724 FUNCTION_EXIT();
james@831 725 return status;
james@831 726 }
james@841 727 xvdd->grant_tag = (ULONG)'VBD0';
james@831 728 }
james@831 729 else
james@831 730 {
james@831 731 xvdd->device_base = ConfigInfo->Reserved;
james@841 732 xvdd->grant_tag = (ULONG)'DUMP';
james@831 733 }
james@831 734
james@841 735 xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED;
james@831 736 status = XenVbd_InitFromConfig(xvdd);
james@831 737 if (status != SP_RETURN_FOUND)
james@831 738 {
james@947 739 /* set inactive here so StartIo is harmless - we still get called with a PNP remove (or similar) */
james@947 740 xvdd->inactive = TRUE;
james@831 741 FUNCTION_EXIT();
james@831 742 return status;
james@831 743 }
james@831 744
james@831 745 xvdd->aligned_buffer_in_use = FALSE;
james@831 746 /* align the buffer to PAGE_SIZE */
james@831 747 xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
james@831 748 KdPrint((__DRIVER_NAME " aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
james@831 749 KdPrint((__DRIVER_NAME " aligned_buffer = %p\n", xvdd->aligned_buffer));
james@831 750
james@841 751 ConfigInfo->MaximumTransferLength = 4 * 1024 * 1024; //BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
james@841 752 ConfigInfo->NumberOfPhysicalBreaks = ConfigInfo->MaximumTransferLength >> PAGE_SHIFT; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
james@831 753 KdPrint((__DRIVER_NAME " ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength));
james@831 754 KdPrint((__DRIVER_NAME " ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks));
james@831 755 if (!dump_mode)
james@831 756 {
james@831 757 ConfigInfo->VirtualDevice = TRUE;
james@841 758 xvdd->aligned_buffer_size = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
james@831 759 }
james@831 760 else
james@831 761 {
james@831 762 ConfigInfo->VirtualDevice = FALSE;
james@841 763 xvdd->aligned_buffer_size = DUMP_MODE_UNALIGNED_PAGES * PAGE_SIZE;
james@831 764 }
james@831 765
james@831 766 KdPrint((__DRIVER_NAME " ConfigInfo->VirtualDevice = %d\n", ConfigInfo->VirtualDevice));
james@831 767 ConfigInfo->ScatterGather = TRUE;
james@831 768 ConfigInfo->Master = TRUE;
james@831 769 ConfigInfo->CachesData = FALSE;
james@831 770 ConfigInfo->MapBuffers = STOR_MAP_ALL_BUFFERS;
james@831 771 KdPrint((__DRIVER_NAME " ConfigInfo->NeedPhysicalAddresses = %d\n", ConfigInfo->NeedPhysicalAddresses));
james@831 772 ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
james@831 773 ConfigInfo->AlignmentMask = 0;
james@831 774 ConfigInfo->NumberOfBuses = 1;
james@831 775 ConfigInfo->InitiatorBusId[0] = 1;
james@831 776 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
james@831 777 ConfigInfo->MaximumNumberOfTargets = 2;
james@831 778 //ConfigInfo->BufferAccessScsiPortControlled = FALSE;
james@831 779 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
james@831 780 {
james@831 781 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
james@831 782 //ConfigInfo->Dma32BitAddresses = FALSE;
james@831 783 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
james@831 784 }
james@831 785 else
james@831 786 {
james@831 787 //ConfigInfo->Dma32BitAddresses = TRUE;
james@831 788 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
james@831 789 }
james@831 790
james@831 791 FUNCTION_EXIT();
james@831 792
james@831 793 return SP_RETURN_FOUND;
james@831 794 }
james@831 795
james@831 796 static ULONG
james@831 797 XenVbd_HwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
james@831 798 {
james@831 799 ULONG status;
james@831 800
james@831 801 FUNCTION_ENTER();
james@831 802 status = XenVbd_VirtualHwStorFindAdapter(DeviceExtension, HwContext, BusInformation, NULL, ArgumentString, ConfigInfo, Again);
james@831 803 FUNCTION_EXIT();
james@831 804 return status;
james@831 805 }
james@831 806
james@831 807 //do this in StartIo instead to prevent races with the driver initialisation
james@831 808 static VOID
james@831 809 XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
james@831 810 {
james@831 811 blkif_request_t *req;
james@831 812 int notify;
james@831 813
james@831 814 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
james@831 815 RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
james@831 816 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
james@831 817 req->operation = 0xff;
james@831 818 xvdd->ring.req_prod_pvt++;
james@831 819 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
james@831 820 req->operation = 0xff;
james@831 821 xvdd->ring.req_prod_pvt++;
james@831 822
james@831 823 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
james@831 824 if (notify)
james@831 825 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
james@831 826 }
james@831 827
james@831 828 static BOOLEAN
james@831 829 XenVbd_HwStorInitialize(PVOID DeviceExtension)
james@831 830 {
james@831 831 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@831 832
james@831 833 FUNCTION_ENTER();
james@831 834 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@831 835 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
james@831 836
james@831 837 if (!xvdd->inactive)
james@831 838 {
james@831 839 if (dump_mode)
james@831 840 {
james@831 841 if (xvdd->cached_use_other)
james@831 842 {
james@831 843 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
james@831 844 xvdd->use_other = TRUE;
james@831 845 }
james@831 846 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
james@831 847 }
james@831 848 InitializeListHead(&xvdd->srb_list);
james@831 849 }
james@831 850 FUNCTION_EXIT();
james@831 851
james@831 852 return TRUE;
james@831 853 }
james@831 854
james@831 855 static ULONG
james@831 856 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
james@831 857 {
james@831 858 PMODE_PARAMETER_HEADER parameter_header = NULL;
james@831 859 PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
james@831 860 PMODE_PARAMETER_BLOCK param_block;
james@831 861 PMODE_FORMAT_PAGE format_page;
james@831 862 ULONG offset = 0;
james@831 863 UCHAR buffer[1024];
james@831 864 BOOLEAN valid_page = FALSE;
james@831 865 BOOLEAN cdb_llbaa;
james@831 866 BOOLEAN cdb_dbd;
james@831 867 UCHAR cdb_page_code;
james@831 868 USHORT cdb_allocation_length;
james@831 869
james@831 870 UNREFERENCED_PARAMETER(xvdd);
james@831 871
james@831 872 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
james@831 873 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
james@831 874 offset = 0;
james@831 875
james@831 876 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
james@831 877
james@831 878 switch (srb->Cdb[0])
james@831 879 {
james@831 880 case SCSIOP_MODE_SENSE:
james@831 881 cdb_llbaa = FALSE;
james@831 882 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
james@831 883 cdb_page_code = srb->Cdb[2] & 0x3f;
james@831 884 cdb_allocation_length = srb->Cdb[4];
james@831 885 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
james@831 886 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
james@831 887 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
james@831 888 parameter_header->MediumType = 0;
james@831 889 parameter_header->DeviceSpecificParameter = 0;
james@831 890 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
james@831 891 {
james@831 892 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
james@831 893 parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
james@831 894 }
james@831 895 offset += sizeof(MODE_PARAMETER_HEADER);
james@831 896 break;
james@831 897 case SCSIOP_MODE_SENSE10:
james@831 898 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
james@831 899 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
james@831 900 cdb_page_code = srb->Cdb[2] & 0x3f;
james@831 901 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
james@831 902 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
james@831 903 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
james@831 904 parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
james@831 905 parameter_header10->MediumType = 0;
james@831 906 parameter_header10->DeviceSpecificParameter = 0;
james@831 907 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
james@831 908 {
james@831 909 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
james@831 910 parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
james@831 911 }
james@831 912 offset += sizeof(MODE_PARAMETER_HEADER10);
james@831 913 break;
james@831 914 default:
james@831 915 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
james@831 916 return FALSE;
james@831 917 }
james@831 918
james@831 919 if (!cdb_dbd)
james@831 920 {
james@831 921 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
james@831 922 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
james@831 923 {
james@831 924 if (xvdd->total_sectors >> 32)
james@831 925 {
james@831 926 param_block->DensityCode = 0xff;
james@831 927 param_block->NumberOfBlocks[0] = 0xff;
james@831 928 param_block->NumberOfBlocks[1] = 0xff;
james@831 929 param_block->NumberOfBlocks[2] = 0xff;
james@831 930 }
james@831 931 else
james@831 932 {
james@831 933 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
james@831 934 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
james@831 935 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
james@831 936 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
james@831 937 }
james@831 938 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
james@831 939 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
james@831 940 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
james@831 941 }
james@831 942 offset += sizeof(MODE_PARAMETER_BLOCK);
james@831 943 }
james@831 944 switch (srb->Cdb[0])
james@831 945 {
james@831 946 case SCSIOP_MODE_SENSE:
james@831 947 parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
james@831 948 break;
james@831 949 case SCSIOP_MODE_SENSE10:
james@831 950 parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
james@831 951 parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
james@831 952 break;
james@831 953 }
james@831 954 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
james@831 955 {
james@831 956 valid_page = TRUE;
james@831 957 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
james@831 958 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
james@831 959 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
james@831 960 /* 256 sectors per track */
james@831 961 format_page->SectorsPerTrack[0] = 0x01;
james@831 962 format_page->SectorsPerTrack[1] = 0x00;
james@831 963 /* xxx bytes per sector */
james@831 964 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
james@831 965 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
james@831 966 format_page->HardSectorFormating = TRUE;
james@831 967 format_page->SoftSectorFormating = TRUE;
james@831 968 offset += sizeof(MODE_FORMAT_PAGE);
james@831 969 }
james@831 970 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
james@831 971 {
james@831 972 PMODE_CACHING_PAGE caching_page;
james@831 973 valid_page = TRUE;
james@831 974 caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
james@831 975 caching_page->PageCode = MODE_PAGE_CACHING;
james@831 976 caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
james@831 977 // caching_page-> // all zeros is just fine... maybe
james@831 978 offset += sizeof(MODE_CACHING_PAGE);
james@831 979 }
james@831 980 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
james@831 981 {
james@831 982 PUCHAR medium_types_page;
james@831 983 valid_page = TRUE;
james@831 984 medium_types_page = &buffer[offset];
james@831 985 medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
james@831 986 medium_types_page[1] = 0x06;
james@831 987 medium_types_page[2] = 0;
james@831 988 medium_types_page[3] = 0;
james@831 989 medium_types_page[4] = 0;
james@831 990 medium_types_page[5] = 0;
james@831 991 medium_types_page[6] = 0;
james@831 992 medium_types_page[7] = 0;
james@831 993 offset += 8;
james@831 994 }
james@831 995 switch (srb->Cdb[0])
james@831 996 {
james@831 997 case SCSIOP_MODE_SENSE:
james@831 998 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
james@831 999 break;
james@831 1000 case SCSIOP_MODE_SENSE10:
james@831 1001 parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
james@831 1002 parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
james@831 1003 break;
james@831 1004 }
james@831 1005
james@831 1006 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
james@831 1007 {
james@831 1008 srb->SrbStatus = SRB_STATUS_ERROR;
james@831 1009 }
james@831 1010 else if(offset < srb->DataTransferLength)
james@831 1011 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
james@831 1012 else
james@831 1013 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@831 1014 srb->DataTransferLength = min(srb->DataTransferLength, offset);
james@831 1015 srb->ScsiStatus = 0;
james@831 1016 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
james@831 1017
james@831 1018 //FUNCTION_EXIT();
james@831 1019
james@831 1020 return TRUE;
james@831 1021 }
james@831 1022
james@831 1023 static ULONG
james@831 1024 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
james@831 1025 {
james@831 1026 PSENSE_DATA sd = srb->SenseInfoBuffer;
james@831 1027
james@831 1028 UNREFERENCED_PARAMETER(xvdd);
james@831 1029
james@831 1030 if (!srb->SenseInfoBuffer)
james@831 1031 return 0;
james@831 1032
james@831 1033 sd->ErrorCode = 0x70;
james@831 1034 sd->Valid = 1;
james@831 1035 sd->SenseKey = sense_key;
james@831 1036 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
james@831 1037 sd->AdditionalSenseCode = additional_sense_code;
james@831 1038 return sizeof(SENSE_DATA);
james@831 1039 }
james@831 1040
james@831 1041 static VOID
james@831 1042 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
james@831 1043 {
james@831 1044 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
james@831 1045 return;
james@831 1046 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
james@831 1047 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
james@831 1048 }
james@831 1049
james@831 1050 static BOOLEAN
james@831 1051 XenVbd_HandleEventSynchronised(PVOID DeviceExtension, PVOID context)
james@831 1052 {
james@831 1053 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@831 1054 PSCSI_REQUEST_BLOCK srb;
james@831 1055 RING_IDX i, rp;
james@831 1056 ULONG j;
james@831 1057 blkif_response_t *rep;
james@841 1058 //int block_count;
james@831 1059 int more_to_do = TRUE;
james@831 1060 blkif_shadow_t *shadow;
james@831 1061 ULONG suspend_resume_state_pdo;
james@841 1062 srb_list_entry_t *srb_entry;
james@831 1063
james@831 1064 UNREFERENCED_PARAMETER(context);
james@831 1065
james@831 1066 //if (dump_mode) FUNCTION_ENTER();
james@831 1067
james@831 1068 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
james@831 1069 KeMemoryBarrier();
james@831 1070
james@831 1071 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
james@831 1072 {
james@831 1073 //FUNCTION_ENTER();
james@831 1074 switch (suspend_resume_state_pdo)
james@831 1075 {
james@831 1076 case SR_STATE_SUSPENDING:
james@831 1077 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
james@831 1078 break;
james@831 1079 case SR_STATE_RESUMING:
james@831 1080 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
james@831 1081 XenVbd_InitFromConfig(xvdd);
james@831 1082 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
james@831 1083 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
james@831 1084 break;
james@831 1085 case SR_STATE_RUNNING:
james@831 1086 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
james@831 1087 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
james@841 1088 xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED; /* could be running on different hardware */
james@831 1089 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
james@831 1090 default:
james@831 1091 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
james@831 1092 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
james@831 1093 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
james@831 1094 break;
james@831 1095 }
james@831 1096 KeMemoryBarrier();
james@831 1097 }
james@831 1098
james@831 1099 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
james@831 1100 {
james@831 1101 return TRUE;
james@831 1102 }
james@831 1103
james@831 1104 while (more_to_do)
james@831 1105 {
james@831 1106 rp = xvdd->ring.sring->rsp_prod;
james@831 1107 KeMemoryBarrier();
james@956 1108 for (i = xvdd->ring.rsp_cons; i != rp; i++)
james@831 1109 {
james@831 1110 rep = XenVbd_GetResponse(xvdd, i);
james@831 1111 /*
james@831 1112 * This code is to automatically detect if the backend is using the same
james@831 1113 * bit width or a different bit width to us. Later versions of Xen do this
james@831 1114 * via a xenstore value, but not all. That 0x0fffffff (notice
james@831 1115 * that the msb is not actually set, so we don't have any problems with
james@831 1116 * sign extending) is to signify the last entry on the right, which is
james@831 1117 * different under 32 and 64 bits, and that is why we set it up there.
james@831 1118
james@831 1119 * To do the detection, we put two initial entries on the ring, with an op
james@831 1120 * of 0xff (which is invalid). The first entry is mostly okay, but the
james@831 1121 * second will be grossly misaligned if the backend bit width is different,
james@831 1122 * and we detect this and switch frontend structures.
james@831 1123 */
james@831 1124 switch (xvdd->ring_detect_state)
james@831 1125 {
james@831 1126 case RING_DETECT_STATE_NOT_STARTED:
james@831 1127 KdPrint((__DRIVER_NAME " premature IRQ\n"));
james@831 1128 break;
james@831 1129 case RING_DETECT_STATE_DETECT1:
james@831 1130 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));
james@831 1131 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));
james@831 1132 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
james@831 1133 break;
james@831 1134 case RING_DETECT_STATE_DETECT2:
james@831 1135 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));
james@831 1136 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));
james@831 1137 *xvdd->event_channel_ptr |= 0x80000000;
james@831 1138 if (rep->operation != 0xff)
james@831 1139 {
james@831 1140 KdPrint((__DRIVER_NAME " switching to 'other' ring size\n"));
james@831 1141 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
james@831 1142 xvdd->use_other = TRUE;
james@831 1143 *xvdd->event_channel_ptr |= 0x40000000;
james@831 1144 }
james@831 1145 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
james@831 1146 break;
james@831 1147 case RING_DETECT_STATE_COMPLETE:
james@889 1148 shadow = &xvdd->shadows[rep->id & SHADOW_ID_ID_MASK];
james@889 1149 if (shadow->reset)
james@889 1150 {
james@889 1151 KdPrint((__DRIVER_NAME " discarding reset shadow\n"));
james@889 1152 for (j = 0; j < shadow->req.nr_segments; j++)
james@889 1153 {
james@889 1154 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
james@889 1155 shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
james@889 1156 }
james@889 1157 }
james@889 1158 else if (dump_mode && !(rep->id & SHADOW_ID_DUMP_FLAG))
james@889 1159 {
james@889 1160 KdPrint((__DRIVER_NAME " discarding stale (non-dump-mode) shadow\n"));
james@889 1161 }
james@831 1162 else
james@831 1163 {
james@889 1164 srb = shadow->srb;
james@889 1165 ASSERT(srb);
james@889 1166 srb_entry = srb->SrbExtension;
james@889 1167 ASSERT(srb_entry);
james@889 1168 /* 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 */
james@889 1169 if (rep->status == BLKIF_RSP_OKAY || (dump_mode && dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
james@889 1170 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@831 1171 else
james@831 1172 {
james@889 1173 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
james@889 1174 if (decode_cdb_is_read(srb))
james@889 1175 KdPrint((__DRIVER_NAME " Operation = Read\n"));
james@889 1176 else
james@889 1177 KdPrint((__DRIVER_NAME " Operation = Write\n"));
james@889 1178 srb_entry->error = TRUE;
james@889 1179 }
james@889 1180 if (shadow->aligned_buffer_in_use)
james@889 1181 {
james@889 1182 ASSERT(xvdd->aligned_buffer_in_use);
james@889 1183 xvdd->aligned_buffer_in_use = FALSE;
james@889 1184 if (srb->SrbStatus == SRB_STATUS_SUCCESS && decode_cdb_is_read(srb))
james@889 1185 memcpy((PUCHAR)shadow->system_address, xvdd->aligned_buffer, shadow->length);
james@889 1186 }
james@889 1187 for (j = 0; j < shadow->req.nr_segments; j++)
james@889 1188 {
james@889 1189 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
james@889 1190 shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
james@889 1191 }
james@889 1192 srb_entry->outstanding_requests--;
james@889 1193 if (!srb_entry->outstanding_requests && srb_entry->offset == srb_entry->length)
james@889 1194 {
james@889 1195 if (srb_entry->error)
james@831 1196 {
james@889 1197 srb->SrbStatus = SRB_STATUS_ERROR;
james@889 1198 srb->ScsiStatus = 0x02;
james@889 1199 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
james@889 1200 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
james@889 1201 XenVbd_MakeAutoSense(xvdd, srb);
james@889 1202 }
james@889 1203 StorPortNotification(RequestComplete, xvdd, srb);
james@831 1204 }
james@831 1205 }
james@831 1206 shadow->aligned_buffer_in_use = FALSE;
james@831 1207 shadow->srb = NULL;
james@889 1208 shadow->reset = FALSE;
james@831 1209 put_shadow_on_freelist(xvdd, shadow);
james@831 1210 break;
james@831 1211 }
james@831 1212 }
james@831 1213
james@831 1214 xvdd->ring.rsp_cons = i;
james@831 1215 if (i != xvdd->ring.req_prod_pvt)
james@831 1216 {
james@831 1217 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
james@831 1218 }
james@831 1219 else
james@831 1220 {
james@831 1221 xvdd->ring.sring->rsp_event = i + 1;
james@831 1222 more_to_do = FALSE;
james@831 1223 }
james@831 1224 }
james@831 1225
james@831 1226 //if (start_ring_detect_state == RING_DETECT_STATE_COMPLETE)
james@831 1227 XenVbd_PutQueuedSrbsOnRing(xvdd);
james@831 1228
james@831 1229 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
james@831 1230 {
james@831 1231 if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
james@831 1232 {
james@831 1233 /* all entries are purged from the list (or we are inactive). ready to suspend */
james@831 1234 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
james@831 1235 KeMemoryBarrier();
james@831 1236 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
james@831 1237 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
james@831 1238 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
james@831 1239 }
james@831 1240 }
james@831 1241 //if (dump_mode) FUNCTION_EXIT();
james@831 1242
james@831 1243 return TRUE;
james@831 1244 }
james@831 1245
james@831 1246 static BOOLEAN
james@831 1247 XenVbd_HandleEvent(PVOID DeviceExtension)
james@831 1248 {
james@831 1249 BOOLEAN retval;
james@839 1250 STOR_LOCK_HANDLE lock_handle;
james@831 1251
james@831 1252 //if (dump_mode) FUNCTION_ENTER();
james@839 1253 StorPortAcquireSpinLock(DeviceExtension, StartIoLock, NULL, &lock_handle);
james@831 1254 retval = StorPortSynchronizeAccess(DeviceExtension, XenVbd_HandleEventSynchronised, NULL);
james@839 1255 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
james@831 1256 //if (dump_mode) FUNCTION_EXIT();
james@831 1257 return retval;
james@831 1258 }
james@831 1259
james@831 1260 /* this is only used during hiber and dump */
james@831 1261 static BOOLEAN
james@831 1262 XenVbd_HwStorInterrupt(PVOID DeviceExtension)
james@831 1263 {
james@831 1264 BOOLEAN retval;
james@831 1265
james@831 1266 //FUNCTION_ENTER();
james@831 1267 retval = XenVbd_HandleEventSynchronised(DeviceExtension, NULL);
james@831 1268 //FUNCTION_EXIT();
james@831 1269 return retval;
james@831 1270 }
james@831 1271
james@831 1272 static BOOLEAN
james@889 1273 XenVbd_HwStorResetBus(PVOID DeviceExtension, ULONG PathId)
james@889 1274 {
james@889 1275 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
james@889 1276 //srb_list_entry_t *srb_entry;
james@889 1277 int i;
james@889 1278 /* need to make sure that each SRB is only reset once */
james@889 1279 LIST_ENTRY srb_reset_list;
james@889 1280 PLIST_ENTRY list_entry;
james@889 1281 //STOR_LOCK_HANDLE lock_handle;
james@889 1282
james@889 1283 UNREFERENCED_PARAMETER(PathId);
james@889 1284
james@889 1285 FUNCTION_ENTER();
james@889 1286
james@889 1287 /* It appears that the StartIo spinlock is already held at this point */
james@889 1288
james@889 1289 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@889 1290
james@889 1291 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
james@889 1292 {
james@889 1293 xvdd->aligned_buffer_in_use = FALSE;
james@889 1294
james@889 1295 InitializeListHead(&srb_reset_list);
james@889 1296
james@889 1297 while((list_entry = RemoveHeadList(&xvdd->srb_list)) != &xvdd->srb_list)
james@889 1298 {
james@891 1299 #if DBG
james@889 1300 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
james@889 1301 KdPrint((__DRIVER_NAME " adding queued SRB %p to reset list\n", srb_entry->srb));
james@891 1302 #endif
james@889 1303 InsertTailList(&srb_reset_list, list_entry);
james@889 1304 }
james@889 1305
james@889 1306 for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
james@889 1307 {
james@889 1308 if (xvdd->shadows[i].srb)
james@889 1309 {
james@889 1310 srb_list_entry_t *srb_entry = xvdd->shadows[i].srb->SrbExtension;
james@889 1311 for (list_entry = srb_reset_list.Flink; list_entry != &srb_reset_list; list_entry = list_entry->Flink)
james@889 1312 {
james@889 1313 if (list_entry == &srb_entry->list_entry)
james@889 1314 break;
james@889 1315 }
james@889 1316 if (list_entry == &srb_reset_list)
james@889 1317 {
james@889 1318 KdPrint((__DRIVER_NAME " adding in-flight SRB %p to reset list\n", srb_entry->srb));
james@889 1319 InsertTailList(&srb_reset_list, &srb_entry->list_entry);
james@889 1320 }
james@889 1321 /* set reset here so that the interrupt won't do anything with the srb but will dispose of the shadow entry correctly */
james@889 1322 xvdd->shadows[i].reset = TRUE;
james@889 1323 xvdd->shadows[i].srb = NULL;
james@889 1324 xvdd->shadows[i].aligned_buffer_in_use = FALSE;
james@889 1325 }
james@889 1326 }
james@889 1327
james@889 1328 while((list_entry = RemoveHeadList(&srb_reset_list)) != &srb_reset_list)
james@889 1329 {
james@889 1330 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
james@889 1331 srb_entry->srb->SrbStatus = SRB_STATUS_BUS_RESET;
james@889 1332 KdPrint((__DRIVER_NAME " completing SRB %p with status SRB_STATUS_BUS_RESET\n", srb_entry->srb));
james@889 1333 StorPortNotification(RequestComplete, xvdd, srb_entry->srb);
james@889 1334 }
james@889 1335
james@889 1336 /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen) */
james@889 1337 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
james@889 1338
james@889 1339 StorPortNotification(NextRequest, DeviceExtension);
james@889 1340 }
james@889 1341
james@889 1342 //StorPortReleaseSpinLock(DeviceExtension, &lock_handle);
james@889 1343
james@889 1344 FUNCTION_EXIT();
james@889 1345
james@889 1346 return TRUE;
james@889 1347 }
james@889 1348
james@889 1349 static BOOLEAN
james@831 1350 XenVbd_HwStorStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
james@831 1351 {
james@831 1352 PUCHAR data_buffer;
james@831 1353 PSCSI_PNP_REQUEST_BLOCK sprb;
james@841 1354 PSCSI_POWER_REQUEST_BLOCK spwrb;
james@831 1355 PMINIPORT_DUMP_POINTERS dump_pointers;
james@831 1356 PCDB cdb;
james@831 1357 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
james@831 1358 ULONG data_transfer_length;
james@831 1359 UCHAR srb_status = SRB_STATUS_PENDING;
james@839 1360 STOR_LOCK_HANDLE lock_handle;
james@831 1361
james@831 1362 //if (dump_mode) FUNCTION_ENTER();
james@831 1363 //if (dump_mode) KdPrint((__DRIVER_NAME " srb = %p\n", srb));
james@831 1364
james@839 1365 StorPortAcquireSpinLock(DeviceExtension, StartIoLock, NULL, &lock_handle);
james@839 1366
james@831 1367 data_transfer_length = srb->DataTransferLength;
james@831 1368
james@831 1369 if (xvdd->inactive)
james@831 1370 {
james@831 1371 KdPrint((__DRIVER_NAME " Inactive srb->Function = %08X\n", srb->Function));
james@831 1372 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
james@831 1373 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@839 1374 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
james@831 1375 return TRUE;
james@831 1376 }
james@831 1377
james@831 1378 if (xvdd->ring_detect_state == RING_DETECT_STATE_NOT_STARTED)
james@831 1379 {
james@831 1380 XenVbd_StartRingDetection(DeviceExtension);
james@831 1381 }
james@831 1382
james@831 1383 // If we haven't enumerated all the devices yet then just defer the request
james@831 1384 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
james@831 1385 {
james@831 1386 srb->SrbStatus = SRB_STATUS_BUSY;
james@831 1387 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1388 KdPrint((__DRIVER_NAME " --- HwStorStartIo (Still figuring out ring)\n"));
james@839 1389 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
james@831 1390 return TRUE;
james@831 1391 }
james@831 1392
james@831 1393 if (!dump_mode && xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
james@831 1394 {
james@833 1395 //KdPrint((__DRIVER_NAME " --> HwStorStartIo (Suspending/Resuming)\n"));
james@831 1396 srb->SrbStatus = SRB_STATUS_BUSY;
james@831 1397 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@833 1398 //KdPrint((__DRIVER_NAME " <-- HwStorStartIo (Suspending/Resuming)\n"));
james@839 1399 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
james@831 1400 return TRUE;
james@831 1401 }
james@831 1402
james@831 1403 if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
james@831 1404 {
james@831 1405 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
james@831 1406 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1407 KdPrint((__DRIVER_NAME " --- HwStorStartIo (Out of bounds - PathId = %d, TargetId = %d, Lun = %d)\n", srb->PathId, srb->TargetId, srb->Lun));
james@839 1408 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
james@831 1409 return TRUE;
james@831 1410 }
james@831 1411
james@831 1412 switch (srb->Function)
james@831 1413 {
james@831 1414 case SRB_FUNCTION_EXECUTE_SCSI:
james@831 1415 cdb = (PCDB)srb->Cdb;
james@831 1416
james@831 1417 switch(cdb->CDB6GENERIC.OperationCode)
james@831 1418 {
james@831 1419 case SCSIOP_TEST_UNIT_READY:
james@831 1420 if (dump_mode)
james@831 1421 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
james@831 1422 srb_status = SRB_STATUS_SUCCESS;
james@831 1423 srb->ScsiStatus = 0;
james@831 1424 break;
james@831 1425 case SCSIOP_INQUIRY:
james@831 1426 if (dump_mode)
james@831 1427 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
james@831 1428 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
james@831 1429 // KdPrint((__DRIVER_NAME " (Length = %d)\n", srb->DataTransferLength));
james@831 1430
james@831 1431 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
james@831 1432 data_buffer = srb->DataBuffer;
james@831 1433 RtlZeroMemory(data_buffer, srb->DataTransferLength);
james@831 1434 srb_status = SRB_STATUS_SUCCESS;
james@831 1435 switch (xvdd->device_type)
james@831 1436 {
james@831 1437 case XENVBD_DEVICETYPE_DISK:
james@831 1438 if ((srb->Cdb[1] & 1) == 0)
james@831 1439 {
james@831 1440 if (srb->Cdb[2])
james@831 1441 {
james@831 1442 srb_status = SRB_STATUS_ERROR;
james@831 1443 }
james@831 1444 else
james@831 1445 {
james@831 1446 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
james@831 1447 id->DeviceType = DIRECT_ACCESS_DEVICE;
james@831 1448 id->Versions = 4; /* minimum that WHQL says we must support */
james@831 1449 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
james@831 1450 id->HiSupport = 1; /* WHQL test says we should set this */
james@831 1451 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
james@831 1452 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
james@831 1453 id->CommandQueue = 1;
james@831 1454 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
james@831 1455 memcpy(id->ProductId, scsi_disk_model, 16); // product id
james@831 1456 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
james@831 1457 data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
james@831 1458 }
james@831 1459 }
james@831 1460 else
james@831 1461 {
james@831 1462 switch (srb->Cdb[2])
james@831 1463 {
james@831 1464 case VPD_SUPPORTED_PAGES: /* list of pages we support */
james@831 1465 data_buffer[0] = DIRECT_ACCESS_DEVICE;
james@831 1466 data_buffer[1] = VPD_SUPPORTED_PAGES;
james@831 1467 data_buffer[2] = 0x00;
james@831 1468 data_buffer[3] = 2;
james@831 1469 data_buffer[4] = 0x00;
james@831 1470 data_buffer[5] = 0x80;
james@831 1471 data_transfer_length = 6;
james@831 1472 break;
james@831 1473 case VPD_SERIAL_NUMBER: /* serial number */
james@831 1474 data_buffer[0] = DIRECT_ACCESS_DEVICE;
james@831 1475 data_buffer[1] = VPD_SERIAL_NUMBER;
james@831 1476 data_buffer[2] = 0x00;
james@831 1477 data_buffer[3] = 8;
james@831 1478 memset(&data_buffer[4], ' ', 8);
james@831 1479 data_transfer_length = 12;
james@831 1480 break;
james@831 1481 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
james@831 1482 data_buffer[0] = DIRECT_ACCESS_DEVICE;
james@831 1483 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
james@831 1484 data_buffer[2] = 0x00;
james@831 1485 data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
james@831 1486 data_buffer[4] = 2; /* ASCII */
james@831 1487 data_buffer[5] = 1; /* VendorId */
james@831 1488 data_buffer[6] = 0;
james@831 1489 data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
james@831 1490 memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
james@831 1491 data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
james@831 1492 break;
james@831 1493 default:
james@831 1494 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
james@831 1495 srb_status = SRB_STATUS_ERROR;
james@831 1496 break;
james@831 1497 }
james@831 1498 }
james@831 1499 break;
james@831 1500 case XENVBD_DEVICETYPE_CDROM:
james@831 1501 if ((srb->Cdb[1] & 1) == 0)
james@831 1502 {
james@831 1503 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
james@831 1504 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@831 1505 id->RemovableMedia = 1;
james@831 1506 id->Versions = 3;
james@831 1507 id->ResponseDataFormat = 0;
james@831 1508 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
james@831 1509 id->CommandQueue = 1;
james@831 1510 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
james@831 1511 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
james@831 1512 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
james@831 1513 data_transfer_length = sizeof(INQUIRYDATA);
james@831 1514 }
james@831 1515 else
james@831 1516 {
james@831 1517 switch (srb->Cdb[2])
james@831 1518 {
james@831 1519 case 0x00:
james@831 1520 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@831 1521 data_buffer[1] = 0x00;
james@831 1522 data_buffer[2] = 0x00;
james@831 1523 data_buffer[3] = 2;
james@831 1524 data_buffer[4] = 0x00;
james@831 1525 data_buffer[5] = 0x80;
james@831 1526 data_transfer_length = 6;
james@831 1527 break;
james@831 1528 case 0x80:
james@831 1529 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@831 1530 data_buffer[1] = 0x80;
james@831 1531 data_buffer[2] = 0x00;
james@831 1532 data_buffer[3] = 8;
james@831 1533 data_buffer[4] = 0x31;
james@831 1534 data_buffer[5] = 0x32;
james@831 1535 data_buffer[6] = 0x33;
james@831 1536 data_buffer[7] = 0x34;
james@831 1537 data_buffer[8] = 0x35;
james@831 1538 data_buffer[9] = 0x36;
james@831 1539 data_buffer[10] = 0x37;
james@831 1540 data_buffer[11] = 0x38;
james@831 1541 data_transfer_length = 12;
james@831 1542 break;
james@831 1543 default:
james@831 1544 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
james@831 1545 srb_status = SRB_STATUS_ERROR;
james@831 1546 break;
james@831 1547 }
james@831 1548 }
james@831 1549 break;
james@831 1550 default:
james@831 1551 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
james@831 1552 srb_status = SRB_STATUS_ERROR;
james@831 1553 break;
james@831 1554 }
james@831 1555 break;
james@831 1556 case SCSIOP_READ_CAPACITY:
james@831 1557 if (dump_mode)
james@831 1558 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
james@831 1559 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
james@831 1560 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
james@831 1561 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
james@831 1562 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
james@831 1563 data_buffer = srb->DataBuffer;
james@831 1564 RtlZeroMemory(data_buffer, srb->DataTransferLength);
james@831 1565 if ((xvdd->total_sectors - 1) >> 32)
james@831 1566 {
james@831 1567 data_buffer[0] = 0xff;
james@831 1568 data_buffer[1] = 0xff;
james@831 1569 data_buffer[2] = 0xff;
james@831 1570 data_buffer[3] = 0xff;
james@831 1571 }
james@831 1572 else
james@831 1573 {
james@831 1574 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
james@831 1575 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
james@831 1576 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
james@831 1577 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
james@831 1578 }
james@831 1579 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
james@831 1580 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
james@831 1581 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
james@831 1582 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
james@831 1583 data_transfer_length = 8;
james@831 1584 srb->ScsiStatus = 0;
james@831 1585 srb_status = SRB_STATUS_SUCCESS;
james@831 1586 break;
james@831 1587 case SCSIOP_READ_CAPACITY16:
james@831 1588 if (dump_mode)
james@831 1589 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
james@831 1590 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
james@831 1591 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
james@831 1592 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
james@831 1593 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
james@831 1594 data_buffer = srb->DataBuffer;
james@831 1595 RtlZeroMemory(data_buffer, srb->DataTransferLength);
james@831 1596 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
james@831 1597 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
james@831 1598 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
james@831 1599 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
james@831 1600 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
james@831 1601 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
james@831 1602 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
james@831 1603 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
james@831 1604 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
james@831 1605 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
james@831 1606 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
james@831 1607 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
james@831 1608 data_transfer_length = 12;
james@831 1609 srb->ScsiStatus = 0;
james@831 1610 srb_status = SRB_STATUS_SUCCESS;
james@831 1611 break;
james@831 1612 case SCSIOP_MODE_SENSE:
james@831 1613 case SCSIOP_MODE_SENSE10:
james@831 1614 if (dump_mode)
james@831 1615 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));
james@831 1616 data_transfer_length = XenVbd_FillModePage(xvdd, srb);
james@831 1617 srb_status = SRB_STATUS_SUCCESS;
james@831 1618 break;
james@831 1619 case SCSIOP_READ:
james@831 1620 case SCSIOP_READ16:
james@831 1621 case SCSIOP_WRITE:
james@831 1622 case SCSIOP_WRITE16:
james@831 1623 //KdPrint((__DRIVER_NAME " srb = %p\n", srb));
james@831 1624 XenVbd_PutSrbOnList(xvdd, srb);
james@831 1625 XenVbd_PutQueuedSrbsOnRing(xvdd);
james@831 1626 break;
james@831 1627 case SCSIOP_VERIFY:
james@831 1628 case SCSIOP_VERIFY16:
james@831 1629 // Should we do more here?
james@831 1630 if (dump_mode)
james@831 1631 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
james@831 1632 srb_status = SRB_STATUS_SUCCESS;
james@831 1633 break;
james@831 1634 #if 0
james@831 1635 case SCSIOP_REPORT_LUNS:
james@831 1636 if (dump_mode)
james@831 1637 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
james@831 1638 switch (srb->Cdb[1])
james@831 1639 {
james@831 1640 }
james@831 1641 srb_status = SRB_STATUS_SUCCESS;;
james@831 1642 break;
james@831 1643 #endif
james@831 1644 case SCSIOP_REQUEST_SENSE:
james@831 1645 if (dump_mode)
james@831 1646 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
james@831 1647 data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
james@831 1648 srb_status = SRB_STATUS_SUCCESS;
james@831 1649 break;
james@831 1650 case SCSIOP_READ_TOC:
james@831 1651 if (dump_mode)
james@831 1652 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
james@831 1653 data_buffer = srb->DataBuffer;
james@831 1654 /*
james@831 1655 #define READ_TOC_FORMAT_TOC 0x00
james@831 1656 #define READ_TOC_FORMAT_SESSION 0x01
james@831 1657 #define READ_TOC_FORMAT_FULL_TOC 0x02
james@831 1658 #define READ_TOC_FORMAT_PMA 0x03
james@831 1659 #define READ_TOC_FORMAT_ATIP 0x04
james@831 1660 */
james@831 1661 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
james@831 1662 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
james@831 1663 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
james@831 1664 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
james@831 1665 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
james@831 1666 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
james@831 1667 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
james@831 1668 switch (cdb->READ_TOC.Format2)
james@831 1669 {
james@831 1670 case READ_TOC_FORMAT_TOC:
james@831 1671 data_buffer[0] = 0; // length MSB
james@831 1672 data_buffer[1] = 10; // length LSB
james@831 1673 data_buffer[2] = 1; // First Track
james@831 1674 data_buffer[3] = 1; // Last Track
james@831 1675 data_buffer[4] = 0; // Reserved
james@831 1676 data_buffer[5] = 0x14; // current position data + uninterrupted data
james@831 1677 data_buffer[6] = 1; // last complete track
james@831 1678 data_buffer[7] = 0; // reserved
james@831 1679 data_buffer[8] = 0; // MSB Block
james@831 1680 data_buffer[9] = 0;
james@831 1681 data_buffer[10] = 0;
james@831 1682 data_buffer[11] = 0; // LSB Block
james@831 1683 data_transfer_length = 12;
james@831 1684 srb_status = SRB_STATUS_SUCCESS;
james@831 1685 break;
james@831 1686 case READ_TOC_FORMAT_SESSION:
james@831 1687 case READ_TOC_FORMAT_FULL_TOC:
james@831 1688 case READ_TOC_FORMAT_PMA:
james@831 1689 case READ_TOC_FORMAT_ATIP:
james@831 1690 srb_status = SRB_STATUS_ERROR;
james@831 1691 break;
james@831 1692 default:
james@831 1693 srb_status = SRB_STATUS_ERROR;
james@831 1694 break;
james@831 1695 }
james@831 1696 break;
james@831 1697 case SCSIOP_START_STOP_UNIT:
james@831 1698 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
james@831 1699 srb_status = SRB_STATUS_SUCCESS;
james@831 1700 break;
james@831 1701 case SCSIOP_RESERVE_UNIT:
james@831 1702 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
james@831 1703 srb_status = SRB_STATUS_SUCCESS;
james@831 1704 break;
james@831 1705 case SCSIOP_RELEASE_UNIT:
james@831 1706 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
james@831 1707 srb_status = SRB_STATUS_SUCCESS;
james@831 1708 break;
james@831 1709 default:
james@831 1710 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
james@831 1711 srb_status = SRB_STATUS_ERROR;
james@831 1712 break;
james@831 1713 }
james@831 1714 if (srb_status == SRB_STATUS_ERROR)
james@831 1715 {
james@831 1716 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
james@831 1717 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
james@831 1718 {
james@831 1719 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
james@831 1720 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
james@831 1721 }
james@831 1722 srb->SrbStatus = srb_status;
james@831 1723 srb->ScsiStatus = 0x02;
james@831 1724 XenVbd_MakeAutoSense(xvdd, srb);
james@831 1725 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1726 }
james@831 1727 else if (srb_status != SRB_STATUS_PENDING)
james@831 1728 {
james@831 1729 if (data_transfer_length > srb->DataTransferLength)
james@831 1730 KdPrint((__DRIVER_NAME " data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength));
james@831 1731
james@831 1732 if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
james@831 1733 {
james@831 1734 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
james@831 1735 srb->DataTransferLength = data_transfer_length;
james@831 1736 }
james@831 1737 else
james@831 1738 {
james@831 1739 srb->SrbStatus = srb_status;
james@831 1740 }
james@831 1741 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
james@831 1742 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
james@831 1743 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1744 }
james@831 1745 break;
james@831 1746 case SRB_FUNCTION_IO_CONTROL:
james@831 1747 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
james@831 1748 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@831 1749 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1750 break;
james@831 1751 case SRB_FUNCTION_FLUSH:
james@831 1752 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
james@831 1753 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@831 1754 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1755 break;
james@831 1756 case SRB_FUNCTION_PNP:
james@831 1757 KdPrint((__DRIVER_NAME " SRB_FUNCTION_PNP\n"));
james@831 1758 sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
james@831 1759 switch (sprb->PnPAction)
james@831 1760 {
james@831 1761 case StorStartDevice:
james@831 1762 KdPrint((__DRIVER_NAME " StorStartDevice\n"));
james@831 1763 break;
james@831 1764 case StorRemoveDevice:
james@831 1765 KdPrint((__DRIVER_NAME " StorRemoveDevice\n"));
james@831 1766 break;
james@831 1767 case StorStopDevice:
james@831 1768 KdPrint((__DRIVER_NAME " StorStopDevice\n"));
james@831 1769 break;
james@831 1770 case StorQueryCapabilities:
james@831 1771 KdPrint((__DRIVER_NAME " StorQueryCapabilities\n"));
james@831 1772 break;
james@831 1773 case StorFilterResourceRequirements:
james@831 1774 KdPrint((__DRIVER_NAME " StorFilterResourceRequirements\n"));
james@831 1775 break;
james@831 1776 default:
james@831 1777 KdPrint((__DRIVER_NAME " Stor%d\n", sprb->PnPAction));
james@831 1778 break;
james@831 1779 }
james@831 1780 KdPrint((__DRIVER_NAME " SrbPnPFlags = %08x\n", sprb->SrbPnPFlags));
james@831 1781 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@831 1782 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1783 break;
james@841 1784
james@841 1785 case SRB_FUNCTION_POWER:
james@841 1786 KdPrint((__DRIVER_NAME " SRB_FUNCTION_POWER\n"));
james@841 1787 spwrb = (PSCSI_POWER_REQUEST_BLOCK)srb;
james@841 1788 switch (spwrb->PowerAction)
james@841 1789 {
james@841 1790 case StorPowerActionNone:
james@841 1791 KdPrint((__DRIVER_NAME " StorPowerActionNone\n"));
james@841 1792 break;
james@841 1793 case StorPowerActionReserved:
james@841 1794 KdPrint((__DRIVER_NAME " StorPowerActionReserved\n"));
james@841 1795 break;
james@841 1796 case StorPowerActionSleep:
james@841 1797 KdPrint((__DRIVER_NAME " StorPowerActionSleep\n"));
james@841 1798 break;
james@841 1799 case StorPowerActionHibernate:
james@841 1800 KdPrint((__DRIVER_NAME " StorPowerActionHibernate\n"));
james@841 1801 break;
james@841 1802 case StorPowerActionShutdown:
james@841 1803 KdPrint((__DRIVER_NAME " StorPowerActionShutdown\n"));
james@841 1804 break;
james@841 1805 case StorPowerActionShutdownReset:
james@841 1806 KdPrint((__DRIVER_NAME " StorPowerActionShutdownReset\n"));
james@841 1807 break;
james@841 1808 case StorPowerActionShutdownOff:
james@841 1809 KdPrint((__DRIVER_NAME " StorPowerActionShutdownOff\n"));
james@841 1810 break;
james@841 1811 case StorPowerActionWarmEject:
james@841 1812 KdPrint((__DRIVER_NAME " StorPowerActionWarmEject\n"));
james@841 1813 break;
james@841 1814 default:
james@841 1815 KdPrint((__DRIVER_NAME " Stor%d\n", spwrb->PowerAction));
james@841 1816 break;
james@841 1817 }
james@841 1818 XenVbd_PutSrbOnList(xvdd, srb);
james@841 1819 XenVbd_PutQueuedSrbsOnRing(xvdd);
james@841 1820 break;
james@831 1821 case SRB_FUNCTION_DUMP_POINTERS:
james@831 1822 KdPrint((__DRIVER_NAME " SRB_FUNCTION_DUMP_POINTERS\n"));
james@831 1823 KdPrint((__DRIVER_NAME " DataTransferLength = %d\n", srb->DataTransferLength));
james@831 1824 dump_pointers = srb->DataBuffer;
james@831 1825 KdPrint((__DRIVER_NAME " Version = %d\n", dump_pointers->Version));
james@831 1826 KdPrint((__DRIVER_NAME " Size = %d\n", dump_pointers->Size));
james@831 1827 KdPrint((__DRIVER_NAME " DriverName = %S\n", dump_pointers->DriverName));
james@831 1828 KdPrint((__DRIVER_NAME " AdapterObject = %p\n", dump_pointers->AdapterObject));
james@831 1829 KdPrint((__DRIVER_NAME " MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
james@831 1830 KdPrint((__DRIVER_NAME " CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
james@831 1831 KdPrint((__DRIVER_NAME " MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
james@831 1832 KdPrint((__DRIVER_NAME " SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
james@831 1833 KdPrint((__DRIVER_NAME " AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
james@831 1834 KdPrint((__DRIVER_NAME " MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
james@831 1835 KdPrint((__DRIVER_NAME " NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
james@831 1836 KdPrint((__DRIVER_NAME " AlignmentMask = %d\n", dump_pointers->AlignmentMask));
james@831 1837 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
james@831 1838 KdPrint((__DRIVER_NAME " NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
james@831 1839 KdPrint((__DRIVER_NAME " Master = %d\n", dump_pointers->Master));
james@831 1840 KdPrint((__DRIVER_NAME " MapBuffers = %d\n", dump_pointers->MapBuffers));
james@831 1841 KdPrint((__DRIVER_NAME " MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
james@831 1842
james@831 1843 dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
james@831 1844 dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
james@831 1845 RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
james@831 1846 dump_pointers->AdapterObject = NULL;
james@831 1847 dump_pointers->MappedRegisterBase = 0;
james@831 1848 dump_pointers->CommonBufferSize = 0;
james@831 1849 dump_pointers->MiniportPrivateDumpData = (PVOID)xvdd->device_base;
james@831 1850 //dump_pointers->SystemIoBusNumber = 0;
james@831 1851 dump_pointers->AdapterInterfaceType = Internal;
james@841 1852 dump_pointers->MaximumTransferLength = 4 * 1024 * 1024; //BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;;
james@841 1853 dump_pointers->NumberOfPhysicalBreaks = dump_pointers->MaximumTransferLength >> PAGE_SHIFT; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
james@831 1854 dump_pointers->AlignmentMask = 0;
james@831 1855 dump_pointers->NumberOfAccessRanges = 1;
james@831 1856 dump_pointers->NumberOfBuses = 1;
james@831 1857 dump_pointers->Master = TRUE;
james@831 1858 dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
james@831 1859 dump_pointers->MaximumNumberOfTargets = 2;
james@831 1860
james@831 1861 KdPrint((__DRIVER_NAME " Version = %d\n", dump_pointers->Version));
james@831 1862 KdPrint((__DRIVER_NAME " Size = %d\n", dump_pointers->Size));
james@841 1863 //KdPrint((__DRIVER_NAME " DriverName = %S\n", dump_pointers->DriverName));
james@831 1864 KdPrint((__DRIVER_NAME " AdapterObject = %p\n", dump_pointers->AdapterObject));
james@831 1865 KdPrint((__DRIVER_NAME " MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
james@831 1866 KdPrint((__DRIVER_NAME " CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
james@831 1867 KdPrint((__DRIVER_NAME " MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
james@831 1868 KdPrint((__DRIVER_NAME " SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
james@831 1869 KdPrint((__DRIVER_NAME " AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
james@831 1870 KdPrint((__DRIVER_NAME " MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
james@831 1871 KdPrint((__DRIVER_NAME " NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
james@831 1872 KdPrint((__DRIVER_NAME " AlignmentMask = %d\n", dump_pointers->AlignmentMask));
james@831 1873 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
james@831 1874 KdPrint((__DRIVER_NAME " NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
james@831 1875 KdPrint((__DRIVER_NAME " Master = %d\n", dump_pointers->Master));
james@831 1876 KdPrint((__DRIVER_NAME " MapBuffers = %d\n", dump_pointers->MapBuffers));
james@831 1877 KdPrint((__DRIVER_NAME " MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
james@831 1878
james@831 1879 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@831 1880 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1881 break;
james@831 1882 case SRB_FUNCTION_SHUTDOWN:
james@831 1883 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
james@841 1884 //ASSERT(IsListEmpty(&xvdd->srb_list));
james@841 1885 //ASSERT(xvdd->shadow_free == SHADOW_ENTRIES);
james@841 1886 XenVbd_PutSrbOnList(xvdd, srb);
james@841 1887 XenVbd_PutQueuedSrbsOnRing(xvdd);
james@841 1888 //srb->SrbStatus = SRB_STATUS_SUCCESS;
james@841 1889 //StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1890 break;
james@889 1891 case SRB_FUNCTION_RESET_BUS:
james@889 1892 case SRB_FUNCTION_RESET_DEVICE:
james@889 1893 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
james@889 1894 /* the path doesn't matter here - only ever one device*/
james@889 1895 XenVbd_HwStorResetBus(DeviceExtension, 0);
james@889 1896 srb->SrbStatus = SRB_STATUS_SUCCESS;
james@889 1897 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@889 1898 break;
james@889 1899
james@831 1900 default:
james@831 1901 KdPrint((__DRIVER_NAME " Unhandled srb->Function = %08X\n", srb->Function));
james@831 1902 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@831 1903 StorPortNotification(RequestComplete, DeviceExtension, srb);
james@831 1904 break;
james@831 1905 }
james@831 1906
james@831 1907 //if (dump_mode) FUNCTION_EXIT();
james@839 1908 StorPortReleaseSpinLock(DeviceExtension, &lock_handle);
james@831 1909 return TRUE;
james@831 1910 }
james@831 1911
james@831 1912 static SCSI_ADAPTER_CONTROL_STATUS
james@831 1913 XenVbd_HwStorAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
james@831 1914 {
james@831 1915 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
james@831 1916 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
james@831 1917 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
james@831 1918 //KIRQL OldIrql;
james@831 1919
james@831 1920 FUNCTION_ENTER();
james@831 1921 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@831 1922 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
james@831 1923
james@831 1924 switch (ControlType)
james@831 1925 {
james@831 1926 case ScsiQuerySupportedControlTypes:
james@831 1927 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
james@831 1928 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
james@831 1929 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
james@831 1930 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
james@831 1931 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
james@831 1932 break;
james@831 1933 case ScsiStopAdapter:
james@831 1934 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
james@841 1935 if (xvdd->inactive)
james@841 1936 {
james@841 1937 KdPrint((__DRIVER_NAME " inactive - nothing to do\n"));
james@841 1938 break;
james@841 1939 }
james@841 1940 ASSERT(IsListEmpty(&xvdd->srb_list));
james@841 1941 ASSERT(xvdd->shadow_free == SHADOW_ENTRIES);
james@831 1942 break;
james@831 1943 case ScsiRestartAdapter:
james@831 1944 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
james@841 1945 if (xvdd->inactive)
james@831 1946 {
james@841 1947 KdPrint((__DRIVER_NAME " inactive - nothing to do\n"));
james@841 1948 break;
james@831 1949 }
james@841 1950 /* increase the tag every time we stop/start to track where the gref's came from */
james@841 1951 xvdd->grant_tag++;
james@979 1952 if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND) {
james@979 1953 #pragma warning(suppress:28159)
james@841 1954 KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR)xvdd, 0, 0);
james@979 1955 }
james@841 1956 xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED;
james@841 1957
james@841 1958 //XenVbd_StartRingDetection(xvdd);
james@831 1959 break;
james@831 1960 case ScsiSetBootConfig:
james@831 1961 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
james@831 1962 break;
james@831 1963 case ScsiSetRunningConfig:
james@831 1964 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
james@831 1965 break;
james@831 1966 default:
james@831 1967 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
james@831 1968 break;
james@831 1969 }
james@831 1970
james@831 1971 FUNCTION_EXIT();
james@831 1972
james@831 1973 return Status;
james@831 1974 }
james@831 1975
james@831 1976 NTSTATUS
james@831 1977 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
james@831 1978 {
james@831 1979 ULONG status;
james@831 1980 VIRTUAL_HW_INITIALIZATION_DATA VHwInitializationData;
james@831 1981 HW_INITIALIZATION_DATA HwInitializationData;
james@831 1982 OBJECT_ATTRIBUTES oa;
james@831 1983 HANDLE service_handle;
james@831 1984 UNICODE_STRING param_name;
james@831 1985 HANDLE param_handle;
james@831 1986 UNICODE_STRING value_name;
james@831 1987 CHAR buf[256];
james@831 1988 ULONG buf_len;
james@831 1989 PKEY_VALUE_PARTIAL_INFORMATION kpv;
james@831 1990
james@831 1991 FUNCTION_ENTER();
james@831 1992 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@831 1993 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
james@831 1994
james@831 1995 /* RegistryPath == NULL when we are invoked as a crash dump driver */
james@831 1996 if (!RegistryPath)
james@831 1997 {
james@831 1998 dump_mode = TRUE;
james@831 1999 }
james@831 2000
james@831 2001 if (!dump_mode)
james@831 2002 {
james@831 2003 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
james@831 2004 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
james@831 2005 if(!NT_SUCCESS(status))
james@831 2006 {
james@831 2007 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
james@831 2008 }
james@831 2009 else
james@831 2010 {
james@831 2011 RtlInitUnicodeString(&param_name, L"Parameters");
james@831 2012 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
james@831 2013 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
james@831 2014 if(!NT_SUCCESS(status))
james@831 2015 {
james@831 2016 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
james@831 2017 }
james@831 2018 else
james@831 2019 {
james@831 2020 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
james@831 2021 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
james@831 2022 RtlFillMemory(scsi_disk_model, 16, ' ');
james@831 2023 RtlFillMemory(scsi_cdrom_model, 16, ' ');
james@831 2024
james@831 2025 RtlInitUnicodeString(&value_name, L"Manufacturer");
james@831 2026 buf_len = 256;
james@831 2027 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
james@831 2028 if(NT_SUCCESS(status))
james@831 2029 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
james@831 2030 else
james@831 2031 RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN ");
james@831 2032
james@831 2033 RtlInitUnicodeString(&value_name, L"Disk_Model");
james@831 2034 buf_len = 256;
james@831 2035 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
james@831 2036 if(NT_SUCCESS(status))
james@831 2037 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
james@831 2038 else
james@831 2039 RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK ");
james@831 2040
james@831 2041 RtlInitUnicodeString(&value_name, L"CDROM_Model");
james@831 2042 buf_len = 256;
james@831 2043 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
james@831 2044 if(NT_SUCCESS(status))
james@831 2045 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
james@831 2046 else
james@831 2047 RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM ");
james@831 2048 ZwClose(param_handle);
james@831 2049 }
james@831 2050 ZwClose(service_handle);
james@831 2051 }
james@831 2052 RtlZeroMemory(&VHwInitializationData, sizeof(VIRTUAL_HW_INITIALIZATION_DATA));
james@831 2053 VHwInitializationData.HwInitializationDataSize = sizeof(VIRTUAL_HW_INITIALIZATION_DATA);
james@831 2054 VHwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* maybe should be internal? */
james@831 2055 VHwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
james@831 2056 VHwInitializationData.SpecificLuExtensionSize = 0;
james@831 2057 VHwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
james@831 2058 VHwInitializationData.NumberOfAccessRanges = 1;
james@831 2059 VHwInitializationData.MapBuffers = STOR_MAP_ALL_BUFFERS;
james@831 2060 //VHwInitializationData.NeedPhysicalAddresses = TRUE;
james@831 2061 VHwInitializationData.TaggedQueuing = TRUE;
james@831 2062 VHwInitializationData.AutoRequestSense = TRUE;
james@831 2063 VHwInitializationData.MultipleRequestPerLu = TRUE;
james@831 2064 VHwInitializationData.ReceiveEvent = TRUE;
james@831 2065 VHwInitializationData.PortVersionFlags = 0;
james@831 2066 VHwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
james@831 2067 VHwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
james@831 2068 VHwInitializationData.HwFindAdapter = XenVbd_VirtualHwStorFindAdapter;
james@831 2069 VHwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
james@831 2070 VHwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
james@831 2071 status = StorPortInitialize(DriverObject, RegistryPath, (PHW_INITIALIZATION_DATA)&VHwInitializationData, NULL);
james@831 2072 }
james@831 2073 else
james@831 2074 {
james@831 2075 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
james@831 2076 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
james@831 2077 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* not Internal */
james@831 2078 HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
james@831 2079 HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
james@831 2080 HwInitializationData.NumberOfAccessRanges = 1;
james@831 2081 HwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
james@831 2082 HwInitializationData.NeedPhysicalAddresses = TRUE;
james@831 2083 HwInitializationData.TaggedQueuing = FALSE;
james@831 2084 HwInitializationData.AutoRequestSense = TRUE;
james@831 2085 HwInitializationData.MultipleRequestPerLu = FALSE;
james@831 2086 HwInitializationData.ReceiveEvent = TRUE;
james@831 2087 HwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
james@831 2088 HwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
james@831 2089 HwInitializationData.HwFindAdapter = XenVbd_HwStorFindAdapter;
james@831 2090 HwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
james@831 2091 HwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
james@831 2092 HwInitializationData.HwInterrupt = XenVbd_HwStorInterrupt;
james@831 2093 status = StorPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
james@831 2094 }
james@831 2095
james@831 2096 if(!NT_SUCCESS(status))
james@831 2097 {
james@831 2098 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
james@831 2099 }
james@831 2100
james@831 2101 FUNCTION_EXIT();
james@831 2102
james@831 2103 return status;
james@831 2104 }