win-pvdrivers

view xenvbd/scsiport.c @ 363:097ab7d19ea2

Merge bug fixer from WDF to WDM.
author Wayne Gong <wayne.gong@oracle.com>
date Mon Jul 07 14:03:39 2008 +0800 (2008-07-07)
parents f7a5c1889c36
children 9ac05494063f
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, &setting, &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 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
244 xvdd->shadow_free = 0;
245 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
246 for (i = 0; i < SHADOW_ENTRIES; i++)
247 {
248 xvdd->shadows[i].req.id = i;
249 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
250 }
252 return SP_RETURN_FOUND;
253 }
255 static VOID
256 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
257 {
258 ULONG block_count, transfer_length;
259 blkif_shadow_t *shadow;
260 PHYSICAL_ADDRESS physical_address;
261 ULONG pfn;
262 ULONG remaining, offset, length;
263 PUCHAR ptr;
264 int notify;
266 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
268 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
269 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
270 block_count *= xvdd->bytes_per_sector / 512;
271 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
272 {
273 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
274 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
275 if (!srb_offset)
276 {
277 xvdd->unaligned_requests++;
278 xvdd->unaligned_bytes += transfer_length;
279 }
280 }
281 else
282 {
283 ptr = srb->DataBuffer;
284 transfer_length = block_count * 512;
285 xvdd->aligned_requests++;
286 xvdd->aligned_bytes += transfer_length;
287 }
289 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
290 {
291 ASSERT(!xvdd->pending_srb);
292 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
293 xvdd->pending_srb = srb;
294 xvdd->no_free_grant_requests++;
295 return;
296 }
298 shadow = get_shadow_from_freelist(xvdd);
299 ASSERT(shadow);
300 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
301 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
302 shadow->req.handle = 0;
303 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
304 shadow->req.nr_segments = 0;
305 shadow->offset = srb_offset;
306 shadow->length = transfer_length;
307 shadow->srb = srb;
309 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
310 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
311 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
313 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
314 {
315 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
316 //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));
317 if (srb->Cdb[0] == SCSIOP_WRITE)
318 {
319 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
320 }
321 }
322 else
323 {
324 ptr = srb->DataBuffer;
325 }
326 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
327 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
328 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
330 remaining = shadow->length;
331 while (remaining > 0)
332 {
333 physical_address = MmGetPhysicalAddress(ptr);
334 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
335 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
336 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref);
337 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
338 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
339 ASSERT((offset & 511) == 0);
340 length = min(PAGE_SIZE - offset, remaining);
341 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
342 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
343 remaining -= length;
344 ptr += length;
345 //KdPrint((__DRIVER_NAME " seg[%d].gref = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].gref));
346 //KdPrint((__DRIVER_NAME " seg[%d].first_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].first_sect));
347 //KdPrint((__DRIVER_NAME " seg[%d].last_sect = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].last_sect));
348 shadow->req.nr_segments++;
349 }
350 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
352 XenVbd_PutRequest(xvdd, &shadow->req);
354 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
355 if (notify)
356 {
357 //KdPrint((__DRIVER_NAME " Notifying\n"));
358 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
359 }
361 if (xvdd->shadow_free && srb_offset == 0)
362 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
364 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
365 }
367 #define RESUME_CHECK_TIMER_INTERVAL (100 * 1000)
369 static VOID
370 XenVbd_HwScsiTimer(PVOID DeviceExtension)
371 {
372 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
373 ULONG i;
374 blkif_shadow_t shadows[SHADOW_ENTRIES];
375 ULONG shadow_entries;
376 blkif_shadow_t *shadow;
378 if (xvdd->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
379 {
380 KdPrint((__DRIVER_NAME " found device in resume state\n"));
381 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
382 // re-submit srb's
384 shadow_entries = 0;
385 for (i = 0; i < SHADOW_ENTRIES; i++)
386 {
387 shadow = &xvdd->shadows[i];
388 if (shadow->srb)
389 {
390 shadows[shadow_entries++] = xvdd->shadows[i];
391 shadow->srb = NULL;
392 }
393 }
395 XenVbd_InitFromConfig(xvdd);
397 for (i = 0; i < shadow_entries; i++)
398 {
399 shadow = &shadows[i];
400 XenVbd_PutSrbOnRing(xvdd, shadow->srb, shadow->offset);
401 }
403 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
405 if (i == 0)
406 {
407 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
408 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
409 }
410 }
412 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
413 }
415 static ULONG
416 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
417 {
418 // PACCESS_RANGE AccessRange;
419 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
420 ULONG status;
421 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
422 PACCESS_RANGE access_range;
424 UNREFERENCED_PARAMETER(HwContext);
425 UNREFERENCED_PARAMETER(BusInformation);
426 UNREFERENCED_PARAMETER(ArgumentString);
428 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
429 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
431 *Again = FALSE;
433 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
434 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
436 if (ConfigInfo->NumberOfAccessRanges != 1)
437 {
438 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
439 return SP_RETURN_BAD_CONFIG;
440 }
442 access_range = &((*(ConfigInfo->AccessRanges))[0]);
444 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
445 access_range->RangeStart.LowPart, access_range->RangeLength));
447 xvdd->device_base = ScsiPortGetDeviceBase(
448 DeviceExtension,
449 ConfigInfo->AdapterInterfaceType,
450 ConfigInfo->SystemIoBusNumber,
451 access_range->RangeStart,
452 access_range->RangeLength,
453 !access_range->RangeInMemory);
454 if (xvdd->device_base == NULL)
455 {
456 KdPrint((__DRIVER_NAME " Unable to map range\n"));
457 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
458 return SP_RETURN_BAD_CONFIG;
459 }
461 status = XenVbd_InitFromConfig(xvdd);
462 if (status != SP_RETURN_FOUND)
463 return status;
465 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
466 ConfigInfo->NumberOfPhysicalBreaks = 0; //BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
467 ConfigInfo->ScatterGather = TRUE;
468 ConfigInfo->AlignmentMask = 0;
469 ConfigInfo->NumberOfBuses = 1;
470 ConfigInfo->InitiatorBusId[0] = 1;
471 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
472 ConfigInfo->MaximumNumberOfTargets = 2;
473 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
474 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
475 {
476 ConfigInfo->Master = TRUE;
477 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
478 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
479 }
480 else
481 {
482 ConfigInfo->Master = FALSE;
483 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
484 }
486 xvdd->ring_detect_state = 0;
488 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
490 return SP_RETURN_FOUND;
491 }
493 static BOOLEAN
494 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
495 {
496 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
497 blkif_request_t *req;
498 int i;
499 int notify;
501 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
502 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
504 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
505 req->operation = 0xff;
506 req->nr_segments = 0;
507 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
508 {
509 req->seg[i].gref = 0; //0xffffffff;
510 req->seg[i].first_sect = 0; //0xff;
511 req->seg[i].last_sect = 0; //0xff;
512 }
513 xvdd->ring.req_prod_pvt++;
515 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
516 req->operation = 0xff;
517 req->nr_segments = 0;
518 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
519 {
520 req->seg[i].gref = 0; //0xffffffff;
521 req->seg[i].first_sect = 0; //0xff;
522 req->seg[i].last_sect = 0; //0xff;
523 }
524 xvdd->ring.req_prod_pvt++;
526 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
527 if (notify)
528 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
530 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, RESUME_CHECK_TIMER_INTERVAL);
532 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
534 return TRUE;
535 }
537 static ULONG
538 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
539 {
540 PCDB cdb;
541 PMODE_PARAMETER_HEADER parameter_header;
542 PMODE_PARAMETER_BLOCK param_block;
543 PMODE_FORMAT_PAGE format_page;
544 UCHAR page_code;
545 ULONG offset;
546 UCHAR buffer[256];
547 BOOLEAN valid_page = FALSE;
549 UNREFERENCED_PARAMETER(xvdd);
551 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
553 cdb = (PCDB)srb->Cdb;
554 page_code = cdb->MODE_SENSE.PageCode;
555 offset = 0;
556 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
557 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
559 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
560 parameter_header->MediumType = 0;
561 parameter_header->DeviceSpecificParameter = 0;
562 parameter_header->BlockDescriptorLength = 0;
563 offset += sizeof(MODE_PARAMETER_HEADER);
565 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
566 {
567 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
568 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
569 }
571 if (!cdb->MODE_SENSE.Dbd)
572 {
573 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
574 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
575 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
576 {
577 if (xvdd->total_sectors >> 32)
578 {
579 param_block->DensityCode = 0xff;
580 param_block->NumberOfBlocks[0] = 0xff;
581 param_block->NumberOfBlocks[1] = 0xff;
582 param_block->NumberOfBlocks[2] = 0xff;
583 }
584 else
585 {
586 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
587 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
588 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
589 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
590 }
591 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
592 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
593 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
594 }
595 offset += sizeof(MODE_PARAMETER_BLOCK);
596 }
597 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (page_code == MODE_PAGE_FORMAT_DEVICE || page_code == MODE_SENSE_RETURN_ALL))
598 {
599 valid_page = TRUE;
600 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
601 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
602 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
603 /* 256 sectors per track */
604 format_page->SectorsPerTrack[0] = 0x01;
605 format_page->SectorsPerTrack[1] = 0x00;
606 /* xxx bytes per sector */
607 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
608 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
609 format_page->HardSectorFormating = TRUE;
610 format_page->SoftSectorFormating = TRUE;
611 offset += sizeof(MODE_FORMAT_PAGE);
612 }
613 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
614 if (!valid_page && page_code != MODE_SENSE_RETURN_ALL)
615 {
616 srb->SrbStatus = SRB_STATUS_ERROR;
617 }
618 else if(offset < srb->DataTransferLength)
619 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
620 else
621 srb->SrbStatus = SRB_STATUS_SUCCESS;
622 srb->DataTransferLength = min(srb->DataTransferLength, offset);
623 srb->ScsiStatus = 0;
624 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
626 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
628 return TRUE;
629 }
631 static VOID
632 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
633 {
634 PSENSE_DATA sd = srb->SenseInfoBuffer;
636 UNREFERENCED_PARAMETER(xvdd);
638 if (!srb->SenseInfoBuffer)
639 return;
641 sd->ErrorCode = 0x70;
642 sd->Valid = 1;
643 sd->SenseKey = sense_key;
644 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
645 sd->AdditionalSenseCode = additional_sense_code;
646 return;
647 }
649 static VOID
650 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
651 {
652 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
653 return;
654 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
655 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
656 }
658 static BOOLEAN
659 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
660 {
661 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
662 PSCSI_REQUEST_BLOCK srb;
663 RING_IDX i, rp;
664 int j;
665 blkif_response_t *rep;
666 int block_count;
667 int more_to_do = TRUE;
668 blkif_shadow_t *shadow;
669 ULONG offset;
671 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
673 xvdd->interrupts++;
674 while (more_to_do)
675 {
676 rp = xvdd->ring.sring->rsp_prod;
677 KeMemoryBarrier();
678 for (i = xvdd->ring.rsp_cons; i != rp; i++)
679 {
680 rep = XenVbd_GetResponse(xvdd, i);
681 /*
682 * This code is to automatically detect if the backend is using the same
683 * bit width or a different bit width to us. Later versions of Xen do this
684 * via a xenstore value, but not all. That 0x0fffffff (notice
685 * that the msb is not actually set, so we don't have any problems with
686 * sign extending) is to signify the last entry on the right, which is
687 * different under 32 and 64 bits, and that is why we set it up there.
689 * To do the detection, we put two initial entries on the ring, with an op
690 * of 0xff (which is invalid). The first entry is mostly okay, but the
691 * second will be grossly misaligned if the backend bit width is different,
692 * and we detect this and switch frontend structures.
693 */
694 switch (xvdd->ring_detect_state)
695 {
696 case 0:
697 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
698 xvdd->ring_detect_state = 1;
699 break;
700 case 1:
701 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
702 if (rep->operation != 0xff)
703 {
704 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
705 xvdd->use_other = TRUE;
706 }
707 xvdd->ring_detect_state = 2;
708 ScsiPortNotification(NextRequest, DeviceExtension);
709 break;
710 case 2:
711 //KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
712 shadow = &xvdd->shadows[rep->id];
713 srb = shadow->srb;
714 ASSERT(srb != NULL);
715 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
716 block_count *= xvdd->bytes_per_sector / 512;
717 if (rep->status == BLKIF_RSP_OKAY)
718 srb->SrbStatus = SRB_STATUS_SUCCESS;
719 else
720 {
721 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
722 if (srb->Cdb[0] == SCSIOP_READ)
723 KdPrint((__DRIVER_NAME " Operation = Read\n"));
724 else
725 KdPrint((__DRIVER_NAME " Operation = Write\n"));
726 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
727 srb->SrbStatus = SRB_STATUS_ERROR;
728 srb->ScsiStatus = 0x02;
729 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
730 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
731 XenVbd_MakeAutoSense(xvdd, srb);
732 }
733 for (j = 0; j < shadow->req.nr_segments; j++)
734 {
735 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
736 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
737 }
739 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
740 {
741 if (srb->Cdb[0] == SCSIOP_READ)
742 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
743 offset = shadow->offset + shadow->length;
744 put_shadow_on_freelist(xvdd, shadow);
745 if (offset == block_count * xvdd->bytes_per_sector)
746 {
747 ScsiPortNotification(RequestComplete, xvdd, srb);
748 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
749 }
750 else
751 {
752 XenVbd_PutSrbOnRing(xvdd, srb, offset);
753 }
754 }
755 else
756 {
757 put_shadow_on_freelist(xvdd, shadow);
758 ScsiPortNotification(RequestComplete, xvdd, srb);
759 if (xvdd->pending_srb)
760 {
761 srb = xvdd->pending_srb;
762 xvdd->pending_srb = NULL;
763 XenVbd_PutSrbOnRing(xvdd, srb, 0);
764 }
765 else
766 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
767 }
768 }
769 }
771 xvdd->ring.rsp_cons = i;
772 if (i != xvdd->ring.req_prod_pvt)
773 {
774 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
775 }
776 else
777 {
778 xvdd->ring.sring->rsp_event = i + 1;
779 more_to_do = FALSE;
780 }
781 }
783 //KdPrint((__DRIVER_NAME " ring.sring->rsp_prod = %d\n", xvdd->ring.sring->rsp_prod));
784 //KdPrint((__DRIVER_NAME " ring.sring->rsp_event = %d\n", xvdd->ring.sring->rsp_event));
785 //KdPrint((__DRIVER_NAME " ring.rsp_cons = %d\n", xvdd->ring.rsp_cons));
786 //KdPrint((__DRIVER_NAME " ring.req_prod_pvt = %d\n", xvdd->ring.req_prod_pvt));
788 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
790 return FALSE; /* we just don't know... */
791 }
793 static BOOLEAN
794 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
795 {
796 PUCHAR DataBuffer;
797 PCDB cdb;
798 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
800 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
802 // If we haven't enumerated all the devices yet then just defer the request
803 if (xvdd->ring_detect_state < 2)
804 {
805 Srb->SrbStatus = SRB_STATUS_BUSY;
806 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
807 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
808 return TRUE;
809 }
811 if (xvdd->device_state->resume_state != RESUME_STATE_RUNNING)
812 {
813 Srb->SrbStatus = SRB_STATUS_BUSY;
814 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
815 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Resuming)\n"));
816 return TRUE;
817 }
819 if (Srb->PathId != 0 || Srb->TargetId != 0)
820 {
821 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
822 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
823 ScsiPortNotification(NextRequest, DeviceExtension);
824 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
825 return TRUE;
826 }
828 switch (Srb->Function)
829 {
830 case SRB_FUNCTION_EXECUTE_SCSI:
831 cdb = (PCDB)Srb->Cdb;
832 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
834 switch(cdb->CDB6GENERIC.OperationCode)
835 {
836 case SCSIOP_TEST_UNIT_READY:
837 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
838 Srb->SrbStatus = SRB_STATUS_SUCCESS;
839 Srb->ScsiStatus = 0;
840 break;
841 case SCSIOP_INQUIRY:
842 // KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
843 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
844 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
845 // KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
846 DataBuffer = Srb->DataBuffer;
847 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
848 Srb->SrbStatus = SRB_STATUS_SUCCESS;
849 switch (xvdd->device_type)
850 {
851 case XENVBD_DEVICETYPE_DISK:
852 if ((Srb->Cdb[1] & 1) == 0)
853 {
854 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
855 id->DeviceType = DIRECT_ACCESS_DEVICE;
856 id->Versions = 3;
857 id->ResponseDataFormat = 0;
858 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
859 id->CommandQueue = 1;
860 memcpy(id->VendorId, "XEN ", 8); // vendor id
861 memcpy(id->ProductId, "PV DISK ", 16); // product id
862 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
863 }
864 else
865 {
866 switch (Srb->Cdb[2])
867 {
868 case 0x00:
869 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
870 DataBuffer[1] = 0x00;
871 DataBuffer[2] = 0x00;
872 DataBuffer[3] = 2;
873 DataBuffer[4] = 0x00;
874 DataBuffer[5] = 0x80;
875 break;
876 case 0x80:
877 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
878 DataBuffer[1] = 0x80;
879 DataBuffer[2] = 0x00;
880 DataBuffer[3] = 8;
881 memset(&DataBuffer[4], ' ', 8);
882 break;
883 default:
884 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
885 Srb->SrbStatus = SRB_STATUS_ERROR;
886 break;
887 }
888 }
889 break;
890 case XENVBD_DEVICETYPE_CDROM:
891 if ((Srb->Cdb[1] & 1) == 0)
892 {
893 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
894 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
895 id->RemovableMedia = 1;
896 id->Versions = 3;
897 id->ResponseDataFormat = 0;
898 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
899 id->CommandQueue = 1;
900 memcpy(id->VendorId, "XEN ", 8); // vendor id
901 memcpy(id->ProductId, "PV CDROM ", 16); // product id
902 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
903 }
904 else
905 {
906 switch (Srb->Cdb[2])
907 {
908 case 0x00:
909 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
910 DataBuffer[1] = 0x00;
911 DataBuffer[2] = 0x00;
912 DataBuffer[3] = 2;
913 DataBuffer[4] = 0x00;
914 DataBuffer[5] = 0x80;
915 break;
916 case 0x80:
917 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
918 DataBuffer[1] = 0x80;
919 DataBuffer[2] = 0x00;
920 DataBuffer[3] = 8;
921 DataBuffer[4] = 0x31;
922 DataBuffer[5] = 0x32;
923 DataBuffer[6] = 0x33;
924 DataBuffer[7] = 0x34;
925 DataBuffer[8] = 0x35;
926 DataBuffer[9] = 0x36;
927 DataBuffer[10] = 0x37;
928 DataBuffer[11] = 0x38;
929 break;
930 default:
931 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
932 Srb->SrbStatus = SRB_STATUS_ERROR;
933 break;
934 }
935 }
936 break;
937 default:
938 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
939 Srb->SrbStatus = SRB_STATUS_ERROR;
940 break;
941 }
942 break;
943 case SCSIOP_READ_CAPACITY:
944 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
945 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
946 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
947 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
948 DataBuffer = Srb->DataBuffer;
949 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
950 if ((xvdd->total_sectors - 1) >> 32)
951 {
952 DataBuffer[0] = 0xff;
953 DataBuffer[1] = 0xff;
954 DataBuffer[2] = 0xff;
955 DataBuffer[3] = 0xff;
956 }
957 else
958 {
959 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
960 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
961 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
962 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
963 }
964 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
965 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
966 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
967 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
968 Srb->ScsiStatus = 0;
969 Srb->SrbStatus = SRB_STATUS_SUCCESS;
970 break;
971 case SCSIOP_MODE_SENSE:
972 // 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));
973 XenVbd_FillModePage(xvdd, Srb);
974 break;
975 case SCSIOP_WRITE:
976 case SCSIOP_READ:
977 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
978 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
979 break;
980 case SCSIOP_VERIFY:
981 // Should we do more here?
982 // KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
983 Srb->SrbStatus = SRB_STATUS_SUCCESS;
984 break;
985 case SCSIOP_REPORT_LUNS:
986 // KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
987 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
988 break;
989 case SCSIOP_REQUEST_SENSE:
990 // KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
991 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
992 Srb->SrbStatus = SRB_STATUS_SUCCESS;
993 break;
994 case SCSIOP_READ_TOC:
995 DataBuffer = Srb->DataBuffer;
996 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
997 /*
998 #define READ_TOC_FORMAT_TOC 0x00
999 #define READ_TOC_FORMAT_SESSION 0x01
1000 #define READ_TOC_FORMAT_FULL_TOC 0x02
1001 #define READ_TOC_FORMAT_PMA 0x03
1002 #define READ_TOC_FORMAT_ATIP 0x04
1003 */
1004 // KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1005 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1006 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1007 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1008 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1009 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1010 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1011 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1012 switch (cdb->READ_TOC.Format2)
1014 case READ_TOC_FORMAT_TOC:
1015 DataBuffer[0] = 0; // length MSB
1016 DataBuffer[1] = 10; // length LSB
1017 DataBuffer[2] = 1; // First Track
1018 DataBuffer[3] = 1; // Last Track
1019 DataBuffer[4] = 0; // Reserved
1020 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1021 DataBuffer[6] = 1; // last complete track
1022 DataBuffer[7] = 0; // reserved
1023 DataBuffer[8] = 0; // MSB Block
1024 DataBuffer[9] = 0;
1025 DataBuffer[10] = 0;
1026 DataBuffer[11] = 0; // LSB Block
1027 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1028 break;
1029 case READ_TOC_FORMAT_SESSION:
1030 case READ_TOC_FORMAT_FULL_TOC:
1031 case READ_TOC_FORMAT_PMA:
1032 case READ_TOC_FORMAT_ATIP:
1033 Srb->SrbStatus = SRB_STATUS_ERROR;
1034 break;
1036 break;
1037 case SCSIOP_START_STOP_UNIT:
1038 // KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1039 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1040 break;
1041 case SCSIOP_RESERVE_UNIT:
1042 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1043 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1044 break;
1045 case SCSIOP_RELEASE_UNIT:
1046 // KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1047 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1048 break;
1049 default:
1050 //KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1051 Srb->SrbStatus = SRB_STATUS_ERROR;
1052 break;
1054 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1056 //KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1057 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1059 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1060 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1062 Srb->ScsiStatus = 0x02;
1063 XenVbd_MakeAutoSense(xvdd, Srb);
1064 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1065 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1067 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1069 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1070 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1071 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1072 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1074 break;
1075 case SRB_FUNCTION_IO_CONTROL:
1076 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1077 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1078 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1079 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1080 break;
1081 case SRB_FUNCTION_FLUSH:
1082 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1083 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1084 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1085 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1086 break;
1087 default:
1088 //KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1089 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1090 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1091 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1092 break;
1095 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1096 return TRUE;
1099 static BOOLEAN
1100 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1102 UNREFERENCED_PARAMETER(DeviceExtension);
1103 UNREFERENCED_PARAMETER(PathId);
1105 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1107 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1108 ScsiPortNotification(NextRequest, DeviceExtension);
1110 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1113 return TRUE;
1116 static BOOLEAN
1117 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1119 UNREFERENCED_PARAMETER(DeviceExtension);
1120 UNREFERENCED_PARAMETER(Context);
1121 UNREFERENCED_PARAMETER(SaveState);
1123 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1124 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1126 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1128 return TRUE;
1131 static SCSI_ADAPTER_CONTROL_STATUS
1132 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1134 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1135 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1136 //KIRQL OldIrql;
1138 UNREFERENCED_PARAMETER(DeviceExtension);
1140 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1141 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1143 switch (ControlType)
1145 case ScsiQuerySupportedControlTypes:
1146 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1147 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1148 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1149 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1150 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1151 break;
1152 case ScsiStopAdapter:
1153 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1154 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1155 break;
1156 case ScsiRestartAdapter:
1157 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1158 break;
1159 case ScsiSetBootConfig:
1160 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1161 break;
1162 case ScsiSetRunningConfig:
1163 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1164 break;
1165 default:
1166 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1167 break;
1170 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1172 return Status;
1175 VOID
1176 XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
1178 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
1179 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1181 HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
1182 HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
1183 HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
1184 HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
1185 HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
1186 HwInitializationData->HwDmaStarted = NULL;
1187 HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
1188 HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
1190 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));