win-pvdrivers

view xenvbd/xenvbd.c @ 527:55c3a1972b54

changed bus type to PNPBus
author James Harper <james.harper@bendigoit.com.au>
date Fri Jan 16 22:35:43 2009 +1100 (2009-01-16)
parents 87aba6fc3a82
children 1d13cbc9a3b0
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 #ifdef ALLOC_PRAGMA
34 DRIVER_INITIALIZE DriverEntry;
35 #pragma alloc_text (INIT, DriverEntry)
36 #endif
38 #if defined(__x86_64__)
39 #define GET_PAGE_ALIGNED(ptr) ((PVOID)(((ULONGLONG)ptr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
40 #else
41 #define GET_PAGE_ALIGNED(ptr) UlongToPtr((PtrToUlong(ptr) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
42 #endif
44 static BOOLEAN dump_mode = FALSE;
46 ULONGLONG parse_numeric_string(PCHAR string)
47 {
48 ULONGLONG val = 0;
49 while (*string != 0)
50 {
51 val = val * 10 + (*string - '0');
52 string++;
53 }
54 return val;
55 }
57 static blkif_shadow_t *
58 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
59 {
60 if (xvdd->shadow_free == 0)
61 {
62 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
63 return NULL;
64 }
65 xvdd->shadow_free--;
66 if (xvdd->shadow_free < xvdd->shadow_min_free)
67 xvdd->shadow_min_free = xvdd->shadow_free;
68 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
69 }
71 static VOID
72 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
73 {
74 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
75 shadow->srb = NULL;
76 xvdd->shadow_free++;
77 }
79 static grant_ref_t
80 get_grant_from_freelist(PXENVBD_DEVICE_DATA xvdd)
81 {
82 if (xvdd->grant_free == 0)
83 {
84 KdPrint((__DRIVER_NAME " No more grant refs\n"));
85 return (grant_ref_t)0x0FFFFFFF;
86 }
87 xvdd->grant_free--;
88 return xvdd->grant_free_list[xvdd->grant_free];
89 }
91 static VOID
92 put_grant_on_freelist(PXENVBD_DEVICE_DATA xvdd, grant_ref_t grant)
93 {
94 xvdd->grant_free_list[xvdd->grant_free] = grant;
95 xvdd->grant_free++;
96 }
98 static blkif_response_t *
99 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
100 {
101 blkif_other_response_t *rep;
102 if (!xvdd->use_other)
103 return RING_GET_RESPONSE(&xvdd->ring, i);
104 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
105 xvdd->tmp_rep.id = rep->id;
106 xvdd->tmp_rep.operation = rep->operation;
107 xvdd->tmp_rep.status = rep->status;
108 return &xvdd->tmp_rep;
109 }
111 static VOID
112 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
113 {
114 blkif_other_request_t *other_req;
116 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
117 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
118 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
119 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
120 if (!xvdd->use_other)
121 {
122 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
123 }
124 else
125 {
126 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
127 other_req->operation = req->operation;
128 other_req->nr_segments = req->nr_segments;
129 other_req->handle = req->handle;
130 other_req->id = req->id;
131 other_req->sector_number = req->sector_number;
132 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
133 }
134 xvdd->ring.req_prod_pvt++;
135 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
136 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
137 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
138 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
139 }
141 static ULONG
142 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
143 {
144 ULONG i;
145 PUCHAR ptr;
146 USHORT type;
147 PCHAR setting, value;
148 ULONG qemu_protocol_version = 0;
150 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
151 xvdd->sring = NULL;
152 xvdd->event_channel = 0;
154 xvdd->inactive = TRUE;
155 ptr = xvdd->device_base;
156 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID) &setting, (PVOID) &value)) != XEN_INIT_TYPE_END)
157 {
158 switch(type)
159 {
160 case XEN_INIT_TYPE_RING: /* frontend ring */
161 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
162 if (strcmp(setting, "ring-ref") == 0)
163 {
164 xvdd->sring = (blkif_sring_t *)value;
165 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
166 /* this bit is for when we have to take over an existing ring on a crash dump */
167 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
168 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
169 }
170 break;
171 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
172 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
173 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
174 if (strcmp(setting, "event-channel") == 0)
175 {
176 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
177 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
178 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
179 if (PtrToUlong(value) & 0x80000000)
180 {
181 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
182 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
183 }
184 }
185 break;
186 case XEN_INIT_TYPE_READ_STRING_BACK:
187 case XEN_INIT_TYPE_READ_STRING_FRONT:
188 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
189 if (strcmp(setting, "sectors") == 0)
190 xvdd->total_sectors = parse_numeric_string(value);
191 else if (strcmp(setting, "sector-size") == 0)
192 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
193 else if (strcmp(setting, "device-type") == 0)
194 {
195 if (strcmp(value, "disk") == 0)
196 {
197 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
198 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
199 }
200 else if (strcmp(value, "cdrom") == 0)
201 {
202 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
203 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
204 }
205 else
206 {
207 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
208 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
209 }
210 }
211 else if (strcmp(setting, "mode") == 0)
212 {
213 if (strncmp(value, "r", 1) == 0)
214 {
215 KdPrint((__DRIVER_NAME " mode = r\n"));
216 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
217 }
218 else if (strncmp(value, "w", 1) == 0)
219 {
220 KdPrint((__DRIVER_NAME " mode = w\n"));
221 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
222 }
223 else
224 {
225 KdPrint((__DRIVER_NAME " mode = unknown\n"));
226 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
227 }
228 }
229 break;
230 case XEN_INIT_TYPE_VECTORS:
231 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
232 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
233 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
234 {
235 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
236 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
237 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
238 return SP_RETURN_BAD_CONFIG;
239 }
240 else
241 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
242 break;
243 case XEN_INIT_TYPE_GRANT_ENTRIES:
244 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
245 xvdd->grant_entries = (USHORT)PtrToUlong(setting);
246 if (dump_mode)
247 {
248 /* check each grant entry first to make sure it isn't in use already */
249 grant_ref_t *gref = (grant_ref_t *)value;
250 xvdd->grant_free = 0;
251 for (i = 0; i < xvdd->grant_entries; i++)
252 {
253 if (xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, *gref, TRUE))
254 {
255 put_grant_on_freelist(xvdd, *gref);
256 }
257 gref++;
258 }
259 }
260 else
261 {
262 memcpy(&xvdd->grant_free_list, value, sizeof(grant_ref_t) * xvdd->grant_entries);
263 xvdd->grant_free = xvdd->grant_entries;
264 }
265 break;
266 case XEN_INIT_TYPE_STATE_PTR:
267 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
268 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
269 break;
270 case XEN_INIT_TYPE_ACTIVE:
271 xvdd->inactive = FALSE;
272 break;
273 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
274 qemu_protocol_version = PtrToUlong(value);
275 default:
276 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
277 break;
278 }
279 }
280 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
281 || xvdd->sring == NULL
282 || xvdd->event_channel == 0
283 || xvdd->total_sectors == 0
284 || xvdd->bytes_per_sector == 0)
285 {
286 KdPrint((__DRIVER_NAME " Missing settings\n"));
287 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
288 return SP_RETURN_BAD_CONFIG;
289 }
290 if (!xvdd->inactive && xvdd->device_type == XENVBD_DEVICETYPE_CDROM && qemu_protocol_version > 0)
291 {
292 xvdd->inactive = TRUE;
293 }
295 if (xvdd->inactive)
296 KdPrint((__DRIVER_NAME " Device is inactive\n"));
298 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
299 {
300 /* CD/DVD drives must have bytes_per_sector = 2048. */
301 xvdd->bytes_per_sector = 2048;
302 }
304 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
305 #ifdef __MINGW32__
306 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
307 {
308 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
309 ULONG index;
311 bit_scan_forward(&index, num_512_byte_sectors);
312 xvdd->total_sectors <<= index-1;
313 }
314 #else
315 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
316 #endif
319 xvdd->shadow_free = 0;
320 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
321 for (i = 0; i < SHADOW_ENTRIES; i++)
322 {
323 xvdd->shadows[i].req.id = i;
324 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
325 }
327 return SP_RETURN_FOUND;
328 }
330 static __inline ULONG
331 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
332 {
333 switch (srb->Cdb[0])
334 {
335 case SCSIOP_READ:
336 case SCSIOP_WRITE:
337 return (srb->Cdb[7] << 8) | srb->Cdb[8];
338 case SCSIOP_READ16:
339 case SCSIOP_WRITE16:
340 return (srb->Cdb[10] << 24) | (srb->Cdb[11] << 16) | (srb->Cdb[12] << 8) | srb->Cdb[13];
341 default:
342 return 0;
343 }
344 }
346 static __inline ULONGLONG
347 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
348 {
349 ULONGLONG sector;
351 switch (srb->Cdb[0])
352 {
353 case SCSIOP_READ:
354 case SCSIOP_WRITE:
355 sector = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
356 break;
357 case SCSIOP_READ16:
358 case SCSIOP_WRITE16:
359 sector = ((ULONGLONG)srb->Cdb[2] << 56) | ((ULONGLONG)srb->Cdb[3] << 48)
360 | ((ULONGLONG)srb->Cdb[4] << 40) | ((ULONGLONG)srb->Cdb[5] << 32)
361 | ((ULONGLONG)srb->Cdb[6] << 24) | ((ULONGLONG)srb->Cdb[7] << 16)
362 | ((ULONGLONG)srb->Cdb[8] << 8) | ((ULONGLONG)srb->Cdb[9]);
363 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
364 break;
365 default:
366 sector = 0;
367 break;
368 }
369 return sector;
370 }
372 static __inline BOOLEAN
373 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
374 {
375 switch (srb->Cdb[0])
376 {
377 case SCSIOP_READ:
378 case SCSIOP_READ16:
379 return TRUE;
380 case SCSIOP_WRITE:
381 case SCSIOP_WRITE16:
382 return FALSE;
383 default:
384 return FALSE;
385 }
386 }
388 static VOID
389 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
390 {
391 ULONG block_count, transfer_length;
392 blkif_shadow_t *shadow;
393 PHYSICAL_ADDRESS physical_address;
394 ULONG pfn;
395 ULONG remaining, offset, length;
396 PUCHAR ptr;
397 int notify;
399 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
401 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
402 block_count = decode_cdb_length(srb);;
403 block_count *= xvdd->bytes_per_sector / 512;
404 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
405 {
406 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
407 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
408 }
409 else
410 {
411 ptr = srb->DataBuffer;
412 transfer_length = block_count * 512;
413 }
415 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
416 {
417 ASSERT(!xvdd->pending_srb);
418 KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
419 xvdd->pending_srb = srb;
420 return;
421 }
423 shadow = get_shadow_from_freelist(xvdd);
424 ASSERT(shadow);
425 shadow->req.sector_number = decode_cdb_sector(srb);
426 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
427 shadow->req.handle = 0;
428 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
429 shadow->req.nr_segments = 0;
430 shadow->offset = srb_offset;
431 shadow->length = transfer_length;
432 shadow->srb = srb;
434 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
435 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
436 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
438 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
439 {
440 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
441 //KdPrint((__DRIVER_NAME " Using unaligned buffer - DataBuffer = %p, SrbExtension = %p, total length = %d, offset = %d, length = %d, sector = %d\n", srb->DataBuffer, srb->SrbExtension, block_count * 512, shadow->offset, shadow->length, (ULONG)shadow->req.sector_number));
442 if (!decode_cdb_is_read(srb))
443 {
444 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
445 }
446 }
447 else
448 {
449 ptr = srb->DataBuffer;
450 }
451 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
452 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
453 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
455 remaining = shadow->length;
456 while (remaining > 0)
457 {
458 physical_address = MmGetPhysicalAddress(ptr);
459 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
460 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
461 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref != INVALID_GRANT_REF);
462 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
463 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
464 ASSERT((offset & 511) == 0);
465 length = min(PAGE_SIZE - offset, remaining);
466 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
467 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
468 remaining -= length;
469 ptr += length;
470 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
471 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
472 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
473 shadow->req.nr_segments++;
474 }
475 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
477 XenVbd_PutRequest(xvdd, &shadow->req);
479 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
480 if (notify)
481 {
482 //KdPrint((__DRIVER_NAME " Notifying\n"));
483 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
484 }
486 if (xvdd->shadow_free && srb_offset == 0)
487 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
489 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
490 }
492 typedef struct {
493 PSCSI_REQUEST_BLOCK srb;
494 ULONG offset;
495 } mini_shadow_t;
497 static VOID
498 XenVbd_Resume(PVOID DeviceExtension)
499 {
500 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
501 ULONG i;
502 mini_shadow_t shadows[MAX_SHADOW_ENTRIES];
503 ULONG shadow_count;
505 FUNCTION_ENTER();
506 KdPrint((__DRIVER_NAME " found device in resume state\n"));
507 //FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE); what was this for???
508 // re-submit srb's
510 shadow_count = 0;
511 for (i = 0; i < SHADOW_ENTRIES; i++)
512 {
513 if (xvdd->shadows[i].srb)
514 {
515 shadows[shadow_count].srb = xvdd->shadows[i].srb;
516 shadows[shadow_count].offset = xvdd->shadows[i].offset;
517 shadow_count++;
518 xvdd->shadows[i].srb = NULL;
519 }
520 }
521 KdPrint((__DRIVER_NAME " About to call InitFromConfig\n"));
522 XenVbd_InitFromConfig(xvdd);
523 KdPrint((__DRIVER_NAME " Back from InitFromConfig\n"));
525 for (i = 0; i < shadow_count; i++)
526 {
527 KdPrint((__DRIVER_NAME " Putting on Shadow entry\n"));
528 XenVbd_PutSrbOnRing(xvdd, shadows[i].srb, shadows[i].offset);
529 }
530 KdPrint((__DRIVER_NAME " Shadows are back on the ring\n"));
532 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
534 KdPrint((__DRIVER_NAME " resume_state set to RESUME_STATE_RUNNING\n"));
536 if (i == 0)
537 {
538 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
539 KdPrint((__DRIVER_NAME " No shadows - notifying to get things started again\n"));
540 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
541 }
542 FUNCTION_EXIT();
543 }
545 static ULONG DDKAPI
546 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
547 {
548 // PACCESS_RANGE AccessRange;
549 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
550 ULONG status;
551 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
552 PACCESS_RANGE access_range;
554 UNREFERENCED_PARAMETER(HwContext);
555 UNREFERENCED_PARAMETER(BusInformation);
556 UNREFERENCED_PARAMETER(ArgumentString);
558 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
559 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
561 *Again = FALSE;
563 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
564 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
566 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
567 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
568 {
569 return SP_RETURN_BAD_CONFIG;
570 }
572 access_range = &((*(ConfigInfo->AccessRanges))[0]);
573 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
574 access_range->RangeStart.LowPart, access_range->RangeLength));
575 xvdd->device_base = ScsiPortGetDeviceBase(
576 DeviceExtension,
577 ConfigInfo->AdapterInterfaceType,
578 ConfigInfo->SystemIoBusNumber,
579 access_range->RangeStart,
580 access_range->RangeLength,
581 !access_range->RangeInMemory);
582 if (!xvdd->device_base)
583 {
584 KdPrint((__DRIVER_NAME " Invalid config\n"));
585 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
586 return SP_RETURN_BAD_CONFIG;
587 }
589 status = XenVbd_InitFromConfig(xvdd);
590 if (status != SP_RETURN_FOUND)
591 return status;
593 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
594 ConfigInfo->NumberOfPhysicalBreaks = 0; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
595 ConfigInfo->ScatterGather = TRUE;
596 ConfigInfo->AlignmentMask = 0;
597 ConfigInfo->NumberOfBuses = 1;
598 ConfigInfo->InitiatorBusId[0] = 1;
599 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
600 ConfigInfo->MaximumNumberOfTargets = 2;
601 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
602 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
603 {
604 ConfigInfo->Master = TRUE;
605 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
606 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
607 }
608 else
609 {
610 ConfigInfo->Master = FALSE;
611 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
612 }
614 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
616 return SP_RETURN_FOUND;
617 }
619 static BOOLEAN DDKAPI
620 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
621 {
622 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
623 blkif_request_t *req;
624 int i;
625 int notify;
627 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
628 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
630 if (!dump_mode)
631 {
632 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
633 req->operation = 0xff;
634 req->nr_segments = 0;
635 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
636 {
637 req->seg[i].gref = 0; //0xffffffff;
638 req->seg[i].first_sect = 0; //0xff;
639 req->seg[i].last_sect = 0; //0xff;
640 }
641 xvdd->ring.req_prod_pvt++;
643 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
644 req->operation = 0xff;
645 req->nr_segments = 0;
646 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
647 {
648 req->seg[i].gref = 0; //0xffffffff;
649 req->seg[i].first_sect = 0; //0xff;
650 req->seg[i].last_sect = 0; //0xff;
651 }
652 xvdd->ring.req_prod_pvt++;
654 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
655 if (notify)
656 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
657 xvdd->ring_detect_state = 0;
658 }
659 else
660 {
661 if (xvdd->cached_use_other)
662 {
663 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
664 xvdd->use_other = TRUE;
665 }
666 xvdd->ring_detect_state = 2;
667 }
669 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
671 return TRUE;
672 }
674 static ULONG
675 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
676 {
677 PMODE_PARAMETER_HEADER parameter_header;
678 PMODE_PARAMETER_BLOCK param_block;
679 PMODE_FORMAT_PAGE format_page;
680 ULONG offset;
681 UCHAR buffer[256];
682 BOOLEAN valid_page = FALSE;
683 BOOLEAN cdb_llbaa;
684 BOOLEAN cdb_dbd;
685 UCHAR cdb_page_code;
686 USHORT cdb_allocation_length;
688 UNREFERENCED_PARAMETER(xvdd);
690 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
692 //cdb = (PCDB)srb->Cdb;
693 switch (srb->Cdb[0])
694 {
695 case SCSIOP_MODE_SENSE:
696 cdb_llbaa = FALSE;
697 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
698 cdb_page_code = srb->Cdb[2] & 0x3f;
699 cdb_allocation_length = srb->Cdb[4];
700 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
701 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
702 break;
703 case SCSIOP_MODE_SENSE10:
704 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
705 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
706 cdb_page_code = srb->Cdb[2] & 0x3f;
707 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
708 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
709 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
710 break;
711 default:
712 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
713 return FALSE;
714 }
715 offset = 0;
716 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
717 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
719 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
720 parameter_header->MediumType = 0;
721 parameter_header->DeviceSpecificParameter = 0;
722 parameter_header->BlockDescriptorLength = 0;
723 offset += sizeof(MODE_PARAMETER_HEADER);
725 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
726 {
727 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
728 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
729 }
731 if (!cdb_dbd)
732 {
733 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
734 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
735 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
736 {
737 if (xvdd->total_sectors >> 32)
738 {
739 param_block->DensityCode = 0xff;
740 param_block->NumberOfBlocks[0] = 0xff;
741 param_block->NumberOfBlocks[1] = 0xff;
742 param_block->NumberOfBlocks[2] = 0xff;
743 }
744 else
745 {
746 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
747 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
748 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
749 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
750 }
751 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
752 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
753 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
754 }
755 offset += sizeof(MODE_PARAMETER_BLOCK);
756 }
757 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
758 {
759 valid_page = TRUE;
760 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
761 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
762 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
763 /* 256 sectors per track */
764 format_page->SectorsPerTrack[0] = 0x01;
765 format_page->SectorsPerTrack[1] = 0x00;
766 /* xxx bytes per sector */
767 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
768 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
769 format_page->HardSectorFormating = TRUE;
770 format_page->SoftSectorFormating = TRUE;
771 offset += sizeof(MODE_FORMAT_PAGE);
772 }
773 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
774 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
775 {
776 srb->SrbStatus = SRB_STATUS_ERROR;
777 }
778 else if(offset < srb->DataTransferLength)
779 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
780 else
781 srb->SrbStatus = SRB_STATUS_SUCCESS;
782 srb->DataTransferLength = min(srb->DataTransferLength, offset);
783 srb->ScsiStatus = 0;
784 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
786 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
788 return TRUE;
789 }
791 static VOID
792 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
793 {
794 PSENSE_DATA sd = srb->SenseInfoBuffer;
796 UNREFERENCED_PARAMETER(xvdd);
798 if (!srb->SenseInfoBuffer)
799 return;
801 sd->ErrorCode = 0x70;
802 sd->Valid = 1;
803 sd->SenseKey = sense_key;
804 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
805 sd->AdditionalSenseCode = additional_sense_code;
806 return;
807 }
809 static VOID
810 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
811 {
812 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
813 return;
814 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
815 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
816 }
818 static BOOLEAN DDKAPI
819 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
820 {
821 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
822 PSCSI_REQUEST_BLOCK srb;
823 RING_IDX i, rp;
824 int j;
825 blkif_response_t *rep;
826 int block_count;
827 int more_to_do = TRUE;
828 blkif_shadow_t *shadow;
829 ULONG offset;
831 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
833 /* in dump mode I think we get called on a timer, not by an actual IRQ */
834 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
835 return FALSE; /* interrupt was not for us */
836 if (xvdd->device_state->resume_state != xvdd->device_state->resume_state_ack)
837 {
838 FUNCTION_ENTER();
839 switch (xvdd->device_state->resume_state)
840 {
841 case RESUME_STATE_SUSPENDING:
842 KdPrint((__DRIVER_NAME " New state SUSPENDING\n"));
843 break;
844 case RESUME_STATE_FRONTEND_RESUME:
845 KdPrint((__DRIVER_NAME " New state RESUME_STATE_FRONTEND_RESUME\n"));
846 XenVbd_Resume(xvdd);
847 break;
848 default:
849 KdPrint((__DRIVER_NAME " New state %d\n", xvdd->device_state->resume_state));
850 break;
851 }
852 xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
853 KeMemoryBarrier();
854 FUNCTION_EXIT();
855 }
857 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
858 {
859 return FALSE;
860 }
862 while (more_to_do)
863 {
864 rp = xvdd->ring.sring->rsp_prod;
865 KeMemoryBarrier();
866 for (i = xvdd->ring.rsp_cons; i < rp; i++)
867 {
868 rep = XenVbd_GetResponse(xvdd, i);
869 /*
870 * This code is to automatically detect if the backend is using the same
871 * bit width or a different bit width to us. Later versions of Xen do this
872 * via a xenstore value, but not all. That 0x0fffffff (notice
873 * that the msb is not actually set, so we don't have any problems with
874 * sign extending) is to signify the last entry on the right, which is
875 * different under 32 and 64 bits, and that is why we set it up there.
877 * To do the detection, we put two initial entries on the ring, with an op
878 * of 0xff (which is invalid). The first entry is mostly okay, but the
879 * second will be grossly misaligned if the backend bit width is different,
880 * and we detect this and switch frontend structures.
881 */
882 switch (xvdd->ring_detect_state)
883 {
884 case 0:
885 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
886 xvdd->ring_detect_state = 1;
887 break;
888 case 1:
889 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
890 *xvdd->event_channel_ptr |= 0x80000000;
891 if (rep->operation != 0xff)
892 {
893 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
894 xvdd->use_other = TRUE;
895 *xvdd->event_channel_ptr |= 0x40000000;
896 }
897 xvdd->ring_detect_state = 2;
898 ScsiPortNotification(NextRequest, DeviceExtension);
899 break;
900 case 2:
901 //KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
902 shadow = &xvdd->shadows[rep->id];
903 srb = shadow->srb;
904 ASSERT(srb != NULL);
905 block_count = decode_cdb_length(srb);
906 block_count *= xvdd->bytes_per_sector / 512;
907 if (rep->status == BLKIF_RSP_OKAY)
908 srb->SrbStatus = SRB_STATUS_SUCCESS;
909 else
910 {
911 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
912 if (decode_cdb_is_read(srb))
913 KdPrint((__DRIVER_NAME " Operation = Read\n"));
914 else
915 KdPrint((__DRIVER_NAME " Operation = Write\n"));
916 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
917 srb->SrbStatus = SRB_STATUS_ERROR;
918 srb->ScsiStatus = 0x02;
919 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
920 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
921 XenVbd_MakeAutoSense(xvdd, srb);
922 }
923 for (j = 0; j < shadow->req.nr_segments; j++)
924 {
925 #if DBG
926 BOOLEAN result =
927 #endif
928 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
929 #if DBG
930 ASSERT(result);
931 #endif
932 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
933 }
935 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
936 {
937 if (decode_cdb_is_read(srb))
938 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
939 offset = shadow->offset + shadow->length;
940 put_shadow_on_freelist(xvdd, shadow);
941 if (offset == (ULONG)block_count * 512)
942 {
943 ScsiPortNotification(RequestComplete, xvdd, srb);
944 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
945 }
946 else
947 {
948 XenVbd_PutSrbOnRing(xvdd, srb, offset);
949 }
950 }
951 else
952 {
953 put_shadow_on_freelist(xvdd, shadow);
954 ScsiPortNotification(RequestComplete, xvdd, srb);
955 if (xvdd->pending_srb)
956 {
957 srb = xvdd->pending_srb;
958 xvdd->pending_srb = NULL;
959 XenVbd_PutSrbOnRing(xvdd, srb, 0);
960 }
961 else
962 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
963 }
964 break;
965 }
966 }
968 xvdd->ring.rsp_cons = i;
969 if (i != xvdd->ring.req_prod_pvt)
970 {
971 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
972 }
973 else
974 {
975 xvdd->ring.sring->rsp_event = i + 1;
976 more_to_do = FALSE;
977 }
978 }
980 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
981 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
982 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
983 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
985 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
987 return FALSE; /* always fall through to the next ISR... */
988 }
990 static BOOLEAN DDKAPI
991 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
992 {
993 PUCHAR DataBuffer;
994 PCDB cdb;
995 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
997 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
999 if (xvdd->inactive)
1001 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1002 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1003 ScsiPortNotification(NextRequest, DeviceExtension);
1004 return TRUE;
1007 // If we haven't enumerated all the devices yet then just defer the request
1008 if (xvdd->ring_detect_state < 2)
1010 Srb->SrbStatus = SRB_STATUS_BUSY;
1011 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1012 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
1013 return TRUE;
1016 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
1018 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
1019 Srb->SrbStatus = SRB_STATUS_BUSY;
1020 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1021 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
1022 return TRUE;
1025 if (Srb->PathId != 0 || Srb->TargetId != 0)
1027 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1028 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1029 ScsiPortNotification(NextRequest, DeviceExtension);
1030 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1031 return TRUE;
1034 switch (Srb->Function)
1036 case SRB_FUNCTION_EXECUTE_SCSI:
1037 cdb = (PCDB)Srb->Cdb;
1038 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1040 switch(cdb->CDB6GENERIC.OperationCode)
1042 case SCSIOP_TEST_UNIT_READY:
1043 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1044 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1045 Srb->ScsiStatus = 0;
1046 break;
1047 case SCSIOP_INQUIRY:
1048 // KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1049 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1050 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
1051 // KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
1052 DataBuffer = Srb->DataBuffer;
1053 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1054 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1055 switch (xvdd->device_type)
1057 case XENVBD_DEVICETYPE_DISK:
1058 if ((Srb->Cdb[1] & 1) == 0)
1060 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1061 id->DeviceType = DIRECT_ACCESS_DEVICE;
1062 id->Versions = 3;
1063 id->ResponseDataFormat = 0;
1064 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1065 id->CommandQueue = 1;
1066 memcpy(id->VendorId, "XEN ", 8); // vendor id
1067 memcpy(id->ProductId, "PV DISK ", 16); // product id
1068 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1070 else
1072 switch (Srb->Cdb[2])
1074 case 0x00:
1075 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1076 DataBuffer[1] = 0x00;
1077 DataBuffer[2] = 0x00;
1078 DataBuffer[3] = 2;
1079 DataBuffer[4] = 0x00;
1080 DataBuffer[5] = 0x80;
1081 break;
1082 case 0x80:
1083 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1084 DataBuffer[1] = 0x80;
1085 DataBuffer[2] = 0x00;
1086 DataBuffer[3] = 8;
1087 memset(&DataBuffer[4], ' ', 8);
1088 break;
1089 default:
1090 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1091 Srb->SrbStatus = SRB_STATUS_ERROR;
1092 break;
1095 break;
1096 case XENVBD_DEVICETYPE_CDROM:
1097 if ((Srb->Cdb[1] & 1) == 0)
1099 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1100 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1101 id->RemovableMedia = 1;
1102 id->Versions = 3;
1103 id->ResponseDataFormat = 0;
1104 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1105 id->CommandQueue = 1;
1106 memcpy(id->VendorId, "XEN ", 8); // vendor id
1107 memcpy(id->ProductId, "PV CDROM ", 16); // product id
1108 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1110 else
1112 switch (Srb->Cdb[2])
1114 case 0x00:
1115 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1116 DataBuffer[1] = 0x00;
1117 DataBuffer[2] = 0x00;
1118 DataBuffer[3] = 2;
1119 DataBuffer[4] = 0x00;
1120 DataBuffer[5] = 0x80;
1121 break;
1122 case 0x80:
1123 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1124 DataBuffer[1] = 0x80;
1125 DataBuffer[2] = 0x00;
1126 DataBuffer[3] = 8;
1127 DataBuffer[4] = 0x31;
1128 DataBuffer[5] = 0x32;
1129 DataBuffer[6] = 0x33;
1130 DataBuffer[7] = 0x34;
1131 DataBuffer[8] = 0x35;
1132 DataBuffer[9] = 0x36;
1133 DataBuffer[10] = 0x37;
1134 DataBuffer[11] = 0x38;
1135 break;
1136 default:
1137 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1138 Srb->SrbStatus = SRB_STATUS_ERROR;
1139 break;
1142 break;
1143 default:
1144 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1145 Srb->SrbStatus = SRB_STATUS_ERROR;
1146 break;
1148 break;
1149 case SCSIOP_READ_CAPACITY:
1150 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1151 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1152 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1153 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1154 DataBuffer = Srb->DataBuffer;
1155 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1156 if ((xvdd->total_sectors - 1) >> 32)
1158 DataBuffer[0] = 0xff;
1159 DataBuffer[1] = 0xff;
1160 DataBuffer[2] = 0xff;
1161 DataBuffer[3] = 0xff;
1163 else
1165 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1166 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1167 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1168 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1170 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1171 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1172 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1173 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1174 Srb->ScsiStatus = 0;
1175 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1176 break;
1177 case SCSIOP_READ_CAPACITY16:
1178 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1179 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1180 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1181 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1182 DataBuffer = Srb->DataBuffer;
1183 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1184 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1185 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1186 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1187 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1188 DataBuffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1189 DataBuffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1190 DataBuffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1191 DataBuffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1192 DataBuffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1193 DataBuffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1194 DataBuffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1195 DataBuffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1196 Srb->ScsiStatus = 0;
1197 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1198 break;
1199 case SCSIOP_MODE_SENSE:
1200 case SCSIOP_MODE_SENSE10:
1201 // 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));
1202 XenVbd_FillModePage(xvdd, Srb);
1203 break;
1204 case SCSIOP_READ:
1205 case SCSIOP_READ16:
1206 case SCSIOP_WRITE:
1207 case SCSIOP_WRITE16:
1208 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1209 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
1210 break;
1211 case SCSIOP_VERIFY:
1212 // Should we do more here?
1213 // KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1214 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1215 break;
1216 case SCSIOP_REPORT_LUNS:
1217 // KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1218 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1219 break;
1220 case SCSIOP_REQUEST_SENSE:
1221 // KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1222 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1223 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1224 break;
1225 case SCSIOP_READ_TOC:
1226 DataBuffer = Srb->DataBuffer;
1227 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1228 /*
1229 #define READ_TOC_FORMAT_TOC 0x00
1230 #define READ_TOC_FORMAT_SESSION 0x01
1231 #define READ_TOC_FORMAT_FULL_TOC 0x02
1232 #define READ_TOC_FORMAT_PMA 0x03
1233 #define READ_TOC_FORMAT_ATIP 0x04
1234 */
1235 // KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1236 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1237 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1238 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1239 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1240 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1241 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1242 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1243 switch (cdb->READ_TOC.Format2)
1245 case READ_TOC_FORMAT_TOC:
1246 DataBuffer[0] = 0; // length MSB
1247 DataBuffer[1] = 10; // length LSB
1248 DataBuffer[2] = 1; // First Track
1249 DataBuffer[3] = 1; // Last Track
1250 DataBuffer[4] = 0; // Reserved
1251 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1252 DataBuffer[6] = 1; // last complete track
1253 DataBuffer[7] = 0; // reserved
1254 DataBuffer[8] = 0; // MSB Block
1255 DataBuffer[9] = 0;
1256 DataBuffer[10] = 0;
1257 DataBuffer[11] = 0; // LSB Block
1258 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1259 break;
1260 case READ_TOC_FORMAT_SESSION:
1261 case READ_TOC_FORMAT_FULL_TOC:
1262 case READ_TOC_FORMAT_PMA:
1263 case READ_TOC_FORMAT_ATIP:
1264 Srb->SrbStatus = SRB_STATUS_ERROR;
1265 break;
1267 break;
1268 case SCSIOP_START_STOP_UNIT:
1269 // KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1270 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1271 break;
1272 case SCSIOP_RESERVE_UNIT:
1273 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1274 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1275 break;
1276 case SCSIOP_RELEASE_UNIT:
1277 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1278 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1279 break;
1280 default:
1281 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1282 Srb->SrbStatus = SRB_STATUS_ERROR;
1283 break;
1285 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1287 //KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1288 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1290 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1291 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1293 Srb->ScsiStatus = 0x02;
1294 XenVbd_MakeAutoSense(xvdd, Srb);
1295 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1296 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1298 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1300 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1301 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1302 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1303 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1305 break;
1306 case SRB_FUNCTION_IO_CONTROL:
1307 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1308 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1309 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1310 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1311 break;
1312 case SRB_FUNCTION_FLUSH:
1313 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1314 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1315 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1316 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1317 break;
1318 default:
1319 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1320 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1321 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1322 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1323 break;
1326 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1327 return TRUE;
1330 static BOOLEAN DDKAPI
1331 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1333 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1335 UNREFERENCED_PARAMETER(DeviceExtension);
1336 UNREFERENCED_PARAMETER(PathId);
1338 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1340 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1341 if (xvdd->ring_detect_state == 2 && xvdd->device_state->resume_state == RESUME_STATE_RUNNING)
1343 ScsiPortNotification(NextRequest, DeviceExtension);
1346 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1349 return TRUE;
1352 static BOOLEAN DDKAPI
1353 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1355 UNREFERENCED_PARAMETER(DeviceExtension);
1356 UNREFERENCED_PARAMETER(Context);
1357 UNREFERENCED_PARAMETER(SaveState);
1359 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1360 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1362 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1364 return TRUE;
1367 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1368 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1370 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1371 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1372 //KIRQL OldIrql;
1374 UNREFERENCED_PARAMETER(DeviceExtension);
1376 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1377 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1379 switch (ControlType)
1381 case ScsiQuerySupportedControlTypes:
1382 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1383 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1384 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1385 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1386 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1387 break;
1388 case ScsiStopAdapter:
1389 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1390 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1391 break;
1392 case ScsiRestartAdapter:
1393 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1394 break;
1395 case ScsiSetBootConfig:
1396 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1397 break;
1398 case ScsiSetRunningConfig:
1399 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1400 break;
1401 default:
1402 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1403 break;
1406 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1408 return Status;
1411 NTSTATUS
1412 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1414 ULONG status;
1415 HW_INITIALIZATION_DATA HwInitializationData;
1416 PVOID driver_extension;
1417 PUCHAR ptr;
1419 FUNCTION_ENTER();
1420 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1421 KdPrint((__DRIVER_NAME " DriverObject = %p\n", DriverObject));
1423 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1424 if (!RegistryPath)
1426 dump_mode = TRUE;
1429 if (!dump_mode)
1431 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1432 ptr = driver_extension;
1433 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
1434 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
1435 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
1436 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL);
1437 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL);
1438 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL);
1439 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL);
1440 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, UlongToPtr(144));
1441 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
1444 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1446 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1447 HwInitializationData.AdapterInterfaceType = PNPBus;
1448 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1449 HwInitializationData.SpecificLuExtensionSize = 0;
1450 /* SrbExtension is not always aligned to a page boundary, so we add PAGE_SIZE-1 to it to make sure we have at least UNALIGNED_DOUBLE_BUFFER_SIZE bytes of page aligned memory */
1451 HwInitializationData.SrbExtensionSize = UNALIGNED_DOUBLE_BUFFER_SIZE + PAGE_SIZE - 1;
1452 HwInitializationData.NumberOfAccessRanges = 1;
1453 HwInitializationData.MapBuffers = TRUE;
1454 HwInitializationData.NeedPhysicalAddresses = FALSE;
1455 HwInitializationData.TaggedQueuing = FALSE;
1456 HwInitializationData.AutoRequestSense = TRUE;
1457 HwInitializationData.MultipleRequestPerLu = TRUE;
1458 HwInitializationData.ReceiveEvent = FALSE;
1459 HwInitializationData.VendorIdLength = 0;
1460 HwInitializationData.VendorId = NULL;
1461 HwInitializationData.DeviceIdLength = 0;
1462 HwInitializationData.DeviceId = NULL;
1464 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1465 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1466 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1467 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1468 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1469 HwInitializationData.HwDmaStarted = NULL;
1470 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
1471 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1473 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1475 if(!NT_SUCCESS(status))
1477 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1480 FUNCTION_EXIT();
1482 return status;