win-pvdrivers

view xenvbd/xenvbd.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children e75bb8d68370
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 LongLongToPtr(x) (PVOID)(x)
40 #else
41 #define LongLongToPtr(x) UlongToPtr(x)
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 blkif_response_t *
80 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
81 {
82 blkif_other_response_t *rep;
83 if (!xvdd->use_other)
84 return RING_GET_RESPONSE(&xvdd->ring, i);
85 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
86 xvdd->tmp_rep.id = rep->id;
87 xvdd->tmp_rep.operation = rep->operation;
88 xvdd->tmp_rep.status = rep->status;
89 return &xvdd->tmp_rep;
90 }
92 static VOID
93 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
94 {
95 blkif_other_request_t *other_req;
97 if (!xvdd->use_other)
98 {
99 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
100 }
101 else
102 {
103 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
104 other_req->operation = req->operation;
105 other_req->nr_segments = req->nr_segments;
106 other_req->handle = req->handle;
107 other_req->id = req->id;
108 other_req->sector_number = req->sector_number;
109 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
110 }
111 xvdd->ring.req_prod_pvt++;
112 }
114 static ULONG
115 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
116 {
117 ULONG i;
118 PUCHAR ptr;
119 USHORT type;
120 PCHAR setting, value, value2;
121 ULONG qemu_protocol_version = 0;
123 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
124 xvdd->sring = NULL;
125 xvdd->event_channel = 0;
127 xvdd->inactive = TRUE;
128 ptr = xvdd->device_base;
129 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
130 {
131 switch(type)
132 {
133 case XEN_INIT_TYPE_RING: /* frontend ring */
134 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
135 if (strcmp(setting, "ring-ref") == 0)
136 {
137 xvdd->sring = (blkif_sring_t *)value;
138 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
139 /* this bit is for when we have to take over an existing ring on a crash dump */
140 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
141 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
142 }
143 break;
144 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
145 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
146 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
147 if (strcmp(setting, "event-channel") == 0)
148 {
149 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
150 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
151 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
152 if (PtrToUlong(value) & 0x80000000)
153 {
154 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
155 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
156 }
157 }
158 break;
159 case XEN_INIT_TYPE_READ_STRING_BACK:
160 case XEN_INIT_TYPE_READ_STRING_FRONT:
161 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
162 if (strcmp(setting, "sectors") == 0)
163 xvdd->total_sectors = parse_numeric_string(value);
164 else if (strcmp(setting, "sector-size") == 0)
165 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
166 else if (strcmp(setting, "device-type") == 0)
167 {
168 if (strcmp(value, "disk") == 0)
169 {
170 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
171 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
172 }
173 else if (strcmp(value, "cdrom") == 0)
174 {
175 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
176 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
177 }
178 else
179 {
180 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
181 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
182 }
183 }
184 else if (strcmp(setting, "mode") == 0)
185 {
186 if (strncmp(value, "r", 1) == 0)
187 {
188 KdPrint((__DRIVER_NAME " mode = r\n"));
189 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
190 }
191 else if (strncmp(value, "w", 1) == 0)
192 {
193 KdPrint((__DRIVER_NAME " mode = w\n"));
194 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
195 }
196 else
197 {
198 KdPrint((__DRIVER_NAME " mode = unknown\n"));
199 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
200 }
201 }
202 break;
203 case XEN_INIT_TYPE_VECTORS:
204 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
205 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
206 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
207 {
208 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
209 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
210 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
211 return SP_RETURN_BAD_CONFIG;
212 }
213 else
214 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
215 break;
216 case XEN_INIT_TYPE_STATE_PTR:
217 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
218 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
219 break;
220 case XEN_INIT_TYPE_ACTIVE:
221 xvdd->inactive = FALSE;
222 break;
223 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
224 qemu_protocol_version = PtrToUlong(value);
225 break;
226 case XEN_INIT_TYPE_GRANT_ENTRIES:
227 xvdd->dump_grant_ref = *(grant_ref_t *)value;
228 break;
229 default:
230 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
231 break;
232 }
233 }
234 if (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"));
252 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
253 {
254 /* CD/DVD drives must have bytes_per_sector = 2048. */
255 xvdd->bytes_per_sector = 2048;
256 }
258 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
259 #ifdef __MINGW32__
260 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
261 {
262 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
263 ULONG index;
265 bit_scan_forward(&index, num_512_byte_sectors);
266 xvdd->total_sectors <<= index-1;
267 }
268 #else
269 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
270 #endif
273 xvdd->shadow_free = 0;
274 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
275 for (i = 0; i < SHADOW_ENTRIES; i++)
276 {
277 xvdd->shadows[i].req.id = i;
278 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
279 }
281 return SP_RETURN_FOUND;
282 }
284 static __inline ULONG
285 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
286 {
287 switch (srb->Cdb[0])
288 {
289 case SCSIOP_READ:
290 case SCSIOP_WRITE:
291 return (srb->Cdb[7] << 8) | srb->Cdb[8];
292 case SCSIOP_READ16:
293 case SCSIOP_WRITE16:
294 return (srb->Cdb[10] << 24) | (srb->Cdb[11] << 16) | (srb->Cdb[12] << 8) | srb->Cdb[13];
295 default:
296 return 0;
297 }
298 }
300 static __inline ULONGLONG
301 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
302 {
303 ULONGLONG sector;
305 switch (srb->Cdb[0])
306 {
307 case SCSIOP_READ:
308 case SCSIOP_WRITE:
309 sector = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
310 break;
311 case SCSIOP_READ16:
312 case SCSIOP_WRITE16:
313 sector = ((ULONGLONG)srb->Cdb[2] << 56) | ((ULONGLONG)srb->Cdb[3] << 48)
314 | ((ULONGLONG)srb->Cdb[4] << 40) | ((ULONGLONG)srb->Cdb[5] << 32)
315 | ((ULONGLONG)srb->Cdb[6] << 24) | ((ULONGLONG)srb->Cdb[7] << 16)
316 | ((ULONGLONG)srb->Cdb[8] << 8) | ((ULONGLONG)srb->Cdb[9]);
317 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
318 break;
319 default:
320 sector = 0;
321 break;
322 }
323 return sector;
324 }
326 static __inline BOOLEAN
327 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
328 {
329 switch (srb->Cdb[0])
330 {
331 case SCSIOP_READ:
332 case SCSIOP_READ16:
333 return TRUE;
334 case SCSIOP_WRITE:
335 case SCSIOP_WRITE16:
336 return FALSE;
337 default:
338 return FALSE;
339 }
340 }
342 static __forceinline PVOID
343 get_databuffer_virtual(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
344 {
345 ULONG data_buffer_length;
347 if (!dump_mode)
348 {
349 return LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
350 }
351 else
352 {
353 /* in dump mode, we can count on srb->DataBuffer being the virtual address we want */
354 return srb->DataBuffer;
355 }
356 }
358 static VOID
359 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
360 {
361 ULONG block_count;
362 blkif_shadow_t *shadow;
363 ULONG remaining, offset, length;
364 PUCHAR ptr;
365 int notify;
367 //FUNCTION_ENTER();
369 ptr = srb->DataBuffer;
371 block_count = decode_cdb_length(srb);;
372 block_count *= xvdd->bytes_per_sector / 512;
373 remaining = block_count * 512;
375 shadow = get_shadow_from_freelist(xvdd);
376 ASSERT(shadow);
377 shadow->req.sector_number = decode_cdb_sector(srb);
378 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
379 shadow->req.handle = 0;
380 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
381 shadow->req.nr_segments = 0;
382 shadow->srb = srb;
384 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
385 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
386 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
388 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
389 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
390 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
391 if (!dump_mode)
392 {
393 while (remaining > 0)
394 {
395 PHYSICAL_ADDRESS physical_address;
396 physical_address = ScsiPortGetPhysicalAddress(xvdd, srb, ptr, &length);
397 offset = physical_address.LowPart & (PAGE_SIZE - 1);
398 if (offset & 511)
399 {
400 KdPrint((__DRIVER_NAME " DataTransferLength = %d, remaining = %d, block_count = %d, offset = %d, ptr = %p, srb->DataBuffer = %p\n",
401 srb->DataTransferLength, remaining, block_count, offset, ptr, srb->DataBuffer));
402 ptr = srb->DataBuffer;
403 block_count = decode_cdb_length(srb);;
404 block_count *= xvdd->bytes_per_sector / 512;
405 remaining = block_count * 512;
406 while (remaining > 0)
407 {
408 physical_address = ScsiPortGetPhysicalAddress(xvdd, srb, ptr, &length);
409 KdPrint((__DRIVER_NAME " ptr = %p, physical_address = %08x:%08x, length = %d\n",
410 ptr, physical_address.HighPart, physical_address.LowPart, length));
411 remaining -= length;
412 ptr += length;
413 KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
414 }
415 }
417 ASSERT((offset & 511) == 0);
418 ASSERT((length & 511) == 0);
419 //length = min(PAGE_SIZE - offset, remaining);
420 //KdPrint((__DRIVER_NAME " length(a) = %d\n", length));
421 shadow->req.seg[shadow->req.nr_segments].gref = (grant_ref_t)(physical_address.QuadPart >> PAGE_SHIFT);
422 //KdPrint((__DRIVER_NAME " length(b) = %d\n", length));
423 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
424 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
425 remaining -= length;
426 ptr += length;
427 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
428 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
429 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
430 shadow->req.nr_segments++;
431 }
432 }
433 else
434 {
435 PHYSICAL_ADDRESS physical_address;
436 //KdPrint((__DRIVER_NAME " remaining = %d\n", remaining));
437 ASSERT(remaining <= PAGE_SIZE); /* one page at a time in dump mode */
438 physical_address = ScsiPortGetPhysicalAddress(xvdd, srb, ptr, &length);
439 offset = physical_address.LowPart & (PAGE_SIZE - 1);
440 ASSERT(offset == 0);
441 //ASSERT((offset & 511) == 0);
442 shadow->req.seg[shadow->req.nr_segments].gref =
443 (grant_ref_t)xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
444 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, xvdd->dump_grant_ref);
445 //KdPrint((__DRIVER_NAME " gref = %d, dump_grant_ref = %d\n",
446 // shadow->req.seg[shadow->req.nr_segments].gref, xvdd->dump_grant_ref));
447 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
448 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + remaining) >> 9) - 1);
449 remaining -= length;
450 shadow->req.nr_segments++;
451 }
452 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
454 XenVbd_PutRequest(xvdd, &shadow->req);
456 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
457 if (notify)
458 {
459 //KdPrint((__DRIVER_NAME " Notifying\n"));
460 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
461 }
463 if (xvdd->shadow_free)
464 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
466 //FUNCTION_EXIT();
467 }
469 #if 0
470 static VOID
471 XenVbd_Resume(PVOID DeviceExtension)
472 {
473 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
474 ULONG i;
476 FUNCTION_ENTER();
477 KdPrint((__DRIVER_NAME " found device in resume state\n"));
478 //FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE); what was this for???
479 // re-submit srb's
481 KdPrint((__DRIVER_NAME " About to call InitFromConfig\n"));
482 XenVbd_InitFromConfig(xvdd);
483 KdPrint((__DRIVER_NAME " Back from InitFromConfig\n"));
486 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
488 KdPrint((__DRIVER_NAME " resume_state set to RESUME_STATE_RUNNING\n"));
490 if (i == 0)
491 {
492 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
493 KdPrint((__DRIVER_NAME " No shadows - notifying to get things started again\n"));
494 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
495 }
496 FUNCTION_EXIT();
497 }
498 #endif
500 static ULONG DDKAPI
501 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
502 {
503 // PACCESS_RANGE AccessRange;
504 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
505 ULONG status;
506 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
507 PACCESS_RANGE access_range;
509 UNREFERENCED_PARAMETER(HwContext);
510 UNREFERENCED_PARAMETER(BusInformation);
511 UNREFERENCED_PARAMETER(ArgumentString);
513 FUNCTION_ENTER();
514 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
516 *Again = FALSE;
518 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
519 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
521 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
522 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
523 {
524 return SP_RETURN_BAD_CONFIG;
525 }
527 access_range = &((*(ConfigInfo->AccessRanges))[0]);
528 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
529 access_range->RangeStart.LowPart, access_range->RangeLength));
530 xvdd->device_base = ScsiPortGetDeviceBase(
531 DeviceExtension,
532 ConfigInfo->AdapterInterfaceType,
533 ConfigInfo->SystemIoBusNumber,
534 access_range->RangeStart,
535 access_range->RangeLength,
536 !access_range->RangeInMemory);
537 if (!xvdd->device_base)
538 {
539 KdPrint((__DRIVER_NAME " Invalid config\n"));
540 FUNCTION_EXIT();
541 return SP_RETURN_BAD_CONFIG;
542 }
544 status = XenVbd_InitFromConfig(xvdd);
545 if (status != SP_RETURN_FOUND)
546 {
547 FUNCTION_EXIT();
548 return status;
549 }
551 if (dump_mode)
552 {
553 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
554 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
555 ConfigInfo->ScatterGather = TRUE;
556 }
557 else
558 {
559 ConfigInfo->MaximumTransferLength = 4096;
560 ConfigInfo->NumberOfPhysicalBreaks = 0;
561 ConfigInfo->ScatterGather = FALSE;
562 }
563 ConfigInfo->AlignmentMask = 0;
564 ConfigInfo->NumberOfBuses = 1;
565 ConfigInfo->InitiatorBusId[0] = 1;
566 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
567 ConfigInfo->MaximumNumberOfTargets = 2;
568 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
569 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
570 {
571 ConfigInfo->Master = TRUE;
572 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
573 ConfigInfo->Dma32BitAddresses = FALSE;
574 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
575 }
576 else
577 {
578 ConfigInfo->Master = TRUE; //FALSE;
579 ConfigInfo->Dma32BitAddresses = TRUE;
580 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
581 }
583 FUNCTION_EXIT();
585 return SP_RETURN_FOUND;
586 }
588 static BOOLEAN DDKAPI
589 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
590 {
591 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
592 blkif_request_t *req;
593 int i;
594 int notify;
596 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
597 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
599 if (!dump_mode)
600 {
601 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
602 req->operation = 0xff;
603 req->nr_segments = 0;
604 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
605 {
606 req->seg[i].gref = 0; //0xffffffff;
607 req->seg[i].first_sect = 0; //0xff;
608 req->seg[i].last_sect = 0; //0xff;
609 }
610 xvdd->ring.req_prod_pvt++;
612 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
613 req->operation = 0xff;
614 req->nr_segments = 0;
615 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
616 {
617 req->seg[i].gref = 0; //0xffffffff;
618 req->seg[i].first_sect = 0; //0xff;
619 req->seg[i].last_sect = 0; //0xff;
620 }
621 xvdd->ring.req_prod_pvt++;
623 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
624 if (notify)
625 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
626 xvdd->ring_detect_state = 0;
627 }
628 else
629 {
630 if (xvdd->cached_use_other)
631 {
632 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
633 xvdd->use_other = TRUE;
634 }
635 xvdd->ring_detect_state = 2;
636 }
638 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
640 return TRUE;
641 }
643 static ULONG
644 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
645 {
646 PMODE_PARAMETER_HEADER parameter_header;
647 PMODE_PARAMETER_BLOCK param_block;
648 PMODE_FORMAT_PAGE format_page;
649 ULONG offset;
650 UCHAR buffer[256];
651 BOOLEAN valid_page = FALSE;
652 BOOLEAN cdb_llbaa;
653 BOOLEAN cdb_dbd;
654 UCHAR cdb_page_code;
655 USHORT cdb_allocation_length;
656 PVOID data_buffer;
657 //ULONG data_buffer_length;
659 UNREFERENCED_PARAMETER(xvdd);
661 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
663 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
664 data_buffer = get_databuffer_virtual(xvdd, srb);
665 //cdb = (PCDB)srb->Cdb;
666 switch (srb->Cdb[0])
667 {
668 case SCSIOP_MODE_SENSE:
669 cdb_llbaa = FALSE;
670 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
671 cdb_page_code = srb->Cdb[2] & 0x3f;
672 cdb_allocation_length = srb->Cdb[4];
673 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
674 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
675 break;
676 case SCSIOP_MODE_SENSE10:
677 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
678 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
679 cdb_page_code = srb->Cdb[2] & 0x3f;
680 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
681 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
682 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
683 break;
684 default:
685 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
686 return FALSE;
687 }
688 offset = 0;
690 RtlZeroMemory(data_buffer, srb->DataTransferLength);
691 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
693 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
694 parameter_header->MediumType = 0;
695 parameter_header->DeviceSpecificParameter = 0;
696 parameter_header->BlockDescriptorLength = 0;
697 offset += sizeof(MODE_PARAMETER_HEADER);
699 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
700 {
701 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
702 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
703 }
705 if (!cdb_dbd)
706 {
707 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
708 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
709 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
710 {
711 if (xvdd->total_sectors >> 32)
712 {
713 param_block->DensityCode = 0xff;
714 param_block->NumberOfBlocks[0] = 0xff;
715 param_block->NumberOfBlocks[1] = 0xff;
716 param_block->NumberOfBlocks[2] = 0xff;
717 }
718 else
719 {
720 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
721 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
722 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
723 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
724 }
725 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
726 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
727 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
728 }
729 offset += sizeof(MODE_PARAMETER_BLOCK);
730 }
731 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
732 {
733 valid_page = TRUE;
734 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
735 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
736 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
737 /* 256 sectors per track */
738 format_page->SectorsPerTrack[0] = 0x01;
739 format_page->SectorsPerTrack[1] = 0x00;
740 /* xxx bytes per sector */
741 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
742 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
743 format_page->HardSectorFormating = TRUE;
744 format_page->SoftSectorFormating = TRUE;
745 offset += sizeof(MODE_FORMAT_PAGE);
746 }
747 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
748 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
749 {
750 srb->SrbStatus = SRB_STATUS_ERROR;
751 }
752 else if(offset < srb->DataTransferLength)
753 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
754 else
755 srb->SrbStatus = SRB_STATUS_SUCCESS;
756 srb->DataTransferLength = min(srb->DataTransferLength, offset);
757 srb->ScsiStatus = 0;
758 memcpy(data_buffer, buffer, srb->DataTransferLength);
760 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
762 return TRUE;
763 }
765 static VOID
766 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
767 {
768 PSENSE_DATA sd = srb->SenseInfoBuffer;
770 UNREFERENCED_PARAMETER(xvdd);
772 if (!srb->SenseInfoBuffer)
773 return;
775 sd->ErrorCode = 0x70;
776 sd->Valid = 1;
777 sd->SenseKey = sense_key;
778 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
779 sd->AdditionalSenseCode = additional_sense_code;
780 return;
781 }
783 static VOID
784 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
785 {
786 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
787 return;
788 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
789 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
790 }
792 static BOOLEAN DDKAPI
793 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
794 {
795 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
796 PSCSI_REQUEST_BLOCK srb;
797 RING_IDX i, rp;
798 blkif_response_t *rep;
799 int block_count;
800 int more_to_do = TRUE;
801 blkif_shadow_t *shadow;
802 ULONG suspend_resume_state_pdo;
804 /* in dump mode I think we get called on a timer, not by an actual IRQ */
805 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
806 return FALSE; /* interrupt was not for us */
808 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
809 KeMemoryBarrier();
811 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
812 {
813 FUNCTION_ENTER();
814 switch (suspend_resume_state_pdo)
815 {
816 case SR_STATE_SUSPENDING:
817 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
818 break;
819 case SR_STATE_RESUMING:
820 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
821 XenVbd_InitFromConfig(xvdd);
822 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
823 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
824 break;
825 case SR_STATE_RUNNING:
826 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
827 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
828 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
829 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
830 default:
831 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
832 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
833 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
834 break;
835 }
836 KeMemoryBarrier();
837 }
839 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
840 {
841 return FALSE;
842 }
844 while (more_to_do)
845 {
846 rp = xvdd->ring.sring->rsp_prod;
847 KeMemoryBarrier();
848 for (i = xvdd->ring.rsp_cons; i < rp; i++)
849 {
850 rep = XenVbd_GetResponse(xvdd, i);
851 /*
852 * This code is to automatically detect if the backend is using the same
853 * bit width or a different bit width to us. Later versions of Xen do this
854 * via a xenstore value, but not all. That 0x0fffffff (notice
855 * that the msb is not actually set, so we don't have any problems with
856 * sign extending) is to signify the last entry on the right, which is
857 * different under 32 and 64 bits, and that is why we set it up there.
859 * To do the detection, we put two initial entries on the ring, with an op
860 * of 0xff (which is invalid). The first entry is mostly okay, but the
861 * second will be grossly misaligned if the backend bit width is different,
862 * and we detect this and switch frontend structures.
863 */
864 switch (xvdd->ring_detect_state)
865 {
866 case 0:
867 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
868 xvdd->ring_detect_state = 1;
869 break;
870 case 1:
871 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
872 *xvdd->event_channel_ptr |= 0x80000000;
873 if (rep->operation != 0xff)
874 {
875 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
876 xvdd->use_other = TRUE;
877 *xvdd->event_channel_ptr |= 0x40000000;
878 }
879 xvdd->ring_detect_state = 2;
880 ScsiPortNotification(NextRequest, DeviceExtension);
881 break;
882 case 2:
883 shadow = &xvdd->shadows[rep->id];
884 srb = shadow->srb;
885 ASSERT(srb != NULL);
886 block_count = decode_cdb_length(srb);
887 block_count *= xvdd->bytes_per_sector / 512;
888 if (rep->status == BLKIF_RSP_OKAY)
889 srb->SrbStatus = SRB_STATUS_SUCCESS;
890 else
891 {
892 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
893 if (decode_cdb_is_read(srb))
894 KdPrint((__DRIVER_NAME " Operation = Read\n"));
895 else
896 KdPrint((__DRIVER_NAME " Operation = Write\n"));
897 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
898 srb->SrbStatus = SRB_STATUS_ERROR;
899 srb->ScsiStatus = 0x02;
900 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
901 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
902 XenVbd_MakeAutoSense(xvdd, srb);
903 }
904 put_shadow_on_freelist(xvdd, shadow);
905 if (dump_mode)
906 {
907 ASSERT(shadow->req.nr_segments == 1);
908 //KdPrint((__DRIVER_NAME " gref = %d, dump_grant_ref = %d\n",
909 // shadow->req.seg[0].gref, xvdd->dump_grant_ref));
910 ASSERT(shadow->req.seg[0].gref == xvdd->dump_grant_ref);
911 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
912 shadow->req.seg[0].gref, TRUE);
913 }
914 ScsiPortNotification(RequestComplete, xvdd, srb);
915 if (suspend_resume_state_pdo == SR_STATE_RUNNING)
916 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
917 break;
918 }
919 }
921 xvdd->ring.rsp_cons = i;
922 if (i != xvdd->ring.req_prod_pvt)
923 {
924 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
925 }
926 else
927 {
928 xvdd->ring.sring->rsp_event = i + 1;
929 more_to_do = FALSE;
930 }
931 }
933 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
934 {
935 if (xvdd->shadow_free == SHADOW_ENTRIES)
936 {
937 /* all entries are purged from the list. ready to suspend */
938 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
939 KeMemoryBarrier();
940 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
941 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
942 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
943 }
944 FUNCTION_EXIT();
945 }
947 return FALSE; /* always fall through to the next ISR... */
948 }
950 static BOOLEAN DDKAPI
951 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
952 {
953 PUCHAR data_buffer;
954 //ULONG data_buffer_length;
955 PCDB cdb;
956 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
958 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
960 if (xvdd->inactive)
961 {
962 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
963 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
964 ScsiPortNotification(NextRequest, DeviceExtension);
965 return TRUE;
966 }
968 // If we haven't enumerated all the devices yet then just defer the request
969 if (xvdd->ring_detect_state < 2)
970 {
971 Srb->SrbStatus = SRB_STATUS_BUSY;
972 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
973 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
974 return TRUE;
975 }
977 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
978 {
979 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
980 Srb->SrbStatus = SRB_STATUS_BUSY;
981 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
982 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
983 return TRUE;
984 }
986 if (Srb->PathId != 0 || Srb->TargetId != 0)
987 {
988 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
989 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
990 ScsiPortNotification(NextRequest, DeviceExtension);
991 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
992 return TRUE;
993 }
995 switch (Srb->Function)
996 {
997 case SRB_FUNCTION_EXECUTE_SCSI:
998 cdb = (PCDB)Srb->Cdb;
1000 switch(cdb->CDB6GENERIC.OperationCode)
1002 case SCSIOP_TEST_UNIT_READY:
1003 if (dump_mode)
1004 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1005 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1006 Srb->ScsiStatus = 0;
1007 break;
1008 case SCSIOP_INQUIRY:
1009 if (dump_mode)
1011 //PHYSICAL_ADDRESS physical;
1012 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1013 //KdPrint((__DRIVER_NAME " Srb->Databuffer = %p\n", Srb->DataBuffer));
1014 //physical = ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length);
1015 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
1017 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1018 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
1020 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1021 data_buffer = get_databuffer_virtual(xvdd, Srb);
1022 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1023 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1024 switch (xvdd->device_type)
1026 case XENVBD_DEVICETYPE_DISK:
1027 if ((Srb->Cdb[1] & 1) == 0)
1029 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1030 id->DeviceType = DIRECT_ACCESS_DEVICE;
1031 id->Versions = 3;
1032 id->ResponseDataFormat = 0;
1033 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1034 id->CommandQueue = 1;
1035 memcpy(id->VendorId, "XEN ", 8); // vendor id
1036 memcpy(id->ProductId, "PV DISK ", 16); // product id
1037 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1039 else
1041 switch (Srb->Cdb[2])
1043 case 0x00:
1044 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1045 data_buffer[1] = 0x00;
1046 data_buffer[2] = 0x00;
1047 data_buffer[3] = 2;
1048 data_buffer[4] = 0x00;
1049 data_buffer[5] = 0x80;
1050 break;
1051 case 0x80:
1052 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1053 data_buffer[1] = 0x80;
1054 data_buffer[2] = 0x00;
1055 data_buffer[3] = 8;
1056 memset(&data_buffer[4], ' ', 8);
1057 break;
1058 default:
1059 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1060 Srb->SrbStatus = SRB_STATUS_ERROR;
1061 break;
1064 break;
1065 case XENVBD_DEVICETYPE_CDROM:
1066 if ((Srb->Cdb[1] & 1) == 0)
1068 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1069 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1070 id->RemovableMedia = 1;
1071 id->Versions = 3;
1072 id->ResponseDataFormat = 0;
1073 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1074 id->CommandQueue = 1;
1075 memcpy(id->VendorId, "XEN ", 8); // vendor id
1076 memcpy(id->ProductId, "PV CDROM ", 16); // product id
1077 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1079 else
1081 switch (Srb->Cdb[2])
1083 case 0x00:
1084 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1085 data_buffer[1] = 0x00;
1086 data_buffer[2] = 0x00;
1087 data_buffer[3] = 2;
1088 data_buffer[4] = 0x00;
1089 data_buffer[5] = 0x80;
1090 break;
1091 case 0x80:
1092 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1093 data_buffer[1] = 0x80;
1094 data_buffer[2] = 0x00;
1095 data_buffer[3] = 8;
1096 data_buffer[4] = 0x31;
1097 data_buffer[5] = 0x32;
1098 data_buffer[6] = 0x33;
1099 data_buffer[7] = 0x34;
1100 data_buffer[8] = 0x35;
1101 data_buffer[9] = 0x36;
1102 data_buffer[10] = 0x37;
1103 data_buffer[11] = 0x38;
1104 break;
1105 default:
1106 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1107 Srb->SrbStatus = SRB_STATUS_ERROR;
1108 break;
1111 break;
1112 default:
1113 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1114 Srb->SrbStatus = SRB_STATUS_ERROR;
1115 break;
1117 break;
1118 case SCSIOP_READ_CAPACITY:
1119 if (dump_mode)
1120 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1121 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1122 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1123 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1124 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1125 data_buffer = get_databuffer_virtual(xvdd, Srb);
1126 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1127 if ((xvdd->total_sectors - 1) >> 32)
1129 data_buffer[0] = 0xff;
1130 data_buffer[1] = 0xff;
1131 data_buffer[2] = 0xff;
1132 data_buffer[3] = 0xff;
1134 else
1136 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1137 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1138 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1139 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1141 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1142 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1143 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1144 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1145 Srb->ScsiStatus = 0;
1146 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1147 break;
1148 case SCSIOP_READ_CAPACITY16:
1149 if (dump_mode)
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 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1155 data_buffer = get_databuffer_virtual(xvdd, Srb);
1156 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1157 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1158 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1159 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1160 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1161 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1162 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1163 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1164 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1165 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1166 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1167 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1168 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1169 Srb->ScsiStatus = 0;
1170 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1171 break;
1172 case SCSIOP_MODE_SENSE:
1173 case SCSIOP_MODE_SENSE10:
1174 if (dump_mode)
1175 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));
1176 XenVbd_FillModePage(xvdd, Srb);
1177 break;
1178 case SCSIOP_READ:
1179 case SCSIOP_READ16:
1180 case SCSIOP_WRITE:
1181 case SCSIOP_WRITE16:
1182 //if (dump_mode)
1183 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1184 XenVbd_PutSrbOnRing(xvdd, Srb);
1185 break;
1186 case SCSIOP_VERIFY:
1187 // Should we do more here?
1188 if (dump_mode)
1189 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1190 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1191 break;
1192 case SCSIOP_REPORT_LUNS:
1193 if (dump_mode)
1194 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1195 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1196 break;
1197 case SCSIOP_REQUEST_SENSE:
1198 if (dump_mode)
1199 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1200 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1201 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1202 break;
1203 case SCSIOP_READ_TOC:
1204 if (dump_mode)
1205 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1206 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1207 data_buffer = get_databuffer_virtual(xvdd, Srb);
1208 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1209 /*
1210 #define READ_TOC_FORMAT_TOC 0x00
1211 #define READ_TOC_FORMAT_SESSION 0x01
1212 #define READ_TOC_FORMAT_FULL_TOC 0x02
1213 #define READ_TOC_FORMAT_PMA 0x03
1214 #define READ_TOC_FORMAT_ATIP 0x04
1215 */
1216 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1217 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1218 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1219 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1220 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1221 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1222 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1223 switch (cdb->READ_TOC.Format2)
1225 case READ_TOC_FORMAT_TOC:
1226 data_buffer[0] = 0; // length MSB
1227 data_buffer[1] = 10; // length LSB
1228 data_buffer[2] = 1; // First Track
1229 data_buffer[3] = 1; // Last Track
1230 data_buffer[4] = 0; // Reserved
1231 data_buffer[5] = 0x14; // current position data + uninterrupted data
1232 data_buffer[6] = 1; // last complete track
1233 data_buffer[7] = 0; // reserved
1234 data_buffer[8] = 0; // MSB Block
1235 data_buffer[9] = 0;
1236 data_buffer[10] = 0;
1237 data_buffer[11] = 0; // LSB Block
1238 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1239 break;
1240 case READ_TOC_FORMAT_SESSION:
1241 case READ_TOC_FORMAT_FULL_TOC:
1242 case READ_TOC_FORMAT_PMA:
1243 case READ_TOC_FORMAT_ATIP:
1244 Srb->SrbStatus = SRB_STATUS_ERROR;
1245 break;
1247 break;
1248 case SCSIOP_START_STOP_UNIT:
1249 if (dump_mode)
1250 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1251 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1252 break;
1253 case SCSIOP_RESERVE_UNIT:
1254 if (dump_mode)
1255 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1256 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1257 break;
1258 case SCSIOP_RELEASE_UNIT:
1259 if (dump_mode)
1260 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1261 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1262 break;
1263 default:
1264 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1265 Srb->SrbStatus = SRB_STATUS_ERROR;
1266 break;
1268 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1270 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1271 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1273 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1274 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1276 Srb->ScsiStatus = 0x02;
1277 XenVbd_MakeAutoSense(xvdd, Srb);
1278 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1279 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1280 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1282 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1284 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1285 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1286 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1287 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1288 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1290 break;
1291 case SRB_FUNCTION_IO_CONTROL:
1292 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1293 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1294 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1295 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1296 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1297 break;
1298 case SRB_FUNCTION_FLUSH:
1299 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1300 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1301 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1302 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1303 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1304 break;
1305 case SRB_FUNCTION_SHUTDOWN:
1306 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p\n", Srb));
1307 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1308 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1309 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1310 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1311 break;
1312 default:
1313 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1314 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1315 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1316 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1317 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1318 break;
1321 //FUNCTION_EXIT();
1322 return TRUE;
1325 static BOOLEAN DDKAPI
1326 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1328 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1330 UNREFERENCED_PARAMETER(DeviceExtension);
1331 UNREFERENCED_PARAMETER(PathId);
1333 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1335 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1336 if (xvdd->ring_detect_state == 2 && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1338 ScsiPortNotification(NextRequest, DeviceExtension);
1341 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1344 return TRUE;
1347 static BOOLEAN DDKAPI
1348 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1350 UNREFERENCED_PARAMETER(DeviceExtension);
1351 UNREFERENCED_PARAMETER(Context);
1352 UNREFERENCED_PARAMETER(SaveState);
1354 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1355 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1357 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1359 return TRUE;
1362 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1363 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1365 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1366 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1367 //KIRQL OldIrql;
1369 UNREFERENCED_PARAMETER(DeviceExtension);
1371 FUNCTION_ENTER();
1372 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1374 switch (ControlType)
1376 case ScsiQuerySupportedControlTypes:
1377 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1378 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1379 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1380 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1381 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1382 break;
1383 case ScsiStopAdapter:
1384 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1385 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1386 break;
1387 case ScsiRestartAdapter:
1388 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1389 break;
1390 case ScsiSetBootConfig:
1391 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1392 break;
1393 case ScsiSetRunningConfig:
1394 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1395 break;
1396 default:
1397 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1398 break;
1401 FUNCTION_EXIT();
1403 return Status;
1406 PVOID init_driver_extension;
1408 static BOOLEAN
1409 XenVbd_DmaNeedVirtualAddress(PIRP irp)
1411 PIO_STACK_LOCATION stack;
1413 //FUNCTION_ENTER();
1415 stack = IoGetCurrentIrpStackLocation(irp);
1416 if (stack->MajorFunction != IRP_MJ_SCSI)
1418 KdPrint((__DRIVER_NAME " Not IRP_MJ_SCSI\n"));
1419 //FUNCTION_EXIT();
1420 return FALSE; /* this actually shouldn't happen */
1423 switch (stack->Parameters.Scsi.Srb->Cdb[0])
1425 case SCSIOP_READ:
1426 case SCSIOP_READ16:
1427 case SCSIOP_WRITE:
1428 case SCSIOP_WRITE16:
1429 //KdPrint((__DRIVER_NAME " read/write operation\n"));
1430 //FUNCTION_EXIT();
1431 return FALSE;
1432 default:
1433 //KdPrint((__DRIVER_NAME " not a read/write operation\n"));
1434 //FUNCTION_EXIT();
1435 return TRUE;
1439 static ULONG
1440 XenVbd_DmaGetAlignment(PIRP irp)
1442 UNREFERENCED_PARAMETER(irp);
1444 //FUNCTION_ENTER();
1445 //FUNCTION_EXIT();
1446 return 512;
1449 dma_driver_extension_t *dma_driver_extension;
1451 NTSTATUS
1452 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1454 ULONG status;
1455 HW_INITIALIZATION_DATA HwInitializationData;
1456 PVOID driver_extension;
1457 PUCHAR ptr;
1459 FUNCTION_ENTER();
1460 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1461 KdPrint((__DRIVER_NAME " DriverObject = %p\n", DriverObject));
1463 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1464 if (!RegistryPath)
1466 dump_mode = TRUE;
1469 if (!dump_mode)
1471 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1472 ptr = driver_extension;
1473 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1474 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1475 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1476 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1477 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1478 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1479 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1480 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(1), NULL); /* 1 ref for use in crash dump */
1481 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1483 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC), sizeof(dma_driver_extension), &dma_driver_extension);
1484 dma_driver_extension->need_virtual_address = XenVbd_DmaNeedVirtualAddress;
1485 dma_driver_extension->get_alignment = XenVbd_DmaGetAlignment;
1488 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1490 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1491 HwInitializationData.AdapterInterfaceType = PNPBus;
1492 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1493 HwInitializationData.SpecificLuExtensionSize = 0;
1494 HwInitializationData.SrbExtensionSize = 0;
1495 HwInitializationData.NumberOfAccessRanges = 1;
1496 #if 0
1497 HwInitializationData.MapBuffers = TRUE;
1498 HwInitializationData.NeedPhysicalAddresses = FALSE;
1499 #else
1500 HwInitializationData.MapBuffers = FALSE;
1501 HwInitializationData.NeedPhysicalAddresses = TRUE;
1502 #endif
1503 HwInitializationData.TaggedQueuing = FALSE;
1504 HwInitializationData.AutoRequestSense = TRUE;
1505 HwInitializationData.MultipleRequestPerLu = TRUE;
1506 HwInitializationData.ReceiveEvent = FALSE;
1507 HwInitializationData.VendorIdLength = 0;
1508 HwInitializationData.VendorId = NULL;
1509 HwInitializationData.DeviceIdLength = 0;
1510 HwInitializationData.DeviceId = NULL;
1512 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1513 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1514 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1515 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1516 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1517 HwInitializationData.HwDmaStarted = NULL;
1518 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
1519 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1521 #if 0
1522 if (dump_mode)
1523 KdBreakPoint();
1524 #endif
1526 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1528 if(!NT_SUCCESS(status))
1530 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1533 FUNCTION_EXIT();
1535 return status;