win-pvdrivers

annotate xenvbd/xenvbd.c @ 810:1293cb31aa0b

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