win-pvdrivers

view xenvbd/xenvbd_storport.c @ 1004:a5d1d333e0e2

Start of major changes to xenpci interface. Now using xenpci as export driver. storport and xennet6 drivers working but not suspend/resume or dump mode
author James Harper <james.harper@bendigoit.com.au>
date Sun Jan 06 14:08:22 2013 +1100 (2013-01-06)
parents c454b24f92b8
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #define INITGUID
21 #include "xenvbd_storport.h"
23 #pragma warning(disable: 4127)
25 #if defined(__x86_64__)
26 #define LongLongToPtr(x) (PVOID)(x)
27 #else
28 #define LongLongToPtr(x) UlongToPtr(x)
29 #endif
31 #if defined(__x86_64__)
32 #define ABI_PROTOCOL "x86_64-abi"
33 #else
34 #define ABI_PROTOCOL "x86_32-abi"
35 #endif
37 /* Not really necessary but keeps PREfast happy */
38 DRIVER_INITIALIZE DriverEntry;
39 static VOID XenVbd_HandleEventDpc(PSTOR_DPC dpc, PVOID DeviceExtension, PVOID arg1, PVOID arg2);
40 static VOID XenVbd_HandleEventDIRQL(PVOID DeviceExtension);
41 static VOID XenVbd_ProcessSrbList(PXENVBD_DEVICE_DATA xvdd);
43 static BOOLEAN dump_mode = FALSE;
44 #define DUMP_MODE_ERROR_LIMIT 64
45 static ULONG dump_mode_errors = 0;
47 CHAR scsi_device_manufacturer[8];
48 CHAR scsi_disk_model[16];
49 CHAR scsi_cdrom_model[16];
51 ULONGLONG parse_numeric_string(PCHAR string)
52 {
53 ULONGLONG val = 0;
54 while (*string != 0)
55 {
56 val = val * 10 + (*string - '0');
57 string++;
58 }
59 return val;
60 }
62 /* called with StartIoLock held */
63 static blkif_shadow_t *
64 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
65 {
66 if (xvdd->shadow_free == 0) {
67 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
68 return NULL;
69 }
70 xvdd->shadow_free--;
71 if (xvdd->shadow_free < xvdd->shadow_min_free)
72 xvdd->shadow_min_free = xvdd->shadow_free;
73 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
74 }
76 /* called with StartIoLock held */
77 static VOID
78 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
79 {
80 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)(shadow->req.id & SHADOW_ID_ID_MASK);
81 shadow->srb = NULL;
82 shadow->reset = FALSE;
83 shadow->aligned_buffer_in_use = FALSE;
84 xvdd->shadow_free++;
85 }
87 static blkif_response_t *
88 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i) {
89 return RING_GET_RESPONSE(&xvdd->ring, i);
90 }
92 static VOID
93 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req) {
94 //FUNCTION_ENTER();
95 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
96 xvdd->ring.req_prod_pvt++;
97 //FUNCTION_EXIT();
98 }
100 #if 0
101 static ULONG
102 XenVbd_InitConfig(PXENVBD_DEVICE_DATA xvdd)
103 {
104 ULONG status;
105 PUCHAR ptr;
106 USHORT type;
107 PCHAR setting, value, value2;
109 FUNCTION_ENTER();
110 /* first read the default config items */
111 ptr = xvdd->device_base;
112 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
113 {
114 switch(type)
115 {
116 case XEN_INIT_TYPE_VECTORS:
117 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
118 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
119 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
120 {
121 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
122 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
123 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
124 return SP_RETURN_BAD_CONFIG;
125 }
126 else
127 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
128 break;
129 default:
130 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
131 break;
132 }
133 }
135 /* then set up all the configuration requests */
136 ptr = xvdd->device_base;
137 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
138 #pragma warning(suppress:4054)
139 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_DPC, "event-channel", (PVOID)XenVbd_HandleEvent, xvdd);
140 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
141 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
142 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
143 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
144 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
145 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialised);
146 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
147 __ADD_XEN_INIT_UCHAR(&ptr, 20);
148 __ADD_XEN_INIT_UCHAR(&ptr, 0);
149 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
150 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
151 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
152 __ADD_XEN_INIT_UCHAR(&ptr, 20);
153 __ADD_XEN_INIT_UCHAR(&ptr, 0);
154 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
155 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
156 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
157 __ADD_XEN_INIT_UCHAR(&ptr, 50);
158 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
159 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
160 __ADD_XEN_INIT_UCHAR(&ptr, 50);
161 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
162 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
163 __ADD_XEN_INIT_UCHAR(&ptr, 50);
164 __ADD_XEN_INIT_UCHAR(&ptr, 0);
165 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
167 /* then configure */
168 status = xvdd->vectors.XenPci_XenConfigDevice(xvdd->vectors.context);
169 if (!NT_SUCCESS(status))
170 {
171 xvdd->vbd_status = VBD_STATUS_INACTIVE;
172 KdPrint(("Failed to complete device configuration (%08x)\n", status));
173 FUNCTION_EXIT();
174 return SP_RETURN_BAD_CONFIG;
175 }
176 FUNCTION_EXIT();
177 return SP_RETURN_FOUND;
178 }
180 static ULONG
181 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
182 {
183 ULONG i;
184 PUCHAR ptr;
185 USHORT type;
186 PCHAR setting, value, value2;
187 ULONG qemu_protocol_version = 0;
189 FUNCTION_ENTER();
191 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
192 xvdd->sring = NULL;
193 xvdd->event_channel = 0;
195 //xvdd->inactive = TRUE;
197 ptr = xvdd->device_base;
198 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
199 {
200 switch(type)
201 {
202 case XEN_INIT_TYPE_VECTORS:
203 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
204 if (dump_mode)
205 {
206 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
207 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
208 {
209 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
210 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
211 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
212 return SP_RETURN_BAD_CONFIG;
213 }
214 else
215 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
216 }
217 break;
218 case XEN_INIT_TYPE_RING: /* frontend ring */
219 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
220 if (strcmp(setting, "ring-ref") == 0)
221 {
222 xvdd->sring = (blkif_sring_t *)value;
223 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
224 /* this bit is for when we have to take over an existing ring on a crash dump */
225 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
226 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
227 }
228 break;
229 case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */
230 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d (%08x)\n", setting, PtrToUlong(value) & 0x3FFFFFFF, PtrToUlong(value)));
231 if (strcmp(setting, "event-channel") == 0)
232 {
233 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
234 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
235 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
236 }
237 break;
238 case XEN_INIT_TYPE_READ_STRING_BACK:
239 case XEN_INIT_TYPE_READ_STRING_FRONT:
240 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
241 if (strcmp(setting, "sectors") == 0)
242 xvdd->total_sectors = parse_numeric_string(value);
243 else if (strcmp(setting, "sector-size") == 0)
244 xvdd->hw_bytes_per_sector = (ULONG)parse_numeric_string(value);
245 else if (strcmp(setting, "device-type") == 0)
246 {
247 if (strcmp(value, "disk") == 0)
248 {
249 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
250 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
251 }
252 else if (strcmp(value, "cdrom") == 0)
253 {
254 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
255 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
256 }
257 else
258 {
259 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
260 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
261 }
262 }
263 else if (strcmp(setting, "mode") == 0)
264 {
265 if (strncmp(value, "r", 1) == 0)
266 {
267 KdPrint((__DRIVER_NAME " mode = r\n"));
268 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
269 }
270 else if (strncmp(value, "w", 1) == 0)
271 {
272 KdPrint((__DRIVER_NAME " mode = w\n"));
273 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
274 }
275 else
276 {
277 KdPrint((__DRIVER_NAME " mode = unknown\n"));
278 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
279 }
280 }
281 break;
282 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
283 qemu_protocol_version = PtrToUlong(value);
284 break;
285 case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
286 qemu_hide_flags_value = PtrToUlong(value);
287 KdPrint((__DRIVER_NAME " qemu_hide_flags_value = %d\n", qemu_hide_flags_value));
288 break;
289 case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
290 qemu_hide_filter = TRUE;
291 KdPrint((__DRIVER_NAME " qemu_hide_filter = TRUE\n"));
292 break;
293 case XEN_INIT_TYPE_STATE_PTR:
294 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
295 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
296 break;
297 default:
298 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
299 break;
300 }
301 }
303 if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
304 xvdd->inactive = FALSE;
306 if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
307 || xvdd->sring == NULL
308 || xvdd->event_channel == 0
309 || xvdd->total_sectors == 0
310 || xvdd->hw_bytes_per_sector == 0))
311 {
312 KdPrint((__DRIVER_NAME " Missing settings\n"));
313 FUNCTION_EXIT();
314 return SP_RETURN_BAD_CONFIG;
315 }
317 if (xvdd->inactive) {
318 KdPrint((__DRIVER_NAME " Device is inactive\n"));
319 } else {
320 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM) {
321 /* CD/DVD drives must have bytes_per_sector = 2048. */
322 xvdd->bytes_per_sector = 2048;
323 xvdd->hw_bytes_per_sector = 2048;
324 } else {
325 xvdd->bytes_per_sector = 512;
326 }
327 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
328 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
330 xvdd->shadow_free = 0;
331 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
332 for (i = 0; i < SHADOW_ENTRIES; i++) {
333 xvdd->shadows[i].req.id = i;
334 /* make sure leftover real requests's are never confused with dump mode requests */
335 if (dump_mode)
336 xvdd->shadows[i].req.id |= SHADOW_ID_DUMP_FLAG;
337 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
338 }
339 }
341 FUNCTION_EXIT();
342 return SP_RETURN_FOUND;
343 }
344 #endif
346 static __inline ULONG
347 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
348 {
349 switch (srb->Cdb[0])
350 {
351 case SCSIOP_READ:
352 case SCSIOP_WRITE:
353 return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
354 case SCSIOP_READ16:
355 case SCSIOP_WRITE16:
356 return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];
357 default:
358 return 0;
359 }
360 }
362 static __inline ULONGLONG
363 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
364 {
365 ULONGLONG sector;
367 switch (srb->Cdb[0])
368 {
369 case SCSIOP_READ:
370 case SCSIOP_WRITE:
371 sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
372 break;
373 case SCSIOP_READ16:
374 case SCSIOP_WRITE16:
375 sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
376 | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
377 | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
378 | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
379 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
380 break;
381 default:
382 sector = 0;
383 break;
384 }
385 return sector;
386 }
388 static __inline BOOLEAN
389 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
390 {
391 switch (srb->Cdb[0])
392 {
393 case SCSIOP_READ:
394 case SCSIOP_READ16:
395 return TRUE;
396 case SCSIOP_WRITE:
397 case SCSIOP_WRITE16:
398 return FALSE;
399 default:
400 return FALSE;
401 }
402 }
404 static VOID
405 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
406 srb_list_entry_t *srb_entry = srb->SrbExtension;
407 srb_entry->srb = srb;
408 srb_entry->outstanding_requests = 0;
409 srb_entry->length = srb->DataTransferLength;
410 srb_entry->offset = 0;
411 srb_entry->error = FALSE;
412 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
413 }
415 /* called with StartIoLock held */
416 /* returns TRUE if something was put on the ring and notify might be required */
417 static BOOLEAN
418 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
419 {
420 srb_list_entry_t *srb_entry = srb->SrbExtension;
421 /* sector_number and block_count are the adjusted-to-512-byte-sector values */
422 ULONGLONG sector_number;
423 ULONG block_count;
424 blkif_shadow_t *shadow;
425 ULONG remaining, offset, length;
426 grant_ref_t gref;
427 PUCHAR ptr;
428 int i;
429 PVOID system_address;
431 //if (dump_mode) FUNCTION_ENTER();
433 //FUNCTION_MSG("aligned_buffer_in_use = %d\n", xvdd->aligned_buffer_in_use);
434 //FUNCTION_MSG("shadow_free = %d\n", xvdd->shadow_free);
436 NT_ASSERT(srb);
438 if (!dump_mode) {
439 if (StorPortGetSystemAddress(xvdd, srb, &system_address) != STOR_STATUS_SUCCESS) {
440 FUNCTION_MSG("Failed to map DataBuffer\n");
441 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
442 return FALSE;
443 }
444 system_address = (PUCHAR)system_address + srb_entry->offset;
445 } else {
446 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
447 system_address = (PUCHAR)srb->DataBuffer + srb_entry->offset;
448 }
449 block_count = decode_cdb_length(srb);
450 sector_number = decode_cdb_sector(srb);
451 block_count *= xvdd->bytes_per_sector / 512;
452 sector_number *= xvdd->bytes_per_sector / 512;
454 NT_ASSERT(block_count * 512 == srb->DataTransferLength);
456 sector_number += srb_entry->offset / 512;
457 block_count -= srb_entry->offset / 512;
459 NT_ASSERT(block_count > 0);
461 /* look for pending writes that overlap this one */
462 /* we get warnings from drbd if we don't */
463 if (srb_entry->offset == 0) {
464 for (i = 0; i < MAX_SHADOW_ENTRIES; i++) {
465 PSCSI_REQUEST_BLOCK srb2;
466 ULONGLONG sector_number2;
467 ULONG block_count2;
469 srb2 = xvdd->shadows[i].srb;
470 if (!srb2)
471 continue;
472 if (decode_cdb_is_read(srb2))
473 continue;
474 block_count2 = decode_cdb_length(srb2);;
475 block_count2 *= xvdd->bytes_per_sector / 512;
476 sector_number2 = decode_cdb_sector(srb2);
477 sector_number2 *= xvdd->bytes_per_sector / 512;
479 if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
480 continue;
481 if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
482 continue;
484 KdPrint((__DRIVER_NAME " Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
485 sector_number, block_count, sector_number2, block_count2));
486 break;
487 }
488 if (i != MAX_SHADOW_ENTRIES) {
489 /* put the srb back at the start of the queue */
490 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
491 return FALSE;
492 }
493 }
495 shadow = get_shadow_from_freelist(xvdd);
496 if (!shadow) {
497 /* put the srb back at the start of the queue */
498 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
499 return FALSE;
500 }
501 NT_ASSERT(!shadow->aligned_buffer_in_use);
502 NT_ASSERT(!shadow->srb);
503 shadow->req.sector_number = sector_number;
504 shadow->req.handle = 0;
505 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
506 shadow->req.nr_segments = 0;
507 shadow->srb = srb;
508 shadow->length = 0;
509 shadow->system_address = system_address;
510 shadow->reset = FALSE;
512 if (!dump_mode) {
513 if ((ULONG_PTR)shadow->system_address & 511) {
514 xvdd->aligned_buffer_in_use = TRUE;
515 /* limit to aligned_buffer_size */
516 block_count = min(block_count, xvdd->aligned_buffer_size / 512);
517 ptr = (PUCHAR)xvdd->aligned_buffer;
518 if (!decode_cdb_is_read(srb))
519 memcpy(ptr, shadow->system_address, block_count * 512);
520 shadow->aligned_buffer_in_use = TRUE;
521 } else {
522 ptr = (PUCHAR)shadow->system_address;
523 shadow->aligned_buffer_in_use = FALSE;
524 }
525 } else {
526 NT_ASSERT(!((ULONG_PTR)shadow->system_address & 511));
527 ptr = shadow->system_address;
528 shadow->aligned_buffer_in_use = FALSE;
529 }
531 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)sector_number, block_count));
532 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
533 //KdPrint((__DRIVER_NAME " system_address = %p\n", shadow->system_address));
534 //KdPrint((__DRIVER_NAME " offset = %d, length = %d\n", srb_entry->offset, srb_entry->length));
535 //KdPrint((__DRIVER_NAME " ptr = %p\n", ptr));
537 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
538 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
540 remaining = block_count * 512;
541 while (remaining > 0 && shadow->req.nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST) {
542 PHYSICAL_ADDRESS physical_address;
544 if (!dump_mode) {
545 physical_address = MmGetPhysicalAddress(ptr);
546 } else {
547 ULONG length;
548 physical_address = StorPortGetPhysicalAddress(xvdd, srb, ptr, &length);
549 }
550 gref = XnGrantAccess(xvdd->handle,
551 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, xvdd->grant_tag);
552 if (gref == INVALID_GRANT_REF) {
553 ULONG i;
554 for (i = 0; i < shadow->req.nr_segments; i++) {
555 XnEndAccess(xvdd->handle,
556 shadow->req.seg[i].gref, FALSE, xvdd->grant_tag);
557 }
558 if (shadow->aligned_buffer_in_use) {
559 shadow->aligned_buffer_in_use = FALSE;
560 xvdd->aligned_buffer_in_use = FALSE;
561 }
562 /* put the srb back at the start of the queue */
563 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
564 put_shadow_on_freelist(xvdd, shadow);
565 KdPrint((__DRIVER_NAME " Out of gref's. Deferring\n"));
566 /* TODO: what if there are no requests currently in progress to kick the queue again?? timer? */
567 return FALSE;
568 }
569 offset = physical_address.LowPart & (PAGE_SIZE - 1);
570 length = min(PAGE_SIZE - offset, remaining);
571 NT_ASSERT((offset & 511) == 0);
572 NT_ASSERT((length & 511) == 0);
573 NT_ASSERT(offset + length <= PAGE_SIZE);
574 shadow->req.seg[shadow->req.nr_segments].gref = gref;
575 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset / 512);
576 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) / 512) - 1);
577 remaining -= length;
578 ptr += length;
579 shadow->length += length;
580 shadow->req.nr_segments++;
581 }
582 srb_entry->offset += shadow->length;
583 srb_entry->outstanding_requests++;
584 if (srb_entry->offset < srb_entry->length) {
585 if (dump_mode) KdPrint((__DRIVER_NAME " inserting back into list\n"));
586 /* put the srb back at the start of the queue to continue on the next request */
587 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
588 }
589 XenVbd_PutRequest(xvdd, &shadow->req);
590 return TRUE;
591 //FUNCTION_EXIT();
592 }
594 static VOID
595 XenVbd_BackendStateCallback(PVOID context, ULONG state) {
596 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)context;
597 PCHAR mode;
598 PCHAR device_type;
599 PFN_NUMBER pfn;
600 ULONG status;
601 BOOLEAN active = FALSE;
602 BOOLEAN qemu_hide_filter = FALSE;
603 ULONG qemu_hide_flags_value = 0;
604 STOR_LOCK_HANDLE lock_handle;
606 FUNCTION_ENTER();
607 if (state == xvdd->backend_state) {
608 FUNCTION_MSG("same state %d\n", state);
609 FUNCTION_EXIT();
610 }
611 FUNCTION_MSG("XenbusState = %d -> %d\n", xvdd->backend_state, state);
613 switch (state) {
614 case XenbusStateUnknown:
615 break;
617 case XenbusStateInitialising:
618 case XenbusStateInitWait:
619 case XenbusStateInitialised:
620 FUNCTION_MSG("XenbusState Initialising/InitWait/Initialised\n");
621 if (xvdd->frontend_state != XenbusStateInitialised) {
622 xvdd->frontend_state = XenbusStateInitialised;
623 xvdd->event_channel = XnAllocateEvent(xvdd->handle);
624 if (!xvdd->event_channel) {
625 // !!PANIC!!
626 }
627 FUNCTION_MSG("event_channel = %d\n", xvdd->event_channel);
628 status = XnBindEvent(xvdd->handle, xvdd->event_channel, XenVbd_HandleEventDIRQL, xvdd);
629 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "event-channel", xvdd->event_channel);
630 xvdd->sring = (blkif_sring_t *)ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENVBD_POOL_TAG);
631 if (!xvdd->sring) {
632 // !!PANIC!!
633 }
634 FUNCTION_MSG("sring = %p\n", xvdd->sring);
635 SHARED_RING_INIT(xvdd->sring);
636 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
637 pfn = MmGetPhysicalAddress(xvdd->sring).QuadPart >> PAGE_SHIFT;
638 FUNCTION_MSG("sring pfn = %d\n", (ULONG)pfn);
639 xvdd->sring_gref = XnGrantAccess(xvdd->handle, (ULONG)pfn, FALSE, INVALID_GRANT_REF, xvdd->grant_tag);
640 FUNCTION_MSG("sring_gref = %d\n", xvdd->sring_gref);
641 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "ring-ref", xvdd->sring_gref);
642 status = XnWriteString(xvdd->handle, XN_BASE_FRONTEND, "protocol", ABI_PROTOCOL);
643 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateInitialised);
644 }
645 break;
647 case XenbusStateConnected:
648 FUNCTION_MSG("XenbusState Connected\n");
649 if (xvdd->frontend_state != XenbusStateConnected) {
650 xvdd->frontend_state = XenbusStateConnected;
651 status = XnReadInt64(xvdd->handle, XN_BASE_BACKEND, "sectors", &xvdd->total_sectors);
652 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "sector-size", &xvdd->hw_bytes_per_sector);
653 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM) {
654 /* CD/DVD drives must have bytes_per_sector = 2048. */
655 xvdd->bytes_per_sector = 2048;
656 xvdd->hw_bytes_per_sector = 2048;
657 } else {
658 xvdd->bytes_per_sector = 512;
659 }
660 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
661 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
662 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-barrier", &xvdd->feature_barrier);
663 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-discard", &xvdd->feature_discard);
664 status = XnReadInt32(xvdd->handle, XN_BASE_BACKEND, "feature-flush-cache", &xvdd->feature_flush_cache);
665 status = XnReadString(xvdd->handle, XN_BASE_BACKEND, "mode", &mode);
666 if (strncmp(mode, "r", 1) == 0) {
667 FUNCTION_MSG("mode = r\n");
668 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
669 } else if (strncmp(mode, "w", 1) == 0) {
670 FUNCTION_MSG("mode = w\n");
671 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
672 } else {
673 FUNCTION_MSG("mode = unknown\n");
674 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
675 }
676 XnFreeMem(xvdd->handle, mode);
678 // read device-type
679 status = XnReadString(xvdd->handle, XN_BASE_FRONTEND, "device-type", &device_type);
680 if (strcmp(device_type, "disk") == 0) {
681 FUNCTION_MSG("device-type = Disk\n");
682 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
683 } else if (strcmp(device_type, "cdrom") == 0) {
684 FUNCTION_MSG("device-type = CDROM\n");
685 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
686 } else {
687 FUNCTION_MSG("device-type = %s (This probably won't work!)\n", device_type);
688 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
689 }
690 XnFreeMem(xvdd->handle, device_type);
691 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateConnected);
692 // check that everything is good
693 XnGetValue(xvdd->handle, XN_VALUE_TYPE_QEMU_HIDE_FLAGS, &qemu_hide_flags_value);
694 XnGetValue(xvdd->handle, XN_VALUE_TYPE_QEMU_FILTER, &qemu_hide_filter);
696 if (((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) && xvdd->device_type != XENVBD_DEVICETYPE_CDROM) || qemu_hide_filter)
697 active = TRUE;
699 if (active && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
700 || xvdd->sring == NULL
701 || xvdd->event_channel == 0
702 || xvdd->total_sectors == 0
703 || xvdd->hw_bytes_per_sector == 0)) {
704 FUNCTION_MSG("Missing settings\n");
705 active = FALSE;
706 }
708 if (active)
709 xvdd->vbd_status = VBD_STATUS_ACTIVE;
710 else
711 xvdd->vbd_status = VBD_STATUS_INACTIVE;
712 StorPortAcquireSpinLock(xvdd, StartIoLock, NULL, &lock_handle);
713 XenVbd_ProcessSrbList(xvdd);
714 StorPortReleaseSpinLock(xvdd, &lock_handle);
715 }
716 break;
718 case XenbusStateClosing:
719 break;
721 case XenbusStateClosed:
722 break;
724 default:
725 break;
726 }
727 xvdd->backend_state = state;
728 FUNCTION_EXIT();
729 }
731 /* called in non-dump mode */
732 static ULONG
733 XenVbd_VirtualHwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PVOID LowerDevice, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
734 {
735 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
737 //UNREFERENCED_PARAMETER(HwContext);
738 UNREFERENCED_PARAMETER(BusInformation);
739 UNREFERENCED_PARAMETER(LowerDevice);
740 UNREFERENCED_PARAMETER(ArgumentString);
742 FUNCTION_ENTER();
743 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
744 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
746 if (XnGetVersion() != 1) {
747 FUNCTION_MSG("Wrong XnGetVersion\n");
748 FUNCTION_EXIT();
749 return SP_RETURN_BAD_CONFIG;
750 }
752 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
753 InitializeListHead(&xvdd->srb_list);
754 xvdd->pdo = (PDEVICE_OBJECT)HwContext;
755 /* this shouldn't race because nothing will be on the srb queue yet */
756 if ((xvdd->handle = XnOpenDevice(xvdd->pdo, XenVbd_BackendStateCallback, xvdd)) == NULL) {
757 return SP_RETURN_BAD_CONFIG;
758 }
760 xvdd->aligned_buffer_in_use = FALSE;
761 /* align the buffer to PAGE_SIZE */
762 xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
763 KdPrint((__DRIVER_NAME " aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
764 KdPrint((__DRIVER_NAME " aligned_buffer = %p\n", xvdd->aligned_buffer));
766 ConfigInfo->MaximumTransferLength = 4 * 1024 * 1024; //BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
767 ConfigInfo->NumberOfPhysicalBreaks = ConfigInfo->MaximumTransferLength >> PAGE_SHIFT; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
768 FUNCTION_MSG("ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength);
769 FUNCTION_MSG("ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks);
770 if (!dump_mode) {
771 ConfigInfo->VirtualDevice = TRUE;
772 xvdd->aligned_buffer_size = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
773 } else {
774 ConfigInfo->VirtualDevice = FALSE;
775 xvdd->aligned_buffer_size = DUMP_MODE_UNALIGNED_PAGES * PAGE_SIZE;
776 }
778 FUNCTION_MSG("ConfigInfo->VirtualDevice = %d\n", ConfigInfo->VirtualDevice);
779 ConfigInfo->ScatterGather = TRUE;
780 ConfigInfo->Master = TRUE;
781 ConfigInfo->CachesData = FALSE;
782 ConfigInfo->MapBuffers = STOR_MAP_ALL_BUFFERS;
783 FUNCTION_MSG("ConfigInfo->NeedPhysicalAddresses = %d\n", ConfigInfo->NeedPhysicalAddresses);
784 ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
785 ConfigInfo->AlignmentMask = 0;
786 ConfigInfo->NumberOfBuses = 1;
787 ConfigInfo->InitiatorBusId[0] = 1;
788 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
789 ConfigInfo->MaximumNumberOfTargets = 2;
790 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) {
791 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
792 FUNCTION_MSG("Dma64BitAddresses supported\n");
793 } else {
794 FUNCTION_MSG("Dma64BitAddresses not supported\n");
795 }
796 *Again = FALSE;
798 FUNCTION_EXIT();
800 return SP_RETURN_FOUND;
801 }
803 /* called in dump mode */
804 static ULONG
805 XenVbd_HwStorFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
806 {
807 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
809 UNREFERENCED_PARAMETER(HwContext);
810 UNREFERENCED_PARAMETER(BusInformation);
811 UNREFERENCED_PARAMETER(ArgumentString);
813 FUNCTION_ENTER();
814 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
815 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
817 memcpy(xvdd, ConfigInfo->Reserved, FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data));
818 xvdd->aligned_buffer_in_use = FALSE;
819 /* align the buffer to PAGE_SIZE */
820 xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
821 KdPrint((__DRIVER_NAME " aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
822 KdPrint((__DRIVER_NAME " aligned_buffer = %p\n", xvdd->aligned_buffer));
824 ConfigInfo->MaximumTransferLength = 4 * 1024 * 1024;
825 ConfigInfo->NumberOfPhysicalBreaks = ConfigInfo->MaximumTransferLength >> PAGE_SHIFT;
826 FUNCTION_MSG("ConfigInfo->MaximumTransferLength = %d\n", ConfigInfo->MaximumTransferLength);
827 FUNCTION_MSG("ConfigInfo->NumberOfPhysicalBreaks = %d\n", ConfigInfo->NumberOfPhysicalBreaks);
828 ConfigInfo->VirtualDevice = FALSE;
829 xvdd->aligned_buffer_size = DUMP_MODE_UNALIGNED_PAGES * PAGE_SIZE;
830 ConfigInfo->ScatterGather = TRUE;
831 ConfigInfo->Master = TRUE;
832 ConfigInfo->CachesData = FALSE;
833 ConfigInfo->MapBuffers = STOR_MAP_ALL_BUFFERS;
834 FUNCTION_MSG("ConfigInfo->NeedPhysicalAddresses = %d\n", ConfigInfo->NeedPhysicalAddresses);
835 ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
836 ConfigInfo->AlignmentMask = 0;
837 ConfigInfo->NumberOfBuses = 1;
838 ConfigInfo->InitiatorBusId[0] = 1;
839 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
840 ConfigInfo->MaximumNumberOfTargets = 2;
841 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) {
842 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
843 FUNCTION_MSG("Dma64BitAddresses supported\n");
844 } else {
845 FUNCTION_MSG("Dma64BitAddresses not supported\n");
846 }
847 *Again = FALSE;
849 FUNCTION_EXIT();
851 return SP_RETURN_FOUND;
852 }
854 /* Called at PASSIVE_LEVEL for non-dump mode */
855 static BOOLEAN
856 XenVbd_HwStorInitialize(PVOID DeviceExtension)
857 {
858 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
859 int i;
861 FUNCTION_ENTER();
862 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
863 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
865 xvdd->shadow_free = 0;
866 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
867 for (i = 0; i < SHADOW_ENTRIES; i++) {
868 xvdd->shadows[i].req.id = i;
869 /* make sure leftover real requests's are never confused with dump mode requests */
870 if (dump_mode)
871 xvdd->shadows[i].req.id |= SHADOW_ID_DUMP_FLAG;
872 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
873 }
875 if (!dump_mode) {
876 StorPortInitializeDpc(DeviceExtension, &xvdd->dpc, XenVbd_HandleEventDpc);
877 } else {
878 xvdd->grant_tag = (ULONG)'DUMP';
879 }
881 FUNCTION_EXIT();
883 return TRUE;
884 }
886 static ULONG
887 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
888 {
889 PMODE_PARAMETER_HEADER parameter_header = NULL;
890 PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
891 PMODE_PARAMETER_BLOCK param_block;
892 PMODE_FORMAT_PAGE format_page;
893 ULONG offset = 0;
894 UCHAR buffer[1024];
895 BOOLEAN valid_page = FALSE;
896 BOOLEAN cdb_llbaa;
897 BOOLEAN cdb_dbd;
898 UCHAR cdb_page_code;
899 USHORT cdb_allocation_length;
901 UNREFERENCED_PARAMETER(xvdd);
903 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
904 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
905 offset = 0;
907 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
909 switch (srb->Cdb[0])
910 {
911 case SCSIOP_MODE_SENSE:
912 cdb_llbaa = FALSE;
913 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
914 cdb_page_code = srb->Cdb[2] & 0x3f;
915 cdb_allocation_length = srb->Cdb[4];
916 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
917 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
918 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
919 parameter_header->MediumType = 0;
920 parameter_header->DeviceSpecificParameter = 0;
921 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
922 {
923 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
924 parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
925 }
926 offset += sizeof(MODE_PARAMETER_HEADER);
927 break;
928 case SCSIOP_MODE_SENSE10:
929 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
930 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
931 cdb_page_code = srb->Cdb[2] & 0x3f;
932 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
933 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
934 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
935 parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
936 parameter_header10->MediumType = 0;
937 parameter_header10->DeviceSpecificParameter = 0;
938 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
939 {
940 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
941 parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
942 }
943 offset += sizeof(MODE_PARAMETER_HEADER10);
944 break;
945 default:
946 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
947 return FALSE;
948 }
950 if (!cdb_dbd)
951 {
952 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
953 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
954 {
955 if (xvdd->total_sectors >> 32)
956 {
957 param_block->DensityCode = 0xff;
958 param_block->NumberOfBlocks[0] = 0xff;
959 param_block->NumberOfBlocks[1] = 0xff;
960 param_block->NumberOfBlocks[2] = 0xff;
961 }
962 else
963 {
964 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
965 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
966 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
967 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
968 }
969 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
970 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
971 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
972 }
973 offset += sizeof(MODE_PARAMETER_BLOCK);
974 }
975 switch (srb->Cdb[0])
976 {
977 case SCSIOP_MODE_SENSE:
978 parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
979 break;
980 case SCSIOP_MODE_SENSE10:
981 parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
982 parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
983 break;
984 }
985 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
986 {
987 valid_page = TRUE;
988 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
989 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
990 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
991 /* 256 sectors per track */
992 format_page->SectorsPerTrack[0] = 0x01;
993 format_page->SectorsPerTrack[1] = 0x00;
994 /* xxx bytes per sector */
995 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
996 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
997 format_page->HardSectorFormating = TRUE;
998 format_page->SoftSectorFormating = TRUE;
999 offset += sizeof(MODE_FORMAT_PAGE);
1001 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL))
1003 PMODE_CACHING_PAGE caching_page;
1004 valid_page = TRUE;
1005 caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
1006 caching_page->PageCode = MODE_PAGE_CACHING;
1007 caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
1008 // caching_page-> // all zeros is just fine... maybe
1009 offset += sizeof(MODE_CACHING_PAGE);
1011 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL))
1013 PUCHAR medium_types_page;
1014 valid_page = TRUE;
1015 medium_types_page = &buffer[offset];
1016 medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
1017 medium_types_page[1] = 0x06;
1018 medium_types_page[2] = 0;
1019 medium_types_page[3] = 0;
1020 medium_types_page[4] = 0;
1021 medium_types_page[5] = 0;
1022 medium_types_page[6] = 0;
1023 medium_types_page[7] = 0;
1024 offset += 8;
1026 switch (srb->Cdb[0])
1028 case SCSIOP_MODE_SENSE:
1029 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
1030 break;
1031 case SCSIOP_MODE_SENSE10:
1032 parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
1033 parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
1034 break;
1037 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
1039 srb->SrbStatus = SRB_STATUS_ERROR;
1041 else if(offset < srb->DataTransferLength)
1042 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1043 else
1044 srb->SrbStatus = SRB_STATUS_SUCCESS;
1045 srb->DataTransferLength = min(srb->DataTransferLength, offset);
1046 srb->ScsiStatus = 0;
1047 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
1049 //FUNCTION_EXIT();
1051 return TRUE;
1054 static ULONG
1055 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
1057 PSENSE_DATA sd = srb->SenseInfoBuffer;
1059 UNREFERENCED_PARAMETER(xvdd);
1061 if (!srb->SenseInfoBuffer)
1062 return 0;
1064 sd->ErrorCode = 0x70;
1065 sd->Valid = 1;
1066 sd->SenseKey = sense_key;
1067 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
1068 sd->AdditionalSenseCode = additional_sense_code;
1069 return sizeof(SENSE_DATA);
1072 static VOID
1073 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
1075 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
1076 return;
1077 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1078 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1081 /* called with StartIo lock held */
1082 static VOID
1083 XenVbd_HandleEvent(PVOID DeviceExtension)
1085 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
1086 PSCSI_REQUEST_BLOCK srb;
1087 RING_IDX i, rp;
1088 ULONG j;
1089 blkif_response_t *rep;
1090 //int block_count;
1091 int more_to_do = TRUE;
1092 blkif_shadow_t *shadow;
1093 //ULONG suspend_resume_state_pdo;
1094 srb_list_entry_t *srb_entry;
1096 //if (dump_mode) FUNCTION_ENTER();
1098 #if 0
1099 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
1100 KeMemoryBarrier();
1102 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
1104 //FUNCTION_ENTER();
1105 switch (suspend_resume_state_pdo)
1107 case SR_STATE_SUSPENDING:
1108 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
1109 break;
1110 case SR_STATE_RESUMING:
1111 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
1112 XenVbd_InitFromConfig(xvdd);
1113 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
1114 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
1115 break;
1116 case SR_STATE_RUNNING:
1117 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
1118 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
1119 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
1120 default:
1121 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
1122 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
1123 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
1124 break;
1126 KeMemoryBarrier();
1128 #endif
1130 #if 0
1131 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
1133 return TRUE;
1135 #endif
1137 while (more_to_do)
1139 rp = xvdd->ring.sring->rsp_prod;
1140 KeMemoryBarrier();
1141 for (i = xvdd->ring.rsp_cons; i != rp; i++)
1143 rep = XenVbd_GetResponse(xvdd, i);
1144 shadow = &xvdd->shadows[rep->id & SHADOW_ID_ID_MASK];
1145 if (shadow->reset)
1147 KdPrint((__DRIVER_NAME " discarding reset shadow\n"));
1148 for (j = 0; j < shadow->req.nr_segments; j++)
1150 XnEndAccess(xvdd->handle,
1151 shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
1154 else if (dump_mode && !(rep->id & SHADOW_ID_DUMP_FLAG))
1156 KdPrint((__DRIVER_NAME " discarding stale (non-dump-mode) shadow\n"));
1158 else
1160 srb = shadow->srb;
1161 NT_ASSERT(srb);
1162 srb_entry = srb->SrbExtension;
1163 NT_ASSERT(srb_entry);
1164 /* 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 */
1165 if (rep->status == BLKIF_RSP_OKAY || (dump_mode && dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
1166 srb->SrbStatus = SRB_STATUS_SUCCESS;
1167 else
1169 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
1170 if (decode_cdb_is_read(srb))
1171 KdPrint((__DRIVER_NAME " Operation = Read\n"));
1172 else
1173 KdPrint((__DRIVER_NAME " Operation = Write\n"));
1174 srb_entry->error = TRUE;
1176 if (shadow->aligned_buffer_in_use)
1178 NT_ASSERT(xvdd->aligned_buffer_in_use);
1179 xvdd->aligned_buffer_in_use = FALSE;
1180 if (srb->SrbStatus == SRB_STATUS_SUCCESS && decode_cdb_is_read(srb))
1181 memcpy((PUCHAR)shadow->system_address, xvdd->aligned_buffer, shadow->length);
1183 for (j = 0; j < shadow->req.nr_segments; j++)
1185 XnEndAccess(xvdd->handle, shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
1187 srb_entry->outstanding_requests--;
1188 if (!srb_entry->outstanding_requests && srb_entry->offset == srb_entry->length)
1190 if (srb_entry->error)
1192 srb->SrbStatus = SRB_STATUS_ERROR;
1193 srb->ScsiStatus = 0x02;
1194 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
1195 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1196 XenVbd_MakeAutoSense(xvdd, srb);
1198 StorPortNotification(RequestComplete, xvdd, srb);
1201 put_shadow_on_freelist(xvdd, shadow);
1204 xvdd->ring.rsp_cons = i;
1205 if (i != xvdd->ring.req_prod_pvt)
1207 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
1209 else
1211 xvdd->ring.sring->rsp_event = i + 1;
1212 more_to_do = FALSE;
1216 XenVbd_ProcessSrbList(xvdd);
1217 #if 0
1218 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
1220 if ((xvdd->vbd_status == VBD_STATUS_ACTIVE) || xvdd->shadow_free == SHADOW_ENTRIES)
1222 /* all entries are purged from the list (or we are inactive). ready to suspend */
1223 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
1224 KeMemoryBarrier();
1225 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
1226 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
1227 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
1230 //if (dump_mode) FUNCTION_EXIT();
1231 #endif
1232 return;
1235 static VOID
1236 XenVbd_HandleEventDpc(PSTOR_DPC dpc, PVOID DeviceExtension, PVOID arg1, PVOID arg2) {
1237 STOR_LOCK_HANDLE lock_handle;
1238 UNREFERENCED_PARAMETER(dpc);
1239 UNREFERENCED_PARAMETER(arg1);
1240 UNREFERENCED_PARAMETER(arg2);
1242 StorPortAcquireSpinLock(DeviceExtension, StartIoLock, NULL, &lock_handle);
1243 XenVbd_HandleEvent(DeviceExtension);
1244 StorPortReleaseSpinLock(DeviceExtension, &lock_handle);
1247 static VOID
1248 XenVbd_HandleEventDIRQL(PVOID DeviceExtension) {
1249 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1250 //if (dump_mode) FUNCTION_ENTER();
1251 StorPortIssueDpc(DeviceExtension, &xvdd->dpc, NULL, NULL);
1252 //if (dump_mode) FUNCTION_EXIT();
1253 return;
1256 /* this is only used during hiber and dump */
1257 static BOOLEAN
1258 XenVbd_HwStorInterrupt(PVOID DeviceExtension)
1260 //FUNCTION_ENTER();
1261 XenVbd_HandleEvent(DeviceExtension);
1262 //FUNCTION_EXIT();
1263 return TRUE;
1266 static BOOLEAN
1267 XenVbd_HwStorResetBus(PVOID DeviceExtension, ULONG PathId)
1269 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1270 //srb_list_entry_t *srb_entry;
1271 int i;
1272 /* need to make sure that each SRB is only reset once */
1273 LIST_ENTRY srb_reset_list;
1274 PLIST_ENTRY list_entry;
1275 //STOR_LOCK_HANDLE lock_handle;
1277 UNREFERENCED_PARAMETER(PathId);
1279 FUNCTION_ENTER();
1281 if (dump_mode) {
1282 FUNCTION_MSG("dump mode - doing nothing\n");
1283 FUNCTION_EXIT();
1284 return TRUE;
1287 /* It appears that the StartIo spinlock is already held at this point */
1289 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1291 // if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1292 // {
1293 xvdd->aligned_buffer_in_use = FALSE;
1295 InitializeListHead(&srb_reset_list);
1297 while((list_entry = RemoveHeadList(&xvdd->srb_list)) != &xvdd->srb_list) {
1298 #if DBG
1299 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
1300 KdPrint((__DRIVER_NAME " adding queued SRB %p to reset list\n", srb_entry->srb));
1301 #endif
1302 InsertTailList(&srb_reset_list, list_entry);
1305 for (i = 0; i < MAX_SHADOW_ENTRIES; i++) {
1306 if (xvdd->shadows[i].srb) {
1307 srb_list_entry_t *srb_entry = xvdd->shadows[i].srb->SrbExtension;
1308 for (list_entry = srb_reset_list.Flink; list_entry != &srb_reset_list; list_entry = list_entry->Flink) {
1309 if (list_entry == &srb_entry->list_entry)
1310 break;
1312 if (list_entry == &srb_reset_list) {
1313 KdPrint((__DRIVER_NAME " adding in-flight SRB %p to reset list\n", srb_entry->srb));
1314 InsertTailList(&srb_reset_list, &srb_entry->list_entry);
1316 /* set reset here so that the interrupt won't do anything with the srb but will dispose of the shadow entry correctly */
1317 xvdd->shadows[i].reset = TRUE;
1318 xvdd->shadows[i].srb = NULL;
1319 xvdd->shadows[i].aligned_buffer_in_use = FALSE;
1323 while((list_entry = RemoveHeadList(&srb_reset_list)) != &srb_reset_list) {
1324 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
1325 srb_entry->srb->SrbStatus = SRB_STATUS_BUS_RESET;
1326 KdPrint((__DRIVER_NAME " completing SRB %p with status SRB_STATUS_BUS_RESET\n", srb_entry->srb));
1327 StorPortNotification(RequestComplete, xvdd, srb_entry->srb);
1330 /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen normally but could in dump mode) */
1331 XnNotify(xvdd->handle, xvdd->event_channel);
1333 StorPortNotification(NextRequest, DeviceExtension);
1334 // }
1336 //StorPortReleaseSpinLock(DeviceExtension, &lock_handle);
1338 FUNCTION_EXIT();
1340 return TRUE;
1343 /* called with StartIo lock held */
1344 VOID
1345 XenVbd_ProcessSrbList(PXENVBD_DEVICE_DATA xvdd) {
1346 PUCHAR data_buffer;
1347 PSCSI_PNP_REQUEST_BLOCK sprb;
1348 PSCSI_POWER_REQUEST_BLOCK spwrb;
1349 PMINIPORT_DUMP_POINTERS dump_pointers;
1350 PCDB cdb;
1351 ULONG data_transfer_length;
1352 UCHAR srb_status = SRB_STATUS_PENDING;
1353 BOOLEAN notify = FALSE;
1354 PSCSI_REQUEST_BLOCK srb;
1355 srb_list_entry_t *srb_entry;
1357 if (xvdd->vbd_status != VBD_STATUS_ACTIVE) {
1358 FUNCTION_MSG("Not yet active\n");
1359 return;
1362 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) {
1363 srb = srb_entry->srb;
1365 if (xvdd->vbd_status == VBD_STATUS_INACTIVE) {
1366 /* need to check again as may have been initialising when this srb was put on the list */
1367 FUNCTION_MSG("HwStorStartIo Inactive Device (in ProcessSrbList)\n");
1368 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1369 StorPortNotification(RequestComplete, xvdd, srb);
1370 continue;
1373 data_transfer_length = srb->DataTransferLength;
1375 switch (srb->Function)
1377 case SRB_FUNCTION_EXECUTE_SCSI:
1378 cdb = (PCDB)srb->Cdb;
1380 switch(cdb->CDB6GENERIC.OperationCode)
1382 case SCSIOP_TEST_UNIT_READY:
1383 if (dump_mode)
1384 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1385 srb_status = SRB_STATUS_SUCCESS;
1386 srb->ScsiStatus = 0;
1387 break;
1388 case SCSIOP_INQUIRY:
1389 if (dump_mode)
1390 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1391 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
1392 // KdPrint((__DRIVER_NAME " (Length = %d)\n", srb->DataTransferLength));
1394 data_buffer = srb->DataBuffer;
1395 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1396 srb_status = SRB_STATUS_SUCCESS;
1397 switch (xvdd->device_type)
1399 case XENVBD_DEVICETYPE_DISK:
1400 if ((srb->Cdb[1] & 1) == 0) {
1401 if (srb->Cdb[2]) {
1402 srb_status = SRB_STATUS_ERROR;
1403 } else {
1404 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1405 id->DeviceType = DIRECT_ACCESS_DEVICE;
1406 id->Versions = 5; /* SPC-3 */
1407 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
1408 id->HiSupport = 1; /* WHQL test says we should set this */
1409 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1410 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
1411 id->CommandQueue = 1;
1412 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1413 memcpy(id->ProductId, scsi_disk_model, 16); // product id
1414 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1415 data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
1417 } else {
1418 switch (srb->Cdb[2]) {
1419 case VPD_SUPPORTED_PAGES: /* list of pages we support */
1420 FUNCTION_MSG("VPD_SUPPORTED_PAGES\n");
1421 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1422 data_buffer[1] = VPD_SUPPORTED_PAGES;
1423 data_buffer[2] = 0x00;
1424 data_buffer[3] = 4;
1425 data_buffer[4] = VPD_SUPPORTED_PAGES;
1426 data_buffer[5] = VPD_SERIAL_NUMBER;
1427 data_buffer[6] = VPD_DEVICE_IDENTIFIERS;
1428 data_buffer[7] = VPD_BLOCK_LIMITS;
1429 data_transfer_length = 8;
1430 break;
1431 case VPD_SERIAL_NUMBER: /* serial number */
1432 FUNCTION_MSG("VPD_SERIAL_NUMBER\n");
1433 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1434 data_buffer[1] = VPD_SERIAL_NUMBER;
1435 data_buffer[2] = 0x00;
1436 data_buffer[3] = 8;
1437 memset(&data_buffer[4], ' ', 8);
1438 data_transfer_length = 12;
1439 break;
1440 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
1441 FUNCTION_MSG("VPD_DEVICE_IDENTIFIERS\n");
1442 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1443 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
1444 data_buffer[2] = 0x00;
1445 //data_buffer[3] = 4 + (UCHAR)strlen(xvdd->vectors.path); /* length */
1446 data_buffer[4] = 2; /* ASCII */
1447 data_buffer[5] = 1; /* VendorId */
1448 data_buffer[6] = 0;
1449 //data_buffer[7] = (UCHAR)strlen(xvdd->vectors.path);
1450 //memcpy(&data_buffer[8], xvdd->vectors.path, strlen(xvdd->vectors.path));
1451 //data_transfer_length = (ULONG)(8 + strlen(xvdd->vectors.path));
1452 break;
1453 case VPD_BLOCK_LIMITS: /* to indicate support for UNMAP (TRIM/DISCARD) */
1454 FUNCTION_MSG("VPD_BLOCK_LIMITS\n");
1455 // max descriptors = 1
1456 // max sectors = 0xFFFFFFFF
1457 // granularity = from xenbus
1458 // alignment = from xenbus(?)
1459 srb_status = SRB_STATUS_ERROR;
1460 break;
1461 default:
1462 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
1463 srb_status = SRB_STATUS_ERROR;
1464 break;
1467 break;
1468 case XENVBD_DEVICETYPE_CDROM:
1469 if ((srb->Cdb[1] & 1) == 0)
1471 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1472 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1473 id->RemovableMedia = 1;
1474 id->Versions = 3;
1475 id->ResponseDataFormat = 0;
1476 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1477 id->CommandQueue = 1;
1478 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1479 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1480 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1481 data_transfer_length = sizeof(INQUIRYDATA);
1483 else
1485 switch (srb->Cdb[2])
1487 case 0x00:
1488 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1489 data_buffer[1] = 0x00;
1490 data_buffer[2] = 0x00;
1491 data_buffer[3] = 2;
1492 data_buffer[4] = 0x00;
1493 data_buffer[5] = 0x80;
1494 data_transfer_length = 6;
1495 break;
1496 case 0x80:
1497 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1498 data_buffer[1] = 0x80;
1499 data_buffer[2] = 0x00;
1500 data_buffer[3] = 8;
1501 data_buffer[4] = 0x31;
1502 data_buffer[5] = 0x32;
1503 data_buffer[6] = 0x33;
1504 data_buffer[7] = 0x34;
1505 data_buffer[8] = 0x35;
1506 data_buffer[9] = 0x36;
1507 data_buffer[10] = 0x37;
1508 data_buffer[11] = 0x38;
1509 data_transfer_length = 12;
1510 break;
1511 default:
1512 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
1513 srb_status = SRB_STATUS_ERROR;
1514 break;
1517 break;
1518 default:
1519 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1520 srb_status = SRB_STATUS_ERROR;
1521 break;
1523 break;
1524 case SCSIOP_READ_CAPACITY:
1525 //if (dump_mode)
1526 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1527 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1528 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1529 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1530 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1531 data_buffer = srb->DataBuffer;
1532 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1533 if ((xvdd->total_sectors - 1) >> 32)
1535 data_buffer[0] = 0xff;
1536 data_buffer[1] = 0xff;
1537 data_buffer[2] = 0xff;
1538 data_buffer[3] = 0xff;
1540 else
1542 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1543 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1544 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1545 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1547 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1548 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1549 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1550 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1551 data_transfer_length = 8;
1552 srb->ScsiStatus = 0;
1553 srb_status = SRB_STATUS_SUCCESS;
1554 break;
1555 case SCSIOP_READ_CAPACITY16:
1556 //if (dump_mode)
1557 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY16\n"));
1558 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1559 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1560 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1561 data_buffer = srb->DataBuffer;
1562 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1563 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1564 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1565 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1566 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1567 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1568 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1569 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1570 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1571 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1572 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1573 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1574 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1575 data_buffer[12] = 0;
1576 switch (xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector) {
1577 case 1:
1578 data_buffer[13] = 0; /* 512 byte hardware sectors */
1579 break;
1580 case 2:
1581 data_buffer[13] = 1; /* 1024 byte hardware sectors */
1582 break;
1583 case 3:
1584 data_buffer[13] = 2; /* 2048 byte hardware sectors */
1585 break;
1586 case 4:
1587 data_buffer[13] = 3; /* 4096 byte hardware sectors */
1588 break;
1589 default:
1590 data_buffer[13] = 0; /* 512 byte hardware sectors */
1591 KdPrint((__DRIVER_NAME " Unknown logical blocks per physical block %d (%d / %d)\n", xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector, xvdd->hw_bytes_per_sector, xvdd->bytes_per_sector));
1592 break;
1594 data_buffer[14] = 0xC0; //0;
1595 data_buffer[15] = 0;
1596 data_transfer_length = 16;
1597 srb->ScsiStatus = 0;
1598 srb_status = SRB_STATUS_SUCCESS;
1599 break;
1600 case SCSIOP_MODE_SENSE:
1601 case SCSIOP_MODE_SENSE10:
1602 if (dump_mode)
1603 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));
1604 data_transfer_length = XenVbd_FillModePage(xvdd, srb);
1605 srb_status = SRB_STATUS_SUCCESS;
1606 break;
1607 case SCSIOP_READ:
1608 case SCSIOP_READ16:
1609 case SCSIOP_WRITE:
1610 case SCSIOP_WRITE16:
1611 //FUNCTION_MSG("srb = %p\n", srb);
1612 if (XenVbd_PutSrbOnRing(xvdd, srb)) {
1613 notify = TRUE;
1615 break;
1616 case SCSIOP_WRITE_SAME:
1617 case SCSIOP_WRITE_SAME16:
1618 /* not yet supported */
1619 FUNCTION_MSG("WRITE_SAME\n");
1620 break;
1621 case SCSIOP_UNMAP:
1622 /* not yet supported */
1623 FUNCTION_MSG("UNMAP\n");
1624 break;
1625 case SCSIOP_VERIFY:
1626 case SCSIOP_VERIFY16:
1627 // Should we do more here?
1628 if (dump_mode)
1629 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1630 srb_status = SRB_STATUS_SUCCESS;
1631 break;
1632 case SCSIOP_REPORT_LUNS:
1633 //if (dump_mode)
1634 FUNCTION_MSG("Command = REPORT_LUNS\n");
1635 switch (srb->Cdb[2]) {
1636 case 1:
1637 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
1638 break;
1639 default:
1640 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
1641 break;
1643 FUNCTION_MSG(" ALLOCATION LENGTH = %d\n", (srb->Cdb[6] << 24)|(srb->Cdb[7] << 16)|(srb->Cdb[8] << 8)|(srb->Cdb[9]));
1644 data_buffer = srb->DataBuffer;
1645 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1646 data_buffer[3] = 8; /* 1 lun */
1647 /* rest of the data is blank */
1648 data_transfer_length = 16;
1649 srb->ScsiStatus = 0;
1650 srb_status = SRB_STATUS_SUCCESS;
1651 break;
1652 case SCSIOP_REQUEST_SENSE:
1653 if (dump_mode)
1654 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1655 data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1656 srb_status = SRB_STATUS_SUCCESS;
1657 break;
1658 case SCSIOP_READ_TOC:
1659 if (dump_mode)
1660 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1661 data_buffer = srb->DataBuffer;
1662 /*
1663 #define READ_TOC_FORMAT_TOC 0x00
1664 #define READ_TOC_FORMAT_SESSION 0x01
1665 #define READ_TOC_FORMAT_FULL_TOC 0x02
1666 #define READ_TOC_FORMAT_PMA 0x03
1667 #define READ_TOC_FORMAT_ATIP 0x04
1668 */
1669 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1670 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1671 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1672 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1673 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1674 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1675 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1676 switch (cdb->READ_TOC.Format2)
1678 case READ_TOC_FORMAT_TOC:
1679 data_buffer[0] = 0; // length MSB
1680 data_buffer[1] = 10; // length LSB
1681 data_buffer[2] = 1; // First Track
1682 data_buffer[3] = 1; // Last Track
1683 data_buffer[4] = 0; // Reserved
1684 data_buffer[5] = 0x14; // current position data + uninterrupted data
1685 data_buffer[6] = 1; // last complete track
1686 data_buffer[7] = 0; // reserved
1687 data_buffer[8] = 0; // MSB Block
1688 data_buffer[9] = 0;
1689 data_buffer[10] = 0;
1690 data_buffer[11] = 0; // LSB Block
1691 data_transfer_length = 12;
1692 srb_status = SRB_STATUS_SUCCESS;
1693 break;
1694 case READ_TOC_FORMAT_SESSION:
1695 case READ_TOC_FORMAT_FULL_TOC:
1696 case READ_TOC_FORMAT_PMA:
1697 case READ_TOC_FORMAT_ATIP:
1698 srb_status = SRB_STATUS_ERROR;
1699 break;
1700 default:
1701 srb_status = SRB_STATUS_ERROR;
1702 break;
1704 break;
1705 case SCSIOP_START_STOP_UNIT:
1706 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1707 srb_status = SRB_STATUS_SUCCESS;
1708 break;
1709 case SCSIOP_RESERVE_UNIT:
1710 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1711 srb_status = SRB_STATUS_SUCCESS;
1712 break;
1713 case SCSIOP_RELEASE_UNIT:
1714 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1715 srb_status = SRB_STATUS_SUCCESS;
1716 break;
1717 default:
1718 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
1719 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1720 srb_status = SRB_STATUS_ERROR;
1721 break;
1723 if (srb_status == SRB_STATUS_ERROR)
1725 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
1726 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1728 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1729 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1731 srb->SrbStatus = srb_status;
1732 srb->ScsiStatus = 0x02;
1733 XenVbd_MakeAutoSense(xvdd, srb);
1734 StorPortNotification(RequestComplete, xvdd, srb);
1736 else if (srb_status != SRB_STATUS_PENDING)
1738 if (data_transfer_length > srb->DataTransferLength)
1739 KdPrint((__DRIVER_NAME " data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength));
1741 if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
1743 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1744 srb->DataTransferLength = data_transfer_length;
1746 else
1748 srb->SrbStatus = srb_status;
1750 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1751 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1752 StorPortNotification(RequestComplete, xvdd, srb);
1754 break;
1755 case SRB_FUNCTION_IO_CONTROL:
1756 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1757 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1758 StorPortNotification(RequestComplete, xvdd, srb);
1759 break;
1760 case SRB_FUNCTION_FLUSH:
1761 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1762 srb->SrbStatus = SRB_STATUS_SUCCESS;
1763 StorPortNotification(RequestComplete, xvdd, srb);
1764 break;
1765 case SRB_FUNCTION_PNP:
1766 KdPrint((__DRIVER_NAME " SRB_FUNCTION_PNP\n"));
1767 sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
1768 switch (sprb->PnPAction)
1770 case StorStartDevice:
1771 KdPrint((__DRIVER_NAME " StorStartDevice\n"));
1772 break;
1773 case StorRemoveDevice:
1774 KdPrint((__DRIVER_NAME " StorRemoveDevice\n"));
1775 break;
1776 case StorStopDevice:
1777 KdPrint((__DRIVER_NAME " StorStopDevice\n"));
1778 break;
1779 case StorQueryCapabilities:
1780 KdPrint((__DRIVER_NAME " StorQueryCapabilities\n"));
1781 break;
1782 case StorFilterResourceRequirements:
1783 KdPrint((__DRIVER_NAME " StorFilterResourceRequirements\n"));
1784 break;
1785 default:
1786 KdPrint((__DRIVER_NAME " Stor%d\n", sprb->PnPAction));
1787 break;
1789 KdPrint((__DRIVER_NAME " SrbPnPFlags = %08x\n", sprb->SrbPnPFlags));
1790 srb->SrbStatus = SRB_STATUS_SUCCESS;
1791 StorPortNotification(RequestComplete, xvdd, srb);
1792 break;
1794 case SRB_FUNCTION_POWER:
1795 KdPrint((__DRIVER_NAME " SRB_FUNCTION_POWER\n"));
1796 spwrb = (PSCSI_POWER_REQUEST_BLOCK)srb;
1797 switch (spwrb->PowerAction)
1799 case StorPowerActionNone:
1800 KdPrint((__DRIVER_NAME " StorPowerActionNone\n"));
1801 break;
1802 case StorPowerActionReserved:
1803 KdPrint((__DRIVER_NAME " StorPowerActionReserved\n"));
1804 break;
1805 case StorPowerActionSleep:
1806 KdPrint((__DRIVER_NAME " StorPowerActionSleep\n"));
1807 break;
1808 case StorPowerActionHibernate:
1809 KdPrint((__DRIVER_NAME " StorPowerActionHibernate\n"));
1810 break;
1811 case StorPowerActionShutdown:
1812 KdPrint((__DRIVER_NAME " StorPowerActionShutdown\n"));
1813 break;
1814 case StorPowerActionShutdownReset:
1815 KdPrint((__DRIVER_NAME " StorPowerActionShutdownReset\n"));
1816 break;
1817 case StorPowerActionShutdownOff:
1818 KdPrint((__DRIVER_NAME " StorPowerActionShutdownOff\n"));
1819 break;
1820 case StorPowerActionWarmEject:
1821 KdPrint((__DRIVER_NAME " StorPowerActionWarmEject\n"));
1822 break;
1823 default:
1824 KdPrint((__DRIVER_NAME " Stor%d\n", spwrb->PowerAction));
1825 break;
1827 srb->SrbStatus = SRB_STATUS_SUCCESS;
1828 StorPortNotification(RequestComplete, xvdd, srb);
1829 break;
1830 case SRB_FUNCTION_DUMP_POINTERS:
1831 KdPrint((__DRIVER_NAME " SRB_FUNCTION_DUMP_POINTERS\n"));
1832 KdPrint((__DRIVER_NAME " DataTransferLength = %d\n", srb->DataTransferLength));
1833 dump_pointers = srb->DataBuffer;
1834 KdPrint((__DRIVER_NAME " Version = %d\n", dump_pointers->Version));
1835 KdPrint((__DRIVER_NAME " Size = %d\n", dump_pointers->Size));
1836 KdPrint((__DRIVER_NAME " DriverName = %S\n", dump_pointers->DriverName));
1837 KdPrint((__DRIVER_NAME " AdapterObject = %p\n", dump_pointers->AdapterObject));
1838 KdPrint((__DRIVER_NAME " MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
1839 KdPrint((__DRIVER_NAME " CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
1840 KdPrint((__DRIVER_NAME " MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
1841 KdPrint((__DRIVER_NAME " SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
1842 KdPrint((__DRIVER_NAME " AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
1843 KdPrint((__DRIVER_NAME " MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
1844 KdPrint((__DRIVER_NAME " NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
1845 KdPrint((__DRIVER_NAME " AlignmentMask = %d\n", dump_pointers->AlignmentMask));
1846 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
1847 KdPrint((__DRIVER_NAME " NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
1848 KdPrint((__DRIVER_NAME " Master = %d\n", dump_pointers->Master));
1849 KdPrint((__DRIVER_NAME " MapBuffers = %d\n", dump_pointers->MapBuffers));
1850 KdPrint((__DRIVER_NAME " MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
1852 dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
1853 dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
1854 RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
1855 dump_pointers->AdapterObject = NULL;
1856 dump_pointers->MappedRegisterBase = 0;
1857 dump_pointers->CommonBufferSize = 0;
1858 dump_pointers->MiniportPrivateDumpData = xvdd;
1859 dump_pointers->AdapterInterfaceType = Internal;
1860 dump_pointers->MaximumTransferLength = 4 * 1024 * 1024; //BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;;
1861 dump_pointers->NumberOfPhysicalBreaks = dump_pointers->MaximumTransferLength >> PAGE_SHIFT; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
1862 dump_pointers->AlignmentMask = 0;
1863 dump_pointers->NumberOfAccessRanges = 1;
1864 dump_pointers->NumberOfBuses = 1;
1865 dump_pointers->Master = TRUE;
1866 dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
1867 dump_pointers->MaximumNumberOfTargets = 2;
1869 KdPrint((__DRIVER_NAME " Version = %d\n", dump_pointers->Version));
1870 KdPrint((__DRIVER_NAME " Size = %d\n", dump_pointers->Size));
1871 //KdPrint((__DRIVER_NAME " DriverName = %S\n", dump_pointers->DriverName));
1872 KdPrint((__DRIVER_NAME " AdapterObject = %p\n", dump_pointers->AdapterObject));
1873 KdPrint((__DRIVER_NAME " MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase));
1874 KdPrint((__DRIVER_NAME " CommonBufferSize = %d\n", dump_pointers->CommonBufferSize));
1875 KdPrint((__DRIVER_NAME " MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData));
1876 KdPrint((__DRIVER_NAME " SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber));
1877 KdPrint((__DRIVER_NAME " AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType));
1878 KdPrint((__DRIVER_NAME " MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength));
1879 KdPrint((__DRIVER_NAME " NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks));
1880 KdPrint((__DRIVER_NAME " AlignmentMask = %d\n", dump_pointers->AlignmentMask));
1881 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges));
1882 KdPrint((__DRIVER_NAME " NumberOfBuses = %d\n", dump_pointers->NumberOfBuses));
1883 KdPrint((__DRIVER_NAME " Master = %d\n", dump_pointers->Master));
1884 KdPrint((__DRIVER_NAME " MapBuffers = %d\n", dump_pointers->MapBuffers));
1885 KdPrint((__DRIVER_NAME " MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets));
1887 srb->SrbStatus = SRB_STATUS_SUCCESS;
1888 StorPortNotification(RequestComplete, xvdd, srb);
1889 break;
1890 case SRB_FUNCTION_SHUTDOWN:
1891 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1892 srb->SrbStatus = SRB_STATUS_SUCCESS;
1893 StorPortNotification(RequestComplete, xvdd, srb);
1894 break;
1895 case SRB_FUNCTION_RESET_BUS:
1896 case SRB_FUNCTION_RESET_DEVICE:
1897 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
1898 /* the path doesn't matter here - only ever one device*/
1899 XenVbd_HwStorResetBus(xvdd, 0);
1900 srb->SrbStatus = SRB_STATUS_SUCCESS;
1901 StorPortNotification(RequestComplete, xvdd, srb);
1902 break;
1903 case SRB_FUNCTION_WMI:
1904 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1905 StorPortNotification(RequestComplete, xvdd, srb);
1906 break;
1908 default:
1909 KdPrint((__DRIVER_NAME " Unhandled srb->Function = %08X\n", srb->Function));
1910 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1911 StorPortNotification(RequestComplete, xvdd, srb);
1912 break;
1915 if (notify) {
1916 notify = FALSE;
1917 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
1918 if (notify) {
1919 XnNotify(xvdd->handle, xvdd->event_channel);
1922 return;
1925 static BOOLEAN
1926 XenVbd_HwStorStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
1928 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1929 STOR_LOCK_HANDLE lock_handle;
1931 //if (dump_mode) FUNCTION_ENTER();
1932 //if (dump_mode) KdPrint((__DRIVER_NAME " srb = %p\n", srb));
1934 StorPortAcquireSpinLock(DeviceExtension, StartIoLock, NULL, &lock_handle);
1936 if (xvdd->vbd_status == VBD_STATUS_INACTIVE) {
1937 FUNCTION_MSG("HwStorStartIo Inactive Device (in StartIo)\n");
1938 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1939 StorPortNotification(RequestComplete, DeviceExtension, srb);
1940 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
1941 return TRUE;
1944 if (srb->PathId != 0 || srb->TargetId != 0 || srb->Lun != 0)
1946 FUNCTION_MSG("HwStorStartIo (Out of bounds - PathId = %d, TargetId = %d, Lun = %d)\n", srb->PathId, srb->TargetId, srb->Lun);
1947 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1948 StorPortNotification(RequestComplete, DeviceExtension, srb);
1949 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
1950 return TRUE;
1953 XenVbd_PutSrbOnList(xvdd, srb);
1954 XenVbd_ProcessSrbList(xvdd);
1955 StorPortReleaseSpinLock (DeviceExtension, &lock_handle);
1956 return TRUE;
1959 static SCSI_ADAPTER_CONTROL_STATUS
1960 XenVbd_HwStorAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1962 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1963 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1964 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1965 //KIRQL OldIrql;
1967 FUNCTION_ENTER();
1968 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1969 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
1971 switch (ControlType)
1973 case ScsiQuerySupportedControlTypes:
1974 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1975 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1976 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1977 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1978 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1979 break;
1980 case ScsiStopAdapter:
1981 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1982 if (xvdd->vbd_status == VBD_STATUS_INACTIVE)
1984 KdPrint((__DRIVER_NAME " inactive - nothing to do\n"));
1985 break;
1987 NT_ASSERT(IsListEmpty(&xvdd->srb_list));
1988 NT_ASSERT(xvdd->shadow_free == SHADOW_ENTRIES);
1989 break;
1990 case ScsiRestartAdapter:
1991 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1992 if (xvdd->vbd_status == VBD_STATUS_INACTIVE)
1994 KdPrint((__DRIVER_NAME " inactive - nothing to do\n"));
1995 break;
1997 /* increase the tag every time we stop/start to track where the gref's came from */
1998 xvdd->grant_tag++;
1999 #if 0
2000 if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND) {
2001 #pragma warning(suppress:28159)
2002 KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR)xvdd, 0, 0);
2004 #endif
2005 break;
2006 case ScsiSetBootConfig:
2007 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
2008 break;
2009 case ScsiSetRunningConfig:
2010 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
2011 break;
2012 default:
2013 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
2014 break;
2017 FUNCTION_EXIT();
2019 return Status;
2022 NTSTATUS
2023 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
2025 ULONG status;
2026 VIRTUAL_HW_INITIALIZATION_DATA VHwInitializationData;
2027 HW_INITIALIZATION_DATA HwInitializationData;
2028 OBJECT_ATTRIBUTES oa;
2029 HANDLE service_handle;
2030 UNICODE_STRING param_name;
2031 HANDLE param_handle;
2032 UNICODE_STRING value_name;
2033 CHAR buf[256];
2034 ULONG buf_len;
2035 PKEY_VALUE_PARTIAL_INFORMATION kpv;
2037 FUNCTION_ENTER();
2038 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
2039 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
2041 /* RegistryPath == NULL when we are invoked as a crash dump driver */
2042 if (!RegistryPath)
2044 dump_mode = TRUE;
2047 if (!dump_mode)
2049 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
2050 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
2051 if(!NT_SUCCESS(status))
2053 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
2055 else
2057 RtlInitUnicodeString(&param_name, L"Parameters");
2058 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
2059 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
2060 if(!NT_SUCCESS(status))
2062 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
2064 else
2066 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
2067 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
2068 RtlFillMemory(scsi_disk_model, 16, ' ');
2069 RtlFillMemory(scsi_cdrom_model, 16, ' ');
2071 RtlInitUnicodeString(&value_name, L"Manufacturer");
2072 buf_len = 256;
2073 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
2074 if(NT_SUCCESS(status))
2075 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
2076 else
2077 RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN ");
2079 RtlInitUnicodeString(&value_name, L"Disk_Model");
2080 buf_len = 256;
2081 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
2082 if(NT_SUCCESS(status))
2083 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
2084 else
2085 RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK ");
2087 RtlInitUnicodeString(&value_name, L"CDROM_Model");
2088 buf_len = 256;
2089 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
2090 if(NT_SUCCESS(status))
2091 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
2092 else
2093 RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM ");
2094 ZwClose(param_handle);
2096 ZwClose(service_handle);
2098 RtlZeroMemory(&VHwInitializationData, sizeof(VIRTUAL_HW_INITIALIZATION_DATA));
2099 VHwInitializationData.HwInitializationDataSize = sizeof(VIRTUAL_HW_INITIALIZATION_DATA);
2100 VHwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* maybe should be internal? */
2101 VHwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE;
2102 VHwInitializationData.SpecificLuExtensionSize = 0;
2103 VHwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
2104 VHwInitializationData.NumberOfAccessRanges = 1;
2105 VHwInitializationData.MapBuffers = STOR_MAP_ALL_BUFFERS;
2106 //VHwInitializationData.NeedPhysicalAddresses = TRUE;
2107 VHwInitializationData.TaggedQueuing = TRUE;
2108 VHwInitializationData.AutoRequestSense = TRUE;
2109 VHwInitializationData.MultipleRequestPerLu = TRUE;
2110 VHwInitializationData.ReceiveEvent = TRUE;
2111 VHwInitializationData.PortVersionFlags = 0;
2112 VHwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
2113 VHwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
2114 VHwInitializationData.HwFindAdapter = XenVbd_VirtualHwStorFindAdapter;
2115 VHwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
2116 VHwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
2117 status = StorPortInitialize(DriverObject, RegistryPath, (PHW_INITIALIZATION_DATA)&VHwInitializationData, NULL);
2119 else
2121 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
2122 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
2123 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus; /* not Internal */
2124 HwInitializationData.DeviceExtensionSize = FIELD_OFFSET(XENVBD_DEVICE_DATA, aligned_buffer_data) + UNALIGNED_BUFFER_DATA_SIZE_DUMP_MODE;
2125 HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
2126 HwInitializationData.NumberOfAccessRanges = 1;
2127 HwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
2128 HwInitializationData.NeedPhysicalAddresses = TRUE;
2129 HwInitializationData.TaggedQueuing = FALSE;
2130 HwInitializationData.AutoRequestSense = TRUE;
2131 HwInitializationData.MultipleRequestPerLu = FALSE;
2132 HwInitializationData.ReceiveEvent = TRUE;
2133 HwInitializationData.HwInitialize = XenVbd_HwStorInitialize;
2134 HwInitializationData.HwStartIo = XenVbd_HwStorStartIo;
2135 HwInitializationData.HwFindAdapter = XenVbd_HwStorFindAdapter;
2136 HwInitializationData.HwResetBus = XenVbd_HwStorResetBus;
2137 HwInitializationData.HwAdapterControl = XenVbd_HwStorAdapterControl;
2138 HwInitializationData.HwInterrupt = XenVbd_HwStorInterrupt;
2139 status = StorPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
2142 if(!NT_SUCCESS(status)) {
2143 FUNCTION_MSG("ScsiPortInitialize failed with status 0x%08x\n", status);
2146 FUNCTION_EXIT();
2148 return status;