win-pvdrivers

annotate xenvbd/xenvbd_storport.c @ 993:61fea9275419

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