win-pvdrivers

view xenvbd/xenvbd.c @ 487:8a0a695cdd97

new config method
author James Harper <james.harper@bendigoit.com.au>
date Mon Dec 08 23:32:55 2008 +1100 (2008-12-08)
parents 4cb1179f76d8
children a6e3f76419c3
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;
45 static BOOLEAN global_inactive = FALSE;
47 static blkif_shadow_t *
48 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
49 {
50 if (xvdd->shadow_free == 0)
51 {
52 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
53 return NULL;
54 }
55 xvdd->shadow_free--;
56 if (xvdd->shadow_free < xvdd->shadow_min_free)
57 xvdd->shadow_min_free = xvdd->shadow_free;
58 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
59 }
61 static VOID
62 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
63 {
64 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
65 shadow->srb = NULL;
66 xvdd->shadow_free++;
67 }
69 static grant_ref_t
70 get_grant_from_freelist(PXENVBD_DEVICE_DATA xvdd)
71 {
72 if (xvdd->grant_free == 0)
73 {
74 KdPrint((__DRIVER_NAME " No more grant refs\n"));
75 return (grant_ref_t)0x0FFFFFFF;
76 }
77 xvdd->grant_free--;
78 return xvdd->grant_free_list[xvdd->grant_free];
79 }
81 static VOID
82 put_grant_on_freelist(PXENVBD_DEVICE_DATA xvdd, grant_ref_t grant)
83 {
84 xvdd->grant_free_list[xvdd->grant_free] = grant;
85 xvdd->grant_free++;
86 }
88 static blkif_response_t *
89 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
90 {
91 blkif_other_response_t *rep;
92 if (!xvdd->use_other)
93 return RING_GET_RESPONSE(&xvdd->ring, i);
94 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
95 xvdd->tmp_rep.id = rep->id;
96 xvdd->tmp_rep.operation = rep->operation;
97 xvdd->tmp_rep.status = rep->status;
98 return &xvdd->tmp_rep;
99 }
101 static VOID
102 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
103 {
104 blkif_other_request_t *other_req;
106 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
107 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
108 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
109 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
110 if (!xvdd->use_other)
111 {
112 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
113 }
114 else
115 {
116 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
117 other_req->operation = req->operation;
118 other_req->nr_segments = req->nr_segments;
119 other_req->handle = req->handle;
120 other_req->id = req->id;
121 other_req->sector_number = req->sector_number;
122 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
123 }
124 xvdd->ring.req_prod_pvt++;
125 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
126 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
127 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
128 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
129 }
131 static ULONG
132 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
133 {
134 ULONG i;
135 PUCHAR ptr;
136 USHORT type;
137 PCHAR setting, value;
139 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
140 xvdd->sring = NULL;
141 xvdd->event_channel = 0;
143 ptr = xvdd->device_base;
144 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID) &setting, (PVOID) &value)) != XEN_INIT_TYPE_END)
145 {
146 switch(type)
147 {
148 case XEN_INIT_TYPE_RING: /* frontend ring */
149 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
150 if (strcmp(setting, "ring-ref") == 0)
151 {
152 xvdd->sring = (blkif_sring_t *)value;
153 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
154 /* this bit is for when we have to take over an existing ring on a crash dump */
155 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
156 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
157 }
158 break;
159 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
160 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
161 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
162 if (strcmp(setting, "event-channel") == 0)
163 {
164 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
165 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
166 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
167 if (PtrToUlong(value) & 0x80000000)
168 {
169 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
170 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
171 }
172 }
173 break;
174 case XEN_INIT_TYPE_READ_STRING_BACK:
175 case XEN_INIT_TYPE_READ_STRING_FRONT:
176 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
177 if (strcmp(setting, "sectors") == 0)
178 xvdd->total_sectors = atoi(value);
179 else if (strcmp(setting, "sector-size") == 0)
180 xvdd->bytes_per_sector = atoi(value);
181 else if (strcmp(setting, "device-type") == 0)
182 {
183 if (strcmp(value, "disk") == 0)
184 {
185 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
186 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
187 }
188 else if (strcmp(value, "cdrom") == 0)
189 {
190 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
191 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
192 }
193 else
194 {
195 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
196 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
197 }
198 }
199 else if (strcmp(setting, "mode") == 0)
200 {
201 if (strncmp(value, "r", 1) == 0)
202 {
203 KdPrint((__DRIVER_NAME " mode = r\n"));
204 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
205 }
206 else if (strncmp(value, "w", 1) == 0)
207 {
208 KdPrint((__DRIVER_NAME " mode = w\n"));
209 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
210 }
211 else
212 {
213 KdPrint((__DRIVER_NAME " mode = unknown\n"));
214 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
215 }
216 }
217 break;
218 case XEN_INIT_TYPE_VECTORS:
219 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
220 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
221 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
222 {
223 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
224 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
225 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
226 return SP_RETURN_BAD_CONFIG;
227 }
228 else
229 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
230 break;
231 case XEN_INIT_TYPE_GRANT_ENTRIES:
232 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
233 xvdd->grant_entries = (USHORT)PtrToUlong(setting);
234 if (dump_mode)
235 {
236 /* check each grant entry first to make sure it isn't in use already */
237 grant_ref_t *gref = (grant_ref_t *)value;
238 xvdd->grant_free = 0;
239 for (i = 0; i < xvdd->grant_entries; i++)
240 {
241 if (xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, *gref, TRUE))
242 {
243 put_grant_on_freelist(xvdd, *gref);
244 }
245 gref++;
246 }
247 }
248 else
249 {
250 memcpy(&xvdd->grant_free_list, value, sizeof(grant_ref_t) * xvdd->grant_entries);
251 xvdd->grant_free = xvdd->grant_entries;
252 }
253 break;
254 case XEN_INIT_TYPE_STATE_PTR:
255 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
256 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
257 break;
258 default:
259 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
260 break;
261 }
262 }
263 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
264 || xvdd->sring == NULL
265 || xvdd->event_channel == 0
266 || xvdd->total_sectors == 0
267 || xvdd->bytes_per_sector == 0)
268 {
269 KdPrint((__DRIVER_NAME " Missing settings\n"));
270 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
271 return SP_RETURN_BAD_CONFIG;
272 }
273 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
274 {
275 /* CD/DVD drives must have bytes_per_sector = 2048. */
276 xvdd->bytes_per_sector = 2048;
277 }
279 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
280 #ifdef __MINGW32__
281 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
282 {
283 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
284 ULONG index;
286 bit_scan_forward(&index, num_512_byte_sectors);
287 xvdd->total_sectors <<= index-1;
288 }
289 #else
290 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
291 #endif
294 xvdd->shadow_free = 0;
295 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
296 for (i = 0; i < SHADOW_ENTRIES; i++)
297 {
298 xvdd->shadows[i].req.id = i;
299 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
300 }
302 return SP_RETURN_FOUND;
303 }
305 ULONG stat_interrupts = 0;
306 ULONG stat_interrupts_for_me = 0;
307 ULONG stat_reads = 0;
308 ULONG stat_writes = 0;
309 ULONG stat_unaligned_le_4096 = 0;
310 ULONG stat_unaligned_le_8192 = 0;
311 ULONG stat_unaligned_le_16384 = 0;
312 ULONG stat_unaligned_le_32768 = 0;
313 ULONG stat_unaligned_le_65536 = 0;
314 ULONG stat_unaligned_gt_65536 = 0;
315 ULONG stat_no_shadows = 0;
316 ULONG stat_no_grants = 0;
317 ULONG stat_outstanding_requests = 0;
319 static VOID
320 XenVbd_DumpStats()
321 {
322 KdPrint((__DRIVER_NAME " stat_interrupts = %d\n", stat_interrupts));
323 KdPrint((__DRIVER_NAME " stat_interrupts_for_me = %d\n", stat_interrupts_for_me));
324 KdPrint((__DRIVER_NAME " stat_reads = %d\n", stat_reads));
325 KdPrint((__DRIVER_NAME " stat_writes = %d\n", stat_writes));
326 KdPrint((__DRIVER_NAME " stat_unaligned_le_4096 = %d\n", stat_unaligned_le_4096));
327 KdPrint((__DRIVER_NAME " stat_unaligned_le_8192 = %d\n", stat_unaligned_le_8192));
328 KdPrint((__DRIVER_NAME " stat_unaligned_le_16384 = %d\n", stat_unaligned_le_16384));
329 KdPrint((__DRIVER_NAME " stat_unaligned_le_32768 = %d\n", stat_unaligned_le_32768));
330 KdPrint((__DRIVER_NAME " stat_unaligned_le_65536 = %d\n", stat_unaligned_le_65536));
331 KdPrint((__DRIVER_NAME " stat_unaligned_gt_65536 = %d\n", stat_unaligned_gt_65536));
332 KdPrint((__DRIVER_NAME " stat_no_shadows = %d\n", stat_no_shadows));
333 KdPrint((__DRIVER_NAME " stat_no_grants = %d\n", stat_no_grants));
334 KdPrint((__DRIVER_NAME " stat_outstanding_requests = %d\n", stat_outstanding_requests));
335 }
337 static VOID
338 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
339 {
340 ULONG block_count, transfer_length;
341 blkif_shadow_t *shadow;
342 PHYSICAL_ADDRESS physical_address;
343 ULONG pfn;
344 ULONG remaining, offset, length;
345 PUCHAR ptr;
346 int notify;
348 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
350 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
351 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
352 block_count *= xvdd->bytes_per_sector / 512;
353 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
354 {
355 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
356 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
357 }
358 else
359 {
360 ptr = srb->DataBuffer;
361 transfer_length = block_count * 512;
362 }
364 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
365 {
366 ASSERT(!xvdd->pending_srb);
367 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
368 xvdd->pending_srb = srb;
369 stat_no_grants++;
370 return;
371 }
373 if (!srb_offset)
374 {
375 if (PtrToUlong(srb->DataBuffer) & 511)
376 {
377 if (block_count * 512 <= 4096)
378 stat_unaligned_le_4096++;
379 else if (block_count * 512 <= 8192)
380 stat_unaligned_le_8192++;
381 else if (block_count * 512 <= 16384)
382 stat_unaligned_le_16384++;
383 else if (block_count * 512 <= 32768)
384 stat_unaligned_le_32768++;
385 else if (block_count * 512 <= 65536)
386 stat_unaligned_le_65536++;
387 else
388 stat_unaligned_gt_65536++;
389 }
390 if (srb->Cdb[0] == SCSIOP_WRITE)
391 stat_writes++;
392 else
393 stat_reads++;
394 stat_outstanding_requests++;
395 }
397 shadow = get_shadow_from_freelist(xvdd);
398 ASSERT(shadow);
399 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
400 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
401 shadow->req.handle = 0;
402 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
403 shadow->req.nr_segments = 0;
404 shadow->offset = srb_offset;
405 shadow->length = transfer_length;
406 shadow->srb = srb;
408 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
409 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
410 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
412 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
413 {
414 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
415 //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, shadow->req.sector_number));
416 if (srb->Cdb[0] == SCSIOP_WRITE)
417 {
418 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
419 }
420 }
421 else
422 {
423 ptr = srb->DataBuffer;
424 }
425 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
426 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
427 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
429 remaining = shadow->length;
430 while (remaining > 0)
431 {
432 physical_address = MmGetPhysicalAddress(ptr);
433 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
434 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
435 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref != INVALID_GRANT_REF);
436 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
437 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
438 ASSERT((offset & 511) == 0);
439 length = min(PAGE_SIZE - offset, remaining);
440 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
441 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
442 remaining -= length;
443 ptr += length;
444 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
445 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
446 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
447 shadow->req.nr_segments++;
448 }
449 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
451 XenVbd_PutRequest(xvdd, &shadow->req);
453 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
454 if (notify)
455 {
456 //KdPrint((__DRIVER_NAME " Notifying\n"));
457 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
458 }
460 if (!xvdd->shadow_free)
461 stat_no_shadows++;
462 if (xvdd->shadow_free && srb_offset == 0)
463 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
465 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
466 }
468 typedef struct {
469 PSCSI_REQUEST_BLOCK srb;
470 ULONG offset;
471 } mini_shadow_t;
473 static VOID
474 XenVbd_Resume(PVOID DeviceExtension)
475 {
476 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
477 ULONG i;
478 mini_shadow_t shadows[MAX_SHADOW_ENTRIES];
479 ULONG shadow_count;
481 FUNCTION_ENTER();
482 KdPrint((__DRIVER_NAME " found device in resume state\n"));
483 //FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE); what was this for???
484 // re-submit srb's
486 shadow_count = 0;
487 for (i = 0; i < SHADOW_ENTRIES; i++)
488 {
489 if (xvdd->shadows[i].srb)
490 {
491 shadows[shadow_count].srb = xvdd->shadows[i].srb;
492 shadows[shadow_count].offset = xvdd->shadows[i].offset;
493 shadow_count++;
494 xvdd->shadows[i].srb = NULL;
495 }
496 }
497 KdPrint((__DRIVER_NAME " About to call InitFromConfig\n"));
498 XenVbd_InitFromConfig(xvdd);
499 KdPrint((__DRIVER_NAME " Back from InitFromConfig\n"));
501 for (i = 0; i < shadow_count; i++)
502 {
503 KdPrint((__DRIVER_NAME " Putting on Shadow entry\n"));
504 XenVbd_PutSrbOnRing(xvdd, shadows[i].srb, shadows[i].offset);
505 }
506 KdPrint((__DRIVER_NAME " Shadows are back on the ring\n"));
508 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
510 KdPrint((__DRIVER_NAME " resume_state set to RESUME_STATE_RUNNING\n"));
512 if (i == 0)
513 {
514 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
515 KdPrint((__DRIVER_NAME " No shadows - notifying to get things started again\n"));
516 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
517 }
518 FUNCTION_EXIT();
519 }
521 static ULONG DDKAPI
522 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
523 {
524 // PACCESS_RANGE AccessRange;
525 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
526 ULONG status;
527 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
528 PACCESS_RANGE access_range;
529 ULONG i;
531 UNREFERENCED_PARAMETER(HwContext);
532 UNREFERENCED_PARAMETER(BusInformation);
533 UNREFERENCED_PARAMETER(ArgumentString);
535 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
536 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
538 *Again = FALSE;
540 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
541 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
543 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
544 {
545 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
546 return SP_RETURN_BAD_CONFIG;
547 }
549 xvdd->inactive = global_inactive;
551 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
552 {
553 access_range = &((*(ConfigInfo->AccessRanges))[i]);
554 if (access_range->RangeStart.QuadPart)
555 {
556 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
557 access_range->RangeStart.LowPart, access_range->RangeLength));
559 xvdd->device_base = ScsiPortGetDeviceBase(
560 DeviceExtension,
561 ConfigInfo->AdapterInterfaceType,
562 ConfigInfo->SystemIoBusNumber,
563 access_range->RangeStart,
564 access_range->RangeLength,
565 !access_range->RangeInMemory);
566 if (xvdd->device_base == NULL)
567 {
568 KdPrint((__DRIVER_NAME " Unable to map range\n"));
569 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
570 return SP_RETURN_BAD_CONFIG;
571 }
572 }
573 else
574 {
575 xvdd->inactive = TRUE;
576 }
577 }
579 if (!xvdd->device_base)
580 {
581 KdPrint((__DRIVER_NAME " Invalid config\n"));
582 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
583 return SP_RETURN_BAD_CONFIG;
584 }
586 status = XenVbd_InitFromConfig(xvdd);
587 if (status != SP_RETURN_FOUND)
588 return status;
590 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
591 ConfigInfo->NumberOfPhysicalBreaks = 0; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
592 ConfigInfo->ScatterGather = TRUE;
593 ConfigInfo->AlignmentMask = 0;
594 ConfigInfo->NumberOfBuses = 1;
595 ConfigInfo->InitiatorBusId[0] = 1;
596 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
597 ConfigInfo->MaximumNumberOfTargets = 2;
598 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
599 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
600 {
601 ConfigInfo->Master = TRUE;
602 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
603 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
604 }
605 else
606 {
607 ConfigInfo->Master = FALSE;
608 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
609 }
611 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
613 return SP_RETURN_FOUND;
614 }
616 static BOOLEAN DDKAPI
617 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
618 {
619 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
620 blkif_request_t *req;
621 int i;
622 int notify;
624 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
625 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
627 if (!dump_mode)
628 {
629 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
630 req->operation = 0xff;
631 req->nr_segments = 0;
632 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
633 {
634 req->seg[i].gref = 0; //0xffffffff;
635 req->seg[i].first_sect = 0; //0xff;
636 req->seg[i].last_sect = 0; //0xff;
637 }
638 xvdd->ring.req_prod_pvt++;
640 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
641 req->operation = 0xff;
642 req->nr_segments = 0;
643 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
644 {
645 req->seg[i].gref = 0; //0xffffffff;
646 req->seg[i].first_sect = 0; //0xff;
647 req->seg[i].last_sect = 0; //0xff;
648 }
649 xvdd->ring.req_prod_pvt++;
651 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
652 if (notify)
653 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
654 xvdd->ring_detect_state = 0;
655 }
656 else
657 {
658 if (xvdd->cached_use_other)
659 {
660 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
661 xvdd->use_other = TRUE;
662 }
663 xvdd->ring_detect_state = 2;
664 }
666 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
668 return TRUE;
669 }
671 static ULONG
672 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
673 {
674 PCDB cdb;
675 PMODE_PARAMETER_HEADER parameter_header;
676 PMODE_PARAMETER_BLOCK param_block;
677 PMODE_FORMAT_PAGE format_page;
678 UCHAR page_code;
679 ULONG offset;
680 UCHAR buffer[256];
681 BOOLEAN valid_page = FALSE;
683 UNREFERENCED_PARAMETER(xvdd);
685 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
687 cdb = (PCDB)srb->Cdb;
688 page_code = cdb->MODE_SENSE.PageCode;
689 offset = 0;
690 RtlZeroMemory(srb->DataBuffer, 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->MODE_SENSE.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 && (page_code == MODE_PAGE_FORMAT_DEVICE || 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 && 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(srb->DataBuffer, 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 int j;
799 blkif_response_t *rep;
800 int block_count;
801 int more_to_do = TRUE;
802 blkif_shadow_t *shadow;
803 ULONG offset;
805 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
807 stat_interrupts++;
808 /* in dump mode I think we get called on a timer, not by an actual IRQ */
809 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
810 return FALSE; /* interrupt was not for us */
811 stat_interrupts_for_me++;
812 if (xvdd->device_state->resume_state != xvdd->device_state->resume_state_ack)
813 {
814 FUNCTION_ENTER();
815 switch (xvdd->device_state->resume_state)
816 {
817 case RESUME_STATE_SUSPENDING:
818 KdPrint((__DRIVER_NAME " New state SUSPENDING\n"));
819 break;
820 case RESUME_STATE_FRONTEND_RESUME:
821 KdPrint((__DRIVER_NAME " New state RESUME_STATE_FRONTEND_RESUME\n"));
822 XenVbd_Resume(xvdd);
823 break;
824 default:
825 KdPrint((__DRIVER_NAME " New state %d\n", xvdd->device_state->resume_state));
826 break;
827 }
828 xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
829 KeMemoryBarrier();
830 FUNCTION_EXIT();
831 }
833 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
834 {
835 return FALSE;
836 }
838 if (!dump_mode && !(stat_interrupts_for_me & 0xFFFF))
839 XenVbd_DumpStats();
841 while (more_to_do)
842 {
843 rp = xvdd->ring.sring->rsp_prod;
844 KeMemoryBarrier();
845 for (i = xvdd->ring.rsp_cons; i < rp; i++)
846 {
847 rep = XenVbd_GetResponse(xvdd, i);
848 /*
849 * This code is to automatically detect if the backend is using the same
850 * bit width or a different bit width to us. Later versions of Xen do this
851 * via a xenstore value, but not all. That 0x0fffffff (notice
852 * that the msb is not actually set, so we don't have any problems with
853 * sign extending) is to signify the last entry on the right, which is
854 * different under 32 and 64 bits, and that is why we set it up there.
856 * To do the detection, we put two initial entries on the ring, with an op
857 * of 0xff (which is invalid). The first entry is mostly okay, but the
858 * second will be grossly misaligned if the backend bit width is different,
859 * and we detect this and switch frontend structures.
860 */
861 switch (xvdd->ring_detect_state)
862 {
863 case 0:
864 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
865 xvdd->ring_detect_state = 1;
866 break;
867 case 1:
868 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
869 *xvdd->event_channel_ptr |= 0x80000000;
870 if (rep->operation != 0xff)
871 {
872 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
873 xvdd->use_other = TRUE;
874 *xvdd->event_channel_ptr |= 0x40000000;
875 }
876 xvdd->ring_detect_state = 2;
877 ScsiPortNotification(NextRequest, DeviceExtension);
878 break;
879 case 2:
880 //KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
881 shadow = &xvdd->shadows[rep->id];
882 srb = shadow->srb;
883 ASSERT(srb != NULL);
884 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
885 block_count *= xvdd->bytes_per_sector / 512;
886 if (rep->status == BLKIF_RSP_OKAY)
887 srb->SrbStatus = SRB_STATUS_SUCCESS;
888 else
889 {
890 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
891 if (srb->Cdb[0] == SCSIOP_READ)
892 KdPrint((__DRIVER_NAME " Operation = Read\n"));
893 else
894 KdPrint((__DRIVER_NAME " Operation = Write\n"));
895 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
896 srb->SrbStatus = SRB_STATUS_ERROR;
897 srb->ScsiStatus = 0x02;
898 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
899 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
900 XenVbd_MakeAutoSense(xvdd, srb);
901 }
902 for (j = 0; j < shadow->req.nr_segments; j++)
903 {
904 #if DBG
905 BOOLEAN result =
906 #endif
907 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
908 #if DBG
909 ASSERT(result);
910 #endif
911 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
912 }
914 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
915 {
916 if (srb->Cdb[0] == SCSIOP_READ)
917 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
918 offset = shadow->offset + shadow->length;
919 put_shadow_on_freelist(xvdd, shadow);
920 if (offset == block_count * xvdd->bytes_per_sector)
921 {
922 ScsiPortNotification(RequestComplete, xvdd, srb);
923 stat_outstanding_requests--;
924 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
925 }
926 else
927 {
928 XenVbd_PutSrbOnRing(xvdd, srb, offset);
929 }
930 }
931 else
932 {
933 put_shadow_on_freelist(xvdd, shadow);
934 ScsiPortNotification(RequestComplete, xvdd, srb);
935 stat_outstanding_requests--;
936 if (xvdd->pending_srb)
937 {
938 srb = xvdd->pending_srb;
939 xvdd->pending_srb = NULL;
940 XenVbd_PutSrbOnRing(xvdd, srb, 0);
941 }
942 else
943 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
944 }
945 break;
946 }
947 }
949 xvdd->ring.rsp_cons = i;
950 if (i != xvdd->ring.req_prod_pvt)
951 {
952 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
953 }
954 else
955 {
956 xvdd->ring.sring->rsp_event = i + 1;
957 more_to_do = FALSE;
958 }
959 }
961 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
962 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
963 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
964 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
966 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
968 return FALSE; /* always fall through to the next ISR... */
969 }
971 static BOOLEAN DDKAPI
972 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
973 {
974 PUCHAR DataBuffer;
975 PCDB cdb;
976 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
978 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
980 if (xvdd->inactive)
981 {
982 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
983 return TRUE;
984 }
986 // If we haven't enumerated all the devices yet then just defer the request
987 if (xvdd->ring_detect_state < 2)
988 {
989 Srb->SrbStatus = SRB_STATUS_BUSY;
990 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
991 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
992 return TRUE;
993 }
995 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
996 {
997 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
998 Srb->SrbStatus = SRB_STATUS_BUSY;
999 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1000 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
1001 return TRUE;
1004 if (Srb->PathId != 0 || Srb->TargetId != 0)
1006 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1007 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1008 ScsiPortNotification(NextRequest, DeviceExtension);
1009 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1010 return TRUE;
1013 switch (Srb->Function)
1015 case SRB_FUNCTION_EXECUTE_SCSI:
1016 cdb = (PCDB)Srb->Cdb;
1017 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1019 switch(cdb->CDB6GENERIC.OperationCode)
1021 case SCSIOP_TEST_UNIT_READY:
1022 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1023 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1024 Srb->ScsiStatus = 0;
1025 break;
1026 case SCSIOP_INQUIRY:
1027 // KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1028 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1029 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
1030 // KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
1031 DataBuffer = Srb->DataBuffer;
1032 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1033 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1034 switch (xvdd->device_type)
1036 case XENVBD_DEVICETYPE_DISK:
1037 if ((Srb->Cdb[1] & 1) == 0)
1039 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1040 id->DeviceType = DIRECT_ACCESS_DEVICE;
1041 id->Versions = 3;
1042 id->ResponseDataFormat = 0;
1043 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1044 id->CommandQueue = 1;
1045 memcpy(id->VendorId, "XEN ", 8); // vendor id
1046 memcpy(id->ProductId, "PV DISK ", 16); // product id
1047 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1049 else
1051 switch (Srb->Cdb[2])
1053 case 0x00:
1054 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1055 DataBuffer[1] = 0x00;
1056 DataBuffer[2] = 0x00;
1057 DataBuffer[3] = 2;
1058 DataBuffer[4] = 0x00;
1059 DataBuffer[5] = 0x80;
1060 break;
1061 case 0x80:
1062 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1063 DataBuffer[1] = 0x80;
1064 DataBuffer[2] = 0x00;
1065 DataBuffer[3] = 8;
1066 memset(&DataBuffer[4], ' ', 8);
1067 break;
1068 default:
1069 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1070 Srb->SrbStatus = SRB_STATUS_ERROR;
1071 break;
1074 break;
1075 case XENVBD_DEVICETYPE_CDROM:
1076 if ((Srb->Cdb[1] & 1) == 0)
1078 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
1079 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1080 id->RemovableMedia = 1;
1081 id->Versions = 3;
1082 id->ResponseDataFormat = 0;
1083 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1084 id->CommandQueue = 1;
1085 memcpy(id->VendorId, "XEN ", 8); // vendor id
1086 memcpy(id->ProductId, "PV CDROM ", 16); // product id
1087 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1089 else
1091 switch (Srb->Cdb[2])
1093 case 0x00:
1094 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1095 DataBuffer[1] = 0x00;
1096 DataBuffer[2] = 0x00;
1097 DataBuffer[3] = 2;
1098 DataBuffer[4] = 0x00;
1099 DataBuffer[5] = 0x80;
1100 break;
1101 case 0x80:
1102 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1103 DataBuffer[1] = 0x80;
1104 DataBuffer[2] = 0x00;
1105 DataBuffer[3] = 8;
1106 DataBuffer[4] = 0x31;
1107 DataBuffer[5] = 0x32;
1108 DataBuffer[6] = 0x33;
1109 DataBuffer[7] = 0x34;
1110 DataBuffer[8] = 0x35;
1111 DataBuffer[9] = 0x36;
1112 DataBuffer[10] = 0x37;
1113 DataBuffer[11] = 0x38;
1114 break;
1115 default:
1116 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1117 Srb->SrbStatus = SRB_STATUS_ERROR;
1118 break;
1121 break;
1122 default:
1123 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1124 Srb->SrbStatus = SRB_STATUS_ERROR;
1125 break;
1127 break;
1128 case SCSIOP_READ_CAPACITY:
1129 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1130 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1131 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1132 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1133 DataBuffer = Srb->DataBuffer;
1134 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1135 if ((xvdd->total_sectors - 1) >> 32)
1137 DataBuffer[0] = 0xff;
1138 DataBuffer[1] = 0xff;
1139 DataBuffer[2] = 0xff;
1140 DataBuffer[3] = 0xff;
1142 else
1144 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1145 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1146 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1147 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1149 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1150 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1151 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1152 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1153 Srb->ScsiStatus = 0;
1154 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1155 break;
1156 case SCSIOP_MODE_SENSE:
1157 // 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));
1158 XenVbd_FillModePage(xvdd, Srb);
1159 break;
1160 case SCSIOP_WRITE:
1161 case SCSIOP_READ:
1162 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1163 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
1164 break;
1165 case SCSIOP_VERIFY:
1166 // Should we do more here?
1167 // KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1168 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1169 break;
1170 case SCSIOP_REPORT_LUNS:
1171 // KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1172 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1173 break;
1174 case SCSIOP_REQUEST_SENSE:
1175 // KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1176 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1177 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1178 break;
1179 case SCSIOP_READ_TOC:
1180 DataBuffer = Srb->DataBuffer;
1181 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1182 /*
1183 #define READ_TOC_FORMAT_TOC 0x00
1184 #define READ_TOC_FORMAT_SESSION 0x01
1185 #define READ_TOC_FORMAT_FULL_TOC 0x02
1186 #define READ_TOC_FORMAT_PMA 0x03
1187 #define READ_TOC_FORMAT_ATIP 0x04
1188 */
1189 // KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1190 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1191 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1192 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1193 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1194 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1195 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1196 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1197 switch (cdb->READ_TOC.Format2)
1199 case READ_TOC_FORMAT_TOC:
1200 DataBuffer[0] = 0; // length MSB
1201 DataBuffer[1] = 10; // length LSB
1202 DataBuffer[2] = 1; // First Track
1203 DataBuffer[3] = 1; // Last Track
1204 DataBuffer[4] = 0; // Reserved
1205 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1206 DataBuffer[6] = 1; // last complete track
1207 DataBuffer[7] = 0; // reserved
1208 DataBuffer[8] = 0; // MSB Block
1209 DataBuffer[9] = 0;
1210 DataBuffer[10] = 0;
1211 DataBuffer[11] = 0; // LSB Block
1212 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1213 break;
1214 case READ_TOC_FORMAT_SESSION:
1215 case READ_TOC_FORMAT_FULL_TOC:
1216 case READ_TOC_FORMAT_PMA:
1217 case READ_TOC_FORMAT_ATIP:
1218 Srb->SrbStatus = SRB_STATUS_ERROR;
1219 break;
1221 break;
1222 case SCSIOP_START_STOP_UNIT:
1223 // KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1224 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1225 break;
1226 case SCSIOP_RESERVE_UNIT:
1227 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1228 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1229 break;
1230 case SCSIOP_RELEASE_UNIT:
1231 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1232 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1233 break;
1234 default:
1235 //KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1236 Srb->SrbStatus = SRB_STATUS_ERROR;
1237 break;
1239 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1241 //KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1242 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1244 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1245 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1247 Srb->ScsiStatus = 0x02;
1248 XenVbd_MakeAutoSense(xvdd, Srb);
1249 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1250 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1252 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1254 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1255 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1256 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1257 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1259 break;
1260 case SRB_FUNCTION_IO_CONTROL:
1261 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1262 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1263 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1264 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1265 break;
1266 case SRB_FUNCTION_FLUSH:
1267 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1268 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1269 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1270 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1271 break;
1272 default:
1273 //KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1274 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1275 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1276 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1277 break;
1280 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1281 return TRUE;
1284 static BOOLEAN DDKAPI
1285 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1287 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1289 UNREFERENCED_PARAMETER(DeviceExtension);
1290 UNREFERENCED_PARAMETER(PathId);
1292 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1294 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1295 if (xvdd->ring_detect_state == 2 && xvdd->device_state->resume_state == RESUME_STATE_RUNNING)
1297 ScsiPortNotification(NextRequest, DeviceExtension);
1300 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1303 return TRUE;
1306 static BOOLEAN DDKAPI
1307 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1309 UNREFERENCED_PARAMETER(DeviceExtension);
1310 UNREFERENCED_PARAMETER(Context);
1311 UNREFERENCED_PARAMETER(SaveState);
1313 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1314 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1316 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1318 return TRUE;
1321 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1322 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1324 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1325 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1326 //KIRQL OldIrql;
1328 UNREFERENCED_PARAMETER(DeviceExtension);
1330 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1331 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1333 switch (ControlType)
1335 case ScsiQuerySupportedControlTypes:
1336 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1337 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1338 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1339 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1340 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1341 break;
1342 case ScsiStopAdapter:
1343 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1344 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1345 break;
1346 case ScsiRestartAdapter:
1347 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1348 break;
1349 case ScsiSetBootConfig:
1350 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1351 break;
1352 case ScsiSetRunningConfig:
1353 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1354 break;
1355 default:
1356 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1357 break;
1360 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1362 return Status;
1365 NTSTATUS
1366 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1368 ULONG status;
1369 HW_INITIALIZATION_DATA HwInitializationData;
1370 PCONFIGURATION_INFORMATION conf_info;
1371 PVOID driver_extension;
1372 PUCHAR ptr;
1374 FUNCTION_ENTER();
1375 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1377 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1378 ptr = driver_extension;
1379 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
1380 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
1381 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
1382 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL);
1383 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL);
1384 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL);
1385 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL);
1386 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, UlongToPtr(144));
1387 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
1389 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1390 if (!RegistryPath)
1392 dump_mode = TRUE;
1394 else
1396 conf_info = IoGetConfigurationInformation();
1397 if (conf_info == NULL)
1399 KdPrint((__DRIVER_NAME " conf_info == NULL\n"));
1401 else
1403 KdPrint((__DRIVER_NAME " conf_info->DiskCount = %d\n", conf_info->DiskCount));
1405 if (conf_info != NULL && conf_info->DiskCount && RegistryPath)
1407 global_inactive = TRUE;
1408 KdPrint((__DRIVER_NAME " Not loaded at boot time so setting inactive\n"));
1411 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1413 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1414 HwInitializationData.AdapterInterfaceType = Internal;
1415 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1416 HwInitializationData.SpecificLuExtensionSize = 0;
1417 /* 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 */
1418 HwInitializationData.SrbExtensionSize = UNALIGNED_DOUBLE_BUFFER_SIZE + PAGE_SIZE - 1;
1419 HwInitializationData.NumberOfAccessRanges = 1;
1420 HwInitializationData.MapBuffers = TRUE;
1421 HwInitializationData.NeedPhysicalAddresses = FALSE;
1422 HwInitializationData.TaggedQueuing = FALSE;
1423 HwInitializationData.AutoRequestSense = TRUE;
1424 HwInitializationData.MultipleRequestPerLu = TRUE;
1425 HwInitializationData.ReceiveEvent = FALSE;
1426 HwInitializationData.VendorIdLength = 0;
1427 HwInitializationData.VendorId = NULL;
1428 HwInitializationData.DeviceIdLength = 0;
1429 HwInitializationData.DeviceId = NULL;
1431 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1432 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1433 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1434 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1435 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1436 HwInitializationData.HwDmaStarted = NULL;
1437 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
1438 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1440 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1442 if(!NT_SUCCESS(status))
1444 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1447 FUNCTION_EXIT();
1449 return status;