win-pvdrivers

view xenvbd/xenvbd.c @ 783:644e5ddb1b47

Handle SCSI INQUIRY command better in xenvbd
author James Harper <james.harper@bendigoit.com.au>
date Mon Feb 15 20:53:57 2010 +1100 (2010-02-15)
parents 2b2bf47e8672
children 744be619e07c
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.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(setting)));
231 //memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * 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_size = 0;
346 static VOID
347 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
348 {
349 srb_list_entry_t *list_entry = srb->SrbExtension;
350 list_entry->srb = srb;
351 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)list_entry);
352 }
354 static VOID
355 XenVbd_PutQueuedSrbsOnRing(PXENVBD_DEVICE_DATA xvdd)
356 {
357 PSCSI_REQUEST_BLOCK srb;
358 srb_list_entry_t *srb_entry;
359 ULONG block_count;
360 blkif_shadow_t *shadow;
361 ULONG remaining, offset, length;
362 grant_ref_t gref;
363 PUCHAR ptr;
364 int notify;
367 //FUNCTION_ENTER();
369 if (xvdd->aligned_buffer_in_use)
370 return;
372 while(xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list)
373 {
374 srb = srb_entry->srb;
375 block_count = decode_cdb_length(srb);;
376 block_count *= xvdd->bytes_per_sector / 512;
377 remaining = block_count * 512;
379 shadow = get_shadow_from_freelist(xvdd);
380 ASSERT(shadow);
381 ASSERT(!shadow->aligned_buffer_in_use);
382 ASSERT(!shadow->srb);
383 shadow->req.sector_number = decode_cdb_sector(srb);
384 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
385 shadow->req.handle = 0;
386 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
387 shadow->req.nr_segments = 0;
388 shadow->srb = srb;
390 if ((ULONG_PTR)srb->DataBuffer & 511)
391 {
392 xvdd->aligned_buffer_in_use = TRUE;
393 ptr = xvdd->aligned_buffer;
394 if (!decode_cdb_is_read(srb))
395 memcpy(ptr, srb->DataBuffer, block_count * 512);
396 shadow->aligned_buffer_in_use = TRUE;
397 }
398 else
399 {
400 ptr = srb->DataBuffer;
401 shadow->aligned_buffer_in_use = FALSE;
402 }
404 if (dump_mode && block_count > max_dump_mode_size)
405 {
406 max_dump_mode_size = block_count;
407 KdPrint((__DRIVER_NAME " max_dump_mode_size = %d\n", max_dump_mode_size));
408 }
410 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
411 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
412 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
414 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
415 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
416 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
418 while (remaining > 0)
419 {
420 PHYSICAL_ADDRESS physical_address = MmGetPhysicalAddress(ptr);
422 gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
423 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF);
424 if (gref == INVALID_GRANT_REF)
425 {
426 ULONG i;
427 for (i = 0; i < shadow->req.nr_segments; i++)
428 {
429 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
430 shadow->req.seg[i].gref, FALSE);
431 }
432 if (shadow->aligned_buffer_in_use)
433 {
434 shadow->aligned_buffer_in_use = FALSE;
435 xvdd->aligned_buffer_in_use = FALSE;
436 }
437 /* put the srb back at the start of the queue */
438 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
439 put_shadow_on_freelist(xvdd, shadow);
440 KdPrint((__DRIVER_NAME " Out of gref's. Deferring\n"));
441 return;
442 }
443 offset = physical_address.LowPart & (PAGE_SIZE - 1);
444 length = min(PAGE_SIZE - offset, remaining);
445 ASSERT((offset & 511) == 0);
446 ASSERT((length & 511) == 0);
447 ASSERT(offset + length <= PAGE_SIZE);
448 shadow->req.seg[shadow->req.nr_segments].gref = gref;
449 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
450 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
451 remaining -= length;
452 ptr += length;
453 shadow->req.nr_segments++;
454 }
456 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
458 XenVbd_PutRequest(xvdd, &shadow->req);
460 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
461 if (notify)
462 {
463 //KdPrint((__DRIVER_NAME " Notifying\n"));
464 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
465 }
467 }
468 if (xvdd->shadow_free && !xvdd->aligned_buffer_in_use)
469 {
470 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
471 }
472 //FUNCTION_EXIT();
473 }
475 static ULONG DDKAPI
476 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
477 {
478 // PACCESS_RANGE AccessRange;
479 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
480 ULONG status;
481 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
482 PACCESS_RANGE access_range;
484 UNREFERENCED_PARAMETER(HwContext);
485 UNREFERENCED_PARAMETER(BusInformation);
486 UNREFERENCED_PARAMETER(ArgumentString);
488 FUNCTION_ENTER();
489 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
490 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
492 {
493 int i;
494 for (i = 0; i < sizeof(XENVBD_DEVICE_DATA); i++)
495 {
496 if (((PUCHAR)xvdd)[i])
497 {
498 KdPrint((__DRIVER_NAME " DeviceExtension is not zeroed!!!\n"));
499 break;
500 }
501 }
502 }
503 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
504 *Again = FALSE;
506 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
507 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
509 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
510 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
511 {
512 return SP_RETURN_BAD_CONFIG;
513 }
515 access_range = &((*(ConfigInfo->AccessRanges))[0]);
516 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
517 access_range->RangeStart.LowPart, access_range->RangeLength));
518 xvdd->device_base = ScsiPortGetDeviceBase(
519 DeviceExtension,
520 ConfigInfo->AdapterInterfaceType,
521 ConfigInfo->SystemIoBusNumber,
522 access_range->RangeStart,
523 access_range->RangeLength,
524 !access_range->RangeInMemory);
525 if (!xvdd->device_base)
526 {
527 KdPrint((__DRIVER_NAME " Invalid config\n"));
528 FUNCTION_EXIT();
529 return SP_RETURN_BAD_CONFIG;
530 }
532 status = XenVbd_InitFromConfig(xvdd);
533 if (status != SP_RETURN_FOUND)
534 {
535 FUNCTION_EXIT();
536 return status;
537 }
539 xvdd->aligned_buffer_in_use = FALSE;
540 /* align the buffer to PAGE_SIZE */
541 xvdd->aligned_buffer = (PVOID)((ULONG_PTR)((PUCHAR)xvdd->aligned_buffer_data + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1));
542 KdPrint((__DRIVER_NAME " aligned_buffer_data = %p\n", xvdd->aligned_buffer_data));
543 KdPrint((__DRIVER_NAME " aligned_buffer = %p\n", xvdd->aligned_buffer));
545 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
546 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
547 ConfigInfo->ScatterGather = TRUE;
549 #if 0
550 if (!dump_mode)
551 {
552 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
553 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
554 ConfigInfo->ScatterGather = TRUE;
555 }
556 else
557 {
558 ConfigInfo->MaximumTransferLength = 4096;
559 ConfigInfo->NumberOfPhysicalBreaks = 0;
560 ConfigInfo->ScatterGather = FALSE;
561 }
562 #endif
563 ConfigInfo->AlignmentMask = 0;
564 ConfigInfo->NumberOfBuses = 1;
565 ConfigInfo->InitiatorBusId[0] = 1;
566 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
567 ConfigInfo->MaximumNumberOfTargets = 2;
568 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
569 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
570 {
571 ConfigInfo->Master = TRUE;
572 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
573 ConfigInfo->Dma32BitAddresses = FALSE;
574 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
575 }
576 else
577 {
578 ConfigInfo->Master = TRUE;
579 ConfigInfo->Dma32BitAddresses = TRUE;
580 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
581 }
583 FUNCTION_EXIT();
585 return SP_RETURN_FOUND;
586 }
588 static VOID
589 XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
590 {
591 blkif_request_t *req;
592 int notify;
594 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
595 RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
596 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
597 req->operation = 0xff;
598 xvdd->ring.req_prod_pvt++;
599 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
600 req->operation = 0xff;
601 xvdd->ring.req_prod_pvt++;
603 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
604 if (notify)
605 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
606 }
608 static BOOLEAN
609 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
610 {
611 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
613 FUNCTION_ENTER();
614 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
615 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
617 if (!xvdd->inactive)
618 {
619 if (!dump_mode)
620 {
621 XenVbd_StartRingDetection(xvdd);
622 }
623 else
624 {
625 if (xvdd->cached_use_other)
626 {
627 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
628 xvdd->use_other = TRUE;
629 }
630 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
631 }
632 InitializeListHead(&xvdd->srb_list);
633 }
634 FUNCTION_EXIT();
636 return TRUE;
637 }
639 static ULONG
640 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
641 {
642 PMODE_PARAMETER_HEADER parameter_header;
643 PMODE_PARAMETER_BLOCK param_block;
644 PMODE_FORMAT_PAGE format_page;
645 ULONG offset;
646 UCHAR buffer[256];
647 BOOLEAN valid_page = FALSE;
648 BOOLEAN cdb_llbaa;
649 BOOLEAN cdb_dbd;
650 UCHAR cdb_page_code;
651 USHORT cdb_allocation_length;
652 PVOID data_buffer;
653 //ULONG data_buffer_length;
655 UNREFERENCED_PARAMETER(xvdd);
657 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
659 data_buffer = srb->DataBuffer;
660 //cdb = (PCDB)srb->Cdb;
661 switch (srb->Cdb[0])
662 {
663 case SCSIOP_MODE_SENSE:
664 cdb_llbaa = FALSE;
665 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
666 cdb_page_code = srb->Cdb[2] & 0x3f;
667 cdb_allocation_length = srb->Cdb[4];
668 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
669 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
670 break;
671 case SCSIOP_MODE_SENSE10:
672 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
673 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
674 cdb_page_code = srb->Cdb[2] & 0x3f;
675 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
676 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
677 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
678 break;
679 default:
680 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
681 return FALSE;
682 }
683 offset = 0;
685 RtlZeroMemory(data_buffer, srb->DataTransferLength);
686 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
688 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
689 parameter_header->MediumType = 0;
690 parameter_header->DeviceSpecificParameter = 0;
691 parameter_header->BlockDescriptorLength = 0;
692 offset += sizeof(MODE_PARAMETER_HEADER);
694 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
695 {
696 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
697 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
698 }
700 if (!cdb_dbd)
701 {
702 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
703 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
704 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
705 {
706 if (xvdd->total_sectors >> 32)
707 {
708 param_block->DensityCode = 0xff;
709 param_block->NumberOfBlocks[0] = 0xff;
710 param_block->NumberOfBlocks[1] = 0xff;
711 param_block->NumberOfBlocks[2] = 0xff;
712 }
713 else
714 {
715 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
716 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
717 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
718 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
719 }
720 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
721 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
722 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
723 }
724 offset += sizeof(MODE_PARAMETER_BLOCK);
725 }
726 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
727 {
728 valid_page = TRUE;
729 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
730 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
731 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
732 /* 256 sectors per track */
733 format_page->SectorsPerTrack[0] = 0x01;
734 format_page->SectorsPerTrack[1] = 0x00;
735 /* xxx bytes per sector */
736 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
737 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
738 format_page->HardSectorFormating = TRUE;
739 format_page->SoftSectorFormating = TRUE;
740 offset += sizeof(MODE_FORMAT_PAGE);
741 }
742 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
743 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
744 {
745 srb->SrbStatus = SRB_STATUS_ERROR;
746 }
747 else if(offset < srb->DataTransferLength)
748 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
749 else
750 srb->SrbStatus = SRB_STATUS_SUCCESS;
751 srb->DataTransferLength = min(srb->DataTransferLength, offset);
752 srb->ScsiStatus = 0;
753 memcpy(data_buffer, buffer, srb->DataTransferLength);
755 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
757 return TRUE;
758 }
760 static VOID
761 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
762 {
763 PSENSE_DATA sd = srb->SenseInfoBuffer;
765 UNREFERENCED_PARAMETER(xvdd);
767 if (!srb->SenseInfoBuffer)
768 return;
770 sd->ErrorCode = 0x70;
771 sd->Valid = 1;
772 sd->SenseKey = sense_key;
773 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
774 sd->AdditionalSenseCode = additional_sense_code;
775 return;
776 }
778 static VOID
779 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
780 {
781 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
782 return;
783 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
784 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
785 }
787 static BOOLEAN DDKAPI
788 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
789 {
790 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
791 PSCSI_REQUEST_BLOCK srb;
792 RING_IDX i, rp;
793 ULONG j;
794 blkif_response_t *rep;
795 int block_count;
796 int more_to_do = TRUE;
797 blkif_shadow_t *shadow;
798 ULONG suspend_resume_state_pdo;
799 BOOLEAN last_interrupt = FALSE;
801 /* in dump mode I think we get called on a timer, not by an actual IRQ */
802 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
803 return FALSE; /* interrupt was not for us */
805 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
806 KeMemoryBarrier();
808 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
809 {
810 FUNCTION_ENTER();
811 switch (suspend_resume_state_pdo)
812 {
813 case SR_STATE_SUSPENDING:
814 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
815 break;
816 case SR_STATE_RESUMING:
817 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
818 XenVbd_InitFromConfig(xvdd);
819 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
820 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
821 break;
822 case SR_STATE_RUNNING:
823 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
824 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
825 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
826 ScsiPortNotification(NextRequest, DeviceExtension);
827 default:
828 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
829 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
830 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
831 break;
832 }
833 KeMemoryBarrier();
834 }
836 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
837 {
838 return last_interrupt;
839 }
841 while (more_to_do)
842 {
843 rp = xvdd->ring.sring->rsp_prod;
844 KeMemoryBarrier();
845 for (i = xvdd->ring.rsp_cons; i < rp; i++)
846 {
847 rep = XenVbd_GetResponse(xvdd, i);
848 /*
849 * This code is to automatically detect if the backend is using the same
850 * bit width or a different bit width to us. Later versions of Xen do this
851 * via a xenstore value, but not all. That 0x0fffffff (notice
852 * that the msb is not actually set, so we don't have any problems with
853 * sign extending) is to signify the last entry on the right, which is
854 * different under 32 and 64 bits, and that is why we set it up there.
856 * To do the detection, we put two initial entries on the ring, with an op
857 * of 0xff (which is invalid). The first entry is mostly okay, but the
858 * second will be grossly misaligned if the backend bit width is different,
859 * and we detect this and switch frontend structures.
860 */
861 switch (xvdd->ring_detect_state)
862 {
863 case RING_DETECT_STATE_NOT_STARTED:
864 KdPrint((__DRIVER_NAME " premature IRQ\n"));
865 break;
866 case RING_DETECT_STATE_DETECT1:
867 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
868 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
869 break;
870 case RING_DETECT_STATE_DETECT2:
871 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
872 *xvdd->event_channel_ptr |= 0x80000000;
873 if (rep->operation != 0xff)
874 {
875 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
876 xvdd->use_other = TRUE;
877 *xvdd->event_channel_ptr |= 0x40000000;
878 }
879 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
880 ScsiPortNotification(NextRequest, DeviceExtension);
881 break;
882 case RING_DETECT_STATE_COMPLETE:
883 shadow = &xvdd->shadows[rep->id];
884 srb = shadow->srb;
885 ASSERT(srb != NULL);
886 block_count = decode_cdb_length(srb);
887 block_count *= xvdd->bytes_per_sector / 512;
888 /* 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 */
889 if (rep->status == BLKIF_RSP_OKAY || (dump_mode && dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT))
890 srb->SrbStatus = SRB_STATUS_SUCCESS;
891 else
892 {
893 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
894 if (decode_cdb_is_read(srb))
895 KdPrint((__DRIVER_NAME " Operation = Read\n"));
896 else
897 KdPrint((__DRIVER_NAME " Operation = Write\n"));
898 if (dump_mode)
899 {
900 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
901 KdPrint((__DRIVER_NAME " DataBuffer = %p, aligned_buffer = %p\n", srb->DataBuffer, xvdd->aligned_buffer));
902 KdPrint((__DRIVER_NAME " Physical = %08x%08x\n", MmGetPhysicalAddress(srb->DataBuffer).HighPart, MmGetPhysicalAddress(srb->DataBuffer).LowPart));
903 KdPrint((__DRIVER_NAME " PFN = %08x\n", (ULONG)(MmGetPhysicalAddress(srb->DataBuffer).QuadPart >> PAGE_SHIFT)));
905 for (j = 0; j < shadow->req.nr_segments; j++)
906 {
907 KdPrint((__DRIVER_NAME " gref = %d\n", shadow->req.seg[j].gref));
908 KdPrint((__DRIVER_NAME " first_sect = %d\n", shadow->req.seg[j].first_sect));
909 KdPrint((__DRIVER_NAME " last_sect = %d\n", shadow->req.seg[j].last_sect));
910 }
911 }
912 srb->SrbStatus = SRB_STATUS_ERROR;
913 srb->ScsiStatus = 0x02;
914 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
915 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
916 XenVbd_MakeAutoSense(xvdd, srb);
917 }
918 if (shadow->aligned_buffer_in_use)
919 {
920 ASSERT(xvdd->aligned_buffer_in_use);
921 xvdd->aligned_buffer_in_use = FALSE;
922 if (decode_cdb_is_read(srb))
923 memcpy(srb->DataBuffer, xvdd->aligned_buffer, block_count * 512);
924 //KdPrint((__DRIVER_NAME " Completed use of buffer\n"));
925 }
927 #if 0
928 if (xvdd->aligned_buffer_in_use)
929 {
930 KdPrint((__DRIVER_NAME " Completed request while aligned buffer in use\n"));
931 }
932 #endif
933 for (j = 0; j < shadow->req.nr_segments; j++)
934 {
935 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
936 shadow->req.seg[j].gref, FALSE);
937 }
938 shadow->aligned_buffer_in_use = FALSE;
939 shadow->srb = NULL;
940 put_shadow_on_freelist(xvdd, shadow);
941 //KdPrint((__DRIVER_NAME " B RequestComplete srb = %p\n", srb));
942 ScsiPortNotification(RequestComplete, xvdd, srb);
943 break;
944 }
945 }
947 xvdd->ring.rsp_cons = i;
948 if (i != xvdd->ring.req_prod_pvt)
949 {
950 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
951 }
952 else
953 {
954 xvdd->ring.sring->rsp_event = i + 1;
955 more_to_do = FALSE;
956 }
957 }
959 XenVbd_PutQueuedSrbsOnRing(xvdd);
961 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
962 {
963 if (xvdd->inactive || xvdd->shadow_free == SHADOW_ENTRIES)
964 {
965 /* all entries are purged from the list (or we are inactive). ready to suspend */
966 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
967 KeMemoryBarrier();
968 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
969 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
970 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
971 }
972 FUNCTION_EXIT();
973 }
975 return last_interrupt;
976 }
978 static BOOLEAN DDKAPI
979 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK srb)
980 {
981 PUCHAR data_buffer;
982 //ULONG data_buffer_length;
983 PCDB cdb;
984 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
985 ULONG data_transfer_length = srb->DataTransferLength;
988 if (xvdd->aligned_buffer_in_use)
989 {
990 KdPrint((__DRIVER_NAME " New request while aligned buffer in use - Function = %x, next_request = %d\n", srb->Function, xvdd->next_request));
991 }
993 if (xvdd->inactive)
994 {
995 KdPrint((__DRIVER_NAME " Inactive srb->Function = %08X\n", srb->Function));
996 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
997 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
998 ScsiPortNotification(NextRequest, DeviceExtension);
999 return TRUE;
1002 // If we haven't enumerated all the devices yet then just defer the request
1003 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
1005 srb->SrbStatus = SRB_STATUS_BUSY;
1006 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1007 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
1008 return TRUE;
1011 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
1013 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Suspending/Resuming)\n"));
1014 srb->SrbStatus = SRB_STATUS_BUSY;
1015 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1016 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Suspending/Resuming)\n"));
1017 return TRUE;
1020 if (srb->PathId != 0 || srb->TargetId != 0)
1022 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1023 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1024 ScsiPortNotification(NextRequest, DeviceExtension);
1025 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1026 return TRUE;
1029 switch (srb->Function)
1031 case SRB_FUNCTION_EXECUTE_SCSI:
1032 cdb = (PCDB)srb->Cdb;
1034 if (xvdd->aligned_buffer_in_use)
1036 KdPrint((__DRIVER_NAME " New request while aligned buffer in use - OP = %x, next_request = %d\n", cdb->CDB6GENERIC.OperationCode, xvdd->next_request));
1039 switch(cdb->CDB6GENERIC.OperationCode)
1041 case SCSIOP_TEST_UNIT_READY:
1042 if (dump_mode)
1043 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1044 srb->SrbStatus = SRB_STATUS_SUCCESS;
1045 srb->ScsiStatus = 0;
1046 break;
1047 case SCSIOP_INQUIRY:
1048 if (dump_mode)
1050 //PHYSICAL_ADDRESS physical;
1051 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1052 //KdPrint((__DRIVER_NAME " srb->Databuffer = %p\n", srb->DataBuffer));
1053 //physical = ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length);
1054 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
1056 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]));
1057 // KdPrint((__DRIVER_NAME " (Length = %d)\n", srb->DataTransferLength));
1059 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1060 data_buffer = srb->DataBuffer;
1061 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1062 srb->SrbStatus = SRB_STATUS_SUCCESS;
1063 switch (xvdd->device_type)
1065 case XENVBD_DEVICETYPE_DISK:
1066 if ((srb->Cdb[1] & 1) == 0)
1068 if (srb->Cdb[2])
1070 srb->SrbStatus = SRB_STATUS_ERROR;
1072 else
1074 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1075 id->DeviceType = DIRECT_ACCESS_DEVICE;
1076 id->Versions = 3;
1077 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
1078 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1079 id->CommandQueue = 1;
1080 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1081 memcpy(id->ProductId, scsi_disk_model, 16); // product id
1082 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1083 data_transfer_length = sizeof(INQUIRYDATA);
1086 else
1088 switch (srb->Cdb[2])
1090 case 0x00:
1091 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1092 data_buffer[1] = 0x00;
1093 data_buffer[2] = 0x00;
1094 data_buffer[3] = 2;
1095 data_buffer[4] = 0x00;
1096 data_buffer[5] = 0x80;
1097 data_transfer_length = 6;
1098 break;
1099 case 0x80:
1100 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1101 data_buffer[1] = 0x80;
1102 data_buffer[2] = 0x00;
1103 data_buffer[3] = 8;
1104 memset(&data_buffer[4], ' ', 8);
1105 data_transfer_length = 12;
1106 break;
1107 default:
1108 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
1109 srb->SrbStatus = SRB_STATUS_ERROR;
1110 break;
1113 break;
1114 case XENVBD_DEVICETYPE_CDROM:
1115 if ((srb->Cdb[1] & 1) == 0)
1117 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1118 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1119 id->RemovableMedia = 1;
1120 id->Versions = 3;
1121 id->ResponseDataFormat = 0;
1122 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1123 id->CommandQueue = 1;
1124 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1125 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1126 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1128 else
1130 switch (srb->Cdb[2])
1132 case 0x00:
1133 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1134 data_buffer[1] = 0x00;
1135 data_buffer[2] = 0x00;
1136 data_buffer[3] = 2;
1137 data_buffer[4] = 0x00;
1138 data_buffer[5] = 0x80;
1139 break;
1140 case 0x80:
1141 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1142 data_buffer[1] = 0x80;
1143 data_buffer[2] = 0x00;
1144 data_buffer[3] = 8;
1145 data_buffer[4] = 0x31;
1146 data_buffer[5] = 0x32;
1147 data_buffer[6] = 0x33;
1148 data_buffer[7] = 0x34;
1149 data_buffer[8] = 0x35;
1150 data_buffer[9] = 0x36;
1151 data_buffer[10] = 0x37;
1152 data_buffer[11] = 0x38;
1153 break;
1154 default:
1155 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", srb->Cdb[2]));
1156 srb->SrbStatus = SRB_STATUS_ERROR;
1157 break;
1160 break;
1161 default:
1162 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1163 srb->SrbStatus = SRB_STATUS_ERROR;
1164 break;
1166 break;
1167 case SCSIOP_READ_CAPACITY:
1168 if (dump_mode)
1169 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1170 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1171 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1172 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1173 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1174 data_buffer = srb->DataBuffer;
1175 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1176 if ((xvdd->total_sectors - 1) >> 32)
1178 data_buffer[0] = 0xff;
1179 data_buffer[1] = 0xff;
1180 data_buffer[2] = 0xff;
1181 data_buffer[3] = 0xff;
1183 else
1185 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1186 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1187 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1188 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1190 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1191 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1192 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1193 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1194 srb->ScsiStatus = 0;
1195 srb->SrbStatus = SRB_STATUS_SUCCESS;
1196 break;
1197 case SCSIOP_READ_CAPACITY16:
1198 if (dump_mode)
1199 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1200 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1));
1201 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]));
1202 //KdPrint((__DRIVER_NAME " PMI = %d\n", srb->Cdb[8] & 1));
1203 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1204 data_buffer = srb->DataBuffer;
1205 RtlZeroMemory(data_buffer, srb->DataTransferLength);
1206 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1207 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1208 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1209 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1210 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1211 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1212 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1213 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1214 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1215 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1216 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1217 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1218 srb->ScsiStatus = 0;
1219 srb->SrbStatus = SRB_STATUS_SUCCESS;
1220 break;
1221 case SCSIOP_MODE_SENSE:
1222 case SCSIOP_MODE_SENSE10:
1223 if (dump_mode)
1224 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));
1225 XenVbd_FillModePage(xvdd, srb);
1226 break;
1227 case SCSIOP_READ:
1228 case SCSIOP_READ16:
1229 case SCSIOP_WRITE:
1230 case SCSIOP_WRITE16:
1231 XenVbd_PutSrbOnList(xvdd, srb);
1232 XenVbd_PutQueuedSrbsOnRing(xvdd);
1233 break;
1234 case SCSIOP_VERIFY:
1235 case SCSIOP_VERIFY16:
1236 // Should we do more here?
1237 if (dump_mode)
1238 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1239 srb->SrbStatus = SRB_STATUS_SUCCESS;
1240 break;
1241 case SCSIOP_REPORT_LUNS:
1242 if (dump_mode)
1243 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1244 srb->SrbStatus = SRB_STATUS_SUCCESS;;
1245 break;
1246 case SCSIOP_REQUEST_SENSE:
1247 if (dump_mode)
1248 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1249 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1250 srb->SrbStatus = SRB_STATUS_SUCCESS;
1251 break;
1252 case SCSIOP_READ_TOC:
1253 if (dump_mode)
1254 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1255 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
1256 data_buffer = srb->DataBuffer;
1257 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1258 /*
1259 #define READ_TOC_FORMAT_TOC 0x00
1260 #define READ_TOC_FORMAT_SESSION 0x01
1261 #define READ_TOC_FORMAT_FULL_TOC 0x02
1262 #define READ_TOC_FORMAT_PMA 0x03
1263 #define READ_TOC_FORMAT_ATIP 0x04
1264 */
1265 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1266 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1267 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1268 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1269 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1270 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1271 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1272 switch (cdb->READ_TOC.Format2)
1274 case READ_TOC_FORMAT_TOC:
1275 data_buffer[0] = 0; // length MSB
1276 data_buffer[1] = 10; // length LSB
1277 data_buffer[2] = 1; // First Track
1278 data_buffer[3] = 1; // Last Track
1279 data_buffer[4] = 0; // Reserved
1280 data_buffer[5] = 0x14; // current position data + uninterrupted data
1281 data_buffer[6] = 1; // last complete track
1282 data_buffer[7] = 0; // reserved
1283 data_buffer[8] = 0; // MSB Block
1284 data_buffer[9] = 0;
1285 data_buffer[10] = 0;
1286 data_buffer[11] = 0; // LSB Block
1287 srb->SrbStatus = SRB_STATUS_SUCCESS;
1288 break;
1289 case READ_TOC_FORMAT_SESSION:
1290 case READ_TOC_FORMAT_FULL_TOC:
1291 case READ_TOC_FORMAT_PMA:
1292 case READ_TOC_FORMAT_ATIP:
1293 srb->SrbStatus = SRB_STATUS_ERROR;
1294 break;
1296 break;
1297 case SCSIOP_START_STOP_UNIT:
1298 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1299 srb->SrbStatus = SRB_STATUS_SUCCESS;
1300 break;
1301 case SCSIOP_RESERVE_UNIT:
1302 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1303 srb->SrbStatus = SRB_STATUS_SUCCESS;
1304 break;
1305 case SCSIOP_RELEASE_UNIT:
1306 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1307 srb->SrbStatus = SRB_STATUS_SUCCESS;
1308 break;
1309 default:
1310 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]));
1311 srb->SrbStatus = SRB_STATUS_ERROR;
1312 break;
1314 if (srb->SrbStatus == SRB_STATUS_ERROR)
1316 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key));
1317 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1319 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1320 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1322 srb->ScsiStatus = 0x02;
1323 XenVbd_MakeAutoSense(xvdd, srb);
1324 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1325 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1327 ScsiPortNotification(NextRequest, DeviceExtension);
1330 else if (srb->SrbStatus != SRB_STATUS_PENDING)
1332 if (srb->SrbStatus == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength)
1334 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1335 srb->DataTransferLength = data_transfer_length;
1337 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1338 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1339 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1340 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1342 ScsiPortNotification(NextRequest, DeviceExtension);
1345 break;
1346 case SRB_FUNCTION_IO_CONTROL:
1347 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1348 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1349 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1350 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1352 ScsiPortNotification(NextRequest, DeviceExtension);
1354 break;
1355 case SRB_FUNCTION_FLUSH:
1356 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1357 srb->SrbStatus = SRB_STATUS_SUCCESS;
1358 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1359 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1361 ScsiPortNotification(NextRequest, DeviceExtension);
1363 break;
1364 case SRB_FUNCTION_SHUTDOWN:
1365 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free));
1366 srb->SrbStatus = SRB_STATUS_SUCCESS;
1367 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1368 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1370 ScsiPortNotification(NextRequest, DeviceExtension);
1372 break;
1373 default:
1374 KdPrint((__DRIVER_NAME " Unhandled srb->Function = %08X\n", srb->Function));
1375 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1376 ScsiPortNotification(RequestComplete, DeviceExtension, srb);
1377 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1379 ScsiPortNotification(NextRequest, DeviceExtension);
1381 break;
1384 //FUNCTION_EXIT();
1385 return TRUE;
1388 static BOOLEAN
1389 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1391 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1393 UNREFERENCED_PARAMETER(DeviceExtension);
1394 UNREFERENCED_PARAMETER(PathId);
1396 FUNCTION_ENTER();
1398 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1399 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1401 ScsiPortNotification(NextRequest, DeviceExtension);
1404 FUNCTION_EXIT();
1407 return TRUE;
1410 static BOOLEAN
1411 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1413 UNREFERENCED_PARAMETER(DeviceExtension);
1414 UNREFERENCED_PARAMETER(Context);
1415 UNREFERENCED_PARAMETER(SaveState);
1417 FUNCTION_ENTER();
1418 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1420 FUNCTION_EXIT();
1422 return TRUE;
1425 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1426 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1428 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1429 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1430 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1431 //KIRQL OldIrql;
1433 FUNCTION_ENTER();
1434 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1435 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
1437 switch (ControlType)
1439 case ScsiQuerySupportedControlTypes:
1440 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1441 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1442 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1443 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1444 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1445 break;
1446 case ScsiStopAdapter:
1447 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1448 //KdBreakPoint();
1449 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1450 break;
1451 case ScsiRestartAdapter:
1452 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1453 if (!xvdd->inactive)
1455 if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
1456 KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR) xvdd, 0, 0);
1457 XenVbd_StartRingDetection(xvdd);
1459 break;
1460 case ScsiSetBootConfig:
1461 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1462 break;
1463 case ScsiSetRunningConfig:
1464 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1465 break;
1466 default:
1467 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1468 break;
1471 FUNCTION_EXIT();
1473 return Status;
1476 NTSTATUS
1477 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1479 ULONG status;
1480 HW_INITIALIZATION_DATA HwInitializationData;
1481 PVOID driver_extension;
1482 PUCHAR ptr;
1483 OBJECT_ATTRIBUTES oa;
1484 HANDLE service_handle;
1485 UNICODE_STRING param_name;
1486 HANDLE param_handle;
1487 UNICODE_STRING value_name;
1488 CHAR buf[256];
1489 ULONG buf_len;
1490 PKEY_VALUE_PARTIAL_INFORMATION kpv;
1492 FUNCTION_ENTER();
1493 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1494 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1496 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1497 if (!RegistryPath)
1499 dump_mode = TRUE;
1502 if (!dump_mode)
1504 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1505 ptr = driver_extension;
1506 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1507 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1508 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1509 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1510 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1511 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1512 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1513 //ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
1514 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1516 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1517 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
1518 if(!NT_SUCCESS(status))
1520 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
1522 else
1524 RtlInitUnicodeString(&param_name, L"Parameters");
1525 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
1526 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
1527 if(!NT_SUCCESS(status))
1529 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
1531 else
1533 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
1534 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
1535 RtlFillMemory(scsi_disk_model, 16, ' ');
1536 RtlFillMemory(scsi_cdrom_model, 16, ' ');
1538 RtlInitUnicodeString(&value_name, L"Manufacturer");
1539 buf_len = 256;
1540 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1541 if(NT_SUCCESS(status))
1542 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
1543 else
1544 RtlStringCbCopyA(scsi_device_manufacturer, 8, "XEN ");
1546 RtlInitUnicodeString(&value_name, L"Disk_Model");
1547 buf_len = 256;
1548 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1549 if(NT_SUCCESS(status))
1550 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1551 else
1552 RtlStringCbCopyA(scsi_disk_model, 16, "PV DISK ");
1554 RtlInitUnicodeString(&value_name, L"CDROM_Model");
1555 buf_len = 256;
1556 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1557 if(NT_SUCCESS(status))
1558 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1559 else
1560 RtlStringCbCopyA(scsi_cdrom_model, 16, "PV CDROM ");
1562 ZwClose(service_handle);
1566 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1568 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1569 HwInitializationData.AdapterInterfaceType = PNPBus;
1570 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1571 HwInitializationData.SpecificLuExtensionSize = 0;
1572 HwInitializationData.SrbExtensionSize = sizeof(srb_list_entry_t);
1573 HwInitializationData.NumberOfAccessRanges = 1;
1574 HwInitializationData.MapBuffers = TRUE;
1575 HwInitializationData.NeedPhysicalAddresses = FALSE;
1576 HwInitializationData.TaggedQueuing = TRUE;
1577 HwInitializationData.AutoRequestSense = TRUE;
1578 HwInitializationData.MultipleRequestPerLu = TRUE;
1579 HwInitializationData.ReceiveEvent = FALSE;
1580 HwInitializationData.VendorIdLength = 0;
1581 HwInitializationData.VendorId = NULL;
1582 HwInitializationData.DeviceIdLength = 0;
1583 HwInitializationData.DeviceId = NULL;
1585 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1586 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1587 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1588 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1589 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1590 HwInitializationData.HwDmaStarted = NULL;
1591 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1592 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1594 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1596 if(!NT_SUCCESS(status))
1598 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1601 FUNCTION_EXIT();
1603 return status;