win-pvdrivers

view xenvbd/scsiport.c @ 309:41c06d83082d

Fixed a crash when running hdtune.
author James Harper <james.harper@bendigoit.com.au>
date Wed Jun 11 21:24:57 2008 +1000 (2008-06-11)
parents b4f7d75fbe24
children 60372bd2582d
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_HwScsiTimer(PVOID DeviceExtension)
94 {
95 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
97 KdPrint((__DRIVER_NAME " aligned requests = %I64d, aligned bytes = %I64d\n", xvdd->aligned_requests, xvdd->aligned_bytes));
98 KdPrint((__DRIVER_NAME " unaligned requests = %I64d, unaligned bytes = %I64d\n", xvdd->unaligned_requests, xvdd->unaligned_bytes));
99 KdPrint((__DRIVER_NAME " interrupts = %I64d\n", xvdd->interrupts));
100 KdPrint((__DRIVER_NAME " no_free_grant_requests = %I64d\n", xvdd->no_free_grant_requests));
101 xvdd->shadow_min_free = xvdd->shadow_free;
102 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, 60 * 1000 * 1000);
103 }
105 static ULONG
106 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
107 {
108 ULONG i;
109 // PACCESS_RANGE AccessRange;
110 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
111 // ULONG status;
112 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
113 PACCESS_RANGE access_range;
114 PUCHAR ptr;
115 USHORT type;
116 PCHAR setting, value;
117 blkif_sring_t *sring;
119 UNREFERENCED_PARAMETER(HwContext);
120 UNREFERENCED_PARAMETER(BusInformation);
121 UNREFERENCED_PARAMETER(ArgumentString);
123 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
124 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
126 *Again = FALSE;
128 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
129 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
131 if (ConfigInfo->NumberOfAccessRanges != 1)
132 {
133 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
134 return SP_RETURN_BAD_CONFIG;
135 }
137 access_range = &((*(ConfigInfo->AccessRanges))[0]);
139 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
140 access_range->RangeStart.LowPart, access_range->RangeLength));
142 ptr = ScsiPortGetDeviceBase(
143 DeviceExtension,
144 ConfigInfo->AdapterInterfaceType,
145 ConfigInfo->SystemIoBusNumber,
146 access_range->RangeStart,
147 access_range->RangeLength,
148 !access_range->RangeInMemory);
149 //ptr = MmMapIoSpace(access_range->RangeStart, access_range->RangeLength, MmCached);
150 if (ptr == NULL)
151 {
152 KdPrint((__DRIVER_NAME " Unable to map range\n"));
153 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
154 return SP_RETURN_BAD_CONFIG;
155 }
157 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
158 sring = NULL;
159 xvdd->event_channel = 0;
160 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value)) != XEN_INIT_TYPE_END)
161 {
162 switch(type)
163 {
164 case XEN_INIT_TYPE_RING: /* frontend ring */
165 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
166 if (strcmp(setting, "ring-ref") == 0)
167 {
168 sring = (blkif_sring_t *)value;
169 FRONT_RING_INIT(&xvdd->ring, sring, PAGE_SIZE);
170 /* this bit is for when we have to take over an existing ring on a bug check */
171 xvdd->ring.req_prod_pvt = sring->req_prod;
172 xvdd->ring.rsp_cons = sring->rsp_prod;
173 }
174 break;
175 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
176 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
177 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
178 if (strcmp(setting, "event-channel") == 0)
179 {
180 xvdd->event_channel = PtrToUlong(value);
181 }
182 break;
183 case XEN_INIT_TYPE_READ_STRING_BACK:
184 case XEN_INIT_TYPE_READ_STRING_FRONT:
185 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
186 if (strcmp(setting, "sectors") == 0)
187 xvdd->total_sectors = atoi(value);
188 else if (strcmp(setting, "sector-size") == 0)
189 xvdd->bytes_per_sector = atoi(value);
190 else if (strcmp(setting, "device-type") == 0)
191 {
192 if (strcmp(value, "disk") == 0)
193 {
194 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
195 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
196 }
197 else if (strcmp(value, "cdrom") == 0)
198 {
199 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
200 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
201 }
202 else
203 {
204 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
205 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
206 }
207 }
208 break;
209 case XEN_INIT_TYPE_VECTORS:
210 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
211 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
212 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
213 {
214 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
215 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
216 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
217 return SP_RETURN_BAD_CONFIG;
218 }
219 else
220 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
221 break;
222 case XEN_INIT_TYPE_GRANT_ENTRIES:
223 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
224 if (PtrToUlong(setting) != GRANT_ENTRIES)
225 {
226 KdPrint((__DRIVER_NAME " grant entries mismatch\n"));
227 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
228 return SP_RETURN_BAD_CONFIG;
229 }
230 else
231 {
232 memcpy(&xvdd->grant_free_list, value, sizeof(ULONG) * PtrToUlong(setting));
233 xvdd->grant_free = GRANT_ENTRIES;
234 }
235 break;
236 default:
237 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
238 break;
239 }
240 }
241 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
242 || sring == NULL
243 || xvdd->event_channel == 0
244 || xvdd->total_sectors == 0
245 || xvdd->bytes_per_sector == 0)
246 {
247 KdPrint((__DRIVER_NAME " Missing settings\n"));
248 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
249 return SP_RETURN_BAD_CONFIG;
250 }
252 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
253 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
255 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
256 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
257 ConfigInfo->ScatterGather = TRUE;
258 ConfigInfo->AlignmentMask = 0;
259 ConfigInfo->NumberOfBuses = 1;
260 ConfigInfo->InitiatorBusId[0] = 1;
261 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
262 ConfigInfo->MaximumNumberOfTargets = 2;
263 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
264 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
265 {
266 ConfigInfo->Master = TRUE;
267 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
268 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
269 }
270 else
271 {
272 ConfigInfo->Master = FALSE;
273 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
274 }
276 xvdd->ring_detect_state = 0;
278 xvdd->shadow_free = 0;
279 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
280 for (i = 0; i < SHADOW_ENTRIES; i++)
281 {
282 xvdd->shadows[i].req.id = i;
283 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
284 }
286 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
288 return SP_RETURN_FOUND;
289 }
291 static BOOLEAN
292 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
293 {
294 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
295 blkif_request_t *req;
296 int i;
297 int notify;
299 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
300 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
302 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
303 req->operation = 0xff;
304 req->nr_segments = 0;
305 for (i = 0; i < req->nr_segments; i++)
306 {
307 req->seg[i].gref = 0xffffffff;
308 req->seg[i].first_sect = 0xff;
309 req->seg[i].last_sect = 0xff;
310 }
311 xvdd->ring.req_prod_pvt++;
313 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
314 req->operation = 0xff;
315 req->nr_segments = 0;
316 for (i = 0; i < req->nr_segments; i++)
317 {
318 req->seg[i].gref = 0xffffffff;
319 req->seg[i].first_sect = 0xff;
320 req->seg[i].last_sect = 0xff;
321 }
322 xvdd->ring.req_prod_pvt++;
324 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
325 if (notify)
326 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
328 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, 60 * 1000 * 1000);
330 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
332 return TRUE;
333 }
335 static VOID
336 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
337 {
338 blkif_other_request_t *other_req;
340 if (!xvdd->use_other)
341 {
342 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
343 }
344 else
345 {
346 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
347 other_req->operation = req->operation;
348 other_req->nr_segments = req->nr_segments;
349 other_req->handle = req->handle;
350 other_req->id = req->id;
351 other_req->sector_number = req->sector_number;
352 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
353 }
354 xvdd->ring.req_prod_pvt++;
355 }
357 static VOID
358 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
359 {
360 ULONG block_count, transfer_length;
361 blkif_shadow_t *shadow;
362 PHYSICAL_ADDRESS physical_address;
363 ULONG pfn;
364 ULONG remaining, offset, length;
365 PUCHAR ptr;
366 int notify;
368 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
370 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
371 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
372 block_count *= xvdd->bytes_per_sector / 512;
373 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
374 {
375 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
376 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
377 if (!srb_offset)
378 {
379 xvdd->unaligned_requests++;
380 xvdd->unaligned_bytes += transfer_length;
381 }
382 }
383 else
384 {
385 ptr = srb->DataBuffer;
386 transfer_length = block_count * 512;
387 xvdd->aligned_requests++;
388 xvdd->aligned_bytes += transfer_length;
389 }
391 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
392 {
393 ASSERT(!xvdd->pending_srb);
394 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
395 xvdd->pending_srb = srb;
396 xvdd->no_free_grant_requests++;
397 return;
398 }
400 shadow = get_shadow_from_freelist(xvdd);
401 ASSERT(shadow);
402 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
403 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
404 shadow->req.handle = 0;
405 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
406 shadow->req.nr_segments = 0;
407 shadow->offset = srb_offset;
408 shadow->length = transfer_length;
409 shadow->srb = srb;
411 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
412 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
413 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
415 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
416 {
417 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
418 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));
419 if (srb->Cdb[0] == SCSIOP_WRITE)
420 {
421 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
422 }
423 }
424 else
425 {
426 ptr = srb->DataBuffer;
427 }
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);
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 shadow->req.nr_segments++;
445 }
447 XenVbd_PutRequest(xvdd, &shadow->req);
449 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
450 if (notify)
451 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
453 if (xvdd->shadow_free && srb_offset == 0)
454 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
456 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
457 }
459 static ULONG
460 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
461 {
462 PCDB cdb;
463 PMODE_PARAMETER_HEADER parameter_header;
464 PMODE_PARAMETER_BLOCK param_block;
465 PMODE_FORMAT_PAGE format_page;
466 UCHAR page_code;
467 ULONG offset;
468 UCHAR buffer[256];
469 BOOLEAN valid_page = FALSE;
471 UNREFERENCED_PARAMETER(xvdd);
473 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
475 cdb = (PCDB)srb->Cdb;
476 page_code = cdb->MODE_SENSE.PageCode;
477 offset = 0;
478 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
479 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
481 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
482 parameter_header->MediumType = 0;
483 parameter_header->DeviceSpecificParameter = 0;
484 parameter_header->BlockDescriptorLength = 0;
485 offset += sizeof(MODE_PARAMETER_HEADER);
487 if (!cdb->MODE_SENSE.Dbd)
488 {
489 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
490 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
491 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
492 {
493 if (xvdd->total_sectors >> 32)
494 {
495 param_block->DensityCode = 0xff;
496 param_block->NumberOfBlocks[0] = 0xff;
497 param_block->NumberOfBlocks[1] = 0xff;
498 param_block->NumberOfBlocks[2] = 0xff;
499 }
500 else
501 {
502 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
503 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
504 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
505 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
506 }
507 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
508 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
509 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
510 }
511 offset += sizeof(MODE_PARAMETER_BLOCK);
512 }
513 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (page_code == MODE_PAGE_FORMAT_DEVICE || page_code == MODE_SENSE_RETURN_ALL))
514 {
515 valid_page = TRUE;
516 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
517 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
518 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
519 /* 256 sectors per track */
520 format_page->SectorsPerTrack[0] = 0x01;
521 format_page->SectorsPerTrack[1] = 0x00;
522 /* xxx bytes per sector */
523 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
524 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
525 format_page->HardSectorFormating = TRUE;
526 format_page->SoftSectorFormating = TRUE;
527 offset += sizeof(MODE_FORMAT_PAGE);
528 }
529 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
530 if (!valid_page && page_code != MODE_SENSE_RETURN_ALL)
531 {
532 srb->SrbStatus = SRB_STATUS_ERROR;
533 }
534 else if(offset < srb->DataTransferLength)
535 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
536 else
537 srb->SrbStatus = SRB_STATUS_SUCCESS;
538 srb->DataTransferLength = min(srb->DataTransferLength, offset);
539 srb->ScsiStatus = 0;
540 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
542 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
544 return TRUE;
545 }
547 static VOID
548 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
549 {
550 PSENSE_DATA sd = srb->SenseInfoBuffer;
552 UNREFERENCED_PARAMETER(xvdd);
554 if (!srb->SenseInfoBuffer)
555 return;
557 sd->ErrorCode = 0x70;
558 sd->Valid = 1;
559 sd->SenseKey = sense_key;
560 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
561 sd->AdditionalSenseCode = additional_sense_code;
562 return;
563 }
565 static VOID
566 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
567 {
568 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
569 return;
570 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
571 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
572 }
574 static BOOLEAN
575 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
576 {
577 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
578 PSCSI_REQUEST_BLOCK srb;
579 RING_IDX i, rp;
580 int j;
581 blkif_response_t *rep;
582 int block_count;
583 int more_to_do = TRUE;
584 blkif_shadow_t *shadow;
585 ULONG offset;
587 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
589 xvdd->interrupts++;
590 while (more_to_do)
591 {
592 rp = xvdd->ring.sring->rsp_prod;
593 KeMemoryBarrier();
594 for (i = xvdd->ring.rsp_cons; i != rp; i++)
595 {
596 rep = XenVbd_GetResponse(xvdd, i);
597 /*
598 * This code is to automatically detect if the backend is using the same
599 * bit width or a different bit width to us. Later versions of Xen do this
600 * via a xenstore value, but not all. That 0x0fffffff (notice
601 * that the msb is not actually set, so we don't have any problems with
602 * sign extending) is to signify the last entry on the right, which is
603 * different under 32 and 64 bits, and that is why we set it up there.
605 * To do the detection, we put two initial entries on the ring, with an op
606 * of 0xff (which is invalid). The first entry is mostly okay, but the
607 * second will be grossly misaligned if the backend bit width is different,
608 * and we detect this and switch frontend structures.
609 */
610 switch (xvdd->ring_detect_state)
611 {
612 case 0:
613 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
614 xvdd->ring_detect_state = 1;
615 break;
616 case 1:
617 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
618 if (rep->operation != 0xff)
619 {
620 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
621 xvdd->use_other = TRUE;
622 }
623 xvdd->ring_detect_state = 2;
624 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
625 break;
626 case 2:
627 shadow = &xvdd->shadows[rep->id];
628 srb = shadow->srb;
629 ASSERT(srb != NULL);
630 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
631 block_count *= xvdd->bytes_per_sector / 512;
632 if (rep->status == BLKIF_RSP_OKAY)
633 srb->SrbStatus = SRB_STATUS_SUCCESS;
634 else
635 {
636 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
637 if (srb->Cdb[0] == SCSIOP_READ)
638 KdPrint((__DRIVER_NAME " Operation = Read\n"));
639 else
640 KdPrint((__DRIVER_NAME " Operation = Write\n"));
641 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
642 srb->SrbStatus = SRB_STATUS_ERROR;
643 srb->ScsiStatus = 0x02;
644 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
645 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
646 XenVbd_MakeAutoSense(xvdd, srb);
647 }
648 for (j = 0; j < shadow->req.nr_segments; j++)
649 {
650 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
651 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
652 }
654 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
655 {
656 if (srb->Cdb[0] == SCSIOP_READ)
657 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
658 offset = shadow->offset + shadow->length;
659 put_shadow_on_freelist(xvdd, shadow);
660 if (offset == block_count * xvdd->bytes_per_sector)
661 {
662 ScsiPortNotification(RequestComplete, xvdd, srb);
663 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
664 }
665 else
666 {
667 XenVbd_PutSrbOnRing(xvdd, srb, offset);
668 }
669 }
670 else
671 {
672 put_shadow_on_freelist(xvdd, shadow);
673 ScsiPortNotification(RequestComplete, xvdd, srb);
674 if (xvdd->pending_srb)
675 {
676 srb = xvdd->pending_srb;
677 xvdd->pending_srb = NULL;
678 XenVbd_PutSrbOnRing(xvdd, srb, 0);
679 }
680 else
681 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
682 }
683 }
684 }
686 xvdd->ring.rsp_cons = i;
687 if (i != xvdd->ring.req_prod_pvt)
688 {
689 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
690 }
691 else
692 {
693 xvdd->ring.sring->rsp_event = i + 1;
694 more_to_do = FALSE;
695 }
696 }
698 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
700 return FALSE; /* we just don't know... */
701 }
703 static BOOLEAN
704 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
705 {
706 PUCHAR DataBuffer;
707 PCDB cdb;
708 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
710 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
712 // If we haven't enumerated all the devices yet then just defer the request
713 if (xvdd->ring_detect_state < 2)
714 {
715 Srb->SrbStatus = SRB_STATUS_BUSY;
716 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
717 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
718 return TRUE;
719 }
721 if (Srb->PathId != 0 || Srb->TargetId != 0)
722 {
723 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
724 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
725 ScsiPortNotification(NextRequest, DeviceExtension);
726 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
727 return TRUE;
728 }
730 switch (Srb->Function)
731 {
732 case SRB_FUNCTION_EXECUTE_SCSI:
733 cdb = (PCDB)Srb->Cdb;
734 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
736 switch(cdb->CDB6GENERIC.OperationCode)
737 {
738 case SCSIOP_TEST_UNIT_READY:
739 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
740 Srb->SrbStatus = SRB_STATUS_SUCCESS;
741 Srb->ScsiStatus = 0;
742 break;
743 case SCSIOP_INQUIRY:
744 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
745 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
746 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
747 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
748 DataBuffer = Srb->DataBuffer;
749 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
750 Srb->SrbStatus = SRB_STATUS_SUCCESS;
751 switch (xvdd->device_type)
752 {
753 case XENVBD_DEVICETYPE_DISK:
754 if ((Srb->Cdb[1] & 1) == 0)
755 {
756 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
757 id->DeviceType = DIRECT_ACCESS_DEVICE;
758 id->Versions = 3;
759 id->ResponseDataFormat = 0;
760 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
761 id->CommandQueue = 1;
762 memcpy(id->VendorId, "XEN ", 8); // vendor id
763 memcpy(id->ProductId, "PV DISK ", 16); // product id
764 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
765 }
766 else
767 {
768 switch (Srb->Cdb[2])
769 {
770 case 0x00:
771 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
772 DataBuffer[1] = 0x00;
773 DataBuffer[2] = 0x00;
774 DataBuffer[3] = 2;
775 DataBuffer[4] = 0x00;
776 DataBuffer[5] = 0x80;
777 break;
778 case 0x80:
779 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
780 DataBuffer[1] = 0x80;
781 DataBuffer[2] = 0x00;
782 DataBuffer[3] = 8;
783 memset(&DataBuffer[4], ' ', 8);
784 break;
785 default:
786 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
787 Srb->SrbStatus = SRB_STATUS_ERROR;
788 break;
789 }
790 }
791 break;
792 case XENVBD_DEVICETYPE_CDROM:
793 if ((Srb->Cdb[1] & 1) == 0)
794 {
795 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
796 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
797 id->RemovableMedia = 1;
798 id->Versions = 3;
799 id->ResponseDataFormat = 0;
800 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
801 id->CommandQueue = 1;
802 memcpy(id->VendorId, "XEN ", 8); // vendor id
803 memcpy(id->ProductId, "PV CDROM ", 16); // product id
804 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
805 }
806 else
807 {
808 switch (Srb->Cdb[2])
809 {
810 case 0x00:
811 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
812 DataBuffer[1] = 0x00;
813 DataBuffer[2] = 0x00;
814 DataBuffer[3] = 2;
815 DataBuffer[4] = 0x00;
816 DataBuffer[5] = 0x80;
817 break;
818 case 0x80:
819 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
820 DataBuffer[1] = 0x80;
821 DataBuffer[2] = 0x00;
822 DataBuffer[3] = 8;
823 DataBuffer[4] = 0x31;
824 DataBuffer[5] = 0x32;
825 DataBuffer[6] = 0x33;
826 DataBuffer[7] = 0x34;
827 DataBuffer[8] = 0x35;
828 DataBuffer[9] = 0x36;
829 DataBuffer[10] = 0x37;
830 DataBuffer[11] = 0x38;
831 break;
832 default:
833 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
834 Srb->SrbStatus = SRB_STATUS_ERROR;
835 break;
836 }
837 }
838 break;
839 default:
840 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
841 Srb->SrbStatus = SRB_STATUS_ERROR;
842 break;
843 }
844 break;
845 case SCSIOP_READ_CAPACITY:
846 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
847 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
848 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
849 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
850 DataBuffer = Srb->DataBuffer;
851 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
852 if ((xvdd->total_sectors - 1) >> 32)
853 {
854 DataBuffer[0] = 0xff;
855 DataBuffer[1] = 0xff;
856 DataBuffer[2] = 0xff;
857 DataBuffer[3] = 0xff;
858 }
859 else
860 {
861 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
862 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
863 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
864 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
865 }
866 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
867 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
868 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
869 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
870 Srb->ScsiStatus = 0;
871 Srb->SrbStatus = SRB_STATUS_SUCCESS;
872 break;
873 case SCSIOP_MODE_SENSE:
874 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));
875 XenVbd_FillModePage(xvdd, Srb);
876 break;
877 case SCSIOP_WRITE:
878 case SCSIOP_READ:
879 //KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
880 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
881 break;
882 case SCSIOP_VERIFY:
883 // Should we do more here?
884 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
885 Srb->SrbStatus = SRB_STATUS_SUCCESS;
886 break;
887 case SCSIOP_REPORT_LUNS:
888 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
889 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
890 break;
891 case SCSIOP_REQUEST_SENSE:
892 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
893 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
894 Srb->SrbStatus = SRB_STATUS_SUCCESS;
895 break;
896 case SCSIOP_READ_TOC:
897 DataBuffer = Srb->DataBuffer;
898 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
899 /*
900 #define READ_TOC_FORMAT_TOC 0x00
901 #define READ_TOC_FORMAT_SESSION 0x01
902 #define READ_TOC_FORMAT_FULL_TOC 0x02
903 #define READ_TOC_FORMAT_PMA 0x03
904 #define READ_TOC_FORMAT_ATIP 0x04
905 */
906 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
907 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
908 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
909 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
910 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
911 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
912 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
913 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
914 switch (cdb->READ_TOC.Format2)
915 {
916 case READ_TOC_FORMAT_TOC:
917 DataBuffer[0] = 0; // length MSB
918 DataBuffer[1] = 10; // length LSB
919 DataBuffer[2] = 1; // First Track
920 DataBuffer[3] = 1; // Last Track
921 DataBuffer[4] = 0; // Reserved
922 DataBuffer[5] = 0x14; // current position data + uninterrupted data
923 DataBuffer[6] = 1; // last complete track
924 DataBuffer[7] = 0; // reserved
925 DataBuffer[8] = 0; // MSB Block
926 DataBuffer[9] = 0;
927 DataBuffer[10] = 0;
928 DataBuffer[11] = 0; // LSB Block
929 Srb->SrbStatus = SRB_STATUS_SUCCESS;
930 break;
931 case READ_TOC_FORMAT_SESSION:
932 case READ_TOC_FORMAT_FULL_TOC:
933 case READ_TOC_FORMAT_PMA:
934 case READ_TOC_FORMAT_ATIP:
935 Srb->SrbStatus = SRB_STATUS_ERROR;
936 break;
937 }
938 break;
939 case SCSIOP_START_STOP_UNIT:
940 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
941 Srb->SrbStatus = SRB_STATUS_SUCCESS;
942 break;
943 case SCSIOP_RESERVE_UNIT:
944 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
945 Srb->SrbStatus = SRB_STATUS_SUCCESS;
946 break;
947 case SCSIOP_RELEASE_UNIT:
948 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
949 Srb->SrbStatus = SRB_STATUS_SUCCESS;
950 break;
951 default:
952 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
953 Srb->SrbStatus = SRB_STATUS_ERROR;
954 break;
955 }
956 if (Srb->SrbStatus == SRB_STATUS_ERROR)
957 {
958 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
959 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
960 {
961 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
962 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
963 }
964 Srb->ScsiStatus = 0x02;
965 XenVbd_MakeAutoSense(xvdd, Srb);
966 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
967 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
968 }
969 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
970 {
971 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
972 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
973 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
974 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
975 }
976 break;
977 case SRB_FUNCTION_IO_CONTROL:
978 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
979 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
980 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
981 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
982 break;
983 case SRB_FUNCTION_FLUSH:
984 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
985 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
986 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
987 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
988 break;
989 default:
990 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
991 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
992 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
993 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
994 break;
995 }
997 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
998 return TRUE;
999 }
1001 static BOOLEAN
1002 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1004 UNREFERENCED_PARAMETER(DeviceExtension);
1005 UNREFERENCED_PARAMETER(PathId);
1007 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1008 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1010 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1012 return TRUE;
1015 static BOOLEAN
1016 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1018 UNREFERENCED_PARAMETER(DeviceExtension);
1019 UNREFERENCED_PARAMETER(Context);
1020 UNREFERENCED_PARAMETER(SaveState);
1022 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1023 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1025 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1027 return TRUE;
1030 static SCSI_ADAPTER_CONTROL_STATUS
1031 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1033 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1034 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1035 //KIRQL OldIrql;
1037 UNREFERENCED_PARAMETER(DeviceExtension);
1039 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1040 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1042 switch (ControlType)
1044 case ScsiQuerySupportedControlTypes:
1045 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1046 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1047 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1048 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1049 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1050 break;
1051 case ScsiStopAdapter:
1052 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1053 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1054 break;
1055 case ScsiRestartAdapter:
1056 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1057 break;
1058 case ScsiSetBootConfig:
1059 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1060 break;
1061 case ScsiSetRunningConfig:
1062 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1063 break;
1064 default:
1065 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1066 break;
1069 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1071 return Status;
1074 VOID
1075 XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
1077 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
1078 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1080 HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
1081 HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
1082 HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
1083 HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
1084 HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
1085 HwInitializationData->HwDmaStarted = NULL;
1086 HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
1087 HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
1089 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));