win-pvdrivers

view xenvbd/xenvbd_scsiport.c @ 947:a05b13795cb2

storport calls StartIo even when the adapter fails to initialise. Make sure this doesn't crash.
author James Harper <james.harper@bendigoit.com.au>
date Mon Aug 22 23:14:01 2011 +1000 (2011-08-22)
parents 6d2ca0f1a48a
children 6e8c5e65f498
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_valid = TRUE;
162 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
163 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
164 }
165 else
166 {
167 xvdd->cached_use_other_valid = FALSE;
168 }
169 }
170 break;
171 case XEN_INIT_TYPE_READ_STRING_BACK:
172 case XEN_INIT_TYPE_READ_STRING_FRONT:
173 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
174 if (strcmp(setting, "sectors") == 0)
175 xvdd->total_sectors = parse_numeric_string(value);
176 else if (strcmp(setting, "sector-size") == 0)
177 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
178 else if (strcmp(setting, "device-type") == 0)
179 {
180 if (strcmp(value, "disk") == 0)
181 {
182 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
183 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
184 }
185 else if (strcmp(value, "cdrom") == 0)
186 {
187 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
188 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
189 }
190 else
191 {
192 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
193 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
194 }
195 }
196 else if (strcmp(setting, "mode") == 0)
197 {
198 if (strncmp(value, "r", 1) == 0)
199 {
200 KdPrint((__DRIVER_NAME " mode = r\n"));
201 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
202 }
203 else if (strncmp(value, "w", 1) == 0)
204 {
205 KdPrint((__DRIVER_NAME " mode = w\n"));
206 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
207 }
208 else
209 {
210 KdPrint((__DRIVER_NAME " mode = unknown\n"));
211 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
212 }
213 }
214 break;
215 case XEN_INIT_TYPE_VECTORS:
216 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
217 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
218 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
219 {
220 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
221 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
222 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
223 return SP_RETURN_BAD_CONFIG;
224 }
225 else
226 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
227 break;
228 case XEN_INIT_TYPE_STATE_PTR:
229 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
230 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
231 break;
232 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
233 qemu_protocol_version = PtrToUlong(value);
234 break;
235 case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
236 qemu_hide_flags_value = PtrToUlong(value);
237 KdPrint((__DRIVER_NAME " qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
238 break;
239 case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
240 qemu_hide_filter = TRUE;
241 KdPrint((__DRIVER_NAME " qemu_hide_filter = TRUE\n"));
242 break;
243 default:
244 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
245 break;
246 }
247 }
249 if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
250 xvdd->inactive = FALSE;
252 if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
253 || xvdd->sring == NULL
254 || xvdd->event_channel == 0
255 || xvdd->total_sectors == 0
256 || xvdd->bytes_per_sector == 0))
257 {
258 KdPrint((__DRIVER_NAME " Missing settings\n"));
259 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
260 return SP_RETURN_BAD_CONFIG;
261 }
263 if (xvdd->inactive)
264 KdPrint((__DRIVER_NAME " Device is inactive\n"));
265 else
266 {
267 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
268 {
269 /* CD/DVD drives must have bytes_per_sector = 2048. */
270 xvdd->bytes_per_sector = 2048;
271 }
273 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
274 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
276 xvdd->shadow_free = 0;
277 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
278 for (i = 0; i < SHADOW_ENTRIES; i++)
279 {
280 xvdd->shadows[i].req.id = i;
281 /* make sure leftover real requests's are never confused with dump mode requests */
282 if (dump_mode)
283 xvdd->shadows[i].req.id |= SHADOW_ID_DUMP_FLAG;
284 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
285 }
286 }
288 return SP_RETURN_FOUND;
289 }
291 static __inline ULONG
292 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
293 {
294 switch (srb->Cdb[0])
295 {
296 case SCSIOP_READ:
297 case SCSIOP_WRITE:
298 return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
299 case SCSIOP_READ16:
300 case SCSIOP_WRITE16:
301 return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];
302 default:
303 return 0;
304 }
305 }
307 static __inline ULONGLONG
308 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
309 {
310 ULONGLONG sector;
312 switch (srb->Cdb[0])
313 {
314 case SCSIOP_READ:
315 case SCSIOP_WRITE:
316 sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
317 break;
318 case SCSIOP_READ16:
319 case SCSIOP_WRITE16:
320 sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
321 | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
322 | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
323 | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
324 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
325 break;
326 default:
327 sector = 0;
328 break;
329 }
330 return sector;
331 }
333 static __inline BOOLEAN
334 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
335 {
336 switch (srb->Cdb[0])
337 {
338 case SCSIOP_READ:
339 case SCSIOP_READ16:
340 return TRUE;
341 case SCSIOP_WRITE:
342 case SCSIOP_WRITE16:
343 return FALSE;
344 default:
345 return FALSE;
346 }
347 }
349 static VOID
350 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
351 {
352 srb_list_entry_t *list_entry = srb->SrbExtension;
353 list_entry->srb = srb;
354 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)list_entry);
355 }
357 static VOID
358 XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
359 {
360 PSCSI_REQUEST_BLOCK srb;
361 srb_list_entry_t *srb_entry;
362 ULONGLONG sector_number;
363 ULONG block_count;
364 blkif_shadow_t *shadow;
365 ULONG remaining, offset, length;
366 grant_ref_t gref;
367 PUCHAR ptr;
368 int notify;
369 int i;
370 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
371 LARGE_INTEGER current_time;
372 #endif
374 //FUNCTION_ENTER();
376 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
377 ScsiPortQuerySystemTime(&current_time);
378 #endif
380 while ((!dump_mode || xvdd->shadow_free == SHADOW_ENTRIES)
381 && xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE
382 && !xvdd->aligned_buffer_in_use
383 && xvdd->shadow_free
384 && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list) /* RemoveHeadList must be last in the expression */
385 {
386 srb = srb_entry->srb;
387 block_count = decode_cdb_length(srb);;
388 block_count *= xvdd->bytes_per_sector / 512;
389 sector_number = decode_cdb_sector(srb);
390 sector_number *= xvdd->bytes_per_sector / 512;
392 /* look for pending writes that overlap this one */
393 /* we get warnings from drbd if we don't */
394 for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
395 {
396 PSCSI_REQUEST_BLOCK srb2;
397 ULONGLONG sector_number2;
398 ULONG block_count2;
400 srb2 = xvdd->shadows[i].srb;
401 if (!srb2)
402 continue;
403 if (decode_cdb_is_read(srb2))
404 continue;
405 block_count2 = decode_cdb_length(srb2);;
406 block_count2 *= xvdd->bytes_per_sector / 512;
407 sector_number2 = decode_cdb_sector(srb2);
408 sector_number2 *= xvdd->bytes_per_sector / 512;
410 if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
411 continue;
412 if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
413 continue;
415 #if 0
416 /* check if the data being written is identical to the data in the pipe */
417 {
418 PUCHAR buf, buf2;
419 ULONG byte_count;
420 int j;
422 buf = (PUCHAR)srb->DataBuffer + (max(sector_number, sector_number2) - sector_number) * xvdd->bytes_per_sector;
423 buf2 = (PUCHAR)srb2->DataBuffer + (max(sector_number, sector_number2) - sector_number2) * xvdd->bytes_per_sector;
424 byte_count = (ULONG)(min(sector_number + block_count, sector_number2 + block_count2) - max(sector_number, sector_number2)) * xvdd->bytes_per_sector;
425 for (j = 0; j < (int)byte_count; j++)
426 {
427 if (buf[j] != buf2[j])
428 break;
429 }
430 }
431 #endif
433 KdPrint((__DRIVER_NAME " Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
434 sector_number, block_count, sector_number2, block_count2));
435 /* put the srb back at the start of the queue */
436 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
437 break;
438 }
439 if (i < MAX_SHADOW_ENTRIES)
440 break; /* stall the queue but fall through so the notify is triggered */
442 remaining = block_count * 512;
443 shadow = get_shadow_from_freelist(xvdd);
444 ASSERT(shadow);
445 ASSERT(!shadow->aligned_buffer_in_use);
446 ASSERT(!shadow->srb);
447 shadow->reset = FALSE;
448 shadow->req.sector_number = sector_number;
449 shadow->req.handle = 0;
450 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
451 shadow->req.nr_segments = 0;
452 shadow->srb = srb;
454 if ((ULONG_PTR)srb->DataBuffer & 511)
455 {
456 if (dump_mode)
457 KdPrint((__DRIVER_NAME " unaligned dump mode buffer = %d bytes\n", block_count * 512));
458 ASSERT(!dump_mode || block_count * 512 < BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE);
459 xvdd->aligned_buffer_in_use = TRUE;
460 ptr = xvdd->aligned_buffer;
461 if (!decode_cdb_is_read(srb))
462 memcpy(ptr, srb->DataBuffer, block_count * 512);
463 shadow->aligned_buffer_in_use = TRUE;
464 }
465 else
466 {
467 ptr = srb->DataBuffer;
468 shadow->aligned_buffer_in_use = FALSE;
469 }
471 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
472 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
473 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
475 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
476 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
477 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
479 while (remaining > 0)
480 {
481 PHYSICAL_ADDRESS physical_address = MmGetPhysicalAddress(ptr);
483 gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
484 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, (ULONG)'SCSI');
485 if (gref == INVALID_GRANT_REF)
486 {
487 ULONG i;
488 for (i = 0; i < shadow->req.nr_segments; i++)
489 {
490 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
491 shadow->req.seg[i].gref, FALSE, (ULONG)'SCSI');
492 }
493 if (shadow->aligned_buffer_in_use)
494 {
495 shadow->aligned_buffer_in_use = FALSE;
496 xvdd->aligned_buffer_in_use = FALSE;
497 }
498 /* put the srb back at the start of the queue, then fall through so that the notify is triggered*/
499 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
500 put_shadow_on_freelist(xvdd, shadow);
501 KdPrint((__DRIVER_NAME " Out of gref's. Deferring\n"));
502 break;
503 }
504 offset = physical_address.LowPart & (PAGE_SIZE - 1);
505 length = min(PAGE_SIZE - offset, remaining);
506 ASSERT((offset & 511) == 0);
507 ASSERT((length & 511) == 0);
508 ASSERT(offset + length <= PAGE_SIZE);
509 shadow->req.seg[shadow->req.nr_segments].gref = gref;
510 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
511 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
512 remaining -= length;
513 ptr += length;
514 shadow->req.nr_segments++;
515 }
517 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
519 XenVbd_PutRequest(xvdd, &shadow->req);
520 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
521 shadow->ring_submit_time = current_time;
522 #endif
524 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
525 if (notify)
526 {
527 //KdPrint((__DRIVER_NAME " Notifying\n"));
528 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
529 }
530 }
531 if (xvdd->shadow_free && !xvdd->aligned_buffer_in_use)
532 {
533 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
534 }
535 //FUNCTION_EXIT();
536 }
538 static ULONG
539 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
540 {
541 // PACCESS_RANGE AccessRange;
542 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
543 ULONG status;
544 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
545 PACCESS_RANGE access_range;
547 UNREFERENCED_PARAMETER(HwContext);
548 UNREFERENCED_PARAMETER(BusInformation);
549 UNREFERENCED_PARAMETER(ArgumentString);
551 FUNCTION_ENTER();
552 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
553 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
555 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
556 *Again = FALSE;
558 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
559 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
561 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
562 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
563 {
564 return SP_RETURN_BAD_CONFIG;
565 }
567 access_range = &((*(ConfigInfo->AccessRanges))[0]);
568 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
569 access_range->RangeStart.LowPart, access_range->RangeLength));
570 xvdd->device_base = ScsiPortGetDeviceBase(
571 DeviceExtension,
572 ConfigInfo->AdapterInterfaceType,
573 ConfigInfo->SystemIoBusNumber,
574 access_range->RangeStart,
575 access_range->RangeLength,
576 !access_range->RangeInMemory);
577 if (!xvdd->device_base)
578 {
579 FUNCTION_MSG("ScsiPortGetDeviceBase failed\n");
580 FUNCTION_EXIT();
581 return SP_RETURN_BAD_CONFIG;
582 }
584 status = XenVbd_InitFromConfig(xvdd);
585 if (status != SP_RETURN_FOUND)
586 {
587 FUNCTION_EXIT();
588 return status;
589 }
591 xvdd->aligned_buffer_in_use = FALSE;
592 /* align the buffer to PAGE_SIZE */
593 xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
594 KdPrint((__DRIVER_NAME " aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
595 KdPrint((__DRIVER_NAME " aligned_buffer = %p\n", xvdd->aligned_buffer));
597 if (!dump_mode)
598 {
599 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
600 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
601 //ConfigInfo->ScatterGather = TRUE;
602 }
603 else
604 {
605 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE * PAGE_SIZE;
606 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST_DUMP_MODE - 1;
607 //ConfigInfo->ScatterGather = FALSE;
608 }
609 KdPrint((__DRIVER_NAME " ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength));
610 KdPrint((__DRIVER_NAME " ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks));
611 ConfigInfo->ScatterGather = FALSE;
612 ConfigInfo->AlignmentMask = 0;
613 ConfigInfo->NumberOfBuses = 1;
614 ConfigInfo->InitiatorBusId[0] = 1;
615 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
616 ConfigInfo->MaximumNumberOfTargets = 2;
617 KdPrint((__DRIVER_NAME " ConfigInfo->CachesData was initialised to %d\n", ConfigInfo->CachesData));
618 ConfigInfo->CachesData = FALSE;
619 ConfigInfo->BufferAccessScsiPortControlled = FALSE;
621 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
622 {
623 ConfigInfo->Master = TRUE;
624 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
625 ConfigInfo->Dma32BitAddresses = FALSE;
626 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
627 }
628 else
629 {
630 ConfigInfo->Master = FALSE;
631 ConfigInfo->Dma32BitAddresses = TRUE;
632 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
633 }
635 FUNCTION_EXIT();
637 return SP_RETURN_FOUND;
638 }
640 static VOID
641 XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
642 {
643 blkif_request_t *req;
644 int notify;
646 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
647 RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
648 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
649 req->operation = 0xff;
650 xvdd->ring.req_prod_pvt++;
651 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
652 req->operation = 0xff;
653 xvdd->ring.req_prod_pvt++;
655 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
656 if (notify)
657 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
658 }
660 static BOOLEAN
661 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
662 {
663 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
665 FUNCTION_ENTER();
666 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
667 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
669 if (!xvdd->inactive)
670 {
671 xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED;
672 if (xvdd->cached_use_other_valid)
673 {
674 if (xvdd->cached_use_other)
675 {
676 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
677 xvdd->use_other = TRUE;
678 }
679 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
680 }
681 InitializeListHead(&xvdd->srb_list);
682 }
683 FUNCTION_EXIT();
685 return TRUE;
686 }
688 static ULONG
689 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
690 {
691 PMODE_PARAMETER_HEADER parameter_header = NULL;
692 PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
693 PMODE_PARAMETER_BLOCK param_block;
694 PMODE_FORMAT_PAGE format_page;
695 ULONG offset = 0;
696 UCHAR buffer[1024];
697 BOOLEAN valid_page = FALSE;
698 BOOLEAN cdb_llbaa;
699 BOOLEAN cdb_dbd;
700 UCHAR cdb_page_code;
701 USHORT cdb_allocation_length;
703 UNREFERENCED_PARAMETER(xvdd);
705 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
706 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
707 offset = 0;
709 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
711 switch (srb->Cdb[0])
712 {
713 case SCSIOP_MODE_SENSE:
714 cdb_llbaa = FALSE;
715 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
716 cdb_page_code = srb->Cdb[2] & 0x3f;
717 cdb_allocation_length = srb->Cdb[4];
718 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
719 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
720 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
721 parameter_header->MediumType = 0;
722 parameter_header->DeviceSpecificParameter = 0;
723 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
724 {
725 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
726 parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
727 }
728 offset += sizeof(MODE_PARAMETER_HEADER);
729 break;
730 case SCSIOP_MODE_SENSE10:
731 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
732 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
733 cdb_page_code = srb->Cdb[2] & 0x3f;
734 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
735 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
736 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
737 parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
738 parameter_header10->MediumType = 0;
739 parameter_header10->DeviceSpecificParameter = 0;
740 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
741 {
742 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
743 parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
744 }
745 offset += sizeof(MODE_PARAMETER_HEADER10);
746 break;
747 default:
748 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
749 return FALSE;
750 }
752 if (!cdb_dbd)
753 {
754 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
755 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
756 {
757 if (xvdd->total_sectors >> 32)
758 {
759 param_block->DensityCode = 0xff;
760 param_block->NumberOfBlocks[0] = 0xff;
761 param_block->NumberOfBlocks[1] = 0xff;
762 param_block->NumberOfBlocks[2] = 0xff;
763 }
764 else
765 {
766 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
767 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
768 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
769 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
770 }
771 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
772 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
773 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
774 }
775 offset += sizeof(MODE_PARAMETER_BLOCK);
776 }
777 switch (srb->Cdb[0])
778 {
779 case SCSIOP_MODE_SENSE:
780 parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
781 break;
782 case SCSIOP_MODE_SENSE10:
783 parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
784 parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
785 break;
786 }
787 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
788 {
789 valid_page = TRUE;
790 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
791 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
792 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
793 /* 256 sectors per track */
794 format_page->SectorsPerTrack[0] = 0x01;
795 format_page->SectorsPerTrack[1] = 0x00;
796 /* xxx bytes per sector */
797 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
798 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
799 format_page->HardSectorFormating = TRUE;
800 format_page->SoftSectorFormating = TRUE;
801 offset += sizeof(MODE_FORMAT_PAGE);
802 }
803 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
804 {
805 PMODE_CACHING_PAGE caching_page;
806 valid_page = TRUE;
807 caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
808 caching_page->PageCode = MODE_PAGE_CACHING;
809 caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
810 // caching_page-> // all zeros is just fine... maybe
811 offset += sizeof(MODE_CACHING_PAGE);
812 }
813 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
814 {
815 PUCHAR medium_types_page;
816 valid_page = TRUE;
817 medium_types_page = &buffer[offset];
818 medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
819 medium_types_page[1] = 0x06;
820 medium_types_page[2] = 0;
821 medium_types_page[3] = 0;
822 medium_types_page[4] = 0;
823 medium_types_page[5] = 0;
824 medium_types_page[6] = 0;
825 medium_types_page[7] = 0;
826 offset += 8;
827 }
828 switch (srb->Cdb[0])
829 {
830 case SCSIOP_MODE_SENSE:
831 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
832 break;
833 case SCSIOP_MODE_SENSE10:
834 parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
835 parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
836 break;
837 }
839 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
840 {
841 srb->SrbStatus = SRB_STATUS_ERROR;
842 }
843 else if(offset < srb->DataTransferLength)
844 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
845 else
846 srb->SrbStatus = SRB_STATUS_SUCCESS;
847 srb->DataTransferLength = min(srb->DataTransferLength, offset);
848 srb->ScsiStatus = 0;
849 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
851 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
853 return TRUE;
854 }
856 static VOID
857 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
858 {
859 PSENSE_DATA sd = srb->SenseInfoBuffer;
861 UNREFERENCED_PARAMETER(xvdd);
863 if (!srb->SenseInfoBuffer)
864 return;
866 sd->ErrorCode = 0x70;
867 sd->Valid = 1;
868 sd->SenseKey = sense_key;
869 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
870 sd->AdditionalSenseCode = additional_sense_code;
871 return;
872 }
874 static VOID
875 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
876 {
877 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
878 return;
879 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
880 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
881 }
883 static BOOLEAN
884 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
885 {
886 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
887 PSCSI_REQUEST_BLOCK srb;
888 RING_IDX i, rp;
889 ULONG j;
890 blkif_response_t *rep;
891 int block_count;
892 int more_to_do = TRUE;
893 blkif_shadow_t *shadow;
894 ULONG suspend_resume_state_pdo;
895 BOOLEAN last_interrupt = FALSE;
896 ULONG start_ring_detect_state = xvdd->ring_detect_state;
897 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
898 srb_list_entry_t *srb_entry;
899 ULONG elapsed;
900 LARGE_INTEGER current_time;
901 #endif
903 /* in dump mode I think we get called on a timer, not by an actual IRQ */
904 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
905 return FALSE; /* interrupt was not for us */
907 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
908 KeMemoryBarrier();
910 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
911 {
912 FUNCTION_ENTER();
913 switch (suspend_resume_state_pdo)
914 {
915 case SR_STATE_SUSPENDING:
916 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
917 break;
918 case SR_STATE_RESUMING:
919 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
920 XenVbd_InitFromConfig(xvdd);
921 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
922 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
923 break;
924 case SR_STATE_RUNNING:
925 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
926 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
927 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
928 ScsiPortNotification(NextRequest, DeviceExtension);
929 default:
930 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
931 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
932 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
933 break;
934 }
935 KeMemoryBarrier();
936 }
938 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
939 {
940 return last_interrupt;
941 }
943 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
944 ScsiPortQuerySystemTime(&current_time);
945 #endif
947 while (more_to_do)
948 {
949 rp = xvdd->ring.sring->rsp_prod;
950 KeMemoryBarrier();
951 for (i = xvdd->ring.rsp_cons; i < rp; i++)
952 {
953 rep = XenVbd_GetResponse(xvdd, i);
954 /*
955 * This code is to automatically detect if the backend is using the same
956 * bit width or a different bit width to us. Later versions of Xen do this
957 * via a xenstore value, but not all. That 0x0fffffff (notice
958 * that the msb is not actually set, so we don't have any problems with
959 * sign extending) is to signify the last entry on the right, which is
960 * different under 32 and 64 bits, and that is why we set it up there.
962 * To do the detection, we put two initial entries on the ring, with an op
963 * of 0xff (which is invalid). The first entry is mostly okay, but the
964 * second will be grossly misaligned if the backend bit width is different,
965 * and we detect this and switch frontend structures.
966 */
967 switch (xvdd->ring_detect_state)
968 {
969 case RING_DETECT_STATE_NOT_STARTED:
970 KdPrint((__DRIVER_NAME " premature IRQ\n"));
971 break;
972 case RING_DETECT_STATE_DETECT1:
973 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));
974 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));
975 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
976 break;
977 case RING_DETECT_STATE_DETECT2:
978 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));
979 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));
980 *xvdd->event_channel_ptr |= 0x80000000;
981 if (rep->operation != 0xff)
982 {
983 KdPrint((__DRIVER_NAME " switching to 'other' ring size\n"));
984 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
985 xvdd->use_other = TRUE;
986 *xvdd->event_channel_ptr |= 0x40000000;
987 }
988 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
989 ScsiPortNotification(NextRequest, DeviceExtension);
990 break;
991 case RING_DETECT_STATE_COMPLETE:
992 shadow = &xvdd->shadows[rep->id & SHADOW_ID_ID_MASK];
993 if (shadow->reset)
994 {
995 shadow->srb->SrbStatus = SRB_STATUS_BUS_RESET;
996 ScsiPortNotification(RequestComplete, xvdd, shadow->srb);
997 KdPrint((__DRIVER_NAME " discarding reset shadow\n"));
998 for (j = 0; j < shadow->req.nr_segments; j++)
999 {
1000 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
1001 shadow->req.seg[j].gref, FALSE, (ULONG)'SCSI');
1004 else if (dump_mode && !(rep->id & SHADOW_ID_DUMP_FLAG))
1006 KdPrint((__DRIVER_NAME " discarding stale (non-dump-mode) shadow\n"));
1008 else
1010 srb = shadow->srb;
1011 ASSERT(srb);
1012 block_count = decode_cdb_length(srb);
1013 block_count *= xvdd->bytes_per_sector / 512;
1014 #if DBG && NTDDI_VERSION >= NTDDI_WINXP
1015 srb_entry = srb->SrbExtension;
1016 elapsed = (ULONG)((current_time.QuadPart - shadow->ring_submit_time.QuadPart) / 10000L);
1017 if (elapsed > 5000)
1018 KdPrint((__DRIVER_NAME " WARNING: SRB completion time %dms\n", elapsed));
1019 #endif
1020 if (rep->status == BLKIF_RSP_OKAY || (dump_mode && dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
1021 /* 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 */
1022 srb->SrbStatus = SRB_STATUS_SUCCESS;
1023 else
1025 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
1026 if (decode_cdb_is_read(srb))
1027 KdPrint((__DRIVER_NAME " Operation = Read\n"));
1028 else
1029 KdPrint((__DRIVER_NAME " Operation = Write\n"));
1030 if (dump_mode)
1032 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
1033 KdPrint((__DRIVER_NAME " DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
1034 KdPrint((__DRIVER_NAME " Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
1035 KdPrint((__DRIVER_NAME " PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
1037 for (j = 0; j < shadow->req.nr_segments; j++)
1039 KdPrint((__DRIVER_NAME " gref = %d\n", shadow->req.seg[j].gref));
1040 KdPrint((__DRIVER_NAME " first_sect = %d\n", shadow->req.seg[j].first_sect));
1041 KdPrint((__DRIVER_NAME " last_sect = %d\n", shadow->req.seg[j].last_sect));
1044 srb->SrbStatus = SRB_STATUS_ERROR;
1045 srb->ScsiStatus = 0x02;
1046 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
1047 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1048 XenVbd_MakeAutoSense(xvdd, srb);
1050 if (shadow->aligned_buffer_in_use)
1052 ASSERT(xvdd->aligned_buffer_in_use);
1053 xvdd->aligned_buffer_in_use = FALSE;
1054 if (srb->SrbStatus == SRB_STATUS_SUCCESS && decode_cdb_is_read(srb))
1055 memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
1057 for (j = 0; j < shadow->req.nr_segments; j++)
1059 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
1060 shadow->req.seg[j].gref, FALSE, (ULONG)'SCSI');
1062 ScsiPortNotification(RequestComplete, xvdd, srb);
1064 shadow->aligned_buffer_in_use = FALSE;
1065 shadow->reset = FALSE;
1066 shadow->srb = NULL;
1067 put_shadow_on_freelist(xvdd, shadow);
1068 break;
1072 xvdd->ring.rsp_cons = i;
1073 if (i != xvdd->ring.req_prod_pvt)
1075 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
1077 else
1079 xvdd->ring.sring->rsp_event = i + 1;
1080 more_to_do = FALSE;
1084 if (start_ring_detect_state > RING_DETECT_STATE_NOT_STARTED)
1085 XenVbd_PutQueuedSrbsOnRing(xvdd);
1087 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
1089 if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
1091 /* all entries are purged from the list (or we are inactive). ready to suspend */
1092 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
1093 KeMemoryBarrier();
1094 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
1095 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
1096 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
1098 FUNCTION_EXIT();
1101 return last_interrupt;
1104 static BOOLEAN
1105 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
1107 PUCHAR data_buffer;
1108 //ULONG data_buffer_length;
1109 PCDB cdb;
1110 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1111 ULONG data_transfer_length = srb->DataTransferLength;
1113 if (xvdd->inactive)
1115 KdPrint((__DRIVER_NAME " Inactive srb->Function = %08X\n", srb->Function));
1116 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1117 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1118 ScsiPortNotification(NextRequest, DeviceExtension);
1119 return TRUE;
1122 // If we haven't enumerated all the devices yet then just defer the request
1123 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
1125 if (xvdd->ring_detect_state == RING_DETECT_STATE_NOT_STARTED)
1126 XenVbd_StartRingDetection(xvdd);
1129 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
1131 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Suspending/Resuming)\n"));
1132 srb->SrbStatus = SRB_STATUS_BUSY;
1133 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1134 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Suspending/Resuming)\n"));
1135 return TRUE;
1138 if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
1140 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1141 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1142 ScsiPortNotification(NextRequest, DeviceExtension);
1143 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1144 return TRUE;
1147 switch (srb->Function)
1149 case SRB_FUNCTION_EXECUTE_SCSI:
1150 cdb = (PCDB)srb->Cdb;
1152 switch(cdb->CDB6GENERIC.OperationCode)
1154 case SCSIOP_TEST_UNIT_READY:
1155 if (dump_mode)
1156 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1157 srb->SrbStatus = SRB_STATUS_SUCCESS;
1158 srb->ScsiStatus = 0;
1159 break;
1160 case SCSIOP_INQUIRY:
1161 if (dump_mode)
1163 //PHYSICAL_ADDRESS physical;
1164 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1165 //KdPrint((__DRIVER_NAME " srb->Databuffer = %p\n", srb->DataBuffer));
1166 //physical = ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length);
1167 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
1169 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
1170 // KdPrint((__DRIVER_NAME " (Length = %d)\n", srb->DataTransferLength));
1172 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1173 data_buffer = srb->DataBuffer;
1174 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1175 srb->SrbStatus = SRB_STATUS_SUCCESS;
1176 switch (xvdd->device_type)
1178 case XENVBD_DEVICETYPE_DISK:
1179 if ((srb->Cdb[1] & 1) == 0)
1181 if (srb->Cdb[2])
1183 srb->SrbStatus = SRB_STATUS_ERROR;
1185 else
1187 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1188 id->DeviceType = DIRECT_ACCESS_DEVICE;
1189 id->Versions = 4; /* minimum that WHQL says we must support */
1190 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
1191 id->HiSupport = 1; /* WHQL test says we should set this */
1192 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1193 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
1194 id->CommandQueue = 1;
1195 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1196 memcpy(id->ProductId, scsi_disk_model, 16); // product id
1197 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1198 data_transfer_length = sizeof(INQUIRYDATA);
1201 else
1203 switch (srb->Cdb[2])
1205 case VPD_SUPPORTED_PAGES: /* list of pages we support */
1206 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1207 data_buffer[1] = VPD_SUPPORTED_PAGES;
1208 data_buffer[2] = 0x00;
1209 data_buffer[3] = 2;
1210 data_buffer[4] = 0x00;
1211 data_buffer[5] = 0x80;
1212 data_transfer_length = 6;
1213 break;
1214 case VPD_SERIAL_NUMBER: /* serial number */
1215 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1216 data_buffer[1] = VPD_SERIAL_NUMBER;
1217 data_buffer[2] = 0x00;
1218 data_buffer[3] = 8;
1219 memset(&data_buffer[4], ' ', 8);
1220 data_transfer_length = 12;
1221 break;
1222 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
1223 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1224 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
1225 data_buffer[2] = 0x00;
1226 data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
1227 data_buffer[4] = 2; /* ASCII */
1228 data_buffer[5] = 1; /* VendorId */
1229 data_buffer[6] = 0;
1230 data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
1231 memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
1232 data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
1233 break;
1234 default:
1235 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
1236 srb->SrbStatus = SRB_STATUS_ERROR;
1237 break;
1240 break;
1241 case XENVBD_DEVICETYPE_CDROM:
1242 if ((srb->Cdb[1] & 1) == 0)
1244 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1245 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1246 id->RemovableMedia = 1;
1247 id->Versions = 3;
1248 id->ResponseDataFormat = 0;
1249 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1250 id->CommandQueue = 1;
1251 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1252 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1253 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1255 else
1257 switch (srb->Cdb[2])
1259 case 0x00:
1260 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1261 data_buffer[1] = 0x00;
1262 data_buffer[2] = 0x00;
1263 data_buffer[3] = 2;
1264 data_buffer[4] = 0x00;
1265 data_buffer[5] = 0x80;
1266 break;
1267 case 0x80:
1268 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1269 data_buffer[1] = 0x80;
1270 data_buffer[2] = 0x00;
1271 data_buffer[3] = 8;
1272 data_buffer[4] = 0x31;
1273 data_buffer[5] = 0x32;
1274 data_buffer[6] = 0x33;
1275 data_buffer[7] = 0x34;
1276 data_buffer[8] = 0x35;
1277 data_buffer[9] = 0x36;
1278 data_buffer[10] = 0x37;
1279 data_buffer[11] = 0x38;
1280 break;
1281 default:
1282 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
1283 srb->SrbStatus = SRB_STATUS_ERROR;
1284 break;
1287 break;
1288 default:
1289 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1290 srb->SrbStatus = SRB_STATUS_ERROR;
1291 break;
1293 break;
1294 case SCSIOP_READ_CAPACITY:
1295 if (dump_mode)
1296 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1297 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1298 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1299 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1300 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1301 data_buffer = srb->DataBuffer;
1302 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1303 if ((xvdd->total_sectors - 1) >> 32)
1305 data_buffer[0] = 0xff;
1306 data_buffer[1] = 0xff;
1307 data_buffer[2] = 0xff;
1308 data_buffer[3] = 0xff;
1310 else
1312 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1313 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1314 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1315 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1317 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1318 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1319 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1320 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1321 srb->ScsiStatus = 0;
1322 srb->SrbStatus = SRB_STATUS_SUCCESS;
1323 break;
1324 case SCSIOP_READ_CAPACITY16:
1325 if (dump_mode)
1326 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1327 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1328 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1329 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1330 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1331 data_buffer = srb->DataBuffer;
1332 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1333 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1334 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1335 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1336 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1337 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1338 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1339 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1340 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1341 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1342 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1343 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1344 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1345 srb->ScsiStatus = 0;
1346 srb->SrbStatus = SRB_STATUS_SUCCESS;
1347 break;
1348 case SCSIOP_MODE_SENSE:
1349 case SCSIOP_MODE_SENSE10:
1350 if (dump_mode)
1351 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));
1352 XenVbd_FillModePage(xvdd, srb);
1353 break;
1354 case SCSIOP_READ:
1355 case SCSIOP_READ16:
1356 case SCSIOP_WRITE:
1357 case SCSIOP_WRITE16:
1358 XenVbd_PutSrbOnList(xvdd, srb);
1359 XenVbd_PutQueuedSrbsOnRing(xvdd);
1360 break;
1361 case SCSIOP_VERIFY:
1362 case SCSIOP_VERIFY16:
1363 // Should we do more here?
1364 if (dump_mode)
1365 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1366 srb->SrbStatus = SRB_STATUS_SUCCESS;
1367 break;
1368 case SCSIOP_REPORT_LUNS:
1369 if (dump_mode)
1370 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1371 srb->SrbStatus = SRB_STATUS_SUCCESS;;
1372 break;
1373 case SCSIOP_REQUEST_SENSE:
1374 if (dump_mode)
1375 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1376 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1377 srb->SrbStatus = SRB_STATUS_SUCCESS;
1378 break;
1379 case SCSIOP_READ_TOC:
1380 if (dump_mode)
1381 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1382 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1383 data_buffer = srb->DataBuffer;
1384 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1385 /*
1386 #define READ_TOC_FORMAT_TOC 0x00
1387 #define READ_TOC_FORMAT_SESSION 0x01
1388 #define READ_TOC_FORMAT_FULL_TOC 0x02
1389 #define READ_TOC_FORMAT_PMA 0x03
1390 #define READ_TOC_FORMAT_ATIP 0x04
1391 */
1392 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1393 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1394 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1395 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1396 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1397 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1398 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1399 switch (cdb->READ_TOC.Format2)
1401 case READ_TOC_FORMAT_TOC:
1402 data_buffer[0] = 0; // length MSB
1403 data_buffer[1] = 10; // length LSB
1404 data_buffer[2] = 1; // First Track
1405 data_buffer[3] = 1; // Last Track
1406 data_buffer[4] = 0; // Reserved
1407 data_buffer[5] = 0x14; // current position data + uninterrupted data
1408 data_buffer[6] = 1; // last complete track
1409 data_buffer[7] = 0; // reserved
1410 data_buffer[8] = 0; // MSB Block
1411 data_buffer[9] = 0;
1412 data_buffer[10] = 0;
1413 data_buffer[11] = 0; // LSB Block
1414 srb->SrbStatus = SRB_STATUS_SUCCESS;
1415 break;
1416 case READ_TOC_FORMAT_SESSION:
1417 case READ_TOC_FORMAT_FULL_TOC:
1418 case READ_TOC_FORMAT_PMA:
1419 case READ_TOC_FORMAT_ATIP:
1420 srb->SrbStatus = SRB_STATUS_ERROR;
1421 break;
1423 break;
1424 case SCSIOP_START_STOP_UNIT:
1425 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1426 srb->SrbStatus = SRB_STATUS_SUCCESS;
1427 break;
1428 case SCSIOP_RESERVE_UNIT:
1429 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1430 srb->SrbStatus = SRB_STATUS_SUCCESS;
1431 break;
1432 case SCSIOP_RELEASE_UNIT:
1433 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1434 srb->SrbStatus = SRB_STATUS_SUCCESS;
1435 break;
1436 default:
1437 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
1438 srb->SrbStatus = SRB_STATUS_ERROR;
1439 break;
1441 if (srb->SrbStatus == SRB_STATUS_ERROR)
1443 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
1444 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1446 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1447 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1449 srb->ScsiStatus = 0x02;
1450 XenVbd_MakeAutoSense(xvdd, srb);
1451 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1452 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1454 ScsiPortNotification(NextRequest, DeviceExtension);
1457 else if (srb->SrbStatus != SRB_STATUS_PENDING)
1459 if (srb->SrbStatus == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
1461 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1462 srb->DataTransferLength = data_transfer_length;
1464 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1465 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1466 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1467 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1469 ScsiPortNotification(NextRequest, DeviceExtension);
1472 break;
1473 case SRB_FUNCTION_IO_CONTROL:
1474 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1475 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1476 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1477 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1479 ScsiPortNotification(NextRequest, DeviceExtension);
1481 break;
1482 case SRB_FUNCTION_FLUSH:
1483 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1484 srb->SrbStatus = SRB_STATUS_SUCCESS;
1485 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1486 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1488 ScsiPortNotification(NextRequest, DeviceExtension);
1490 break;
1491 case SRB_FUNCTION_SHUTDOWN:
1492 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1493 srb->SrbStatus = SRB_STATUS_SUCCESS;
1494 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1495 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1497 ScsiPortNotification(NextRequest, DeviceExtension);
1499 break;
1500 default:
1501 KdPrint((__DRIVER_NAME " Unhandled srb->Function = %08X\n", srb->Function));
1502 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1503 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1504 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1506 ScsiPortNotification(NextRequest, DeviceExtension);
1508 break;
1511 //FUNCTION_EXIT();
1512 return TRUE;
1515 static BOOLEAN
1516 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1518 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1519 srb_list_entry_t *srb_entry;
1520 PSCSI_REQUEST_BLOCK srb;
1521 int i;
1523 UNREFERENCED_PARAMETER(DeviceExtension);
1524 UNREFERENCED_PARAMETER(PathId);
1526 FUNCTION_ENTER();
1528 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1529 xvdd->aligned_buffer_in_use = FALSE;
1531 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1533 while((srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
1535 srb = srb_entry->srb;
1536 srb->SrbStatus = SRB_STATUS_BUS_RESET;
1537 KdPrint((__DRIVER_NAME " completing queued SRB %p with status SRB_STATUS_BUS_RESET\n", srb));
1538 ScsiPortNotification(RequestComplete, xvdd, srb);
1541 for (i = 0; i < MAX_SHADOW_ENTRIES; i++)
1543 if (xvdd->shadows[i].srb)
1545 //KdPrint((__DRIVER_NAME " Completing in-flight srb %p with status SRB_STATUS_BUS_RESET\n", xvdd->shadows[i].srb));
1546 /* set reset here so that the interrupt will return it with SRB_STATUS_BUS_RESET */
1547 xvdd->shadows[i].reset = TRUE;
1551 /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen) */
1552 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
1554 ScsiPortNotification(NextRequest, DeviceExtension);
1557 FUNCTION_EXIT();
1559 return TRUE;
1562 static BOOLEAN
1563 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1565 UNREFERENCED_PARAMETER(DeviceExtension);
1566 UNREFERENCED_PARAMETER(Context);
1567 UNREFERENCED_PARAMETER(SaveState);
1569 FUNCTION_ENTER();
1570 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1572 FUNCTION_EXIT();
1574 return TRUE;
1577 static SCSI_ADAPTER_CONTROL_STATUS
1578 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1580 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1581 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1582 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1583 //KIRQL OldIrql;
1585 FUNCTION_ENTER();
1586 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1587 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
1589 switch (ControlType)
1591 case ScsiQuerySupportedControlTypes:
1592 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1593 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1594 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1595 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1596 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1597 break;
1598 case ScsiStopAdapter:
1599 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1600 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1601 break;
1602 case ScsiRestartAdapter:
1603 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1604 if (!xvdd->inactive)
1606 if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
1607 KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR) xvdd, 0, 0);
1608 xvdd->ring_detect_state = RING_DETECT_STATE_NOT_STARTED;
1610 break;
1611 case ScsiSetBootConfig:
1612 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1613 break;
1614 case ScsiSetRunningConfig:
1615 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1616 break;
1617 default:
1618 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1619 break;
1622 FUNCTION_EXIT();
1624 return Status;
1627 NTSTATUS
1628 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1630 ULONG status;
1631 HW_INITIALIZATION_DATA HwInitializationData;
1632 PVOID driver_extension;
1633 PUCHAR ptr;
1634 OBJECT_ATTRIBUTES oa;
1635 HANDLE service_handle;
1636 UNICODE_STRING param_name;
1637 HANDLE param_handle;
1638 UNICODE_STRING value_name;
1639 CHAR buf[256];
1640 ULONG buf_len;
1641 PKEY_VALUE_PARTIAL_INFORMATION kpv;
1643 FUNCTION_ENTER();
1644 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1645 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1647 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1648 if (!RegistryPath)
1650 dump_mode = TRUE;
1653 if (!dump_mode)
1655 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1656 ptr = driver_extension;
1657 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1658 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1659 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1660 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1661 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1662 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1663 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1664 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
1665 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
1666 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
1667 __ADD_XEN_INIT_UCHAR(&ptr, 20);
1668 __ADD_XEN_INIT_UCHAR(&ptr, 0);
1669 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
1670 //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
1671 //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
1672 //__ADD_XEN_INIT_UCHAR(&ptr, 20);
1673 __ADD_XEN_INIT_UCHAR(&ptr, 0);
1674 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
1675 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
1676 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
1677 __ADD_XEN_INIT_UCHAR(&ptr, 50);
1678 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
1679 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
1680 __ADD_XEN_INIT_UCHAR(&ptr, 50);
1681 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
1682 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
1683 __ADD_XEN_INIT_UCHAR(&ptr, 50);
1684 __ADD_XEN_INIT_UCHAR(&ptr, 0);
1686 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1688 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1689 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
1690 if(!NT_SUCCESS(status))
1692 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
1694 else
1696 RtlInitUnicodeString(&param_name, L"Parameters");
1697 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
1698 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
1699 if(!NT_SUCCESS(status))
1701 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
1703 else
1705 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
1706 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
1707 RtlFillMemory(scsi_disk_model, 16, ' ');
1708 RtlFillMemory(scsi_cdrom_model, 16, ' ');
1710 RtlInitUnicodeString(&value_name, L"Manufacturer");
1711 buf_len = 256;
1712 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1713 if(NT_SUCCESS(status))
1714 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
1715 else
1716 RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN ");
1718 RtlInitUnicodeString(&value_name, L"Disk_Model");
1719 buf_len = 256;
1720 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1721 if(NT_SUCCESS(status))
1722 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1723 else
1724 RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK ");
1726 RtlInitUnicodeString(&value_name, L"CDROM_Model");
1727 buf_len = 256;
1728 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1729 if(NT_SUCCESS(status))
1730 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1731 else
1732 RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM ");
1733 ZwClose(param_handle);
1735 ZwClose(service_handle);
1739 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1741 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1742 HwInitializationData.AdapterInterfaceType = PNPBus;
1743 if (!dump_mode)
1744 HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
1745 else
1746 HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
1747 HwInitializationData.SpecificLuExtensionSize = 0;
1748 HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
1749 HwInitializationData.NumberOfAccessRanges = 1;
1750 HwInitializationData.MapBuffers = TRUE;
1751 HwInitializationData.NeedPhysicalAddresses = FALSE;
1752 HwInitializationData.TaggedQueuing = TRUE;
1753 HwInitializationData.AutoRequestSense = TRUE;
1754 HwInitializationData.MultipleRequestPerLu = TRUE;
1755 HwInitializationData.ReceiveEvent = FALSE;
1756 HwInitializationData.VendorIdLength = 0;
1757 HwInitializationData.VendorId = NULL;
1758 HwInitializationData.DeviceIdLength = 0;
1759 HwInitializationData.DeviceId = NULL;
1761 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1762 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1763 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1764 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1765 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1766 HwInitializationData.HwDmaStarted = NULL;
1767 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1768 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1770 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1772 if(!NT_SUCCESS(status))
1774 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1777 FUNCTION_EXIT();
1779 return status;