win-pvdrivers

view xenvbd/xenvbd.c @ 587:cfe35004c0f7

Zero the ring before doing bit-width detection.
author James Harper <james.harper@bendigoit.com.au>
date Tue Jun 09 12:01:23 2009 +1000 (2009-06-09)
parents 17e6a7e1d3df
children d40c760a4f6b
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 //KdPrint((__DRIVER_NAME " length(a) = %d\n", length));
402 shadow->req.seg[shadow->req.nr_segments].gref = gref;
403 //KdPrint((__DRIVER_NAME " length(b) = %d\n", length));
404 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
405 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
406 remaining -= length;
407 ptr += length;
408 shadow->req.nr_segments++;
409 }
411 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
413 XenVbd_PutRequest(xvdd, &shadow->req);
415 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
416 if (notify)
417 {
418 //KdPrint((__DRIVER_NAME " Notifying\n"));
419 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
420 }
422 if (xvdd->shadow_free)
423 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
425 //FUNCTION_EXIT();
426 }
428 static ULONG DDKAPI
429 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
430 {
431 // PACCESS_RANGE AccessRange;
432 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
433 ULONG status;
434 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
435 PACCESS_RANGE access_range;
437 UNREFERENCED_PARAMETER(HwContext);
438 UNREFERENCED_PARAMETER(BusInformation);
439 UNREFERENCED_PARAMETER(ArgumentString);
441 FUNCTION_ENTER();
442 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
443 KdPrint((__DRIVER_NAME " xvdd = %p\n", xvdd));
445 {
446 int i;
447 for (i = 0; i < sizeof(XENVBD_DEVICE_DATA); i++)
448 {
449 if (((PUCHAR)xvdd)[i])
450 {
451 KdPrint((__DRIVER_NAME " DeviceExtension is not zeroed!!!\n"));
452 break;
453 }
454 }
455 }
456 RtlZeroMemory(xvdd, sizeof(XENVBD_DEVICE_DATA));
457 *Again = FALSE;
459 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
460 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
462 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
463 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
464 {
465 return SP_RETURN_BAD_CONFIG;
466 }
468 access_range = &((*(ConfigInfo->AccessRanges))[0]);
469 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
470 access_range->RangeStart.LowPart, access_range->RangeLength));
471 xvdd->device_base = ScsiPortGetDeviceBase(
472 DeviceExtension,
473 ConfigInfo->AdapterInterfaceType,
474 ConfigInfo->SystemIoBusNumber,
475 access_range->RangeStart,
476 access_range->RangeLength,
477 !access_range->RangeInMemory);
478 if (!xvdd->device_base)
479 {
480 KdPrint((__DRIVER_NAME " Invalid config\n"));
481 FUNCTION_EXIT();
482 return SP_RETURN_BAD_CONFIG;
483 }
485 status = XenVbd_InitFromConfig(xvdd);
486 if (status != SP_RETURN_FOUND)
487 {
488 FUNCTION_EXIT();
489 return status;
490 }
492 if (!dump_mode)
493 {
494 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
495 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
496 ConfigInfo->ScatterGather = TRUE;
497 }
498 else
499 {
500 ConfigInfo->MaximumTransferLength = 4096;
501 ConfigInfo->NumberOfPhysicalBreaks = 0;
502 ConfigInfo->ScatterGather = FALSE;
503 }
504 ConfigInfo->AlignmentMask = 0;
505 ConfigInfo->NumberOfBuses = 1;
506 ConfigInfo->InitiatorBusId[0] = 1;
507 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
508 ConfigInfo->MaximumNumberOfTargets = 2;
509 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
510 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
511 {
512 ConfigInfo->Master = TRUE;
513 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
514 ConfigInfo->Dma32BitAddresses = FALSE;
515 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
516 }
517 else
518 {
519 ConfigInfo->Master = TRUE;
520 ConfigInfo->Dma32BitAddresses = TRUE;
521 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
522 }
524 FUNCTION_EXIT();
526 return SP_RETURN_FOUND;
527 }
529 static VOID
530 XenVbd_StartRingDetection(PXENVBD_DEVICE_DATA xvdd)
531 {
532 blkif_request_t *req;
533 int notify;
535 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
536 RtlZeroMemory(xvdd->sring->ring, PAGE_SIZE);
537 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
538 req->operation = 0xff;
539 xvdd->ring.req_prod_pvt++;
540 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
541 req->operation = 0xff;
542 xvdd->ring.req_prod_pvt++;
544 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
545 if (notify)
546 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
547 }
549 static BOOLEAN
550 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
551 {
552 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
554 FUNCTION_ENTER();
555 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
556 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
558 if (!xvdd->inactive)
559 {
560 if (!dump_mode)
561 {
562 XenVbd_StartRingDetection(xvdd);
563 }
564 else
565 {
566 if (xvdd->cached_use_other)
567 {
568 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
569 xvdd->use_other = TRUE;
570 }
571 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
572 }
573 }
574 FUNCTION_EXIT();
576 return TRUE;
577 }
579 static ULONG
580 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
581 {
582 PMODE_PARAMETER_HEADER parameter_header;
583 PMODE_PARAMETER_BLOCK param_block;
584 PMODE_FORMAT_PAGE format_page;
585 ULONG offset;
586 UCHAR buffer[256];
587 BOOLEAN valid_page = FALSE;
588 BOOLEAN cdb_llbaa;
589 BOOLEAN cdb_dbd;
590 UCHAR cdb_page_code;
591 USHORT cdb_allocation_length;
592 PVOID data_buffer;
593 //ULONG data_buffer_length;
595 UNREFERENCED_PARAMETER(xvdd);
597 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
599 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
600 data_buffer = get_databuffer_virtual(xvdd, srb);
601 //cdb = (PCDB)srb->Cdb;
602 switch (srb->Cdb[0])
603 {
604 case SCSIOP_MODE_SENSE:
605 cdb_llbaa = FALSE;
606 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
607 cdb_page_code = srb->Cdb[2] & 0x3f;
608 cdb_allocation_length = srb->Cdb[4];
609 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
610 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
611 break;
612 case SCSIOP_MODE_SENSE10:
613 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
614 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
615 cdb_page_code = srb->Cdb[2] & 0x3f;
616 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
617 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
618 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
619 break;
620 default:
621 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
622 return FALSE;
623 }
624 offset = 0;
626 RtlZeroMemory(data_buffer, srb->DataTransferLength);
627 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
629 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
630 parameter_header->MediumType = 0;
631 parameter_header->DeviceSpecificParameter = 0;
632 parameter_header->BlockDescriptorLength = 0;
633 offset += sizeof(MODE_PARAMETER_HEADER);
635 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
636 {
637 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
638 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
639 }
641 if (!cdb_dbd)
642 {
643 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
644 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
645 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
646 {
647 if (xvdd->total_sectors >> 32)
648 {
649 param_block->DensityCode = 0xff;
650 param_block->NumberOfBlocks[0] = 0xff;
651 param_block->NumberOfBlocks[1] = 0xff;
652 param_block->NumberOfBlocks[2] = 0xff;
653 }
654 else
655 {
656 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
657 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
658 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
659 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
660 }
661 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
662 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
663 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
664 }
665 offset += sizeof(MODE_PARAMETER_BLOCK);
666 }
667 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
668 {
669 valid_page = TRUE;
670 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
671 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
672 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
673 /* 256 sectors per track */
674 format_page->SectorsPerTrack[0] = 0x01;
675 format_page->SectorsPerTrack[1] = 0x00;
676 /* xxx bytes per sector */
677 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
678 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
679 format_page->HardSectorFormating = TRUE;
680 format_page->SoftSectorFormating = TRUE;
681 offset += sizeof(MODE_FORMAT_PAGE);
682 }
683 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
684 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
685 {
686 srb->SrbStatus = SRB_STATUS_ERROR;
687 }
688 else if(offset < srb->DataTransferLength)
689 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
690 else
691 srb->SrbStatus = SRB_STATUS_SUCCESS;
692 srb->DataTransferLength = min(srb->DataTransferLength, offset);
693 srb->ScsiStatus = 0;
694 memcpy(data_buffer, buffer, srb->DataTransferLength);
696 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
698 return TRUE;
699 }
701 static VOID
702 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
703 {
704 PSENSE_DATA sd = srb->SenseInfoBuffer;
706 UNREFERENCED_PARAMETER(xvdd);
708 if (!srb->SenseInfoBuffer)
709 return;
711 sd->ErrorCode = 0x70;
712 sd->Valid = 1;
713 sd->SenseKey = sense_key;
714 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
715 sd->AdditionalSenseCode = additional_sense_code;
716 return;
717 }
719 static VOID
720 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
721 {
722 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
723 return;
724 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
725 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
726 }
728 static BOOLEAN DDKAPI
729 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
730 {
731 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
732 PSCSI_REQUEST_BLOCK srb;
733 RING_IDX i, rp;
734 ULONG j;
735 blkif_response_t *rep;
736 int block_count;
737 int more_to_do = TRUE;
738 blkif_shadow_t *shadow;
739 ULONG suspend_resume_state_pdo;
740 BOOLEAN last_interrupt = FALSE;
742 /* in dump mode I think we get called on a timer, not by an actual IRQ */
743 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
744 return FALSE; /* interrupt was not for us */
746 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
747 KeMemoryBarrier();
749 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
750 {
751 FUNCTION_ENTER();
752 switch (suspend_resume_state_pdo)
753 {
754 case SR_STATE_SUSPENDING:
755 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
756 break;
757 case SR_STATE_RESUMING:
758 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
759 XenVbd_InitFromConfig(xvdd);
760 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
761 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
762 break;
763 case SR_STATE_RUNNING:
764 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
765 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
766 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
767 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
768 default:
769 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
770 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
771 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
772 break;
773 }
774 KeMemoryBarrier();
775 }
777 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
778 {
779 return last_interrupt;
780 }
782 while (more_to_do)
783 {
784 rp = xvdd->ring.sring->rsp_prod;
785 KeMemoryBarrier();
786 for (i = xvdd->ring.rsp_cons; i < rp; i++)
787 {
788 rep = XenVbd_GetResponse(xvdd, i);
789 /*
790 * This code is to automatically detect if the backend is using the same
791 * bit width or a different bit width to us. Later versions of Xen do this
792 * via a xenstore value, but not all. That 0x0fffffff (notice
793 * that the msb is not actually set, so we don't have any problems with
794 * sign extending) is to signify the last entry on the right, which is
795 * different under 32 and 64 bits, and that is why we set it up there.
797 * To do the detection, we put two initial entries on the ring, with an op
798 * of 0xff (which is invalid). The first entry is mostly okay, but the
799 * second will be grossly misaligned if the backend bit width is different,
800 * and we detect this and switch frontend structures.
801 */
802 switch (xvdd->ring_detect_state)
803 {
804 case RING_DETECT_STATE_NOT_STARTED:
805 KdPrint((__DRIVER_NAME " premature IRQ\n"));
806 break;
807 case RING_DETECT_STATE_DETECT1:
808 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
809 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
810 break;
811 case RING_DETECT_STATE_DETECT2:
812 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
813 *xvdd->event_channel_ptr |= 0x80000000;
814 if (rep->operation != 0xff)
815 {
816 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
817 xvdd->use_other = TRUE;
818 *xvdd->event_channel_ptr |= 0x40000000;
819 }
820 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
821 ScsiPortNotification(NextRequest, DeviceExtension);
822 break;
823 case RING_DETECT_STATE_COMPLETE:
824 shadow = &xvdd->shadows[rep->id];
825 srb = shadow->srb;
826 ASSERT(srb != NULL);
827 block_count = decode_cdb_length(srb);
828 block_count *= xvdd->bytes_per_sector / 512;
829 if (rep->status == BLKIF_RSP_OKAY)
830 srb->SrbStatus = SRB_STATUS_SUCCESS;
831 else
832 {
833 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
834 if (decode_cdb_is_read(srb))
835 KdPrint((__DRIVER_NAME " Operation = Read\n"));
836 else
837 KdPrint((__DRIVER_NAME " Operation = Write\n"));
838 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
839 srb->SrbStatus = SRB_STATUS_ERROR;
840 srb->ScsiStatus = 0x02;
841 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
842 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
843 XenVbd_MakeAutoSense(xvdd, srb);
844 }
845 put_shadow_on_freelist(xvdd, shadow);
846 if (dump_mode)
847 {
848 for (j = 0; j < shadow->req.nr_segments; j++)
849 {
850 ASSERT(shadow->req.seg[j].gref == xvdd->dump_grant_refs[j]);
851 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
852 shadow->req.seg[j].gref, TRUE);
853 }
854 }
855 ScsiPortNotification(RequestComplete, xvdd, srb);
856 if (suspend_resume_state_pdo == SR_STATE_RUNNING)
857 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
858 break;
859 }
860 }
862 xvdd->ring.rsp_cons = i;
863 if (i != xvdd->ring.req_prod_pvt)
864 {
865 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
866 }
867 else
868 {
869 xvdd->ring.sring->rsp_event = i + 1;
870 more_to_do = FALSE;
871 }
872 }
874 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
875 {
876 if (xvdd->shadow_free == SHADOW_ENTRIES)
877 {
878 /* all entries are purged from the list. ready to suspend */
879 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
880 KeMemoryBarrier();
881 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
882 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
883 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
884 }
885 FUNCTION_EXIT();
886 }
888 return last_interrupt;
889 }
891 static BOOLEAN DDKAPI
892 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
893 {
894 PUCHAR data_buffer;
895 //ULONG data_buffer_length;
896 PCDB cdb;
897 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
899 if (xvdd->inactive)
900 {
901 KdPrint((__DRIVER_NAME " Inactive Srb->Function = %08X\n", Srb->Function));
902 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
903 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
904 ScsiPortNotification(NextRequest, DeviceExtension);
905 return TRUE;
906 }
908 // If we haven't enumerated all the devices yet then just defer the request
909 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
910 {
911 Srb->SrbStatus = SRB_STATUS_BUSY;
912 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
913 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
914 return TRUE;
915 }
917 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
918 {
919 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
920 Srb->SrbStatus = SRB_STATUS_BUSY;
921 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
922 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
923 return TRUE;
924 }
926 if (Srb->PathId != 0 || Srb->TargetId != 0)
927 {
928 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
929 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
930 ScsiPortNotification(NextRequest, DeviceExtension);
931 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
932 return TRUE;
933 }
935 switch (Srb->Function)
936 {
937 case SRB_FUNCTION_EXECUTE_SCSI:
938 cdb = (PCDB)Srb->Cdb;
940 switch(cdb->CDB6GENERIC.OperationCode)
941 {
942 case SCSIOP_TEST_UNIT_READY:
943 if (dump_mode)
944 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
945 Srb->SrbStatus = SRB_STATUS_SUCCESS;
946 Srb->ScsiStatus = 0;
947 break;
948 case SCSIOP_INQUIRY:
949 if (dump_mode)
950 {
951 //PHYSICAL_ADDRESS physical;
952 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
953 //KdPrint((__DRIVER_NAME " Srb->Databuffer = %p\n", Srb->DataBuffer));
954 //physical = ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length);
955 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
956 }
957 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
958 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
960 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
961 data_buffer = get_databuffer_virtual(xvdd, Srb);
962 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
963 Srb->SrbStatus = SRB_STATUS_SUCCESS;
964 switch (xvdd->device_type)
965 {
966 case XENVBD_DEVICETYPE_DISK:
967 if ((Srb->Cdb[1] & 1) == 0)
968 {
969 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
970 id->DeviceType = DIRECT_ACCESS_DEVICE;
971 id->Versions = 3;
972 id->ResponseDataFormat = 0;
973 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
974 id->CommandQueue = 1;
975 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
976 memcpy(id->ProductId, scsi_disk_model, 16); // product id
977 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
978 }
979 else
980 {
981 switch (Srb->Cdb[2])
982 {
983 case 0x00:
984 data_buffer[0] = DIRECT_ACCESS_DEVICE;
985 data_buffer[1] = 0x00;
986 data_buffer[2] = 0x00;
987 data_buffer[3] = 2;
988 data_buffer[4] = 0x00;
989 data_buffer[5] = 0x80;
990 break;
991 case 0x80:
992 data_buffer[0] = DIRECT_ACCESS_DEVICE;
993 data_buffer[1] = 0x80;
994 data_buffer[2] = 0x00;
995 data_buffer[3] = 8;
996 memset(&data_buffer[4], ' ', 8);
997 break;
998 default:
999 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1000 Srb->SrbStatus = SRB_STATUS_ERROR;
1001 break;
1004 break;
1005 case XENVBD_DEVICETYPE_CDROM:
1006 if ((Srb->Cdb[1] & 1) == 0)
1008 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1009 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1010 id->RemovableMedia = 1;
1011 id->Versions = 3;
1012 id->ResponseDataFormat = 0;
1013 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1014 id->CommandQueue = 1;
1015 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1016 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1017 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1019 else
1021 switch (Srb->Cdb[2])
1023 case 0x00:
1024 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1025 data_buffer[1] = 0x00;
1026 data_buffer[2] = 0x00;
1027 data_buffer[3] = 2;
1028 data_buffer[4] = 0x00;
1029 data_buffer[5] = 0x80;
1030 break;
1031 case 0x80:
1032 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1033 data_buffer[1] = 0x80;
1034 data_buffer[2] = 0x00;
1035 data_buffer[3] = 8;
1036 data_buffer[4] = 0x31;
1037 data_buffer[5] = 0x32;
1038 data_buffer[6] = 0x33;
1039 data_buffer[7] = 0x34;
1040 data_buffer[8] = 0x35;
1041 data_buffer[9] = 0x36;
1042 data_buffer[10] = 0x37;
1043 data_buffer[11] = 0x38;
1044 break;
1045 default:
1046 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1047 Srb->SrbStatus = SRB_STATUS_ERROR;
1048 break;
1051 break;
1052 default:
1053 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1054 Srb->SrbStatus = SRB_STATUS_ERROR;
1055 break;
1057 break;
1058 case SCSIOP_READ_CAPACITY:
1059 if (dump_mode)
1060 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1061 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1062 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1063 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1064 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1065 data_buffer = get_databuffer_virtual(xvdd, Srb);
1066 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1067 if ((xvdd->total_sectors - 1) >> 32)
1069 data_buffer[0] = 0xff;
1070 data_buffer[1] = 0xff;
1071 data_buffer[2] = 0xff;
1072 data_buffer[3] = 0xff;
1074 else
1076 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1077 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1078 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1079 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1081 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1082 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1083 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1084 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1085 Srb->ScsiStatus = 0;
1086 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1087 break;
1088 case SCSIOP_READ_CAPACITY16:
1089 if (dump_mode)
1090 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1091 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1092 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1093 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1094 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1095 data_buffer = get_databuffer_virtual(xvdd, Srb);
1096 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1097 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1098 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1099 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1100 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1101 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1102 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1103 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1104 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1105 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1106 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1107 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1108 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1109 Srb->ScsiStatus = 0;
1110 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1111 break;
1112 case SCSIOP_MODE_SENSE:
1113 case SCSIOP_MODE_SENSE10:
1114 if (dump_mode)
1115 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));
1116 XenVbd_FillModePage(xvdd, Srb);
1117 break;
1118 case SCSIOP_READ:
1119 case SCSIOP_READ16:
1120 case SCSIOP_WRITE:
1121 case SCSIOP_WRITE16:
1122 //if (dump_mode)
1123 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1124 XenVbd_PutSrbOnRing(xvdd, Srb);
1125 break;
1126 case SCSIOP_VERIFY:
1127 // Should we do more here?
1128 if (dump_mode)
1129 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1130 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1131 break;
1132 case SCSIOP_REPORT_LUNS:
1133 if (dump_mode)
1134 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1135 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1136 break;
1137 case SCSIOP_REQUEST_SENSE:
1138 if (dump_mode)
1139 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1140 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1141 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1142 break;
1143 case SCSIOP_READ_TOC:
1144 if (dump_mode)
1145 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1146 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1147 data_buffer = get_databuffer_virtual(xvdd, Srb);
1148 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1149 /*
1150 #define READ_TOC_FORMAT_TOC 0x00
1151 #define READ_TOC_FORMAT_SESSION 0x01
1152 #define READ_TOC_FORMAT_FULL_TOC 0x02
1153 #define READ_TOC_FORMAT_PMA 0x03
1154 #define READ_TOC_FORMAT_ATIP 0x04
1155 */
1156 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1157 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1158 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1159 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1160 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1161 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1162 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1163 switch (cdb->READ_TOC.Format2)
1165 case READ_TOC_FORMAT_TOC:
1166 data_buffer[0] = 0; // length MSB
1167 data_buffer[1] = 10; // length LSB
1168 data_buffer[2] = 1; // First Track
1169 data_buffer[3] = 1; // Last Track
1170 data_buffer[4] = 0; // Reserved
1171 data_buffer[5] = 0x14; // current position data + uninterrupted data
1172 data_buffer[6] = 1; // last complete track
1173 data_buffer[7] = 0; // reserved
1174 data_buffer[8] = 0; // MSB Block
1175 data_buffer[9] = 0;
1176 data_buffer[10] = 0;
1177 data_buffer[11] = 0; // LSB Block
1178 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1179 break;
1180 case READ_TOC_FORMAT_SESSION:
1181 case READ_TOC_FORMAT_FULL_TOC:
1182 case READ_TOC_FORMAT_PMA:
1183 case READ_TOC_FORMAT_ATIP:
1184 Srb->SrbStatus = SRB_STATUS_ERROR;
1185 break;
1187 break;
1188 case SCSIOP_START_STOP_UNIT:
1189 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1190 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1191 break;
1192 case SCSIOP_RESERVE_UNIT:
1193 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1194 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1195 break;
1196 case SCSIOP_RELEASE_UNIT:
1197 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1198 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1199 break;
1200 default:
1201 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1202 Srb->SrbStatus = SRB_STATUS_ERROR;
1203 break;
1205 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1207 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1208 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1210 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1211 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1213 Srb->ScsiStatus = 0x02;
1214 XenVbd_MakeAutoSense(xvdd, Srb);
1215 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1216 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1217 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1219 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1221 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1222 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1223 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1224 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1225 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1227 break;
1228 case SRB_FUNCTION_IO_CONTROL:
1229 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1230 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1231 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1232 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1233 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1234 break;
1235 case SRB_FUNCTION_FLUSH:
1236 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1237 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1238 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1239 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1240 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1241 break;
1242 case SRB_FUNCTION_SHUTDOWN:
1243 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1244 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1245 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1246 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1247 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1248 break;
1249 default:
1250 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1251 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1252 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1253 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1254 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1255 break;
1258 //FUNCTION_EXIT();
1259 return TRUE;
1262 static BOOLEAN
1263 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1265 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1267 UNREFERENCED_PARAMETER(DeviceExtension);
1268 UNREFERENCED_PARAMETER(PathId);
1270 FUNCTION_ENTER();
1272 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1273 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1275 ScsiPortNotification(NextRequest, DeviceExtension);
1278 FUNCTION_EXIT();
1281 return TRUE;
1284 static BOOLEAN
1285 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1287 UNREFERENCED_PARAMETER(DeviceExtension);
1288 UNREFERENCED_PARAMETER(Context);
1289 UNREFERENCED_PARAMETER(SaveState);
1291 FUNCTION_ENTER();
1292 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1294 FUNCTION_EXIT();
1296 return TRUE;
1299 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1300 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1302 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1303 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1304 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1305 //KIRQL OldIrql;
1307 FUNCTION_ENTER();
1308 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
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 XenVbd_InitFromConfig(xvdd);
1327 if (!xvdd->inactive)
1328 XenVbd_StartRingDetection(xvdd);
1329 //if (xvdd->use_other)
1330 // xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
1331 break;
1332 case ScsiSetBootConfig:
1333 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1334 break;
1335 case ScsiSetRunningConfig:
1336 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1337 break;
1338 default:
1339 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1340 break;
1343 FUNCTION_EXIT();
1345 return Status;
1348 PVOID init_driver_extension;
1350 static BOOLEAN
1351 XenVbd_DmaNeedVirtualAddress(PIRP irp)
1353 PIO_STACK_LOCATION stack;
1355 //FUNCTION_ENTER();
1357 stack = IoGetCurrentIrpStackLocation(irp);
1358 if (stack->MajorFunction != IRP_MJ_SCSI)
1360 KdPrint((__DRIVER_NAME " Not IRP_MJ_SCSI\n"));
1361 //FUNCTION_EXIT();
1362 return FALSE; /* this actually shouldn't happen */
1365 switch (stack->Parameters.Scsi.Srb->Cdb[0])
1367 case SCSIOP_READ:
1368 case SCSIOP_READ16:
1369 case SCSIOP_WRITE:
1370 case SCSIOP_WRITE16:
1371 //KdPrint((__DRIVER_NAME " read/write operation\n"));
1372 //FUNCTION_EXIT();
1373 return FALSE;
1374 default:
1375 //KdPrint((__DRIVER_NAME " not a read/write operation\n"));
1376 //FUNCTION_EXIT();
1377 return TRUE;
1381 static ULONG
1382 XenVbd_DmaGetAlignment(PIRP irp)
1384 UNREFERENCED_PARAMETER(irp);
1386 //FUNCTION_ENTER();
1387 //FUNCTION_EXIT();
1388 return 512;
1391 dma_driver_extension_t *dma_driver_extension;
1393 NTSTATUS
1394 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1396 ULONG status;
1397 HW_INITIALIZATION_DATA HwInitializationData;
1398 PVOID driver_extension;
1399 PUCHAR ptr;
1400 OBJECT_ATTRIBUTES oa;
1401 HANDLE service_handle;
1402 UNICODE_STRING param_name;
1403 HANDLE param_handle;
1404 UNICODE_STRING value_name;
1405 CHAR buf[256];
1406 ULONG buf_len;
1407 PKEY_VALUE_PARTIAL_INFORMATION kpv;
1409 FUNCTION_ENTER();
1410 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1411 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1413 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1414 if (!RegistryPath)
1416 dump_mode = TRUE;
1419 if (!dump_mode)
1421 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1422 ptr = driver_extension;
1423 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1424 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));
1425 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1426 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1427 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1428 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1429 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1430 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1431 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
1432 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1434 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC), sizeof(dma_driver_extension_t), &dma_driver_extension);
1435 dma_driver_extension->need_virtual_address = XenVbd_DmaNeedVirtualAddress;
1436 dma_driver_extension->get_alignment = XenVbd_DmaGetAlignment;
1437 dma_driver_extension->max_sg_elements = 0;
1439 // get registry service key handle
1440 // get parameters key handle
1441 // get disk value name
1442 // get cdrom value name
1444 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1445 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
1446 if(!NT_SUCCESS(status))
1448 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
1450 else
1452 RtlInitUnicodeString(&param_name, L"Parameters");
1453 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
1454 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
1455 if(!NT_SUCCESS(status))
1457 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
1459 else
1461 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
1462 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
1463 RtlFillMemory(scsi_disk_model, 16, ' ');
1464 RtlFillMemory(scsi_cdrom_model, 16, ' ');
1466 RtlInitUnicodeString(&value_name, L"Manufacturer");
1467 buf_len = 256;
1468 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1469 if(NT_SUCCESS(status))
1470 wcstombs(scsi_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
1471 else
1472 strncpy(scsi_device_manufacturer, "XEN ", 8);
1474 RtlInitUnicodeString(&value_name, L"Disk_Model");
1475 buf_len = 256;
1476 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1477 if(NT_SUCCESS(status))
1478 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1479 else
1480 strncpy(scsi_disk_model, "PV DISK ", 16);
1482 RtlInitUnicodeString(&value_name, L"CDROM_Model");
1483 buf_len = 256;
1484 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1485 if(NT_SUCCESS(status))
1486 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1487 else
1488 strncpy(scsi_cdrom_model, "PV CDROM ", 16);
1490 ZwClose(service_handle);
1494 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1496 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1497 HwInitializationData.AdapterInterfaceType = PNPBus;
1498 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1499 HwInitializationData.SpecificLuExtensionSize = 0;
1500 HwInitializationData.SrbExtensionSize = 0;
1501 HwInitializationData.NumberOfAccessRanges = 1;
1502 HwInitializationData.MapBuffers = FALSE;
1503 HwInitializationData.NeedPhysicalAddresses = TRUE;
1504 HwInitializationData.TaggedQueuing = TRUE;
1505 HwInitializationData.AutoRequestSense = TRUE;
1506 HwInitializationData.MultipleRequestPerLu = TRUE;
1507 HwInitializationData.ReceiveEvent = FALSE;
1508 HwInitializationData.VendorIdLength = 0;
1509 HwInitializationData.VendorId = NULL;
1510 HwInitializationData.DeviceIdLength = 0;
1511 HwInitializationData.DeviceId = NULL;
1513 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1514 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1515 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1516 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1517 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1518 HwInitializationData.HwDmaStarted = NULL;
1519 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1520 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1522 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1524 if(!NT_SUCCESS(status))
1526 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1529 FUNCTION_EXIT();
1531 return status;