win-pvdrivers

view xenvbd/xenvbd_scsiport.c @ 911:60e760e70c21

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