win-pvdrivers

view xenvbd/xenvbd.c @ 497:312a41f82b8f

Updated to support the proposed patches to qemu from Steven Smith on ~20081216
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 19 22:08:17 2008 +1100 (2008-12-19)
parents 785de85f3db7
children 81a13e8a064f
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 xvdd->inactive = TRUE;
293 if (xvdd->inactive)
294 KdPrint((__DRIVER_NAME " Device is inactive\n"));
296 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
297 {
298 /* CD/DVD drives must have bytes_per_sector = 2048. */
299 xvdd->bytes_per_sector = 2048;
300 }
302 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
303 #ifdef __MINGW32__
304 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
305 {
306 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
307 ULONG index;
309 bit_scan_forward(&index, num_512_byte_sectors);
310 xvdd->total_sectors <<= index-1;
311 }
312 #else
313 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
314 #endif
317 xvdd->shadow_free = 0;
318 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
319 for (i = 0; i < SHADOW_ENTRIES; i++)
320 {
321 xvdd->shadows[i].req.id = i;
322 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
323 }
325 return SP_RETURN_FOUND;
326 }
328 ULONG stat_interrupts = 0;
329 ULONG stat_interrupts_for_me = 0;
330 ULONG stat_reads = 0;
331 ULONG stat_writes = 0;
332 ULONG stat_unaligned_le_4096 = 0;
333 ULONG stat_unaligned_le_8192 = 0;
334 ULONG stat_unaligned_le_16384 = 0;
335 ULONG stat_unaligned_le_32768 = 0;
336 ULONG stat_unaligned_le_65536 = 0;
337 ULONG stat_unaligned_gt_65536 = 0;
338 ULONG stat_no_shadows = 0;
339 ULONG stat_no_grants = 0;
340 ULONG stat_outstanding_requests = 0;
342 static VOID
343 XenVbd_DumpStats()
344 {
345 KdPrint((__DRIVER_NAME " stat_interrupts = %d\n", stat_interrupts));
346 KdPrint((__DRIVER_NAME " stat_interrupts_for_me = %d\n", stat_interrupts_for_me));
347 KdPrint((__DRIVER_NAME " stat_reads = %d\n", stat_reads));
348 KdPrint((__DRIVER_NAME " stat_writes = %d\n", stat_writes));
349 KdPrint((__DRIVER_NAME " stat_unaligned_le_4096 = %d\n", stat_unaligned_le_4096));
350 KdPrint((__DRIVER_NAME " stat_unaligned_le_8192 = %d\n", stat_unaligned_le_8192));
351 KdPrint((__DRIVER_NAME " stat_unaligned_le_16384 = %d\n", stat_unaligned_le_16384));
352 KdPrint((__DRIVER_NAME " stat_unaligned_le_32768 = %d\n", stat_unaligned_le_32768));
353 KdPrint((__DRIVER_NAME " stat_unaligned_le_65536 = %d\n", stat_unaligned_le_65536));
354 KdPrint((__DRIVER_NAME " stat_unaligned_gt_65536 = %d\n", stat_unaligned_gt_65536));
355 KdPrint((__DRIVER_NAME " stat_no_shadows = %d\n", stat_no_shadows));
356 KdPrint((__DRIVER_NAME " stat_no_grants = %d\n", stat_no_grants));
357 KdPrint((__DRIVER_NAME " stat_outstanding_requests = %d\n", stat_outstanding_requests));
358 }
360 static __inline ULONG
361 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
362 {
363 switch (srb->Cdb[0])
364 {
365 case SCSIOP_READ:
366 case SCSIOP_WRITE:
367 return (srb->Cdb[7] << 8) | srb->Cdb[8];
368 case SCSIOP_READ16:
369 case SCSIOP_WRITE16:
370 return (srb->Cdb[10] << 24) | (srb->Cdb[11] << 16) | (srb->Cdb[12] << 8) | srb->Cdb[13];
371 default:
372 return 0;
373 }
374 }
376 static __inline ULONGLONG
377 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
378 {
379 ULONGLONG sector;
381 switch (srb->Cdb[0])
382 {
383 case SCSIOP_READ:
384 case SCSIOP_WRITE:
385 sector = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
386 break;
387 case SCSIOP_READ16:
388 case SCSIOP_WRITE16:
389 sector = ((ULONGLONG)srb->Cdb[2] << 56) | ((ULONGLONG)srb->Cdb[3] << 48)
390 | ((ULONGLONG)srb->Cdb[4] << 40) | ((ULONGLONG)srb->Cdb[5] << 32)
391 | ((ULONGLONG)srb->Cdb[6] << 24) | ((ULONGLONG)srb->Cdb[7] << 16)
392 | ((ULONGLONG)srb->Cdb[8] << 8) | ((ULONGLONG)srb->Cdb[9]);
393 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
394 break;
395 default:
396 sector = 0;
397 break;
398 }
399 return sector;
400 }
402 static __inline BOOLEAN
403 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
404 {
405 switch (srb->Cdb[0])
406 {
407 case SCSIOP_READ:
408 case SCSIOP_READ16:
409 return TRUE;
410 case SCSIOP_WRITE:
411 case SCSIOP_WRITE16:
412 return FALSE;
413 default:
414 return FALSE;
415 }
416 }
418 static VOID
419 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
420 {
421 ULONG block_count, transfer_length;
422 blkif_shadow_t *shadow;
423 PHYSICAL_ADDRESS physical_address;
424 ULONG pfn;
425 ULONG remaining, offset, length;
426 PUCHAR ptr;
427 int notify;
429 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
431 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
432 block_count = decode_cdb_length(srb);;
433 block_count *= xvdd->bytes_per_sector / 512;
434 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
435 {
436 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
437 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
438 }
439 else
440 {
441 ptr = srb->DataBuffer;
442 transfer_length = block_count * 512;
443 }
445 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
446 {
447 ASSERT(!xvdd->pending_srb);
448 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
449 xvdd->pending_srb = srb;
450 stat_no_grants++;
451 return;
452 }
454 if (!srb_offset)
455 {
456 if (PtrToUlong(srb->DataBuffer) & 511)
457 {
458 if (block_count * 512 <= 4096)
459 stat_unaligned_le_4096++;
460 else if (block_count * 512 <= 8192)
461 stat_unaligned_le_8192++;
462 else if (block_count * 512 <= 16384)
463 stat_unaligned_le_16384++;
464 else if (block_count * 512 <= 32768)
465 stat_unaligned_le_32768++;
466 else if (block_count * 512 <= 65536)
467 stat_unaligned_le_65536++;
468 else
469 stat_unaligned_gt_65536++;
470 }
471 if (decode_cdb_is_read(srb))
472 stat_reads++;
473 else
474 stat_writes++;
475 stat_outstanding_requests++;
476 }
478 shadow = get_shadow_from_freelist(xvdd);
479 ASSERT(shadow);
480 shadow->req.sector_number = decode_cdb_sector(srb);
481 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
482 shadow->req.handle = 0;
483 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
484 shadow->req.nr_segments = 0;
485 shadow->offset = srb_offset;
486 shadow->length = transfer_length;
487 shadow->srb = srb;
489 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
490 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
491 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
493 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
494 {
495 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
496 //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));
497 if (!decode_cdb_is_read(srb))
498 {
499 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
500 }
501 }
502 else
503 {
504 ptr = srb->DataBuffer;
505 }
506 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
507 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
508 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
510 remaining = shadow->length;
511 while (remaining > 0)
512 {
513 physical_address = MmGetPhysicalAddress(ptr);
514 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
515 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
516 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref != INVALID_GRANT_REF);
517 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
518 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
519 ASSERT((offset & 511) == 0);
520 length = min(PAGE_SIZE - offset, remaining);
521 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
522 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
523 remaining -= length;
524 ptr += length;
525 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
526 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
527 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
528 shadow->req.nr_segments++;
529 }
530 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
532 XenVbd_PutRequest(xvdd, &shadow->req);
534 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
535 if (notify)
536 {
537 //KdPrint((__DRIVER_NAME " Notifying\n"));
538 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
539 }
541 if (!xvdd->shadow_free)
542 stat_no_shadows++;
543 if (xvdd->shadow_free && srb_offset == 0)
544 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
546 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
547 }
549 typedef struct {
550 PSCSI_REQUEST_BLOCK srb;
551 ULONG offset;
552 } mini_shadow_t;
554 static VOID
555 XenVbd_Resume(PVOID DeviceExtension)
556 {
557 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
558 ULONG i;
559 mini_shadow_t shadows[MAX_SHADOW_ENTRIES];
560 ULONG shadow_count;
562 FUNCTION_ENTER();
563 KdPrint((__DRIVER_NAME " found device in resume state\n"));
564 //FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE); what was this for???
565 // re-submit srb's
567 shadow_count = 0;
568 for (i = 0; i < SHADOW_ENTRIES; i++)
569 {
570 if (xvdd->shadows[i].srb)
571 {
572 shadows[shadow_count].srb = xvdd->shadows[i].srb;
573 shadows[shadow_count].offset = xvdd->shadows[i].offset;
574 shadow_count++;
575 xvdd->shadows[i].srb = NULL;
576 }
577 }
578 KdPrint((__DRIVER_NAME " About to call InitFromConfig\n"));
579 XenVbd_InitFromConfig(xvdd);
580 KdPrint((__DRIVER_NAME " Back from InitFromConfig\n"));
582 for (i = 0; i < shadow_count; i++)
583 {
584 KdPrint((__DRIVER_NAME " Putting on Shadow entry\n"));
585 XenVbd_PutSrbOnRing(xvdd, shadows[i].srb, shadows[i].offset);
586 }
587 KdPrint((__DRIVER_NAME " Shadows are back on the ring\n"));
589 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
591 KdPrint((__DRIVER_NAME " resume_state set to RESUME_STATE_RUNNING\n"));
593 if (i == 0)
594 {
595 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
596 KdPrint((__DRIVER_NAME " No shadows - notifying to get things started again\n"));
597 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
598 }
599 FUNCTION_EXIT();
600 }
602 static ULONG DDKAPI
603 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
604 {
605 // PACCESS_RANGE AccessRange;
606 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
607 ULONG status;
608 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
609 PACCESS_RANGE access_range;
611 UNREFERENCED_PARAMETER(HwContext);
612 UNREFERENCED_PARAMETER(BusInformation);
613 UNREFERENCED_PARAMETER(ArgumentString);
615 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
616 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
618 *Again = FALSE;
620 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
621 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
623 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
624 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
625 {
626 return SP_RETURN_BAD_CONFIG;
627 }
629 access_range = &((*(ConfigInfo->AccessRanges))[0]);
630 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
631 access_range->RangeStart.LowPart, access_range->RangeLength));
632 xvdd->device_base = ScsiPortGetDeviceBase(
633 DeviceExtension,
634 ConfigInfo->AdapterInterfaceType,
635 ConfigInfo->SystemIoBusNumber,
636 access_range->RangeStart,
637 access_range->RangeLength,
638 !access_range->RangeInMemory);
639 if (!xvdd->device_base)
640 {
641 KdPrint((__DRIVER_NAME " Invalid config\n"));
642 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
643 return SP_RETURN_BAD_CONFIG;
644 }
646 status = XenVbd_InitFromConfig(xvdd);
647 if (status != SP_RETURN_FOUND)
648 return status;
650 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
651 ConfigInfo->NumberOfPhysicalBreaks = 0; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
652 ConfigInfo->ScatterGather = TRUE;
653 ConfigInfo->AlignmentMask = 0;
654 ConfigInfo->NumberOfBuses = 1;
655 ConfigInfo->InitiatorBusId[0] = 1;
656 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
657 ConfigInfo->MaximumNumberOfTargets = 2;
658 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
659 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
660 {
661 ConfigInfo->Master = TRUE;
662 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
663 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
664 }
665 else
666 {
667 ConfigInfo->Master = FALSE;
668 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
669 }
671 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
673 return SP_RETURN_FOUND;
674 }
676 static BOOLEAN DDKAPI
677 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
678 {
679 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
680 blkif_request_t *req;
681 int i;
682 int notify;
684 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
685 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
687 if (!dump_mode)
688 {
689 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
690 req->operation = 0xff;
691 req->nr_segments = 0;
692 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
693 {
694 req->seg[i].gref = 0; //0xffffffff;
695 req->seg[i].first_sect = 0; //0xff;
696 req->seg[i].last_sect = 0; //0xff;
697 }
698 xvdd->ring.req_prod_pvt++;
700 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
701 req->operation = 0xff;
702 req->nr_segments = 0;
703 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
704 {
705 req->seg[i].gref = 0; //0xffffffff;
706 req->seg[i].first_sect = 0; //0xff;
707 req->seg[i].last_sect = 0; //0xff;
708 }
709 xvdd->ring.req_prod_pvt++;
711 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
712 if (notify)
713 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
714 xvdd->ring_detect_state = 0;
715 }
716 else
717 {
718 if (xvdd->cached_use_other)
719 {
720 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
721 xvdd->use_other = TRUE;
722 }
723 xvdd->ring_detect_state = 2;
724 }
726 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
728 return TRUE;
729 }
731 static ULONG
732 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
733 {
734 PMODE_PARAMETER_HEADER parameter_header;
735 PMODE_PARAMETER_BLOCK param_block;
736 PMODE_FORMAT_PAGE format_page;
737 ULONG offset;
738 UCHAR buffer[256];
739 BOOLEAN valid_page = FALSE;
740 BOOLEAN cdb_llbaa;
741 BOOLEAN cdb_dbd;
742 UCHAR cdb_page_code;
743 USHORT cdb_allocation_length;
745 UNREFERENCED_PARAMETER(xvdd);
747 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
749 //cdb = (PCDB)srb->Cdb;
750 switch (srb->Cdb[0])
751 {
752 case SCSIOP_MODE_SENSE:
753 cdb_llbaa = FALSE;
754 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
755 cdb_page_code = srb->Cdb[2] & 0x3f;
756 cdb_allocation_length = srb->Cdb[4];
757 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
758 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
759 break;
760 case SCSIOP_MODE_SENSE10:
761 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
762 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
763 cdb_page_code = srb->Cdb[2] & 0x3f;
764 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
765 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
766 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
767 break;
768 default:
769 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
770 return FALSE;
771 }
772 offset = 0;
773 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
774 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
776 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
777 parameter_header->MediumType = 0;
778 parameter_header->DeviceSpecificParameter = 0;
779 parameter_header->BlockDescriptorLength = 0;
780 offset += sizeof(MODE_PARAMETER_HEADER);
782 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
783 {
784 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
785 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
786 }
788 if (!cdb_dbd)
789 {
790 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
791 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
792 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
793 {
794 if (xvdd->total_sectors >> 32)
795 {
796 param_block->DensityCode = 0xff;
797 param_block->NumberOfBlocks[0] = 0xff;
798 param_block->NumberOfBlocks[1] = 0xff;
799 param_block->NumberOfBlocks[2] = 0xff;
800 }
801 else
802 {
803 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
804 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
805 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
806 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
807 }
808 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
809 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
810 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
811 }
812 offset += sizeof(MODE_PARAMETER_BLOCK);
813 }
814 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
815 {
816 valid_page = TRUE;
817 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
818 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
819 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
820 /* 256 sectors per track */
821 format_page->SectorsPerTrack[0] = 0x01;
822 format_page->SectorsPerTrack[1] = 0x00;
823 /* xxx bytes per sector */
824 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
825 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
826 format_page->HardSectorFormating = TRUE;
827 format_page->SoftSectorFormating = TRUE;
828 offset += sizeof(MODE_FORMAT_PAGE);
829 }
830 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
831 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
832 {
833 srb->SrbStatus = SRB_STATUS_ERROR;
834 }
835 else if(offset < srb->DataTransferLength)
836 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
837 else
838 srb->SrbStatus = SRB_STATUS_SUCCESS;
839 srb->DataTransferLength = min(srb->DataTransferLength, offset);
840 srb->ScsiStatus = 0;
841 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
843 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
845 return TRUE;
846 }
848 static VOID
849 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
850 {
851 PSENSE_DATA sd = srb->SenseInfoBuffer;
853 UNREFERENCED_PARAMETER(xvdd);
855 if (!srb->SenseInfoBuffer)
856 return;
858 sd->ErrorCode = 0x70;
859 sd->Valid = 1;
860 sd->SenseKey = sense_key;
861 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
862 sd->AdditionalSenseCode = additional_sense_code;
863 return;
864 }
866 static VOID
867 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
868 {
869 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
870 return;
871 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
872 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
873 }
875 static BOOLEAN DDKAPI
876 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
877 {
878 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
879 PSCSI_REQUEST_BLOCK srb;
880 RING_IDX i, rp;
881 int j;
882 blkif_response_t *rep;
883 int block_count;
884 int more_to_do = TRUE;
885 blkif_shadow_t *shadow;
886 ULONG offset;
888 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
890 stat_interrupts++;
891 /* in dump mode I think we get called on a timer, not by an actual IRQ */
892 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
893 return FALSE; /* interrupt was not for us */
894 stat_interrupts_for_me++;
895 if (xvdd->device_state->resume_state != xvdd->device_state->resume_state_ack)
896 {
897 FUNCTION_ENTER();
898 switch (xvdd->device_state->resume_state)
899 {
900 case RESUME_STATE_SUSPENDING:
901 KdPrint((__DRIVER_NAME " New state SUSPENDING\n"));
902 break;
903 case RESUME_STATE_FRONTEND_RESUME:
904 KdPrint((__DRIVER_NAME " New state RESUME_STATE_FRONTEND_RESUME\n"));
905 XenVbd_Resume(xvdd);
906 break;
907 default:
908 KdPrint((__DRIVER_NAME " New state %d\n", xvdd->device_state->resume_state));
909 break;
910 }
911 xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
912 KeMemoryBarrier();
913 FUNCTION_EXIT();
914 }
916 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
917 {
918 return FALSE;
919 }
921 if (!dump_mode && !(stat_interrupts_for_me & 0xFFFF))
922 XenVbd_DumpStats();
924 while (more_to_do)
925 {
926 rp = xvdd->ring.sring->rsp_prod;
927 KeMemoryBarrier();
928 for (i = xvdd->ring.rsp_cons; i < rp; i++)
929 {
930 rep = XenVbd_GetResponse(xvdd, i);
931 /*
932 * This code is to automatically detect if the backend is using the same
933 * bit width or a different bit width to us. Later versions of Xen do this
934 * via a xenstore value, but not all. That 0x0fffffff (notice
935 * that the msb is not actually set, so we don't have any problems with
936 * sign extending) is to signify the last entry on the right, which is
937 * different under 32 and 64 bits, and that is why we set it up there.
939 * To do the detection, we put two initial entries on the ring, with an op
940 * of 0xff (which is invalid). The first entry is mostly okay, but the
941 * second will be grossly misaligned if the backend bit width is different,
942 * and we detect this and switch frontend structures.
943 */
944 switch (xvdd->ring_detect_state)
945 {
946 case 0:
947 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
948 xvdd->ring_detect_state = 1;
949 break;
950 case 1:
951 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
952 *xvdd->event_channel_ptr |= 0x80000000;
953 if (rep->operation != 0xff)
954 {
955 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
956 xvdd->use_other = TRUE;
957 *xvdd->event_channel_ptr |= 0x40000000;
958 }
959 xvdd->ring_detect_state = 2;
960 ScsiPortNotification(NextRequest, DeviceExtension);
961 break;
962 case 2:
963 //KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
964 shadow = &xvdd->shadows[rep->id];
965 srb = shadow->srb;
966 ASSERT(srb != NULL);
967 block_count = decode_cdb_length(srb);
968 block_count *= xvdd->bytes_per_sector / 512;
969 if (rep->status == BLKIF_RSP_OKAY)
970 srb->SrbStatus = SRB_STATUS_SUCCESS;
971 else
972 {
973 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
974 if (decode_cdb_is_read(srb))
975 KdPrint((__DRIVER_NAME " Operation = Read\n"));
976 else
977 KdPrint((__DRIVER_NAME " Operation = Write\n"));
978 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
979 srb->SrbStatus = SRB_STATUS_ERROR;
980 srb->ScsiStatus = 0x02;
981 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
982 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
983 XenVbd_MakeAutoSense(xvdd, srb);
984 }
985 for (j = 0; j < shadow->req.nr_segments; j++)
986 {
987 #if DBG
988 BOOLEAN result =
989 #endif
990 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
991 #if DBG
992 ASSERT(result);
993 #endif
994 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
995 }
997 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
998 {
999 if (decode_cdb_is_read(srb))
1000 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
1001 offset = shadow->offset + shadow->length;
1002 put_shadow_on_freelist(xvdd, shadow);
1003 if (offset == (ULONG)block_count * 512)
1005 ScsiPortNotification(RequestComplete, xvdd, srb);
1006 stat_outstanding_requests--;
1007 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1009 else
1011 XenVbd_PutSrbOnRing(xvdd, srb, offset);
1014 else
1016 put_shadow_on_freelist(xvdd, shadow);
1017 ScsiPortNotification(RequestComplete, xvdd, srb);
1018 stat_outstanding_requests--;
1019 if (xvdd->pending_srb)
1021 srb = xvdd->pending_srb;
1022 xvdd->pending_srb = NULL;
1023 XenVbd_PutSrbOnRing(xvdd, srb, 0);
1025 else
1026 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1028 break;
1032 xvdd->ring.rsp_cons = i;
1033 if (i != xvdd->ring.req_prod_pvt)
1035 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
1037 else
1039 xvdd->ring.sring->rsp_event = i + 1;
1040 more_to_do = FALSE;
1044 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
1045 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
1046 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
1047 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
1049 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1051 return FALSE; /* always fall through to the next ISR... */
1054 static BOOLEAN DDKAPI
1055 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
1057 PUCHAR DataBuffer;
1058 PCDB cdb;
1059 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1061 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
1063 if (xvdd->inactive)
1065 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1066 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1067 ScsiPortNotification(NextRequest, DeviceExtension);
1068 return TRUE;
1071 // If we haven't enumerated all the devices yet then just defer the request
1072 if (xvdd->ring_detect_state < 2)
1074 Srb->SrbStatus = SRB_STATUS_BUSY;
1075 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1076 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
1077 return TRUE;
1080 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
1082 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
1083 Srb->SrbStatus = SRB_STATUS_BUSY;
1084 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1085 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
1086 return TRUE;
1089 if (Srb->PathId != 0 || Srb->TargetId != 0)
1091 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1092 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1093 ScsiPortNotification(NextRequest, DeviceExtension);
1094 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1095 return TRUE;
1098 switch (Srb->Function)
1100 case SRB_FUNCTION_EXECUTE_SCSI:
1101 cdb = (PCDB)Srb->Cdb;
1102 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1104 switch(cdb->CDB6GENERIC.OperationCode)
1106 case SCSIOP_TEST_UNIT_READY:
1107 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1108 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1109 Srb->ScsiStatus = 0;
1110 break;
1111 case SCSIOP_INQUIRY:
1112 // KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1113 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1114 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
1115 // KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
1116 DataBuffer = Srb->DataBuffer;
1117 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1118 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1119 switch (xvdd->device_type)
1121 case XENVBD_DEVICETYPE_DISK:
1122 if ((Srb->Cdb[1] & 1) == 0)
1124 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1125 id->DeviceType = DIRECT_ACCESS_DEVICE;
1126 id->Versions = 3;
1127 id->ResponseDataFormat = 0;
1128 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1129 id->CommandQueue = 1;
1130 memcpy(id->VendorId, "XEN ", 8); // vendor id
1131 memcpy(id->ProductId, "PV DISK ", 16); // product id
1132 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1134 else
1136 switch (Srb->Cdb[2])
1138 case 0x00:
1139 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1140 DataBuffer[1] = 0x00;
1141 DataBuffer[2] = 0x00;
1142 DataBuffer[3] = 2;
1143 DataBuffer[4] = 0x00;
1144 DataBuffer[5] = 0x80;
1145 break;
1146 case 0x80:
1147 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1148 DataBuffer[1] = 0x80;
1149 DataBuffer[2] = 0x00;
1150 DataBuffer[3] = 8;
1151 memset(&DataBuffer[4], ' ', 8);
1152 break;
1153 default:
1154 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1155 Srb->SrbStatus = SRB_STATUS_ERROR;
1156 break;
1159 break;
1160 case XENVBD_DEVICETYPE_CDROM:
1161 if ((Srb->Cdb[1] & 1) == 0)
1163 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1164 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1165 id->RemovableMedia = 1;
1166 id->Versions = 3;
1167 id->ResponseDataFormat = 0;
1168 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1169 id->CommandQueue = 1;
1170 memcpy(id->VendorId, "XEN ", 8); // vendor id
1171 memcpy(id->ProductId, "PV CDROM ", 16); // product id
1172 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1174 else
1176 switch (Srb->Cdb[2])
1178 case 0x00:
1179 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1180 DataBuffer[1] = 0x00;
1181 DataBuffer[2] = 0x00;
1182 DataBuffer[3] = 2;
1183 DataBuffer[4] = 0x00;
1184 DataBuffer[5] = 0x80;
1185 break;
1186 case 0x80:
1187 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1188 DataBuffer[1] = 0x80;
1189 DataBuffer[2] = 0x00;
1190 DataBuffer[3] = 8;
1191 DataBuffer[4] = 0x31;
1192 DataBuffer[5] = 0x32;
1193 DataBuffer[6] = 0x33;
1194 DataBuffer[7] = 0x34;
1195 DataBuffer[8] = 0x35;
1196 DataBuffer[9] = 0x36;
1197 DataBuffer[10] = 0x37;
1198 DataBuffer[11] = 0x38;
1199 break;
1200 default:
1201 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1202 Srb->SrbStatus = SRB_STATUS_ERROR;
1203 break;
1206 break;
1207 default:
1208 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1209 Srb->SrbStatus = SRB_STATUS_ERROR;
1210 break;
1212 break;
1213 case SCSIOP_READ_CAPACITY:
1214 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1215 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1216 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1217 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1218 DataBuffer = Srb->DataBuffer;
1219 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1220 if ((xvdd->total_sectors - 1) >> 32)
1222 DataBuffer[0] = 0xff;
1223 DataBuffer[1] = 0xff;
1224 DataBuffer[2] = 0xff;
1225 DataBuffer[3] = 0xff;
1227 else
1229 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1230 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1231 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1232 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1234 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1235 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1236 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1237 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1238 Srb->ScsiStatus = 0;
1239 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1240 break;
1241 case SCSIOP_READ_CAPACITY16:
1242 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1243 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1244 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1245 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1246 DataBuffer = Srb->DataBuffer;
1247 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1248 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1249 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1250 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1251 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1252 DataBuffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1253 DataBuffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1254 DataBuffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1255 DataBuffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1256 DataBuffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1257 DataBuffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1258 DataBuffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1259 DataBuffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1260 Srb->ScsiStatus = 0;
1261 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1262 break;
1263 case SCSIOP_MODE_SENSE:
1264 case SCSIOP_MODE_SENSE10:
1265 // 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));
1266 XenVbd_FillModePage(xvdd, Srb);
1267 break;
1268 case SCSIOP_READ:
1269 case SCSIOP_READ16:
1270 case SCSIOP_WRITE:
1271 case SCSIOP_WRITE16:
1272 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1273 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
1274 break;
1275 case SCSIOP_VERIFY:
1276 // Should we do more here?
1277 // KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1278 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1279 break;
1280 case SCSIOP_REPORT_LUNS:
1281 // KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1282 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1283 break;
1284 case SCSIOP_REQUEST_SENSE:
1285 // KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1286 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1287 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1288 break;
1289 case SCSIOP_READ_TOC:
1290 DataBuffer = Srb->DataBuffer;
1291 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1292 /*
1293 #define READ_TOC_FORMAT_TOC 0x00
1294 #define READ_TOC_FORMAT_SESSION 0x01
1295 #define READ_TOC_FORMAT_FULL_TOC 0x02
1296 #define READ_TOC_FORMAT_PMA 0x03
1297 #define READ_TOC_FORMAT_ATIP 0x04
1298 */
1299 // KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1300 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1301 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1302 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1303 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1304 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1305 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1306 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1307 switch (cdb->READ_TOC.Format2)
1309 case READ_TOC_FORMAT_TOC:
1310 DataBuffer[0] = 0; // length MSB
1311 DataBuffer[1] = 10; // length LSB
1312 DataBuffer[2] = 1; // First Track
1313 DataBuffer[3] = 1; // Last Track
1314 DataBuffer[4] = 0; // Reserved
1315 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1316 DataBuffer[6] = 1; // last complete track
1317 DataBuffer[7] = 0; // reserved
1318 DataBuffer[8] = 0; // MSB Block
1319 DataBuffer[9] = 0;
1320 DataBuffer[10] = 0;
1321 DataBuffer[11] = 0; // LSB Block
1322 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1323 break;
1324 case READ_TOC_FORMAT_SESSION:
1325 case READ_TOC_FORMAT_FULL_TOC:
1326 case READ_TOC_FORMAT_PMA:
1327 case READ_TOC_FORMAT_ATIP:
1328 Srb->SrbStatus = SRB_STATUS_ERROR;
1329 break;
1331 break;
1332 case SCSIOP_START_STOP_UNIT:
1333 // KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1334 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1335 break;
1336 case SCSIOP_RESERVE_UNIT:
1337 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1338 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1339 break;
1340 case SCSIOP_RELEASE_UNIT:
1341 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1342 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1343 break;
1344 default:
1345 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1346 Srb->SrbStatus = SRB_STATUS_ERROR;
1347 break;
1349 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1351 //KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1352 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1354 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1355 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1357 Srb->ScsiStatus = 0x02;
1358 XenVbd_MakeAutoSense(xvdd, Srb);
1359 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1360 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1362 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1364 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1365 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1366 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1367 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1369 break;
1370 case SRB_FUNCTION_IO_CONTROL:
1371 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1372 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1373 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1374 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1375 break;
1376 case SRB_FUNCTION_FLUSH:
1377 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1378 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1379 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1380 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1381 break;
1382 default:
1383 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1384 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1385 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1386 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1387 break;
1390 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1391 return TRUE;
1394 static BOOLEAN DDKAPI
1395 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1397 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1399 UNREFERENCED_PARAMETER(DeviceExtension);
1400 UNREFERENCED_PARAMETER(PathId);
1402 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1404 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1405 if (xvdd->ring_detect_state == 2 && xvdd->device_state->resume_state == RESUME_STATE_RUNNING)
1407 ScsiPortNotification(NextRequest, DeviceExtension);
1410 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1413 return TRUE;
1416 static BOOLEAN DDKAPI
1417 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1419 UNREFERENCED_PARAMETER(DeviceExtension);
1420 UNREFERENCED_PARAMETER(Context);
1421 UNREFERENCED_PARAMETER(SaveState);
1423 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1424 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1426 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1428 return TRUE;
1431 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1432 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1434 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1435 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1436 //KIRQL OldIrql;
1438 UNREFERENCED_PARAMETER(DeviceExtension);
1440 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1441 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1443 switch (ControlType)
1445 case ScsiQuerySupportedControlTypes:
1446 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1447 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1448 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1449 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1450 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1451 break;
1452 case ScsiStopAdapter:
1453 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1454 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1455 break;
1456 case ScsiRestartAdapter:
1457 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1458 break;
1459 case ScsiSetBootConfig:
1460 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1461 break;
1462 case ScsiSetRunningConfig:
1463 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1464 break;
1465 default:
1466 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1467 break;
1470 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1472 return Status;
1475 NTSTATUS
1476 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1478 ULONG status;
1479 HW_INITIALIZATION_DATA HwInitializationData;
1480 PVOID driver_extension;
1481 PUCHAR ptr;
1483 FUNCTION_ENTER();
1484 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1485 KdPrint((__DRIVER_NAME " DriverObject = %p\n", DriverObject));
1487 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1488 ptr = driver_extension;
1489 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
1490 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
1491 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
1492 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL);
1493 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL);
1494 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL);
1495 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL);
1496 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, UlongToPtr(144));
1497 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
1499 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1500 if (!RegistryPath)
1502 dump_mode = TRUE;
1504 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1506 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1507 HwInitializationData.AdapterInterfaceType = Internal;
1508 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1509 HwInitializationData.SpecificLuExtensionSize = 0;
1510 /* 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 */
1511 HwInitializationData.SrbExtensionSize = UNALIGNED_DOUBLE_BUFFER_SIZE + PAGE_SIZE - 1;
1512 HwInitializationData.NumberOfAccessRanges = 1;
1513 HwInitializationData.MapBuffers = TRUE;
1514 HwInitializationData.NeedPhysicalAddresses = FALSE;
1515 HwInitializationData.TaggedQueuing = FALSE;
1516 HwInitializationData.AutoRequestSense = TRUE;
1517 HwInitializationData.MultipleRequestPerLu = TRUE;
1518 HwInitializationData.ReceiveEvent = FALSE;
1519 HwInitializationData.VendorIdLength = 0;
1520 HwInitializationData.VendorId = NULL;
1521 HwInitializationData.DeviceIdLength = 0;
1522 HwInitializationData.DeviceId = NULL;
1524 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1525 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1526 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1527 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1528 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1529 HwInitializationData.HwDmaStarted = NULL;
1530 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
1531 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1533 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1535 if(!NT_SUCCESS(status))
1537 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1540 FUNCTION_EXIT();
1542 return status;