win-pvdrivers

view xenvbd/xenvbd.c @ 577:17e6a7e1d3df

If a device sharing the same IRQ triggered an interrupt, xenvbd could crash. Fixed.
author James Harper <james.harper@bendigoit.com.au>
date Thu May 21 00:05:11 2009 +1000 (2009-05-21)
parents b162a1156e3f
children cfe35004c0f7
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; //FALSE;
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 i;
534 int notify;
536 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT1;
538 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
539 req->operation = 0xff;
540 req->nr_segments = 0;
541 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
542 {
543 req->seg[i].gref = 0; //0xffffffff;
544 req->seg[i].first_sect = 0; //0xff;
545 req->seg[i].last_sect = 0; //0xff;
546 }
547 xvdd->ring.req_prod_pvt++;
549 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
550 req->operation = 0xff;
551 req->nr_segments = 0;
552 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
553 {
554 req->seg[i].gref = 0; //0xffffffff;
555 req->seg[i].first_sect = 0; //0xff;
556 req->seg[i].last_sect = 0; //0xff;
557 }
558 xvdd->ring.req_prod_pvt++;
560 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
561 if (notify)
562 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
563 }
565 static BOOLEAN
566 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
567 {
568 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
570 FUNCTION_ENTER();
571 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
572 KdPrint((__DRIVER_NAME " dump_mode = %d\n", dump_mode));
574 if (!xvdd->inactive)
575 {
576 if (!dump_mode)
577 {
578 XenVbd_StartRingDetection(xvdd);
579 }
580 else
581 {
582 if (xvdd->cached_use_other)
583 {
584 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
585 xvdd->use_other = TRUE;
586 }
587 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
588 }
589 }
590 FUNCTION_EXIT();
592 return TRUE;
593 }
595 static ULONG
596 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
597 {
598 PMODE_PARAMETER_HEADER parameter_header;
599 PMODE_PARAMETER_BLOCK param_block;
600 PMODE_FORMAT_PAGE format_page;
601 ULONG offset;
602 UCHAR buffer[256];
603 BOOLEAN valid_page = FALSE;
604 BOOLEAN cdb_llbaa;
605 BOOLEAN cdb_dbd;
606 UCHAR cdb_page_code;
607 USHORT cdb_allocation_length;
608 PVOID data_buffer;
609 //ULONG data_buffer_length;
611 UNREFERENCED_PARAMETER(xvdd);
613 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
615 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
616 data_buffer = get_databuffer_virtual(xvdd, srb);
617 //cdb = (PCDB)srb->Cdb;
618 switch (srb->Cdb[0])
619 {
620 case SCSIOP_MODE_SENSE:
621 cdb_llbaa = FALSE;
622 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
623 cdb_page_code = srb->Cdb[2] & 0x3f;
624 cdb_allocation_length = srb->Cdb[4];
625 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
626 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
627 break;
628 case SCSIOP_MODE_SENSE10:
629 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
630 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
631 cdb_page_code = srb->Cdb[2] & 0x3f;
632 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
633 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
634 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
635 break;
636 default:
637 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
638 return FALSE;
639 }
640 offset = 0;
642 RtlZeroMemory(data_buffer, srb->DataTransferLength);
643 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
645 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
646 parameter_header->MediumType = 0;
647 parameter_header->DeviceSpecificParameter = 0;
648 parameter_header->BlockDescriptorLength = 0;
649 offset += sizeof(MODE_PARAMETER_HEADER);
651 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
652 {
653 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
654 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
655 }
657 if (!cdb_dbd)
658 {
659 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
660 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
661 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
662 {
663 if (xvdd->total_sectors >> 32)
664 {
665 param_block->DensityCode = 0xff;
666 param_block->NumberOfBlocks[0] = 0xff;
667 param_block->NumberOfBlocks[1] = 0xff;
668 param_block->NumberOfBlocks[2] = 0xff;
669 }
670 else
671 {
672 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
673 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
674 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
675 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
676 }
677 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
678 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
679 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
680 }
681 offset += sizeof(MODE_PARAMETER_BLOCK);
682 }
683 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
684 {
685 valid_page = TRUE;
686 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
687 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
688 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
689 /* 256 sectors per track */
690 format_page->SectorsPerTrack[0] = 0x01;
691 format_page->SectorsPerTrack[1] = 0x00;
692 /* xxx bytes per sector */
693 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
694 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
695 format_page->HardSectorFormating = TRUE;
696 format_page->SoftSectorFormating = TRUE;
697 offset += sizeof(MODE_FORMAT_PAGE);
698 }
699 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
700 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
701 {
702 srb->SrbStatus = SRB_STATUS_ERROR;
703 }
704 else if(offset < srb->DataTransferLength)
705 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
706 else
707 srb->SrbStatus = SRB_STATUS_SUCCESS;
708 srb->DataTransferLength = min(srb->DataTransferLength, offset);
709 srb->ScsiStatus = 0;
710 memcpy(data_buffer, buffer, srb->DataTransferLength);
712 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
714 return TRUE;
715 }
717 static VOID
718 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
719 {
720 PSENSE_DATA sd = srb->SenseInfoBuffer;
722 UNREFERENCED_PARAMETER(xvdd);
724 if (!srb->SenseInfoBuffer)
725 return;
727 sd->ErrorCode = 0x70;
728 sd->Valid = 1;
729 sd->SenseKey = sense_key;
730 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
731 sd->AdditionalSenseCode = additional_sense_code;
732 return;
733 }
735 static VOID
736 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
737 {
738 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
739 return;
740 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
741 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
742 }
744 static BOOLEAN DDKAPI
745 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
746 {
747 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
748 PSCSI_REQUEST_BLOCK srb;
749 RING_IDX i, rp;
750 ULONG j;
751 blkif_response_t *rep;
752 int block_count;
753 int more_to_do = TRUE;
754 blkif_shadow_t *shadow;
755 ULONG suspend_resume_state_pdo;
756 BOOLEAN last_interrupt = FALSE;
758 /* in dump mode I think we get called on a timer, not by an actual IRQ */
759 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel, &last_interrupt))
760 return FALSE; /* interrupt was not for us */
762 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
763 KeMemoryBarrier();
765 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
766 {
767 FUNCTION_ENTER();
768 switch (suspend_resume_state_pdo)
769 {
770 case SR_STATE_SUSPENDING:
771 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
772 break;
773 case SR_STATE_RESUMING:
774 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
775 XenVbd_InitFromConfig(xvdd);
776 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
777 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
778 break;
779 case SR_STATE_RUNNING:
780 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
781 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
782 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
783 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
784 default:
785 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
786 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
787 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
788 break;
789 }
790 KeMemoryBarrier();
791 }
793 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
794 {
795 return last_interrupt;
796 }
798 while (more_to_do)
799 {
800 rp = xvdd->ring.sring->rsp_prod;
801 KeMemoryBarrier();
802 for (i = xvdd->ring.rsp_cons; i < rp; i++)
803 {
804 rep = XenVbd_GetResponse(xvdd, i);
805 /*
806 * This code is to automatically detect if the backend is using the same
807 * bit width or a different bit width to us. Later versions of Xen do this
808 * via a xenstore value, but not all. That 0x0fffffff (notice
809 * that the msb is not actually set, so we don't have any problems with
810 * sign extending) is to signify the last entry on the right, which is
811 * different under 32 and 64 bits, and that is why we set it up there.
813 * To do the detection, we put two initial entries on the ring, with an op
814 * of 0xff (which is invalid). The first entry is mostly okay, but the
815 * second will be grossly misaligned if the backend bit width is different,
816 * and we detect this and switch frontend structures.
817 */
818 switch (xvdd->ring_detect_state)
819 {
820 case RING_DETECT_STATE_NOT_STARTED:
821 KdPrint((__DRIVER_NAME " premature IRQ\n"));
822 break;
823 case RING_DETECT_STATE_DETECT1:
824 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
825 xvdd->ring_detect_state = RING_DETECT_STATE_DETECT2;
826 break;
827 case RING_DETECT_STATE_DETECT2:
828 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
829 *xvdd->event_channel_ptr |= 0x80000000;
830 if (rep->operation != 0xff)
831 {
832 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
833 xvdd->use_other = TRUE;
834 *xvdd->event_channel_ptr |= 0x40000000;
835 }
836 xvdd->ring_detect_state = RING_DETECT_STATE_COMPLETE;
837 ScsiPortNotification(NextRequest, DeviceExtension);
838 break;
839 case RING_DETECT_STATE_COMPLETE:
840 shadow = &xvdd->shadows[rep->id];
841 srb = shadow->srb;
842 ASSERT(srb != NULL);
843 block_count = decode_cdb_length(srb);
844 block_count *= xvdd->bytes_per_sector / 512;
845 if (rep->status == BLKIF_RSP_OKAY)
846 srb->SrbStatus = SRB_STATUS_SUCCESS;
847 else
848 {
849 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
850 if (decode_cdb_is_read(srb))
851 KdPrint((__DRIVER_NAME " Operation = Read\n"));
852 else
853 KdPrint((__DRIVER_NAME " Operation = Write\n"));
854 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
855 srb->SrbStatus = SRB_STATUS_ERROR;
856 srb->ScsiStatus = 0x02;
857 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
858 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
859 XenVbd_MakeAutoSense(xvdd, srb);
860 }
861 put_shadow_on_freelist(xvdd, shadow);
862 if (dump_mode)
863 {
864 for (j = 0; j < shadow->req.nr_segments; j++)
865 {
866 ASSERT(shadow->req.seg[j].gref == xvdd->dump_grant_refs[j]);
867 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
868 shadow->req.seg[j].gref, TRUE);
869 }
870 }
871 ScsiPortNotification(RequestComplete, xvdd, srb);
872 if (suspend_resume_state_pdo == SR_STATE_RUNNING)
873 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
874 break;
875 }
876 }
878 xvdd->ring.rsp_cons = i;
879 if (i != xvdd->ring.req_prod_pvt)
880 {
881 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
882 }
883 else
884 {
885 xvdd->ring.sring->rsp_event = i + 1;
886 more_to_do = FALSE;
887 }
888 }
890 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
891 {
892 if (xvdd->shadow_free == SHADOW_ENTRIES)
893 {
894 /* all entries are purged from the list. ready to suspend */
895 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
896 KeMemoryBarrier();
897 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
898 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
899 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
900 }
901 FUNCTION_EXIT();
902 }
904 return last_interrupt;
905 }
907 static BOOLEAN DDKAPI
908 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
909 {
910 PUCHAR data_buffer;
911 //ULONG data_buffer_length;
912 PCDB cdb;
913 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
915 if (xvdd->inactive)
916 {
917 KdPrint((__DRIVER_NAME " Inactive Srb->Function = %08X\n", Srb->Function));
918 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
919 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
920 ScsiPortNotification(NextRequest, DeviceExtension);
921 return TRUE;
922 }
924 // If we haven't enumerated all the devices yet then just defer the request
925 if (xvdd->ring_detect_state < RING_DETECT_STATE_COMPLETE)
926 {
927 Srb->SrbStatus = SRB_STATUS_BUSY;
928 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
929 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
930 return TRUE;
931 }
933 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
934 {
935 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
936 Srb->SrbStatus = SRB_STATUS_BUSY;
937 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
938 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
939 return TRUE;
940 }
942 if (Srb->PathId != 0 || Srb->TargetId != 0)
943 {
944 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
945 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
946 ScsiPortNotification(NextRequest, DeviceExtension);
947 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
948 return TRUE;
949 }
951 switch (Srb->Function)
952 {
953 case SRB_FUNCTION_EXECUTE_SCSI:
954 cdb = (PCDB)Srb->Cdb;
956 switch(cdb->CDB6GENERIC.OperationCode)
957 {
958 case SCSIOP_TEST_UNIT_READY:
959 if (dump_mode)
960 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
961 Srb->SrbStatus = SRB_STATUS_SUCCESS;
962 Srb->ScsiStatus = 0;
963 break;
964 case SCSIOP_INQUIRY:
965 if (dump_mode)
966 {
967 //PHYSICAL_ADDRESS physical;
968 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
969 //KdPrint((__DRIVER_NAME " Srb->Databuffer = %p\n", Srb->DataBuffer));
970 //physical = ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length);
971 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
972 }
973 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
974 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
976 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
977 data_buffer = get_databuffer_virtual(xvdd, Srb);
978 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
979 Srb->SrbStatus = SRB_STATUS_SUCCESS;
980 switch (xvdd->device_type)
981 {
982 case XENVBD_DEVICETYPE_DISK:
983 if ((Srb->Cdb[1] & 1) == 0)
984 {
985 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
986 id->DeviceType = DIRECT_ACCESS_DEVICE;
987 id->Versions = 3;
988 id->ResponseDataFormat = 0;
989 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
990 id->CommandQueue = 1;
991 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
992 memcpy(id->ProductId, scsi_disk_model, 16); // product id
993 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
994 }
995 else
996 {
997 switch (Srb->Cdb[2])
998 {
999 case 0x00:
1000 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1001 data_buffer[1] = 0x00;
1002 data_buffer[2] = 0x00;
1003 data_buffer[3] = 2;
1004 data_buffer[4] = 0x00;
1005 data_buffer[5] = 0x80;
1006 break;
1007 case 0x80:
1008 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1009 data_buffer[1] = 0x80;
1010 data_buffer[2] = 0x00;
1011 data_buffer[3] = 8;
1012 memset(&data_buffer[4], ' ', 8);
1013 break;
1014 default:
1015 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1016 Srb->SrbStatus = SRB_STATUS_ERROR;
1017 break;
1020 break;
1021 case XENVBD_DEVICETYPE_CDROM:
1022 if ((Srb->Cdb[1] & 1) == 0)
1024 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1025 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1026 id->RemovableMedia = 1;
1027 id->Versions = 3;
1028 id->ResponseDataFormat = 0;
1029 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1030 id->CommandQueue = 1;
1031 memcpy(id->VendorId, scsi_device_manufacturer, 8); // vendor id
1032 memcpy(id->ProductId, scsi_cdrom_model, 16); // product id
1033 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1035 else
1037 switch (Srb->Cdb[2])
1039 case 0x00:
1040 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1041 data_buffer[1] = 0x00;
1042 data_buffer[2] = 0x00;
1043 data_buffer[3] = 2;
1044 data_buffer[4] = 0x00;
1045 data_buffer[5] = 0x80;
1046 break;
1047 case 0x80:
1048 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1049 data_buffer[1] = 0x80;
1050 data_buffer[2] = 0x00;
1051 data_buffer[3] = 8;
1052 data_buffer[4] = 0x31;
1053 data_buffer[5] = 0x32;
1054 data_buffer[6] = 0x33;
1055 data_buffer[7] = 0x34;
1056 data_buffer[8] = 0x35;
1057 data_buffer[9] = 0x36;
1058 data_buffer[10] = 0x37;
1059 data_buffer[11] = 0x38;
1060 break;
1061 default:
1062 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1063 Srb->SrbStatus = SRB_STATUS_ERROR;
1064 break;
1067 break;
1068 default:
1069 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1070 Srb->SrbStatus = SRB_STATUS_ERROR;
1071 break;
1073 break;
1074 case SCSIOP_READ_CAPACITY:
1075 if (dump_mode)
1076 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1077 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1078 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1079 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1080 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1081 data_buffer = get_databuffer_virtual(xvdd, Srb);
1082 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1083 if ((xvdd->total_sectors - 1) >> 32)
1085 data_buffer[0] = 0xff;
1086 data_buffer[1] = 0xff;
1087 data_buffer[2] = 0xff;
1088 data_buffer[3] = 0xff;
1090 else
1092 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1093 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1094 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1095 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1097 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1098 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1099 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1100 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1101 Srb->ScsiStatus = 0;
1102 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1103 break;
1104 case SCSIOP_READ_CAPACITY16:
1105 if (dump_mode)
1106 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1107 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1108 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1109 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1110 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1111 data_buffer = get_databuffer_virtual(xvdd, Srb);
1112 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1113 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1114 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1115 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1116 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1117 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1118 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1119 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1120 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1121 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1122 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1123 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1124 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1125 Srb->ScsiStatus = 0;
1126 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1127 break;
1128 case SCSIOP_MODE_SENSE:
1129 case SCSIOP_MODE_SENSE10:
1130 if (dump_mode)
1131 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));
1132 XenVbd_FillModePage(xvdd, Srb);
1133 break;
1134 case SCSIOP_READ:
1135 case SCSIOP_READ16:
1136 case SCSIOP_WRITE:
1137 case SCSIOP_WRITE16:
1138 //if (dump_mode)
1139 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1140 XenVbd_PutSrbOnRing(xvdd, Srb);
1141 break;
1142 case SCSIOP_VERIFY:
1143 // Should we do more here?
1144 if (dump_mode)
1145 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1146 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1147 break;
1148 case SCSIOP_REPORT_LUNS:
1149 if (dump_mode)
1150 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1151 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1152 break;
1153 case SCSIOP_REQUEST_SENSE:
1154 if (dump_mode)
1155 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1156 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1157 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1158 break;
1159 case SCSIOP_READ_TOC:
1160 if (dump_mode)
1161 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1162 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1163 data_buffer = get_databuffer_virtual(xvdd, Srb);
1164 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1165 /*
1166 #define READ_TOC_FORMAT_TOC 0x00
1167 #define READ_TOC_FORMAT_SESSION 0x01
1168 #define READ_TOC_FORMAT_FULL_TOC 0x02
1169 #define READ_TOC_FORMAT_PMA 0x03
1170 #define READ_TOC_FORMAT_ATIP 0x04
1171 */
1172 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1173 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1174 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1175 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1176 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1177 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1178 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1179 switch (cdb->READ_TOC.Format2)
1181 case READ_TOC_FORMAT_TOC:
1182 data_buffer[0] = 0; // length MSB
1183 data_buffer[1] = 10; // length LSB
1184 data_buffer[2] = 1; // First Track
1185 data_buffer[3] = 1; // Last Track
1186 data_buffer[4] = 0; // Reserved
1187 data_buffer[5] = 0x14; // current position data + uninterrupted data
1188 data_buffer[6] = 1; // last complete track
1189 data_buffer[7] = 0; // reserved
1190 data_buffer[8] = 0; // MSB Block
1191 data_buffer[9] = 0;
1192 data_buffer[10] = 0;
1193 data_buffer[11] = 0; // LSB Block
1194 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1195 break;
1196 case READ_TOC_FORMAT_SESSION:
1197 case READ_TOC_FORMAT_FULL_TOC:
1198 case READ_TOC_FORMAT_PMA:
1199 case READ_TOC_FORMAT_ATIP:
1200 Srb->SrbStatus = SRB_STATUS_ERROR;
1201 break;
1203 break;
1204 case SCSIOP_START_STOP_UNIT:
1205 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1206 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1207 break;
1208 case SCSIOP_RESERVE_UNIT:
1209 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1210 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1211 break;
1212 case SCSIOP_RELEASE_UNIT:
1213 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1214 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1215 break;
1216 default:
1217 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1218 Srb->SrbStatus = SRB_STATUS_ERROR;
1219 break;
1221 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1223 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1224 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1226 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1227 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1229 Srb->ScsiStatus = 0x02;
1230 XenVbd_MakeAutoSense(xvdd, Srb);
1231 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1232 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1233 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1235 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1237 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1238 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1239 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1240 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1241 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1243 break;
1244 case SRB_FUNCTION_IO_CONTROL:
1245 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1246 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1247 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1248 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1249 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1250 break;
1251 case SRB_FUNCTION_FLUSH:
1252 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1253 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1254 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1255 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1256 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1257 break;
1258 case SRB_FUNCTION_SHUTDOWN:
1259 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", Srb, xvdd->shadow_free));
1260 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1261 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1262 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1263 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1264 break;
1265 default:
1266 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1267 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1268 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1269 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1270 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1271 break;
1274 //FUNCTION_EXIT();
1275 return TRUE;
1278 static BOOLEAN
1279 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1281 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1283 UNREFERENCED_PARAMETER(DeviceExtension);
1284 UNREFERENCED_PARAMETER(PathId);
1286 FUNCTION_ENTER();
1288 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1289 if (xvdd->ring_detect_state == RING_DETECT_STATE_COMPLETE && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1291 ScsiPortNotification(NextRequest, DeviceExtension);
1294 FUNCTION_EXIT();
1297 return TRUE;
1300 static BOOLEAN
1301 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1303 UNREFERENCED_PARAMETER(DeviceExtension);
1304 UNREFERENCED_PARAMETER(Context);
1305 UNREFERENCED_PARAMETER(SaveState);
1307 FUNCTION_ENTER();
1308 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1310 FUNCTION_EXIT();
1312 return TRUE;
1315 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1316 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1318 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1319 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1320 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1321 //KIRQL OldIrql;
1323 FUNCTION_ENTER();
1324 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1326 switch (ControlType)
1328 case ScsiQuerySupportedControlTypes:
1329 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1330 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1331 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1332 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1333 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1334 break;
1335 case ScsiStopAdapter:
1336 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1337 //KdBreakPoint();
1338 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1339 break;
1340 case ScsiRestartAdapter:
1341 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1342 XenVbd_InitFromConfig(xvdd);
1343 if (!xvdd->inactive)
1344 XenVbd_StartRingDetection(xvdd);
1345 //if (xvdd->use_other)
1346 // xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
1347 break;
1348 case ScsiSetBootConfig:
1349 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1350 break;
1351 case ScsiSetRunningConfig:
1352 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1353 break;
1354 default:
1355 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1356 break;
1359 FUNCTION_EXIT();
1361 return Status;
1364 PVOID init_driver_extension;
1366 static BOOLEAN
1367 XenVbd_DmaNeedVirtualAddress(PIRP irp)
1369 PIO_STACK_LOCATION stack;
1371 //FUNCTION_ENTER();
1373 stack = IoGetCurrentIrpStackLocation(irp);
1374 if (stack->MajorFunction != IRP_MJ_SCSI)
1376 KdPrint((__DRIVER_NAME " Not IRP_MJ_SCSI\n"));
1377 //FUNCTION_EXIT();
1378 return FALSE; /* this actually shouldn't happen */
1381 switch (stack->Parameters.Scsi.Srb->Cdb[0])
1383 case SCSIOP_READ:
1384 case SCSIOP_READ16:
1385 case SCSIOP_WRITE:
1386 case SCSIOP_WRITE16:
1387 //KdPrint((__DRIVER_NAME " read/write operation\n"));
1388 //FUNCTION_EXIT();
1389 return FALSE;
1390 default:
1391 //KdPrint((__DRIVER_NAME " not a read/write operation\n"));
1392 //FUNCTION_EXIT();
1393 return TRUE;
1397 static ULONG
1398 XenVbd_DmaGetAlignment(PIRP irp)
1400 UNREFERENCED_PARAMETER(irp);
1402 //FUNCTION_ENTER();
1403 //FUNCTION_EXIT();
1404 return 512;
1407 dma_driver_extension_t *dma_driver_extension;
1409 NTSTATUS
1410 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1412 ULONG status;
1413 HW_INITIALIZATION_DATA HwInitializationData;
1414 PVOID driver_extension;
1415 PUCHAR ptr;
1416 OBJECT_ATTRIBUTES oa;
1417 HANDLE service_handle;
1418 UNICODE_STRING param_name;
1419 HANDLE param_handle;
1420 UNICODE_STRING value_name;
1421 CHAR buf[256];
1422 ULONG buf_len;
1423 PKEY_VALUE_PARTIAL_INFORMATION kpv;
1425 FUNCTION_ENTER();
1426 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1427 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1429 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1430 if (!RegistryPath)
1432 dump_mode = TRUE;
1435 if (!dump_mode)
1437 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1438 ptr = driver_extension;
1439 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1440 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));
1441 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1442 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1443 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1444 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1445 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1446 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1447 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
1448 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1450 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC), sizeof(dma_driver_extension_t), &dma_driver_extension);
1451 dma_driver_extension->need_virtual_address = XenVbd_DmaNeedVirtualAddress;
1452 dma_driver_extension->get_alignment = XenVbd_DmaGetAlignment;
1453 dma_driver_extension->max_sg_elements = 0;
1455 // get registry service key handle
1456 // get parameters key handle
1457 // get disk value name
1458 // get cdrom value name
1460 InitializeObjectAttributes(&oa, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
1461 status = ZwOpenKey(&service_handle, KEY_READ, &oa);
1462 if(!NT_SUCCESS(status))
1464 KdPrint((__DRIVER_NAME " ZwOpenKey(Service) returned %08x\n", status));
1466 else
1468 RtlInitUnicodeString(&param_name, L"Parameters");
1469 InitializeObjectAttributes(&oa, &param_name, OBJ_CASE_INSENSITIVE, service_handle, NULL);
1470 status = ZwOpenKey(&param_handle, KEY_READ, &oa);
1471 if(!NT_SUCCESS(status))
1473 KdPrint((__DRIVER_NAME " ZwOpenKey(Parameters) returned %08x\n", status));
1475 else
1477 kpv = (PKEY_VALUE_PARTIAL_INFORMATION)buf;
1478 RtlFillMemory(scsi_device_manufacturer, 8, ' ');
1479 RtlFillMemory(scsi_disk_model, 16, ' ');
1480 RtlFillMemory(scsi_cdrom_model, 16, ' ');
1482 RtlInitUnicodeString(&value_name, L"Manufacturer");
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_device_manufacturer, (PWCHAR)kpv->Data, min(kpv->DataLength, 8));
1487 else
1488 strncpy(scsi_device_manufacturer, "XEN ", 8);
1490 RtlInitUnicodeString(&value_name, L"Disk_Model");
1491 buf_len = 256;
1492 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1493 if(NT_SUCCESS(status))
1494 wcstombs(scsi_disk_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1495 else
1496 strncpy(scsi_disk_model, "PV DISK ", 16);
1498 RtlInitUnicodeString(&value_name, L"CDROM_Model");
1499 buf_len = 256;
1500 status = ZwQueryValueKey(param_handle, &value_name, KeyValuePartialInformation, buf, buf_len, &buf_len);
1501 if(NT_SUCCESS(status))
1502 wcstombs(scsi_cdrom_model, (PWCHAR)kpv->Data, min(kpv->DataLength, 16));
1503 else
1504 strncpy(scsi_cdrom_model, "PV CDROM ", 16);
1506 ZwClose(service_handle);
1510 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1512 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1513 HwInitializationData.AdapterInterfaceType = PNPBus;
1514 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1515 HwInitializationData.SpecificLuExtensionSize = 0;
1516 HwInitializationData.SrbExtensionSize = 0;
1517 HwInitializationData.NumberOfAccessRanges = 1;
1518 HwInitializationData.MapBuffers = FALSE;
1519 HwInitializationData.NeedPhysicalAddresses = TRUE;
1520 HwInitializationData.TaggedQueuing = TRUE;
1521 HwInitializationData.AutoRequestSense = TRUE;
1522 HwInitializationData.MultipleRequestPerLu = TRUE;
1523 HwInitializationData.ReceiveEvent = FALSE;
1524 HwInitializationData.VendorIdLength = 0;
1525 HwInitializationData.VendorId = NULL;
1526 HwInitializationData.DeviceIdLength = 0;
1527 HwInitializationData.DeviceId = NULL;
1529 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1530 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1531 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1532 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1533 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1534 HwInitializationData.HwDmaStarted = NULL;
1535 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1536 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1538 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1540 if(!NT_SUCCESS(status))
1542 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1545 FUNCTION_EXIT();
1547 return status;