win-pvdrivers

view xenvbd/scsiport.c @ 403:abdcb860cfdf

More suspend/resume updates.
author James Harper <james.harper@bendigoit.com.au>
date Mon Jul 21 11:47:29 2008 +1000 (2008-07-21)
parents fdb7f8853695
children d84a58b968e8
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 #include "xenvbd.h"
21 #include <io/blkif.h>
22 #include <scsi.h>
23 #include <ntddscsi.h>
24 #include <ntdddisk.h>
25 #include <stdlib.h>
26 #include <xen_public.h>
27 #include <io/xenbus.h>
28 #include <io/protocols.h>
30 #pragma warning(disable: 4127)
32 #if defined(__x86_64__)
33 #define GET_PAGE_ALIGNED(ptr) ((PVOID)(((ULONGLONG)ptr + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
34 #else
35 #define GET_PAGE_ALIGNED(ptr) UlongToPtr((PtrToUlong(ptr) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
36 #endif
38 static blkif_shadow_t *
39 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
40 {
41 if (xvdd->shadow_free == 0)
42 {
43 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
44 return NULL;
45 }
46 xvdd->shadow_free--;
47 if (xvdd->shadow_free < xvdd->shadow_min_free)
48 xvdd->shadow_min_free = xvdd->shadow_free;
49 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
50 }
52 static VOID
53 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
54 {
55 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
56 shadow->srb = NULL;
57 xvdd->shadow_free++;
58 }
60 static grant_ref_t
61 get_grant_from_freelist(PXENVBD_DEVICE_DATA xvdd)
62 {
63 if (xvdd->grant_free == 0)
64 {
65 KdPrint((__DRIVER_NAME " No more grant refs\n"));
66 return (grant_ref_t)0x0FFFFFFF;
67 }
68 xvdd->grant_free--;
69 return xvdd->grant_free_list[xvdd->grant_free];
70 }
72 static VOID
73 put_grant_on_freelist(PXENVBD_DEVICE_DATA xvdd, grant_ref_t grant)
74 {
75 xvdd->grant_free_list[xvdd->grant_free] = grant;
76 xvdd->grant_free++;
77 }
79 static blkif_response_t *
80 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
81 {
82 blkif_other_response_t *rep;
83 if (!xvdd->use_other)
84 return RING_GET_RESPONSE(&xvdd->ring, i);
85 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
86 xvdd->tmp_rep.id = rep->id;
87 xvdd->tmp_rep.operation = rep->operation;
88 xvdd->tmp_rep.status = rep->status;
89 return &xvdd->tmp_rep;
90 }
92 static VOID
93 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
94 {
95 blkif_other_request_t *other_req;
97 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
98 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
99 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
100 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
101 if (!xvdd->use_other)
102 {
103 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
104 }
105 else
106 {
107 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
108 other_req->operation = req->operation;
109 other_req->nr_segments = req->nr_segments;
110 other_req->handle = req->handle;
111 other_req->id = req->id;
112 other_req->sector_number = req->sector_number;
113 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
114 }
115 xvdd->ring.req_prod_pvt++;
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 }
122 static ULONG
123 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
124 {
125 ULONG i;
126 PUCHAR ptr;
127 USHORT type;
128 PCHAR setting, value;
130 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
131 xvdd->sring = NULL;
132 xvdd->event_channel = 0;
134 ptr = xvdd->device_base;
135 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID) &setting, (PVOID) &value)) != XEN_INIT_TYPE_END)
136 {
137 switch(type)
138 {
139 case XEN_INIT_TYPE_RING: /* frontend ring */
140 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
141 if (strcmp(setting, "ring-ref") == 0)
142 {
143 xvdd->sring = (blkif_sring_t *)value;
144 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
145 /* this bit is for when we have to take over an existing ring on a bug check */
146 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
147 xvdd->ring.rsp_cons = xvdd->sring->rsp_prod;
148 }
149 break;
150 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
151 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
152 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
153 if (strcmp(setting, "event-channel") == 0)
154 {
155 xvdd->event_channel = PtrToUlong(value);
156 }
157 break;
158 case XEN_INIT_TYPE_READ_STRING_BACK:
159 case XEN_INIT_TYPE_READ_STRING_FRONT:
160 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
161 if (strcmp(setting, "sectors") == 0)
162 xvdd->total_sectors = atoi(value);
163 else if (strcmp(setting, "sector-size") == 0)
164 xvdd->bytes_per_sector = atoi(value);
165 else if (strcmp(setting, "device-type") == 0)
166 {
167 if (strcmp(value, "disk") == 0)
168 {
169 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
170 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
171 }
172 else if (strcmp(value, "cdrom") == 0)
173 {
174 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
175 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
176 }
177 else
178 {
179 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
180 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
181 }
182 }
183 else if (strcmp(setting, "mode") == 0)
184 {
185 if (strncmp(value, "r", 1) == 0)
186 {
187 KdPrint((__DRIVER_NAME " mode = r\n"));
188 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
189 }
190 else if (strncmp(value, "w", 1) == 0)
191 {
192 KdPrint((__DRIVER_NAME " mode = w\n"));
193 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
194 }
195 else
196 {
197 KdPrint((__DRIVER_NAME " mode = unknown\n"));
198 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
199 }
200 }
201 break;
202 case XEN_INIT_TYPE_VECTORS:
203 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
204 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
205 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
206 {
207 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
208 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
209 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
210 return SP_RETURN_BAD_CONFIG;
211 }
212 else
213 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
214 break;
215 case XEN_INIT_TYPE_GRANT_ENTRIES:
216 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
217 xvdd->grant_entries = (USHORT)PtrToUlong(setting);
218 memcpy(&xvdd->grant_free_list, value, sizeof(grant_ref_t) * xvdd->grant_entries);
219 xvdd->grant_free = xvdd->grant_entries;
220 break;
221 case XEN_INIT_TYPE_STATE_PTR:
222 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
223 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
224 break;
225 default:
226 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
227 break;
228 }
229 }
230 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
231 || xvdd->sring == NULL
232 || xvdd->event_channel == 0
233 || xvdd->total_sectors == 0
234 || xvdd->bytes_per_sector == 0)
235 {
236 KdPrint((__DRIVER_NAME " Missing settings\n"));
237 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
238 return SP_RETURN_BAD_CONFIG;
239 }
241 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
242 #ifdef __MINGW32__
243 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
244 {
245 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
246 ULONG index;
248 bit_scan_forward(&index, num_512_byte_sectors);
249 xvdd->total_sectors <<= index-1;
250 }
251 #else
252 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
253 #endif
256 xvdd->shadow_free = 0;
257 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
258 for (i = 0; i < SHADOW_ENTRIES; i++)
259 {
260 xvdd->shadows[i].req.id = i;
261 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
262 }
264 return SP_RETURN_FOUND;
265 }
267 static VOID
268 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
269 {
270 ULONG block_count, transfer_length;
271 blkif_shadow_t *shadow;
272 PHYSICAL_ADDRESS physical_address;
273 ULONG pfn;
274 ULONG remaining, offset, length;
275 PUCHAR ptr;
276 int notify;
278 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
280 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
281 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
282 block_count *= xvdd->bytes_per_sector / 512;
283 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
284 {
285 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
286 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
287 if (!srb_offset)
288 {
289 xvdd->unaligned_requests++;
290 xvdd->unaligned_bytes += transfer_length;
291 }
292 }
293 else
294 {
295 ptr = srb->DataBuffer;
296 transfer_length = block_count * 512;
297 xvdd->aligned_requests++;
298 xvdd->aligned_bytes += transfer_length;
299 }
301 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
302 {
303 ASSERT(!xvdd->pending_srb);
304 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
305 xvdd->pending_srb = srb;
306 xvdd->no_free_grant_requests++;
307 return;
308 }
310 shadow = get_shadow_from_freelist(xvdd);
311 ASSERT(shadow);
312 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
313 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
314 shadow->req.handle = 0;
315 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
316 shadow->req.nr_segments = 0;
317 shadow->offset = srb_offset;
318 shadow->length = transfer_length;
319 shadow->srb = srb;
321 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
322 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
323 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
325 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
326 {
327 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
328 //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));
329 if (srb->Cdb[0] == SCSIOP_WRITE)
330 {
331 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
332 }
333 }
334 else
335 {
336 ptr = srb->DataBuffer;
337 }
338 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
339 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
340 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
342 remaining = shadow->length;
343 while (remaining > 0)
344 {
345 physical_address = MmGetPhysicalAddress(ptr);
346 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
347 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
348 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref);
349 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
350 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
351 ASSERT((offset & 511) == 0);
352 length = min(PAGE_SIZE - offset, remaining);
353 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
354 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
355 remaining -= length;
356 ptr += length;
357 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
358 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
359 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
360 shadow->req.nr_segments++;
361 }
362 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
364 XenVbd_PutRequest(xvdd, &shadow->req);
366 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
367 if (notify)
368 {
369 //KdPrint((__DRIVER_NAME " Notifying\n"));
370 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
371 }
373 if (xvdd->shadow_free && srb_offset == 0)
374 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
376 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
377 }
379 #define RESUME_CHECK_TIMER_INTERVAL (100 * 1000)
381 static VOID
382 XenVbd_HwScsiTimer(PVOID DeviceExtension)
383 {
384 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
385 ULONG i;
386 blkif_shadow_t shadows[SHADOW_ENTRIES];
387 ULONG shadow_entries;
388 blkif_shadow_t *shadow;
390 if (xvdd->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
391 {
392 KdPrint((__DRIVER_NAME " found device in resume state\n"));
393 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
394 // re-submit srb's
396 shadow_entries = 0;
397 for (i = 0; i < SHADOW_ENTRIES; i++)
398 {
399 shadow = &xvdd->shadows[i];
400 if (shadow->srb)
401 {
402 shadows[shadow_entries++] = xvdd->shadows[i];
403 shadow->srb = NULL;
404 }
405 }
407 XenVbd_InitFromConfig(xvdd);
409 for (i = 0; i < shadow_entries; i++)
410 {
411 shadow = &shadows[i];
412 XenVbd_PutSrbOnRing(xvdd, shadow->srb, shadow->offset);
413 }
415 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
417 if (i == 0)
418 {
419 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
420 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
421 }
422 }
424 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
425 }
427 static ULONG DDKAPI
428 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
429 {
430 // PACCESS_RANGE AccessRange;
431 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
432 ULONG status;
433 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
434 PACCESS_RANGE access_range;
436 UNREFERENCED_PARAMETER(HwContext);
437 UNREFERENCED_PARAMETER(BusInformation);
438 UNREFERENCED_PARAMETER(ArgumentString);
440 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
441 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
443 *Again = FALSE;
445 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
446 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
448 if (ConfigInfo->NumberOfAccessRanges != 1)
449 {
450 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
451 return SP_RETURN_BAD_CONFIG;
452 }
454 access_range = &((*(ConfigInfo->AccessRanges))[0]);
456 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
457 access_range->RangeStart.LowPart, access_range->RangeLength));
459 xvdd->device_base = ScsiPortGetDeviceBase(
460 DeviceExtension,
461 ConfigInfo->AdapterInterfaceType,
462 ConfigInfo->SystemIoBusNumber,
463 access_range->RangeStart,
464 access_range->RangeLength,
465 !access_range->RangeInMemory);
466 if (xvdd->device_base == NULL)
467 {
468 KdPrint((__DRIVER_NAME " Unable to map range\n"));
469 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
470 return SP_RETURN_BAD_CONFIG;
471 }
473 status = XenVbd_InitFromConfig(xvdd);
474 if (status != SP_RETURN_FOUND)
475 return status;
477 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
478 ConfigInfo->NumberOfPhysicalBreaks = 0; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
479 ConfigInfo->ScatterGather = TRUE;
480 ConfigInfo->AlignmentMask = 0;
481 ConfigInfo->NumberOfBuses = 1;
482 ConfigInfo->InitiatorBusId[0] = 1;
483 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
484 ConfigInfo->MaximumNumberOfTargets = 2;
485 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
486 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
487 {
488 ConfigInfo->Master = TRUE;
489 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
490 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
491 }
492 else
493 {
494 ConfigInfo->Master = FALSE;
495 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
496 }
498 xvdd->ring_detect_state = 0;
500 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
502 return SP_RETURN_FOUND;
503 }
505 static BOOLEAN DDKAPI
506 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
507 {
508 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
509 blkif_request_t *req;
510 int i;
511 int notify;
513 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
514 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
516 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
517 req->operation = 0xff;
518 req->nr_segments = 0;
519 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
520 {
521 req->seg[i].gref = 0; //0xffffffff;
522 req->seg[i].first_sect = 0; //0xff;
523 req->seg[i].last_sect = 0; //0xff;
524 }
525 xvdd->ring.req_prod_pvt++;
527 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
528 req->operation = 0xff;
529 req->nr_segments = 0;
530 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
531 {
532 req->seg[i].gref = 0; //0xffffffff;
533 req->seg[i].first_sect = 0; //0xff;
534 req->seg[i].last_sect = 0; //0xff;
535 }
536 xvdd->ring.req_prod_pvt++;
538 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
539 if (notify)
540 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
542 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
544 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
546 return TRUE;
547 }
549 static ULONG
550 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
551 {
552 PCDB cdb;
553 PMODE_PARAMETER_HEADER parameter_header;
554 PMODE_PARAMETER_BLOCK param_block;
555 PMODE_FORMAT_PAGE format_page;
556 UCHAR page_code;
557 ULONG offset;
558 UCHAR buffer[256];
559 BOOLEAN valid_page = FALSE;
561 UNREFERENCED_PARAMETER(xvdd);
563 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
565 cdb = (PCDB)srb->Cdb;
566 page_code = cdb->MODE_SENSE.PageCode;
567 offset = 0;
568 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
569 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
571 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
572 parameter_header->MediumType = 0;
573 parameter_header->DeviceSpecificParameter = 0;
574 parameter_header->BlockDescriptorLength = 0;
575 offset += sizeof(MODE_PARAMETER_HEADER);
577 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
578 {
579 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
580 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
581 }
583 if (!cdb->MODE_SENSE.Dbd)
584 {
585 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
586 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
587 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
588 {
589 if (xvdd->total_sectors >> 32)
590 {
591 param_block->DensityCode = 0xff;
592 param_block->NumberOfBlocks[0] = 0xff;
593 param_block->NumberOfBlocks[1] = 0xff;
594 param_block->NumberOfBlocks[2] = 0xff;
595 }
596 else
597 {
598 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
599 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
600 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
601 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
602 }
603 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
604 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
605 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
606 }
607 offset += sizeof(MODE_PARAMETER_BLOCK);
608 }
609 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (page_code == MODE_PAGE_FORMAT_DEVICE || page_code == MODE_SENSE_RETURN_ALL))
610 {
611 valid_page = TRUE;
612 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
613 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
614 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
615 /* 256 sectors per track */
616 format_page->SectorsPerTrack[0] = 0x01;
617 format_page->SectorsPerTrack[1] = 0x00;
618 /* xxx bytes per sector */
619 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
620 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
621 format_page->HardSectorFormating = TRUE;
622 format_page->SoftSectorFormating = TRUE;
623 offset += sizeof(MODE_FORMAT_PAGE);
624 }
625 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
626 if (!valid_page && page_code != MODE_SENSE_RETURN_ALL)
627 {
628 srb->SrbStatus = SRB_STATUS_ERROR;
629 }
630 else if(offset < srb->DataTransferLength)
631 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
632 else
633 srb->SrbStatus = SRB_STATUS_SUCCESS;
634 srb->DataTransferLength = min(srb->DataTransferLength, offset);
635 srb->ScsiStatus = 0;
636 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
638 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
640 return TRUE;
641 }
643 static VOID
644 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
645 {
646 PSENSE_DATA sd = srb->SenseInfoBuffer;
648 UNREFERENCED_PARAMETER(xvdd);
650 if (!srb->SenseInfoBuffer)
651 return;
653 sd->ErrorCode = 0x70;
654 sd->Valid = 1;
655 sd->SenseKey = sense_key;
656 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
657 sd->AdditionalSenseCode = additional_sense_code;
658 return;
659 }
661 static VOID
662 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
663 {
664 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
665 return;
666 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
667 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
668 }
670 static BOOLEAN DDKAPI
671 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
672 {
673 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
674 PSCSI_REQUEST_BLOCK srb;
675 RING_IDX i, rp;
676 int j;
677 blkif_response_t *rep;
678 int block_count;
679 int more_to_do = TRUE;
680 blkif_shadow_t *shadow;
681 ULONG offset;
683 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
685 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
686 {
687 KdPrint((__DRIVER_NAME " --- " __FUNCTION__ " device_state event\n"));
688 xvdd->device_state->resume_state_ack = xvdd->device_state->resume_state;
689 KeMemoryBarrier();
690 return FALSE;
691 }
693 xvdd->interrupts++;
694 while (more_to_do)
695 {
696 rp = xvdd->ring.sring->rsp_prod;
697 KeMemoryBarrier();
698 for (i = xvdd->ring.rsp_cons; i != rp; i++)
699 {
700 rep = XenVbd_GetResponse(xvdd, i);
701 /*
702 * This code is to automatically detect if the backend is using the same
703 * bit width or a different bit width to us. Later versions of Xen do this
704 * via a xenstore value, but not all. That 0x0fffffff (notice
705 * that the msb is not actually set, so we don't have any problems with
706 * sign extending) is to signify the last entry on the right, which is
707 * different under 32 and 64 bits, and that is why we set it up there.
709 * To do the detection, we put two initial entries on the ring, with an op
710 * of 0xff (which is invalid). The first entry is mostly okay, but the
711 * second will be grossly misaligned if the backend bit width is different,
712 * and we detect this and switch frontend structures.
713 */
714 switch (xvdd->ring_detect_state)
715 {
716 case 0:
717 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
718 xvdd->ring_detect_state = 1;
719 break;
720 case 1:
721 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
722 if (rep->operation != 0xff)
723 {
724 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
725 xvdd->use_other = TRUE;
726 }
727 xvdd->ring_detect_state = 2;
728 ScsiPortNotification(NextRequest, DeviceExtension);
729 break;
730 case 2:
731 //KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
732 shadow = &xvdd->shadows[rep->id];
733 srb = shadow->srb;
734 ASSERT(srb != NULL);
735 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
736 block_count *= xvdd->bytes_per_sector / 512;
737 if (rep->status == BLKIF_RSP_OKAY)
738 srb->SrbStatus = SRB_STATUS_SUCCESS;
739 else
740 {
741 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
742 if (srb->Cdb[0] == SCSIOP_READ)
743 KdPrint((__DRIVER_NAME " Operation = Read\n"));
744 else
745 KdPrint((__DRIVER_NAME " Operation = Write\n"));
746 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
747 srb->SrbStatus = SRB_STATUS_ERROR;
748 srb->ScsiStatus = 0x02;
749 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
750 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
751 XenVbd_MakeAutoSense(xvdd, srb);
752 }
753 for (j = 0; j < shadow->req.nr_segments; j++)
754 {
755 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
756 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
757 }
759 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
760 {
761 if (srb->Cdb[0] == SCSIOP_READ)
762 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
763 offset = shadow->offset + shadow->length;
764 put_shadow_on_freelist(xvdd, shadow);
765 if (offset == block_count * xvdd->bytes_per_sector)
766 {
767 ScsiPortNotification(RequestComplete, xvdd, srb);
768 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
769 }
770 else
771 {
772 XenVbd_PutSrbOnRing(xvdd, srb, offset);
773 }
774 }
775 else
776 {
777 put_shadow_on_freelist(xvdd, shadow);
778 ScsiPortNotification(RequestComplete, xvdd, srb);
779 if (xvdd->pending_srb)
780 {
781 srb = xvdd->pending_srb;
782 xvdd->pending_srb = NULL;
783 XenVbd_PutSrbOnRing(xvdd, srb, 0);
784 }
785 else
786 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
787 }
788 }
789 }
791 xvdd->ring.rsp_cons = i;
792 if (i != xvdd->ring.req_prod_pvt)
793 {
794 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
795 }
796 else
797 {
798 xvdd->ring.sring->rsp_event = i + 1;
799 more_to_do = FALSE;
800 }
801 }
803 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
804 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
805 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
806 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
808 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
810 return FALSE; /* we just don't know... */
811 }
813 static BOOLEAN DDKAPI
814 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
815 {
816 PUCHAR DataBuffer;
817 PCDB cdb;
818 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
820 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
822 // If we haven't enumerated all the devices yet then just defer the request
823 if (xvdd->ring_detect_state < 2)
824 {
825 Srb->SrbStatus = SRB_STATUS_BUSY;
826 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
827 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
828 return TRUE;
829 }
831 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
832 {
833 Srb->SrbStatus = SRB_STATUS_BUSY;
834 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
835 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Resuming)\n"));
836 return TRUE;
837 }
839 if (Srb->PathId != 0 || Srb->TargetId != 0)
840 {
841 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
842 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
843 ScsiPortNotification(NextRequest, DeviceExtension);
844 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
845 return TRUE;
846 }
848 switch (Srb->Function)
849 {
850 case SRB_FUNCTION_EXECUTE_SCSI:
851 cdb = (PCDB)Srb->Cdb;
852 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
854 switch(cdb->CDB6GENERIC.OperationCode)
855 {
856 case SCSIOP_TEST_UNIT_READY:
857 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
858 Srb->SrbStatus = SRB_STATUS_SUCCESS;
859 Srb->ScsiStatus = 0;
860 break;
861 case SCSIOP_INQUIRY:
862 // KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
863 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
864 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
865 // KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
866 DataBuffer = Srb->DataBuffer;
867 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
868 Srb->SrbStatus = SRB_STATUS_SUCCESS;
869 switch (xvdd->device_type)
870 {
871 case XENVBD_DEVICETYPE_DISK:
872 if ((Srb->Cdb[1] & 1) == 0)
873 {
874 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
875 id->DeviceType = DIRECT_ACCESS_DEVICE;
876 id->Versions = 3;
877 id->ResponseDataFormat = 0;
878 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
879 id->CommandQueue = 1;
880 memcpy(id->VendorId, "XEN ", 8); // vendor id
881 memcpy(id->ProductId, "PV DISK ", 16); // product id
882 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
883 }
884 else
885 {
886 switch (Srb->Cdb[2])
887 {
888 case 0x00:
889 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
890 DataBuffer[1] = 0x00;
891 DataBuffer[2] = 0x00;
892 DataBuffer[3] = 2;
893 DataBuffer[4] = 0x00;
894 DataBuffer[5] = 0x80;
895 break;
896 case 0x80:
897 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
898 DataBuffer[1] = 0x80;
899 DataBuffer[2] = 0x00;
900 DataBuffer[3] = 8;
901 memset(&DataBuffer[4], ' ', 8);
902 break;
903 default:
904 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
905 Srb->SrbStatus = SRB_STATUS_ERROR;
906 break;
907 }
908 }
909 break;
910 case XENVBD_DEVICETYPE_CDROM:
911 if ((Srb->Cdb[1] & 1) == 0)
912 {
913 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
914 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
915 id->RemovableMedia = 1;
916 id->Versions = 3;
917 id->ResponseDataFormat = 0;
918 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
919 id->CommandQueue = 1;
920 memcpy(id->VendorId, "XEN ", 8); // vendor id
921 memcpy(id->ProductId, "PV CDROM ", 16); // product id
922 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
923 }
924 else
925 {
926 switch (Srb->Cdb[2])
927 {
928 case 0x00:
929 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
930 DataBuffer[1] = 0x00;
931 DataBuffer[2] = 0x00;
932 DataBuffer[3] = 2;
933 DataBuffer[4] = 0x00;
934 DataBuffer[5] = 0x80;
935 break;
936 case 0x80:
937 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
938 DataBuffer[1] = 0x80;
939 DataBuffer[2] = 0x00;
940 DataBuffer[3] = 8;
941 DataBuffer[4] = 0x31;
942 DataBuffer[5] = 0x32;
943 DataBuffer[6] = 0x33;
944 DataBuffer[7] = 0x34;
945 DataBuffer[8] = 0x35;
946 DataBuffer[9] = 0x36;
947 DataBuffer[10] = 0x37;
948 DataBuffer[11] = 0x38;
949 break;
950 default:
951 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
952 Srb->SrbStatus = SRB_STATUS_ERROR;
953 break;
954 }
955 }
956 break;
957 default:
958 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
959 Srb->SrbStatus = SRB_STATUS_ERROR;
960 break;
961 }
962 break;
963 case SCSIOP_READ_CAPACITY:
964 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
965 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
966 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
967 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
968 DataBuffer = Srb->DataBuffer;
969 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
970 if ((xvdd->total_sectors - 1) >> 32)
971 {
972 DataBuffer[0] = 0xff;
973 DataBuffer[1] = 0xff;
974 DataBuffer[2] = 0xff;
975 DataBuffer[3] = 0xff;
976 }
977 else
978 {
979 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
980 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
981 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
982 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
983 }
984 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
985 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
986 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
987 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
988 Srb->ScsiStatus = 0;
989 Srb->SrbStatus = SRB_STATUS_SUCCESS;
990 break;
991 case SCSIOP_MODE_SENSE:
992 // 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));
993 XenVbd_FillModePage(xvdd, Srb);
994 break;
995 case SCSIOP_WRITE:
996 case SCSIOP_READ:
997 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
998 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
999 break;
1000 case SCSIOP_VERIFY:
1001 // Should we do more here?
1002 // KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1003 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1004 break;
1005 case SCSIOP_REPORT_LUNS:
1006 // KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1007 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1008 break;
1009 case SCSIOP_REQUEST_SENSE:
1010 // KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1011 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1012 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1013 break;
1014 case SCSIOP_READ_TOC:
1015 DataBuffer = Srb->DataBuffer;
1016 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1017 /*
1018 #define READ_TOC_FORMAT_TOC 0x00
1019 #define READ_TOC_FORMAT_SESSION 0x01
1020 #define READ_TOC_FORMAT_FULL_TOC 0x02
1021 #define READ_TOC_FORMAT_PMA 0x03
1022 #define READ_TOC_FORMAT_ATIP 0x04
1023 */
1024 // KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1025 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1026 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1027 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1028 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1029 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1030 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1031 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1032 switch (cdb->READ_TOC.Format2)
1034 case READ_TOC_FORMAT_TOC:
1035 DataBuffer[0] = 0; // length MSB
1036 DataBuffer[1] = 10; // length LSB
1037 DataBuffer[2] = 1; // First Track
1038 DataBuffer[3] = 1; // Last Track
1039 DataBuffer[4] = 0; // Reserved
1040 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1041 DataBuffer[6] = 1; // last complete track
1042 DataBuffer[7] = 0; // reserved
1043 DataBuffer[8] = 0; // MSB Block
1044 DataBuffer[9] = 0;
1045 DataBuffer[10] = 0;
1046 DataBuffer[11] = 0; // LSB Block
1047 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1048 break;
1049 case READ_TOC_FORMAT_SESSION:
1050 case READ_TOC_FORMAT_FULL_TOC:
1051 case READ_TOC_FORMAT_PMA:
1052 case READ_TOC_FORMAT_ATIP:
1053 Srb->SrbStatus = SRB_STATUS_ERROR;
1054 break;
1056 break;
1057 case SCSIOP_START_STOP_UNIT:
1058 // KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1059 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1060 break;
1061 case SCSIOP_RESERVE_UNIT:
1062 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1063 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1064 break;
1065 case SCSIOP_RELEASE_UNIT:
1066 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1067 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1068 break;
1069 default:
1070 //KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1071 Srb->SrbStatus = SRB_STATUS_ERROR;
1072 break;
1074 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1076 //KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1077 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1079 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1080 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1082 Srb->ScsiStatus = 0x02;
1083 XenVbd_MakeAutoSense(xvdd, Srb);
1084 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1085 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1087 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1089 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1090 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1091 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1092 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1094 break;
1095 case SRB_FUNCTION_IO_CONTROL:
1096 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1097 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1098 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1099 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1100 break;
1101 case SRB_FUNCTION_FLUSH:
1102 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1103 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1104 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1105 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1106 break;
1107 default:
1108 //KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1109 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1110 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1111 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1112 break;
1115 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1116 return TRUE;
1119 static BOOLEAN DDKAPI
1120 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1122 UNREFERENCED_PARAMETER(DeviceExtension);
1123 UNREFERENCED_PARAMETER(PathId);
1125 // KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1127 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1128 ScsiPortNotification(NextRequest, DeviceExtension);
1130 // KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1133 return TRUE;
1136 static BOOLEAN DDKAPI
1137 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1139 UNREFERENCED_PARAMETER(DeviceExtension);
1140 UNREFERENCED_PARAMETER(Context);
1141 UNREFERENCED_PARAMETER(SaveState);
1143 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1144 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1146 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1148 return TRUE;
1151 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1152 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1154 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1155 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1156 //KIRQL OldIrql;
1158 UNREFERENCED_PARAMETER(DeviceExtension);
1160 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1161 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1163 switch (ControlType)
1165 case ScsiQuerySupportedControlTypes:
1166 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1167 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1168 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1169 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1170 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1171 break;
1172 case ScsiStopAdapter:
1173 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1174 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1175 break;
1176 case ScsiRestartAdapter:
1177 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1178 break;
1179 case ScsiSetBootConfig:
1180 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1181 break;
1182 case ScsiSetRunningConfig:
1183 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1184 break;
1185 default:
1186 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1187 break;
1190 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1192 return Status;
1195 VOID
1196 XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
1198 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
1199 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1201 HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
1202 HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
1203 HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
1204 HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
1205 HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
1206 HwInitializationData->HwDmaStarted = NULL;
1207 HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
1208 HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
1210 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));