win-pvdrivers

view xenvbd/xenvbd_storport.c @ 983:d9da5f8f7431

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