win-pvdrivers

view xenvbd/scsiport.c @ 310:60372bd2582d

First cut of putting xenbus config details in the .inf file - xenvbd may yet pass WHQL
author James Harper <james.harper@bendigoit.com.au>
date Fri Jun 13 14:16:50 2008 +1000 (2008-06-13)
parents 41c06d83082d
children 0488ef11be09
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 xvdd->grant_entries = (USHORT)PtrToUlong(setting);
225 memcpy(&xvdd->grant_free_list, value, sizeof(grant_ref_t) * xvdd->grant_entries);
226 xvdd->grant_free = xvdd->grant_entries;
227 break;
228 default:
229 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
230 break;
231 }
232 }
233 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
234 || sring == NULL
235 || xvdd->event_channel == 0
236 || xvdd->total_sectors == 0
237 || xvdd->bytes_per_sector == 0)
238 {
239 KdPrint((__DRIVER_NAME " Missing settings\n"));
240 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
241 return SP_RETURN_BAD_CONFIG;
242 }
244 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
245 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
247 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
248 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
249 ConfigInfo->ScatterGather = TRUE;
250 ConfigInfo->AlignmentMask = 0;
251 ConfigInfo->NumberOfBuses = 1;
252 ConfigInfo->InitiatorBusId[0] = 1;
253 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
254 ConfigInfo->MaximumNumberOfTargets = 2;
255 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
256 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
257 {
258 ConfigInfo->Master = TRUE;
259 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
260 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
261 }
262 else
263 {
264 ConfigInfo->Master = FALSE;
265 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
266 }
268 xvdd->ring_detect_state = 0;
270 xvdd->shadow_free = 0;
271 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
272 for (i = 0; i < SHADOW_ENTRIES; i++)
273 {
274 xvdd->shadows[i].req.id = i;
275 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
276 }
278 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
280 return SP_RETURN_FOUND;
281 }
283 static BOOLEAN
284 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
285 {
286 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
287 blkif_request_t *req;
288 int i;
289 int notify;
291 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
292 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
294 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
295 req->operation = 0xff;
296 req->nr_segments = 0;
297 for (i = 0; i < req->nr_segments; i++)
298 {
299 req->seg[i].gref = 0xffffffff;
300 req->seg[i].first_sect = 0xff;
301 req->seg[i].last_sect = 0xff;
302 }
303 xvdd->ring.req_prod_pvt++;
305 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
306 req->operation = 0xff;
307 req->nr_segments = 0;
308 for (i = 0; i < req->nr_segments; i++)
309 {
310 req->seg[i].gref = 0xffffffff;
311 req->seg[i].first_sect = 0xff;
312 req->seg[i].last_sect = 0xff;
313 }
314 xvdd->ring.req_prod_pvt++;
316 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
317 if (notify)
318 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
320 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_HwScsiTimer, 60 * 1000 * 1000);
322 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
324 return TRUE;
325 }
327 static VOID
328 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
329 {
330 blkif_other_request_t *other_req;
332 if (!xvdd->use_other)
333 {
334 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
335 }
336 else
337 {
338 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
339 other_req->operation = req->operation;
340 other_req->nr_segments = req->nr_segments;
341 other_req->handle = req->handle;
342 other_req->id = req->id;
343 other_req->sector_number = req->sector_number;
344 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
345 }
346 xvdd->ring.req_prod_pvt++;
347 }
349 static VOID
350 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
351 {
352 ULONG block_count, transfer_length;
353 blkif_shadow_t *shadow;
354 PHYSICAL_ADDRESS physical_address;
355 ULONG pfn;
356 ULONG remaining, offset, length;
357 PUCHAR ptr;
358 int notify;
360 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
362 //ASSERT(!(srb_offset == 0 && xvdd->split_request_in_progress));
363 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
364 block_count *= xvdd->bytes_per_sector / 512;
365 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
366 {
367 ptr = GET_PAGE_ALIGNED(srb->SrbExtension);
368 transfer_length = min(block_count * 512 - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
369 if (!srb_offset)
370 {
371 xvdd->unaligned_requests++;
372 xvdd->unaligned_bytes += transfer_length;
373 }
374 }
375 else
376 {
377 ptr = srb->DataBuffer;
378 transfer_length = block_count * 512;
379 xvdd->aligned_requests++;
380 xvdd->aligned_bytes += transfer_length;
381 }
383 if (xvdd->grant_free <= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ptr, transfer_length))
384 {
385 ASSERT(!xvdd->pending_srb);
386 //KdPrint((__DRIVER_NAME " No enough grants - deferring\n"));
387 xvdd->pending_srb = srb;
388 xvdd->no_free_grant_requests++;
389 return;
390 }
392 shadow = get_shadow_from_freelist(xvdd);
393 ASSERT(shadow);
394 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
395 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
396 shadow->req.handle = 0;
397 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
398 shadow->req.nr_segments = 0;
399 shadow->offset = srb_offset;
400 shadow->length = transfer_length;
401 shadow->srb = srb;
403 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
404 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
405 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
407 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
408 {
409 shadow->req.sector_number += srb_offset / 512; //xvdd->bytes_per_sector;
410 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));
411 if (srb->Cdb[0] == SCSIOP_WRITE)
412 {
413 memcpy(ptr, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
414 }
415 }
416 else
417 {
418 ptr = srb->DataBuffer;
419 }
421 remaining = shadow->length;
422 while (remaining > 0)
423 {
424 physical_address = MmGetPhysicalAddress(ptr);
425 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
426 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xvdd);
427 ASSERT(shadow->req.seg[shadow->req.nr_segments].gref);
428 xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
429 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
430 ASSERT((offset & 511) == 0);
431 length = min(PAGE_SIZE - offset, remaining);
432 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
433 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
434 remaining -= length;
435 ptr += length;
436 shadow->req.nr_segments++;
437 }
439 XenVbd_PutRequest(xvdd, &shadow->req);
441 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
442 if (notify)
443 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
445 if (xvdd->shadow_free && srb_offset == 0)
446 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
448 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
449 }
451 static ULONG
452 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
453 {
454 PCDB cdb;
455 PMODE_PARAMETER_HEADER parameter_header;
456 PMODE_PARAMETER_BLOCK param_block;
457 PMODE_FORMAT_PAGE format_page;
458 UCHAR page_code;
459 ULONG offset;
460 UCHAR buffer[256];
461 BOOLEAN valid_page = FALSE;
463 UNREFERENCED_PARAMETER(xvdd);
465 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
467 cdb = (PCDB)srb->Cdb;
468 page_code = cdb->MODE_SENSE.PageCode;
469 offset = 0;
470 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
471 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
473 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
474 parameter_header->MediumType = 0;
475 parameter_header->DeviceSpecificParameter = 0;
476 parameter_header->BlockDescriptorLength = 0;
477 offset += sizeof(MODE_PARAMETER_HEADER);
479 if (!cdb->MODE_SENSE.Dbd)
480 {
481 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
482 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
483 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
484 {
485 if (xvdd->total_sectors >> 32)
486 {
487 param_block->DensityCode = 0xff;
488 param_block->NumberOfBlocks[0] = 0xff;
489 param_block->NumberOfBlocks[1] = 0xff;
490 param_block->NumberOfBlocks[2] = 0xff;
491 }
492 else
493 {
494 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
495 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
496 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
497 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
498 }
499 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
500 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
501 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
502 }
503 offset += sizeof(MODE_PARAMETER_BLOCK);
504 }
505 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (page_code == MODE_PAGE_FORMAT_DEVICE || page_code == MODE_SENSE_RETURN_ALL))
506 {
507 valid_page = TRUE;
508 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
509 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
510 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
511 /* 256 sectors per track */
512 format_page->SectorsPerTrack[0] = 0x01;
513 format_page->SectorsPerTrack[1] = 0x00;
514 /* xxx bytes per sector */
515 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
516 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
517 format_page->HardSectorFormating = TRUE;
518 format_page->SoftSectorFormating = TRUE;
519 offset += sizeof(MODE_FORMAT_PAGE);
520 }
521 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
522 if (!valid_page && page_code != MODE_SENSE_RETURN_ALL)
523 {
524 srb->SrbStatus = SRB_STATUS_ERROR;
525 }
526 else if(offset < srb->DataTransferLength)
527 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
528 else
529 srb->SrbStatus = SRB_STATUS_SUCCESS;
530 srb->DataTransferLength = min(srb->DataTransferLength, offset);
531 srb->ScsiStatus = 0;
532 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
534 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
536 return TRUE;
537 }
539 static VOID
540 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
541 {
542 PSENSE_DATA sd = srb->SenseInfoBuffer;
544 UNREFERENCED_PARAMETER(xvdd);
546 if (!srb->SenseInfoBuffer)
547 return;
549 sd->ErrorCode = 0x70;
550 sd->Valid = 1;
551 sd->SenseKey = sense_key;
552 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
553 sd->AdditionalSenseCode = additional_sense_code;
554 return;
555 }
557 static VOID
558 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
559 {
560 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
561 return;
562 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
563 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
564 }
566 static BOOLEAN
567 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
568 {
569 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
570 PSCSI_REQUEST_BLOCK srb;
571 RING_IDX i, rp;
572 int j;
573 blkif_response_t *rep;
574 int block_count;
575 int more_to_do = TRUE;
576 blkif_shadow_t *shadow;
577 ULONG offset;
579 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
581 xvdd->interrupts++;
582 while (more_to_do)
583 {
584 rp = xvdd->ring.sring->rsp_prod;
585 KeMemoryBarrier();
586 for (i = xvdd->ring.rsp_cons; i != rp; i++)
587 {
588 rep = XenVbd_GetResponse(xvdd, i);
589 /*
590 * This code is to automatically detect if the backend is using the same
591 * bit width or a different bit width to us. Later versions of Xen do this
592 * via a xenstore value, but not all. That 0x0fffffff (notice
593 * that the msb is not actually set, so we don't have any problems with
594 * sign extending) is to signify the last entry on the right, which is
595 * different under 32 and 64 bits, and that is why we set it up there.
597 * To do the detection, we put two initial entries on the ring, with an op
598 * of 0xff (which is invalid). The first entry is mostly okay, but the
599 * second will be grossly misaligned if the backend bit width is different,
600 * and we detect this and switch frontend structures.
601 */
602 switch (xvdd->ring_detect_state)
603 {
604 case 0:
605 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
606 xvdd->ring_detect_state = 1;
607 break;
608 case 1:
609 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
610 if (rep->operation != 0xff)
611 {
612 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
613 xvdd->use_other = TRUE;
614 }
615 xvdd->ring_detect_state = 2;
616 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
617 break;
618 case 2:
619 shadow = &xvdd->shadows[rep->id];
620 srb = shadow->srb;
621 ASSERT(srb != NULL);
622 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
623 block_count *= xvdd->bytes_per_sector / 512;
624 if (rep->status == BLKIF_RSP_OKAY)
625 srb->SrbStatus = SRB_STATUS_SUCCESS;
626 else
627 {
628 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
629 if (srb->Cdb[0] == SCSIOP_READ)
630 KdPrint((__DRIVER_NAME " Operation = Read\n"));
631 else
632 KdPrint((__DRIVER_NAME " Operation = Write\n"));
633 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
634 srb->SrbStatus = SRB_STATUS_ERROR;
635 srb->ScsiStatus = 0x02;
636 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
637 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
638 XenVbd_MakeAutoSense(xvdd, srb);
639 }
640 for (j = 0; j < shadow->req.nr_segments; j++)
641 {
642 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
643 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
644 }
646 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
647 {
648 if (srb->Cdb[0] == SCSIOP_READ)
649 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, GET_PAGE_ALIGNED(srb->SrbExtension), shadow->length);
650 offset = shadow->offset + shadow->length;
651 put_shadow_on_freelist(xvdd, shadow);
652 if (offset == block_count * xvdd->bytes_per_sector)
653 {
654 ScsiPortNotification(RequestComplete, xvdd, srb);
655 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
656 }
657 else
658 {
659 XenVbd_PutSrbOnRing(xvdd, srb, offset);
660 }
661 }
662 else
663 {
664 put_shadow_on_freelist(xvdd, shadow);
665 ScsiPortNotification(RequestComplete, xvdd, srb);
666 if (xvdd->pending_srb)
667 {
668 srb = xvdd->pending_srb;
669 xvdd->pending_srb = NULL;
670 XenVbd_PutSrbOnRing(xvdd, srb, 0);
671 }
672 else
673 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
674 }
675 }
676 }
678 xvdd->ring.rsp_cons = i;
679 if (i != xvdd->ring.req_prod_pvt)
680 {
681 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
682 }
683 else
684 {
685 xvdd->ring.sring->rsp_event = i + 1;
686 more_to_do = FALSE;
687 }
688 }
690 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
692 return FALSE; /* we just don't know... */
693 }
695 static BOOLEAN
696 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
697 {
698 PUCHAR DataBuffer;
699 PCDB cdb;
700 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
702 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
704 // If we haven't enumerated all the devices yet then just defer the request
705 if (xvdd->ring_detect_state < 2)
706 {
707 Srb->SrbStatus = SRB_STATUS_BUSY;
708 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
709 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
710 return TRUE;
711 }
713 if (Srb->PathId != 0 || Srb->TargetId != 0)
714 {
715 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
716 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
717 ScsiPortNotification(NextRequest, DeviceExtension);
718 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
719 return TRUE;
720 }
722 switch (Srb->Function)
723 {
724 case SRB_FUNCTION_EXECUTE_SCSI:
725 cdb = (PCDB)Srb->Cdb;
726 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
728 switch(cdb->CDB6GENERIC.OperationCode)
729 {
730 case SCSIOP_TEST_UNIT_READY:
731 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
732 Srb->SrbStatus = SRB_STATUS_SUCCESS;
733 Srb->ScsiStatus = 0;
734 break;
735 case SCSIOP_INQUIRY:
736 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
737 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
738 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
739 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
740 DataBuffer = Srb->DataBuffer;
741 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
742 Srb->SrbStatus = SRB_STATUS_SUCCESS;
743 switch (xvdd->device_type)
744 {
745 case XENVBD_DEVICETYPE_DISK:
746 if ((Srb->Cdb[1] & 1) == 0)
747 {
748 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
749 id->DeviceType = DIRECT_ACCESS_DEVICE;
750 id->Versions = 3;
751 id->ResponseDataFormat = 0;
752 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
753 id->CommandQueue = 1;
754 memcpy(id->VendorId, "XEN ", 8); // vendor id
755 memcpy(id->ProductId, "PV DISK ", 16); // product id
756 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
757 }
758 else
759 {
760 switch (Srb->Cdb[2])
761 {
762 case 0x00:
763 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
764 DataBuffer[1] = 0x00;
765 DataBuffer[2] = 0x00;
766 DataBuffer[3] = 2;
767 DataBuffer[4] = 0x00;
768 DataBuffer[5] = 0x80;
769 break;
770 case 0x80:
771 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
772 DataBuffer[1] = 0x80;
773 DataBuffer[2] = 0x00;
774 DataBuffer[3] = 8;
775 memset(&DataBuffer[4], ' ', 8);
776 break;
777 default:
778 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
779 Srb->SrbStatus = SRB_STATUS_ERROR;
780 break;
781 }
782 }
783 break;
784 case XENVBD_DEVICETYPE_CDROM:
785 if ((Srb->Cdb[1] & 1) == 0)
786 {
787 PINQUIRYDATA id = (PINQUIRYDATA)DataBuffer;
788 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
789 id->RemovableMedia = 1;
790 id->Versions = 3;
791 id->ResponseDataFormat = 0;
792 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
793 id->CommandQueue = 1;
794 memcpy(id->VendorId, "XEN ", 8); // vendor id
795 memcpy(id->ProductId, "PV CDROM ", 16); // product id
796 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
797 }
798 else
799 {
800 switch (Srb->Cdb[2])
801 {
802 case 0x00:
803 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
804 DataBuffer[1] = 0x00;
805 DataBuffer[2] = 0x00;
806 DataBuffer[3] = 2;
807 DataBuffer[4] = 0x00;
808 DataBuffer[5] = 0x80;
809 break;
810 case 0x80:
811 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
812 DataBuffer[1] = 0x80;
813 DataBuffer[2] = 0x00;
814 DataBuffer[3] = 8;
815 DataBuffer[4] = 0x31;
816 DataBuffer[5] = 0x32;
817 DataBuffer[6] = 0x33;
818 DataBuffer[7] = 0x34;
819 DataBuffer[8] = 0x35;
820 DataBuffer[9] = 0x36;
821 DataBuffer[10] = 0x37;
822 DataBuffer[11] = 0x38;
823 break;
824 default:
825 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
826 Srb->SrbStatus = SRB_STATUS_ERROR;
827 break;
828 }
829 }
830 break;
831 default:
832 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
833 Srb->SrbStatus = SRB_STATUS_ERROR;
834 break;
835 }
836 break;
837 case SCSIOP_READ_CAPACITY:
838 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
839 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
840 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
841 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
842 DataBuffer = Srb->DataBuffer;
843 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
844 if ((xvdd->total_sectors - 1) >> 32)
845 {
846 DataBuffer[0] = 0xff;
847 DataBuffer[1] = 0xff;
848 DataBuffer[2] = 0xff;
849 DataBuffer[3] = 0xff;
850 }
851 else
852 {
853 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
854 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
855 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
856 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
857 }
858 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
859 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
860 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
861 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
862 Srb->ScsiStatus = 0;
863 Srb->SrbStatus = SRB_STATUS_SUCCESS;
864 break;
865 case SCSIOP_MODE_SENSE:
866 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));
867 XenVbd_FillModePage(xvdd, Srb);
868 break;
869 case SCSIOP_WRITE:
870 case SCSIOP_READ:
871 //KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
872 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
873 break;
874 case SCSIOP_VERIFY:
875 // Should we do more here?
876 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
877 Srb->SrbStatus = SRB_STATUS_SUCCESS;
878 break;
879 case SCSIOP_REPORT_LUNS:
880 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
881 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
882 break;
883 case SCSIOP_REQUEST_SENSE:
884 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
885 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
886 Srb->SrbStatus = SRB_STATUS_SUCCESS;
887 break;
888 case SCSIOP_READ_TOC:
889 DataBuffer = Srb->DataBuffer;
890 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
891 /*
892 #define READ_TOC_FORMAT_TOC 0x00
893 #define READ_TOC_FORMAT_SESSION 0x01
894 #define READ_TOC_FORMAT_FULL_TOC 0x02
895 #define READ_TOC_FORMAT_PMA 0x03
896 #define READ_TOC_FORMAT_ATIP 0x04
897 */
898 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
899 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
900 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
901 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
902 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
903 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
904 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
905 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
906 switch (cdb->READ_TOC.Format2)
907 {
908 case READ_TOC_FORMAT_TOC:
909 DataBuffer[0] = 0; // length MSB
910 DataBuffer[1] = 10; // length LSB
911 DataBuffer[2] = 1; // First Track
912 DataBuffer[3] = 1; // Last Track
913 DataBuffer[4] = 0; // Reserved
914 DataBuffer[5] = 0x14; // current position data + uninterrupted data
915 DataBuffer[6] = 1; // last complete track
916 DataBuffer[7] = 0; // reserved
917 DataBuffer[8] = 0; // MSB Block
918 DataBuffer[9] = 0;
919 DataBuffer[10] = 0;
920 DataBuffer[11] = 0; // LSB Block
921 Srb->SrbStatus = SRB_STATUS_SUCCESS;
922 break;
923 case READ_TOC_FORMAT_SESSION:
924 case READ_TOC_FORMAT_FULL_TOC:
925 case READ_TOC_FORMAT_PMA:
926 case READ_TOC_FORMAT_ATIP:
927 Srb->SrbStatus = SRB_STATUS_ERROR;
928 break;
929 }
930 break;
931 case SCSIOP_START_STOP_UNIT:
932 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
933 Srb->SrbStatus = SRB_STATUS_SUCCESS;
934 break;
935 case SCSIOP_RESERVE_UNIT:
936 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
937 Srb->SrbStatus = SRB_STATUS_SUCCESS;
938 break;
939 case SCSIOP_RELEASE_UNIT:
940 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
941 Srb->SrbStatus = SRB_STATUS_SUCCESS;
942 break;
943 default:
944 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
945 Srb->SrbStatus = SRB_STATUS_ERROR;
946 break;
947 }
948 if (Srb->SrbStatus == SRB_STATUS_ERROR)
949 {
950 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
951 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
952 {
953 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
954 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
955 }
956 Srb->ScsiStatus = 0x02;
957 XenVbd_MakeAutoSense(xvdd, Srb);
958 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
959 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
960 }
961 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
962 {
963 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
964 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
965 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
966 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
967 }
968 break;
969 case SRB_FUNCTION_IO_CONTROL:
970 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
971 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
972 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
973 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
974 break;
975 case SRB_FUNCTION_FLUSH:
976 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
977 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
978 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
979 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
980 break;
981 default:
982 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
983 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
984 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
985 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
986 break;
987 }
989 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
990 return TRUE;
991 }
993 static BOOLEAN
994 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
995 {
996 UNREFERENCED_PARAMETER(DeviceExtension);
997 UNREFERENCED_PARAMETER(PathId);
999 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1000 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1002 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1004 return TRUE;
1007 static BOOLEAN
1008 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1010 UNREFERENCED_PARAMETER(DeviceExtension);
1011 UNREFERENCED_PARAMETER(Context);
1012 UNREFERENCED_PARAMETER(SaveState);
1014 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1015 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1017 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1019 return TRUE;
1022 static SCSI_ADAPTER_CONTROL_STATUS
1023 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1025 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1026 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1027 //KIRQL OldIrql;
1029 UNREFERENCED_PARAMETER(DeviceExtension);
1031 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1032 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1034 switch (ControlType)
1036 case ScsiQuerySupportedControlTypes:
1037 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1038 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1039 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1040 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1041 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1042 break;
1043 case ScsiStopAdapter:
1044 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1045 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1046 break;
1047 case ScsiRestartAdapter:
1048 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1049 break;
1050 case ScsiSetBootConfig:
1051 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1052 break;
1053 case ScsiSetRunningConfig:
1054 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1055 break;
1056 default:
1057 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1058 break;
1061 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1063 return Status;
1066 VOID
1067 XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
1069 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
1070 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1072 HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
1073 HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
1074 HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
1075 HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
1076 HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
1077 HwInitializationData->HwDmaStarted = NULL;
1078 HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
1079 HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
1081 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));