win-pvdrivers

view xenvbd/xenvbd.c @ 692:1fe30f6966eb

Fix bug where changing network adapter properties would not reload the adapter correctly
author James Harper <james.harper@bendigoit.com.au>
date Sun Nov 08 22:24:33 2009 +1100 (2009-11-08)
parents c548d9eb5107
children d7ad5ed2732f
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 static BOOLEAN dump_mode = FALSE;
41 CHAR scsi_device_manufacturer[8];
42 CHAR scsi_disk_model[16];
43 CHAR scsi_cdrom_model[16];
45 ULONGLONG parse_numeric_string(PCHAR string)
46 {
47 ULONGLONG val = 0;
48 while (*string != 0)
49 {
50 val = val * 10 + (*string - '0');
51 string++;
52 }
53 return val;
54 }
56 static blkif_shadow_t *
57 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
58 {
59 if (xvdd->shadow_free == 0)
60 {
61 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
62 return NULL;
63 }
64 xvdd->shadow_free--;
65 if (xvdd->shadow_free < xvdd->shadow_min_free)
66 xvdd->shadow_min_free = xvdd->shadow_free;
67 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
68 }
70 static VOID
71 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
72 {
73 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
74 shadow->srb = NULL;
75 xvdd->shadow_free++;
76 }
78 static blkif_response_t *
79 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
80 {
81 blkif_other_response_t *rep;
82 if (!xvdd->use_other)
83 return RING_GET_RESPONSE(&xvdd->ring, i);
84 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
85 xvdd->tmp_rep.id = rep->id;
86 xvdd->tmp_rep.operation = rep->operation;
87 xvdd->tmp_rep.status = rep->status;
88 return &xvdd->tmp_rep;
89 }
91 static VOID
92 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
93 {
94 blkif_other_request_t *other_req;
96 if (!xvdd->use_other)
97 {
98 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
99 }
100 else
101 {
102 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
103 other_req->operation = req->operation;
104 other_req->nr_segments = req->nr_segments;
105 other_req->handle = req->handle;
106 other_req->id = req->id;
107 other_req->sector_number = req->sector_number;
108 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
109 }
110 xvdd->ring.req_prod_pvt++;
111 }
113 static ULONG
114 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
115 {
116 ULONG i;
117 PUCHAR ptr;
118 USHORT type;
119 PCHAR setting, value, value2;
120 ULONG qemu_protocol_version = 0;
122 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
123 xvdd->sring = NULL;
124 xvdd->event_channel = 0;
126 xvdd->inactive = TRUE;
127 ptr = xvdd->device_base;
128 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
129 {
130 switch(type)
131 {
132 case XEN_INIT_TYPE_RING: /* frontend ring */
133 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
134 if (strcmp(setting, "ring-ref") == 0)
135 {
136 xvdd->sring = (blkif_sring_t *)value;
137 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
138 /* this bit is for when we have to take over an existing ring on a crash dump */
139 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
140 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
141 }
142 break;
143 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
144 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
145 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
146 if (strcmp(setting, "event-channel") == 0)
147 {
148 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
149 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
150 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
151 if (PtrToUlong(value) & 0x80000000)
152 {
153 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
154 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
155 }
156 }
157 break;
158 case XEN_INIT_TYPE_READ_STRING_BACK:
159 case XEN_INIT_TYPE_READ_STRING_FRONT:
160 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
161 if (strcmp(setting, "sectors") == 0)
162 xvdd->total_sectors = parse_numeric_string(value);
163 else if (strcmp(setting, "sector-size") == 0)
164 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
165 else if (strcmp(setting, "device-type") == 0)
166 {
167 if (strcmp(value, "disk") == 0)
168 {
169 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
170 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
171 }
172 else if (strcmp(value, "cdrom") == 0)
173 {
174 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
175 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
176 }
177 else
178 {
179 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
180 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
181 }
182 }
183 else if (strcmp(setting, "mode") == 0)
184 {
185 if (strncmp(value, "r", 1) == 0)
186 {
187 KdPrint((__DRIVER_NAME " mode = r\n"));
188 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
189 }
190 else if (strncmp(value, "w", 1) == 0)
191 {
192 KdPrint((__DRIVER_NAME " mode = w\n"));
193 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
194 }
195 else
196 {
197 KdPrint((__DRIVER_NAME " mode = unknown\n"));
198 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
199 }
200 }
201 break;
202 case XEN_INIT_TYPE_VECTORS:
203 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
204 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
205 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
206 {
207 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
208 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
209 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
210 return SP_RETURN_BAD_CONFIG;
211 }
212 else
213 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
214 break;
215 case XEN_INIT_TYPE_STATE_PTR:
216 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
217 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
218 break;
219 case XEN_INIT_TYPE_ACTIVE:
220 xvdd->inactive = FALSE;
221 break;
222 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
223 qemu_protocol_version = PtrToUlong(value);
224 break;
225 case XEN_INIT_TYPE_GRANT_ENTRIES:
226 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - entries = %d\n", PtrToUlong(setting)));
227 memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * sizeof(grant_ref_t));
228 break;
229 default:
230 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
231 break;
232 }
233 }
234 if (!xvdd->inactive && (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
235 || xvdd->sring == NULL
236 || xvdd->event_channel == 0
237 || xvdd->total_sectors == 0
238 || xvdd->bytes_per_sector == 0))
239 {
240 KdPrint((__DRIVER_NAME " Missing settings\n"));
241 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
242 return SP_RETURN_BAD_CONFIG;
243 }
244 if (!xvdd->inactive && xvdd->device_type == XENVBD_DEVICETYPE_CDROM && qemu_protocol_version > 0)
245 {
246 xvdd->inactive = TRUE;
247 }
249 if (xvdd->inactive)
250 KdPrint((__DRIVER_NAME " Device is inactive\n"));
251 else
252 {
253 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
254 {
255 /* CD/DVD drives must have bytes_per_sector = 2048. */
256 xvdd->bytes_per_sector = 2048;
257 }
259 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
260 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
262 xvdd->shadow_free = 0;
263 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
264 for (i = 0; i < SHADOW_ENTRIES; i++)
265 {
266 xvdd->shadows[i].req.id = i;
267 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
268 }
269 }
271 return SP_RETURN_FOUND;
272 }
274 static __inline ULONG
275 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
276 {
277 switch (srb->Cdb[0])
278 {
279 case SCSIOP_READ:
280 case SCSIOP_WRITE:
281 return (srb->Cdb[7] << 8) | srb->Cdb[8];
282 case SCSIOP_READ16:
283 case SCSIOP_WRITE16:
284 return (srb->Cdb[10] << 24) | (srb->Cdb[11] << 16) | (srb->Cdb[12] << 8) | srb->Cdb[13];
285 default:
286 return 0;
287 }
288 }
290 static __inline ULONGLONG
291 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
292 {
293 ULONGLONG sector;
295 switch (srb->Cdb[0])
296 {
297 case SCSIOP_READ:
298 case SCSIOP_WRITE:
299 sector = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
300 break;
301 case SCSIOP_READ16:
302 case SCSIOP_WRITE16:
303 sector = ((ULONGLONG)srb->Cdb[2] << 56) | ((ULONGLONG)srb->Cdb[3] << 48)
304 | ((ULONGLONG)srb->Cdb[4] << 40) | ((ULONGLONG)srb->Cdb[5] << 32)
305 | ((ULONGLONG)srb->Cdb[6] << 24) | ((ULONGLONG)srb->Cdb[7] << 16)
306 | ((ULONGLONG)srb->Cdb[8] << 8) | ((ULONGLONG)srb->Cdb[9]);
307 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
308 break;
309 default:
310 sector = 0;
311 break;
312 }
313 return sector;
314 }
316 static __inline BOOLEAN
317 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
318 {
319 switch (srb->Cdb[0])
320 {
321 case SCSIOP_READ:
322 case SCSIOP_READ16:
323 return TRUE;
324 case SCSIOP_WRITE:
325 case SCSIOP_WRITE16:
326 return FALSE;
327 default:
328 return FALSE;
329 }
330 }
332 static __forceinline PVOID
333 get_databuffer_virtual(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
334 {
335 ULONG data_buffer_length;
337 if (!dump_mode)
338 {
339 return LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
340 }
341 else
342 {
343 /* in dump mode, we can count on srb->DataBuffer being the virtual address we want */
344 return srb->DataBuffer;
345 }
346 }
348 static VOID
349 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
350 {
351 ULONG block_count;
352 blkif_shadow_t *shadow;
353 ULONG remaining, offset, length;
354 grant_ref_t gref;
355 ULONG gref_index;
356 PUCHAR ptr;
357 int notify;
359 //FUNCTION_ENTER();
361 ptr = srb->DataBuffer;
363 block_count = decode_cdb_length(srb);;
364 block_count *= xvdd->bytes_per_sector / 512;
365 remaining = block_count * 512;
367 shadow = get_shadow_from_freelist(xvdd);
368 ASSERT(shadow);
369 shadow->req.sector_number = decode_cdb_sector(srb);
370 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
371 shadow->req.handle = 0;
372 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
373 shadow->req.nr_segments = 0;
374 shadow->srb = srb;
376 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
377 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
378 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
380 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
381 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
382 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
383 gref_index = 0;
384 while (remaining > 0)
385 {
386 PHYSICAL_ADDRESS physical_address;
387 physical_address = ScsiPortGetPhysicalAddress(xvdd, srb, ptr, &length);
388 if (!dump_mode)
389 {
390 gref = (grant_ref_t)(physical_address.QuadPart >> PAGE_SHIFT);
391 }
392 else
393 {
394 gref = (grant_ref_t)xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
395 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, xvdd->dump_grant_refs[gref_index++]);
396 }
397 offset = physical_address.LowPart & (PAGE_SIZE - 1);
398 length = min(PAGE_SIZE - offset, remaining);
399 ASSERT((offset & 511) == 0);
400 ASSERT((length & 511) == 0);
401 ASSERT(offset + length <= PAGE_SIZE);
402 shadow->req.seg[shadow->req.nr_segments].gref = gref;
403 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
404 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
405 remaining -= length;
406 ptr += length;
407 shadow->req.nr_segments++;
408 }
410 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
412 XenVbd_PutRequest(xvdd, &shadow->req);
414 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
415 if (notify)
416 {
417 //KdPrint((__DRIVER_NAME " Notifying\n"));
418 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
419 }
421 if (xvdd->shadow_free)
422 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
424 //FUNCTION_EXIT();
425 }
427 static ULONG DDKAPI
428 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
429 {
430 // PACCESS_RANGE AccessRange;
431 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
432 ULONG status;
433 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
434 PACCESS_RANGE access_range;
436 UNREFERENCED_PARAMETER(HwContext);
437 UNREFERENCED_PARAMETER(BusInformation);
438 UNREFERENCED_PARAMETER(ArgumentString);
440 FUNCTION_ENTER();
441 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
442 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
444 {
445 int i;
446 for (i = 0; i < sizeof(XENVBD_DEVICE_DATA); i++)
447 {
448 if (((PUCHAR)xvdd)[i])
449 {
450 KdPrint((__DRIVER_NAME " DeviceExtension is not zeroed!!!\n"));
451 break;
452 }
453 }
454 }
455 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
456 *Again = FALSE;
458 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
459 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
461 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
462 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
463 {
464 return SP_RETURN_BAD_CONFIG;
465 }
467 access_range = &((*(ConfigInfo->AccessRanges))[0]);
468 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
469 access_range->RangeStart.LowPart, access_range->RangeLength));
470 xvdd->device_base = ScsiPortGetDeviceBase(
471 DeviceExtension,
472 ConfigInfo->AdapterInterfaceType,
473 ConfigInfo->SystemIoBusNumber,
474 access_range->RangeStart,
475 access_range->RangeLength,
476 !access_range->RangeInMemory);
477 if (!xvdd->device_base)
478 {
479 KdPrint((__DRIVER_NAME " Invalid config\n"));
480 FUNCTION_EXIT();
481 return SP_RETURN_BAD_CONFIG;
482 }
484 status = XenVbd_InitFromConfig(xvdd);
485 if (status != SP_RETURN_FOUND)
486 {
487 FUNCTION_EXIT();
488 return status;
489 }
491 if (!dump_mode)
492 {
493 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
494 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
495 ConfigInfo->ScatterGather = TRUE;
496 }
497 else
498 {
499 ConfigInfo->MaximumTransferLength = 4096;
500 ConfigInfo->NumberOfPhysicalBreaks = 0;
501 ConfigInfo->ScatterGather = FALSE;
502 }
503 ConfigInfo->AlignmentMask = 0;
504 ConfigInfo->NumberOfBuses = 1;
505 ConfigInfo->InitiatorBusId[0] = 1;
506 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
507 ConfigInfo->MaximumNumberOfTargets = 2;
508 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
509 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
510 {
511 ConfigInfo->Master = TRUE;
512 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
513 ConfigInfo->Dma32BitAddresses = FALSE;
514 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
515 }
516 else
517 {
518 ConfigInfo->Master = TRUE;
519 ConfigInfo->Dma32BitAddresses = TRUE;
520 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
521 }
523 FUNCTION_EXIT();
525 return SP_RETURN_FOUND;
526 }
528 static VOID
529 XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
530 {
531 blkif_request_t *req;
532 int notify;
534 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
535 RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE - FIELD_OFFSET(blkif_sring_t, ring));
536 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
537 req->operation = 0xff;
538 xvdd->ring.req_prod_pvt++;
539 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
540 req->operation = 0xff;
541 xvdd->ring.req_prod_pvt++;
543 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
544 if (notify)
545 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
546 }
548 static BOOLEAN
549 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
550 {
551 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
553 FUNCTION_ENTER();
554 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
555 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
557 if (!xvdd->inactive)
558 {
559 if (!dump_mode)
560 {
561 XenVbd_StartRingDetection(xvdd);
562 }
563 else
564 {
565 if (xvdd->cached_use_other)
566 {
567 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
568 xvdd->use_other = TRUE;
569 }
570 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
571 }
572 }
573 FUNCTION_EXIT();
575 return TRUE;
576 }
578 static ULONG
579 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
580 {
581 PMODE_PARAMETER_HEADER parameter_header;
582 PMODE_PARAMETER_BLOCK param_block;
583 PMODE_FORMAT_PAGE format_page;
584 ULONG offset;
585 UCHAR buffer[256];
586 BOOLEAN valid_page = FALSE;
587 BOOLEAN cdb_llbaa;
588 BOOLEAN cdb_dbd;
589 UCHAR cdb_page_code;
590 USHORT cdb_allocation_length;
591 PVOID data_buffer;
592 //ULONG data_buffer_length;
594 UNREFERENCED_PARAMETER(xvdd);
596 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
598 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
599 data_buffer = get_databuffer_virtual(xvdd, srb);
600 //cdb = (PCDB)srb->Cdb;
601 switch (srb->Cdb[0])
602 {
603 case SCSIOP_MODE_SENSE:
604 cdb_llbaa = FALSE;
605 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
606 cdb_page_code = srb->Cdb[2] & 0x3f;
607 cdb_allocation_length = srb->Cdb[4];
608 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
609 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
610 break;
611 case SCSIOP_MODE_SENSE10:
612 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
613 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
614 cdb_page_code = srb->Cdb[2] & 0x3f;
615 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
616 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
617 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
618 break;
619 default:
620 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
621 return FALSE;
622 }
623 offset = 0;
625 RtlZeroMemory(data_buffer, srb->DataTransferLength);
626 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
628 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
629 parameter_header->MediumType = 0;
630 parameter_header->DeviceSpecificParameter = 0;
631 parameter_header->BlockDescriptorLength = 0;
632 offset += sizeof(MODE_PARAMETER_HEADER);
634 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
635 {
636 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
637 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
638 }
640 if (!cdb_dbd)
641 {
642 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
643 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
644 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
645 {
646 if (xvdd->total_sectors >> 32)
647 {
648 param_block->DensityCode = 0xff;
649 param_block->NumberOfBlocks[0] = 0xff;
650 param_block->NumberOfBlocks[1] = 0xff;
651 param_block->NumberOfBlocks[2] = 0xff;
652 }
653 else
654 {
655 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
656 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
657 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
658 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
659 }
660 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
661 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
662 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
663 }
664 offset += sizeof(MODE_PARAMETER_BLOCK);
665 }
666 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
667 {
668 valid_page = TRUE;
669 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
670 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
671 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
672 /* 256 sectors per track */
673 format_page->SectorsPerTrack[0] = 0x01;
674 format_page->SectorsPerTrack[1] = 0x00;
675 /* xxx bytes per sector */
676 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
677 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
678 format_page->HardSectorFormating = TRUE;
679 format_page->SoftSectorFormating = TRUE;
680 offset += sizeof(MODE_FORMAT_PAGE);
681 }
682 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
683 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
684 {
685 srb->SrbStatus = SRB_STATUS_ERROR;
686 }
687 else if(offset < srb->DataTransferLength)
688 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
689 else
690 srb->SrbStatus = SRB_STATUS_SUCCESS;
691 srb->DataTransferLength = min(srb->DataTransferLength, offset);
692 srb->ScsiStatus = 0;
693 memcpy(data_buffer, buffer, srb->DataTransferLength);
695 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
697 return TRUE;
698 }
700 static VOID
701 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
702 {
703 PSENSE_DATA sd = srb->SenseInfoBuffer;
705 UNREFERENCED_PARAMETER(xvdd);
707 if (!srb->SenseInfoBuffer)
708 return;
710 sd->ErrorCode = 0x70;
711 sd->Valid = 1;
712 sd->SenseKey = sense_key;
713 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
714 sd->AdditionalSenseCode = additional_sense_code;
715 return;
716 }
718 static VOID
719 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
720 {
721 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
722 return;
723 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
724 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
725 }
727 static BOOLEAN DDKAPI
728 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
729 {
730 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
731 PSCSI_REQUEST_BLOCK srb;
732 RING_IDX i, rp;
733 ULONG j;
734 blkif_response_t *rep;
735 int block_count;
736 int more_to_do = TRUE;
737 blkif_shadow_t *shadow;
738 ULONG suspend_resume_state_pdo;
739 BOOLEAN last_interrupt = FALSE;
741 /* in dump mode I think we get called on a timer, not by an actual IRQ */
742 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
743 return FALSE; /* interrupt was not for us */
745 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
746 KeMemoryBarrier();
748 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
749 {
750 FUNCTION_ENTER();
751 switch (suspend_resume_state_pdo)
752 {
753 case SR_STATE_SUSPENDING:
754 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
755 break;
756 case SR_STATE_RESUMING:
757 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
758 XenVbd_InitFromConfig(xvdd);
759 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
760 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
761 break;
762 case SR_STATE_RUNNING:
763 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
764 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
765 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
766 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
767 default:
768 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
769 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
770 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
771 break;
772 }
773 KeMemoryBarrier();
774 }
776 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
777 {
778 return last_interrupt;
779 }
781 while (more_to_do)
782 {
783 rp = xvdd->ring.sring->rsp_prod;
784 KeMemoryBarrier();
785 for (i = xvdd->ring.rsp_cons; i < rp; i++)
786 {
787 rep = XenVbd_GetResponse(xvdd, i);
788 /*
789 * This code is to automatically detect if the backend is using the same
790 * bit width or a different bit width to us. Later versions of Xen do this
791 * via a xenstore value, but not all. That 0x0fffffff (notice
792 * that the msb is not actually set, so we don't have any problems with
793 * sign extending) is to signify the last entry on the right, which is
794 * different under 32 and 64 bits, and that is why we set it up there.
796 * To do the detection, we put two initial entries on the ring, with an op
797 * of 0xff (which is invalid). The first entry is mostly okay, but the
798 * second will be grossly misaligned if the backend bit width is different,
799 * and we detect this and switch frontend structures.
800 */
801 switch (xvdd->ring_detect_state)
802 {
803 case RING_DETECT_STATE_NOT_STARTED:
804 KdPrint((__DRIVER_NAME " premature IRQ\n"));
805 break;
806 case RING_DETECT_STATE_DETECT1:
807 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
808 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
809 break;
810 case RING_DETECT_STATE_DETECT2:
811 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
812 *xvdd->event_channel_ptr |= 0x80000000;
813 if (rep->operation != 0xff)
814 {
815 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
816 xvdd->use_other = TRUE;
817 *xvdd->event_channel_ptr |= 0x40000000;
818 }
819 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
820 ScsiPortNotification(NextRequest, DeviceExtension);
821 break;
822 case RING_DETECT_STATE_COMPLETE:
823 shadow = &xvdd->shadows[rep->id];
824 srb = shadow->srb;
825 ASSERT(srb != NULL);
826 block_count = decode_cdb_length(srb);
827 block_count *= xvdd->bytes_per_sector / 512;
828 if (rep->status == BLKIF_RSP_OKAY)
829 srb->SrbStatus = SRB_STATUS_SUCCESS;
830 else
831 {
832 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
833 if (decode_cdb_is_read(srb))
834 KdPrint((__DRIVER_NAME " Operation = Read\n"));
835 else
836 KdPrint((__DRIVER_NAME " Operation = Write\n"));
837 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
838 srb->SrbStatus = SRB_STATUS_ERROR;
839 srb->ScsiStatus = 0x02;
840 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
841 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
842 XenVbd_MakeAutoSense(xvdd, srb);
843 }
844 put_shadow_on_freelist(xvdd, shadow);
845 if (dump_mode)
846 {
847 for (j = 0; j < shadow->req.nr_segments; j++)
848 {
849 ASSERT(shadow->req.seg[j].gref == xvdd->dump_grant_refs[j]);
850 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
851 shadow->req.seg[j].gref, TRUE);
852 }
853 }
854 ScsiPortNotification(RequestComplete, xvdd, srb);
855 if (suspend_resume_state_pdo == SR_STATE_RUNNING)
856 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
857 break;
858 }
859 }
861 xvdd->ring.rsp_cons = i;
862 if (i != xvdd->ring.req_prod_pvt)
863 {
864 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
865 }
866 else
867 {
868 xvdd->ring.sring->rsp_event = i + 1;
869 more_to_do = FALSE;
870 }
871 }
873 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
874 {
875 if (xvdd->shadow_free == SHADOW_ENTRIES)
876 {
877 /* all entries are purged from the list. ready to suspend */
878 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
879 KeMemoryBarrier();
880 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
881 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
882 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
883 }
884 FUNCTION_EXIT();
885 }
887 return last_interrupt;
888 }
890 static BOOLEAN DDKAPI
891 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
892 {
893 PUCHAR data_buffer;
894 //ULONG data_buffer_length;
895 PCDB cdb;
896 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
898 if (xvdd->inactive)
899 {
900 KdPrint((__DRIVER_NAME " Inactive Srb->Function = %08X\n", Srb->Function));
901 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
902 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
903 ScsiPortNotification(NextRequest, DeviceExtension);
904 return TRUE;
905 }
907 // If we haven't enumerated all the devices yet then just defer the request
908 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
909 {
910 Srb->SrbStatus = SRB_STATUS_BUSY;
911 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
912 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
913 return TRUE;
914 }
916 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
917 {
918 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
919 Srb->SrbStatus = SRB_STATUS_BUSY;
920 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
921 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
922 return TRUE;
923 }
925 if (Srb->PathId != 0 || Srb->TargetId != 0)
926 {
927 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
928 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
929 ScsiPortNotification(NextRequest, DeviceExtension);
930 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
931 return TRUE;
932 }
934 switch (Srb->Function)
935 {
936 case SRB_FUNCTION_EXECUTE_SCSI:
937 cdb = (PCDB)Srb->Cdb;
939 switch(cdb->CDB6GENERIC.OperationCode)
940 {
941 case SCSIOP_TEST_UNIT_READY:
942 if (dump_mode)
943 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
944 Srb->SrbStatus = SRB_STATUS_SUCCESS;
945 Srb->ScsiStatus = 0;
946 break;
947 case SCSIOP_INQUIRY:
948 if (dump_mode)
949 {
950 //PHYSICAL_ADDRESS physical;
951 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
952 //KdPrint((__DRIVER_NAME " Srb->Databuffer = %p\n", Srb->DataBuffer));
953 //physical = ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length);
954 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
955 }
956 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
957 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
959 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
960 data_buffer = get_databuffer_virtual(xvdd, Srb);
961 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
962 Srb->SrbStatus = SRB_STATUS_SUCCESS;
963 switch (xvdd->device_type)
964 {
965 case XENVBD_DEVICETYPE_DISK:
966 if ((Srb->Cdb[1] & 1) == 0)
967 {
968 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
969 id->DeviceType = DIRECT_ACCESS_DEVICE;
970 id->Versions = 3;
971 id->ResponseDataFormat = 0;
972 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
973 id->CommandQueue = 1;
974 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
975 memcpy(id->ProductId, scsi_disk_model, 16); // product id
976 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
977 }
978 else
979 {
980 switch (Srb->Cdb[2])
981 {
982 case 0x00:
983 data_buffer[0] = DIRECT_ACCESS_DEVICE;
984 data_buffer[1] = 0x00;
985 data_buffer[2] = 0x00;
986 data_buffer[3] = 2;
987 data_buffer[4] = 0x00;
988 data_buffer[5] = 0x80;
989 break;
990 case 0x80:
991 data_buffer[0] = DIRECT_ACCESS_DEVICE;
992 data_buffer[1] = 0x80;
993 data_buffer[2] = 0x00;
994 data_buffer[3] = 8;
995 memset(&data_buffer[4], ' ', 8);
996 break;
997 default:
998 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
999 Srb->SrbStatus = SRB_STATUS_ERROR;
1000 break;
1003 break;
1004 case XENVBD_DEVICETYPE_CDROM:
1005 if ((Srb->Cdb[1] & 1) == 0)
1007 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1008 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1009 id->RemovableMedia = 1;
1010 id->Versions = 3;
1011 id->ResponseDataFormat = 0;
1012 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1013 id->CommandQueue = 1;
1014 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1015 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1016 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1018 else
1020 switch (Srb->Cdb[2])
1022 case 0x00:
1023 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1024 data_buffer[1] = 0x00;
1025 data_buffer[2] = 0x00;
1026 data_buffer[3] = 2;
1027 data_buffer[4] = 0x00;
1028 data_buffer[5] = 0x80;
1029 break;
1030 case 0x80:
1031 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1032 data_buffer[1] = 0x80;
1033 data_buffer[2] = 0x00;
1034 data_buffer[3] = 8;
1035 data_buffer[4] = 0x31;
1036 data_buffer[5] = 0x32;
1037 data_buffer[6] = 0x33;
1038 data_buffer[7] = 0x34;
1039 data_buffer[8] = 0x35;
1040 data_buffer[9] = 0x36;
1041 data_buffer[10] = 0x37;
1042 data_buffer[11] = 0x38;
1043 break;
1044 default:
1045 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1046 Srb->SrbStatus = SRB_STATUS_ERROR;
1047 break;
1050 break;
1051 default:
1052 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1053 Srb->SrbStatus = SRB_STATUS_ERROR;
1054 break;
1056 break;
1057 case SCSIOP_READ_CAPACITY:
1058 if (dump_mode)
1059 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1060 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1061 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1062 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1063 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1064 data_buffer = get_databuffer_virtual(xvdd, Srb);
1065 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1066 if ((xvdd->total_sectors - 1) >> 32)
1068 data_buffer[0] = 0xff;
1069 data_buffer[1] = 0xff;
1070 data_buffer[2] = 0xff;
1071 data_buffer[3] = 0xff;
1073 else
1075 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1076 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1077 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1078 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1080 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1081 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1082 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1083 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1084 Srb->ScsiStatus = 0;
1085 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1086 break;
1087 case SCSIOP_READ_CAPACITY16:
1088 if (dump_mode)
1089 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1090 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1091 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1092 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1093 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1094 data_buffer = get_databuffer_virtual(xvdd, Srb);
1095 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1096 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1097 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1098 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1099 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1100 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1101 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1102 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1103 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1104 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1105 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1106 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1107 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1108 Srb->ScsiStatus = 0;
1109 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1110 break;
1111 case SCSIOP_MODE_SENSE:
1112 case SCSIOP_MODE_SENSE10:
1113 if (dump_mode)
1114 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));
1115 XenVbd_FillModePage(xvdd, Srb);
1116 break;
1117 case SCSIOP_READ:
1118 case SCSIOP_READ16:
1119 case SCSIOP_WRITE:
1120 case SCSIOP_WRITE16:
1121 //if (dump_mode)
1122 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1123 XenVbd_PutSrbOnRing(xvdd, Srb);
1124 break;
1125 case SCSIOP_VERIFY:
1126 // Should we do more here?
1127 if (dump_mode)
1128 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1129 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1130 break;
1131 case SCSIOP_REPORT_LUNS:
1132 if (dump_mode)
1133 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1134 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1135 break;
1136 case SCSIOP_REQUEST_SENSE:
1137 if (dump_mode)
1138 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1139 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1140 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1141 break;
1142 case SCSIOP_READ_TOC:
1143 if (dump_mode)
1144 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1145 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1146 data_buffer = get_databuffer_virtual(xvdd, Srb);
1147 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1148 /*
1149 #define READ_TOC_FORMAT_TOC 0x00
1150 #define READ_TOC_FORMAT_SESSION 0x01
1151 #define READ_TOC_FORMAT_FULL_TOC 0x02
1152 #define READ_TOC_FORMAT_PMA 0x03
1153 #define READ_TOC_FORMAT_ATIP 0x04
1154 */
1155 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1156 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1157 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1158 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1159 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1160 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1161 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1162 switch (cdb->READ_TOC.Format2)
1164 case READ_TOC_FORMAT_TOC:
1165 data_buffer[0] = 0; // length MSB
1166 data_buffer[1] = 10; // length LSB
1167 data_buffer[2] = 1; // First Track
1168 data_buffer[3] = 1; // Last Track
1169 data_buffer[4] = 0; // Reserved
1170 data_buffer[5] = 0x14; // current position data + uninterrupted data
1171 data_buffer[6] = 1; // last complete track
1172 data_buffer[7] = 0; // reserved
1173 data_buffer[8] = 0; // MSB Block
1174 data_buffer[9] = 0;
1175 data_buffer[10] = 0;
1176 data_buffer[11] = 0; // LSB Block
1177 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1178 break;
1179 case READ_TOC_FORMAT_SESSION:
1180 case READ_TOC_FORMAT_FULL_TOC:
1181 case READ_TOC_FORMAT_PMA:
1182 case READ_TOC_FORMAT_ATIP:
1183 Srb->SrbStatus = SRB_STATUS_ERROR;
1184 break;
1186 break;
1187 case SCSIOP_START_STOP_UNIT:
1188 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1189 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1190 break;
1191 case SCSIOP_RESERVE_UNIT:
1192 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1193 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1194 break;
1195 case SCSIOP_RELEASE_UNIT:
1196 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1197 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1198 break;
1199 default:
1200 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1201 Srb->SrbStatus = SRB_STATUS_ERROR;
1202 break;
1204 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1206 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1207 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1209 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1210 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1212 Srb->ScsiStatus = 0x02;
1213 XenVbd_MakeAutoSense(xvdd, Srb);
1214 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1215 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1216 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1218 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1220 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1221 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1222 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1223 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1224 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1226 break;
1227 case SRB_FUNCTION_IO_CONTROL:
1228 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1229 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1230 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1231 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1232 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1233 break;
1234 case SRB_FUNCTION_FLUSH:
1235 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1236 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1237 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1238 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1239 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1240 break;
1241 case SRB_FUNCTION_SHUTDOWN:
1242 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1243 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1244 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1245 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1246 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1247 break;
1248 default:
1249 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1250 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1251 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1252 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1253 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1254 break;
1257 //FUNCTION_EXIT();
1258 return TRUE;
1261 static BOOLEAN
1262 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1264 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1266 UNREFERENCED_PARAMETER(DeviceExtension);
1267 UNREFERENCED_PARAMETER(PathId);
1269 FUNCTION_ENTER();
1271 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1272 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1274 ScsiPortNotification(NextRequest, DeviceExtension);
1277 FUNCTION_EXIT();
1280 return TRUE;
1283 static BOOLEAN
1284 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1286 UNREFERENCED_PARAMETER(DeviceExtension);
1287 UNREFERENCED_PARAMETER(Context);
1288 UNREFERENCED_PARAMETER(SaveState);
1290 FUNCTION_ENTER();
1291 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1293 FUNCTION_EXIT();
1295 return TRUE;
1298 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1299 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1301 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1302 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1303 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1304 //KIRQL OldIrql;
1306 FUNCTION_ENTER();
1307 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1308 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
1310 switch (ControlType)
1312 case ScsiQuerySupportedControlTypes:
1313 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1314 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1315 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1316 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1317 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1318 break;
1319 case ScsiStopAdapter:
1320 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1321 //KdBreakPoint();
1322 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1323 break;
1324 case ScsiRestartAdapter:
1325 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1326 if (!xvdd->inactive)
1328 if (XenVbd_InitFromConfig(xvdd) != SP_RETURN_FOUND)
1329 KeBugCheckEx(DATA_COHERENCY_EXCEPTION, 0, (ULONG_PTR) xvdd, 0, 0);
1330 XenVbd_StartRingDetection(xvdd);
1332 break;
1333 case ScsiSetBootConfig:
1334 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1335 break;
1336 case ScsiSetRunningConfig:
1337 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1338 break;
1339 default:
1340 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1341 break;
1344 FUNCTION_EXIT();
1346 return Status;
1349 PVOID init_driver_extension;
1351 static BOOLEAN
1352 XenVbd_DmaNeedVirtualAddress(PIRP irp)
1354 PIO_STACK_LOCATION stack;
1356 //FUNCTION_ENTER();
1358 stack = IoGetCurrentIrpStackLocation(irp);
1359 if (stack->MajorFunction != IRP_MJ_SCSI)
1361 KdPrint((__DRIVER_NAME " Not IRP_MJ_SCSI\n"));
1362 //FUNCTION_EXIT();
1363 return FALSE; /* this actually shouldn't happen */
1366 switch (stack->Parameters.Scsi.Srb->Cdb[0])
1368 case SCSIOP_READ:
1369 case SCSIOP_READ16:
1370 case SCSIOP_WRITE:
1371 case SCSIOP_WRITE16:
1372 //KdPrint((__DRIVER_NAME " read/write operation\n"));
1373 //FUNCTION_EXIT();
1374 return FALSE;
1375 default:
1376 //KdPrint((__DRIVER_NAME " not a read/write operation\n"));
1377 //FUNCTION_EXIT();
1378 return TRUE;
1382 static ULONG
1383 XenVbd_DmaGetAlignment(PIRP irp)
1385 UNREFERENCED_PARAMETER(irp);
1387 //FUNCTION_ENTER();
1388 //FUNCTION_EXIT();
1389 return 512;
1392 dma_driver_extension_t *dma_driver_extension;
1394 NTSTATUS
1395 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1397 ULONG status;
1398 HW_INITIALIZATION_DATA HwInitializationData;
1399 PVOID driver_extension;
1400 PUCHAR ptr;
1401 OBJECT_ATTRIBUTES oa;
1402 HANDLE service_handle;
1403 UNICODE_STRING param_name;
1404 HANDLE param_handle;
1405 UNICODE_STRING value_name;
1406 CHAR buf[256];
1407 ULONG buf_len;
1408 PKEY_VALUE_PARTIAL_INFORMATION kpv;
1410 FUNCTION_ENTER();
1411 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1412 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1414 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1415 if (!RegistryPath)
1417 dump_mode = TRUE;
1420 if (!dump_mode)
1422 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1423 ptr = driver_extension;
1424 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1425 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_MATCH_FRONT, "device-type", "disk", UlongToPtr(XEN_INIT_MATCH_TYPE_IF_NOT_MATCH|XEN_INIT_MATCH_TYPE_SET_INACTIVE|XEN_INIT_MATCH_TYPE_DONT_CONFIG));
1426 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1427 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1428 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1429 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1430 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1431 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1432 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
1433 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1435 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC), sizeof(dma_driver_extension_t), &dma_driver_extension);
1436 dma_driver_extension->need_virtual_address = XenVbd_DmaNeedVirtualAddress;
1437 dma_driver_extension->get_alignment = XenVbd_DmaGetAlignment;
1438 dma_driver_extension->max_sg_elements = 0;
1440 // get registry service key handle
1441 // get parameters key handle
1442 // get disk value name
1443 // get cdrom value name
1445 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1446 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
1447 if(!NT_SUCCESS(status))
1449 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
1451 else
1453 RtlInitUnicodeString(&param_name, L"Parameters");
1454 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
1455 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
1456 if(!NT_SUCCESS(status))
1458 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
1460 else
1462 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
1463 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
1464 RtlFillMemory(scsi_disk_model, 16, ' ');
1465 RtlFillMemory(scsi_cdrom_model, 16, ' ');
1467 RtlInitUnicodeString(&value_name, L"Manufacturer");
1468 buf_len = 256;
1469 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1470 if(NT_SUCCESS(status))
1471 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
1472 else
1473 strncpy(scsi_device_manufacturer, "XEN ", 8);
1475 RtlInitUnicodeString(&value_name, L"Disk_Model");
1476 buf_len = 256;
1477 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1478 if(NT_SUCCESS(status))
1479 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1480 else
1481 strncpy(scsi_disk_model, "PV DISK ", 16);
1483 RtlInitUnicodeString(&value_name, L"CDROM_Model");
1484 buf_len = 256;
1485 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1486 if(NT_SUCCESS(status))
1487 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1488 else
1489 strncpy(scsi_cdrom_model, "PV CDROM ", 16);
1491 ZwClose(service_handle);
1495 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1497 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1498 HwInitializationData.AdapterInterfaceType = PNPBus;
1499 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1500 HwInitializationData.SpecificLuExtensionSize = 0;
1501 HwInitializationData.SrbExtensionSize = 0;
1502 HwInitializationData.NumberOfAccessRanges = 1;
1503 HwInitializationData.MapBuffers = FALSE;
1504 HwInitializationData.NeedPhysicalAddresses = TRUE;
1505 HwInitializationData.TaggedQueuing = TRUE;
1506 HwInitializationData.AutoRequestSense = TRUE;
1507 HwInitializationData.MultipleRequestPerLu = TRUE;
1508 HwInitializationData.ReceiveEvent = FALSE;
1509 HwInitializationData.VendorIdLength = 0;
1510 HwInitializationData.VendorId = NULL;
1511 HwInitializationData.DeviceIdLength = 0;
1512 HwInitializationData.DeviceId = NULL;
1514 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1515 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1516 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1517 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1518 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1519 HwInitializationData.HwDmaStarted = NULL;
1520 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1521 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1523 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1525 if(!NT_SUCCESS(status))
1527 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1530 FUNCTION_EXIT();
1532 return status;