win-pvdrivers

view xenvbd/xenvbd_scsiport.c @ 868:9096c1757947

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