win-pvdrivers

view xenvbd_common/common_miniport.h @ 1032:306c10cdcba1

Added online resize. Untested under storport yet (>= Vista)
author James Harper <james.harper@bendigoit.com.au>
date Sun Mar 03 12:19:31 2013 +1100 (2013-03-03)
parents aa2e51f67f7c
children 9f476ac2fbe1
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2013 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 #if defined(__x86_64__)
21 #define LongLongToPtr(x) (PVOID)(x)
22 #else
23 #define LongLongToPtr(x) UlongToPtr(x)
24 #endif
26 #if defined(__x86_64__)
27 #define ABI_PROTOCOL "x86_64-abi"
28 #else
29 #define ABI_PROTOCOL "x86_32-abi"
30 #endif
32 ULONGLONG parse_numeric_string(PCHAR string) {
33 ULONGLONG val = 0;
34 while (*string != 0) {
35 val = val * 10 + (*string - '0');
36 string++;
37 }
38 return val;
39 }
41 /* called with StartIoLock held */
42 static blkif_shadow_t *
43 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd) {
44 if (xvdd->shadow_free == 0) {
45 FUNCTION_MSG("No more shadow entries\n");
46 return NULL;
47 }
48 xvdd->shadow_free--;
49 //if (xvdd->shadow_free < xvdd->shadow_min_free)
50 // xvdd->shadow_min_free = xvdd->shadow_free;
51 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
52 }
54 /* called with StartIoLock held */
55 static VOID
56 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
57 {
58 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)(shadow->req.id & SHADOW_ID_ID_MASK);
59 shadow->srb = NULL;
60 shadow->reset = FALSE;
61 shadow->aligned_buffer_in_use = FALSE;
62 xvdd->shadow_free++;
63 }
65 static __inline ULONG
66 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
67 {
68 switch (srb->Cdb[0])
69 {
70 case SCSIOP_READ:
71 case SCSIOP_WRITE:
72 return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
73 case SCSIOP_READ16:
74 case SCSIOP_WRITE16:
75 return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];
76 default:
77 return 0;
78 }
79 }
81 static blkif_response_t *
82 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i) {
83 return RING_GET_RESPONSE(&xvdd->ring, i);
84 }
86 static VOID
87 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req) {
88 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
89 xvdd->ring.req_prod_pvt++;
90 }
92 static VOID
93 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
94 srb_list_entry_t *srb_entry = srb->SrbExtension;
95 srb_entry->srb = srb;
96 srb_entry->outstanding_requests = 0;
97 srb_entry->length = srb->DataTransferLength;
98 srb_entry->offset = 0;
99 srb_entry->error = FALSE;
100 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
101 }
103 static __inline ULONGLONG
104 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
105 {
106 ULONGLONG sector;
108 switch (srb->Cdb[0])
109 {
110 case SCSIOP_READ:
111 case SCSIOP_WRITE:
112 sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
113 break;
114 case SCSIOP_READ16:
115 case SCSIOP_WRITE16:
116 sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
117 | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
118 | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
119 | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
120 //FUNCTION_MSG("sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector);
121 break;
122 default:
123 sector = 0;
124 break;
125 }
126 return sector;
127 }
129 static __inline BOOLEAN
130 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
131 {
132 switch (srb->Cdb[0])
133 {
134 case SCSIOP_READ:
135 case SCSIOP_READ16:
136 return TRUE;
137 case SCSIOP_WRITE:
138 case SCSIOP_WRITE16:
139 return FALSE;
140 default:
141 return FALSE;
142 }
143 }
145 static ULONG
146 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
147 {
148 PSENSE_DATA sd = srb->SenseInfoBuffer;
150 UNREFERENCED_PARAMETER(xvdd);
152 if (!srb->SenseInfoBuffer)
153 return 0;
155 sd->ErrorCode = 0x70;
156 sd->Valid = 1;
157 sd->SenseKey = sense_key;
158 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
159 sd->AdditionalSenseCode = additional_sense_code;
160 return sizeof(SENSE_DATA);
161 }
163 static VOID
164 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
165 {
166 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
167 return;
168 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
169 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
170 }
172 /* called with StartIo lock held */
173 static VOID
174 XenVbd_HandleEvent(PXENVBD_DEVICE_DATA xvdd) {
175 PSCSI_REQUEST_BLOCK srb;
176 RING_IDX i, rp;
177 ULONG j;
178 blkif_response_t *rep;
179 //int block_count;
180 int more_to_do = TRUE;
181 blkif_shadow_t *shadow;
182 srb_list_entry_t *srb_entry;
184 if (xvdd->device_state != DEVICE_STATE_ACTIVE && xvdd->device_state != DEVICE_STATE_DISCONNECTING) {
185 /* if we aren't active (eg just restored from hibernate) then we still want to process non-scsi srb's */
186 XenVbd_ProcessSrbList(xvdd);
187 return;
188 }
190 while (more_to_do) {
191 rp = xvdd->ring.sring->rsp_prod;
192 KeMemoryBarrier();
193 for (i = xvdd->ring.rsp_cons; i != rp; i++) {
194 rep = XenVbd_GetResponse(xvdd, i);
195 shadow = &xvdd->shadows[rep->id & SHADOW_ID_ID_MASK];
196 if (shadow->reset) {
197 /* the srb's here have already been returned */
198 FUNCTION_MSG("discarding reset shadow\n");
199 for (j = 0; j < shadow->req.nr_segments; j++) {
200 XnEndAccess(xvdd->handle,
201 shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
202 }
203 } else if (dump_mode && !(rep->id & SHADOW_ID_DUMP_FLAG)) {
204 FUNCTION_MSG("discarding stale (non-dump-mode) shadow\n");
205 } else {
206 srb = shadow->srb;
207 XN_ASSERT(srb);
208 srb_entry = srb->SrbExtension;
209 XN_ASSERT(srb_entry);
210 /* a few errors occur in dump mode because Xen refuses to allow us to map pages we are using for other stuff. Just ignore them */
211 if (rep->status == BLKIF_RSP_OKAY || (dump_mode && dump_mode_errors++ < DUMP_MODE_ERROR_LIMIT)) {
212 srb->SrbStatus = SRB_STATUS_SUCCESS;
213 } else {
214 FUNCTION_MSG("Xen Operation returned error\n");
215 if (decode_cdb_is_read(srb))
216 FUNCTION_MSG("Operation = Read\n");
217 else
218 FUNCTION_MSG("Operation = Write\n");
219 srb_entry->error = TRUE;
220 }
221 if (shadow->aligned_buffer_in_use) {
222 XN_ASSERT(xvdd->aligned_buffer_in_use);
223 xvdd->aligned_buffer_in_use = FALSE;
224 if (srb->SrbStatus == SRB_STATUS_SUCCESS && decode_cdb_is_read(srb))
225 memcpy((PUCHAR)shadow->system_address, xvdd->aligned_buffer, shadow->length);
226 }
227 for (j = 0; j < shadow->req.nr_segments; j++) {
228 XnEndAccess(xvdd->handle, shadow->req.seg[j].gref, FALSE, xvdd->grant_tag);
229 }
230 srb_entry->outstanding_requests--;
231 if (srb_entry->outstanding_requests == 0 && srb_entry->offset == srb_entry->length) {
232 if (srb_entry->error) {
233 srb->SrbStatus = SRB_STATUS_ERROR;
234 srb->ScsiStatus = 0x02;
235 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
236 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
237 XenVbd_MakeAutoSense(xvdd, srb);
238 }
239 SxxxPortNotification(RequestComplete, xvdd, srb);
240 }
241 }
242 put_shadow_on_freelist(xvdd, shadow);
243 }
245 /* put queue'd Srbs onto the ring now so we can set the event in the best possible way */
246 if (dump_mode || xvdd->device_state == DEVICE_STATE_ACTIVE) {
247 XenVbd_ProcessSrbList(xvdd);
248 }
250 xvdd->ring.rsp_cons = i;
251 if (i == xvdd->ring.req_prod_pvt) {
252 /* all possible requests complete - can't have more responses than requests */
253 more_to_do = FALSE;
254 xvdd->ring.sring->rsp_event = i + 1;
255 } else {
256 more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xvdd->ring);
257 if (!more_to_do) {
258 xvdd->ring.sring->rsp_event = i + max(1, (SHADOW_ENTRIES - xvdd->shadow_free) / 2);
259 more_to_do = RING_HAS_UNCONSUMED_RESPONSES(&xvdd->ring);
260 }
261 }
262 }
264 if (xvdd->device_state == DEVICE_STATE_DISCONNECTING && xvdd->shadow_free == SHADOW_ENTRIES) {
265 FUNCTION_MSG("ring now empty - completing disconnect\n");
266 XenVbd_CompleteDisconnect(xvdd);
267 }
268 return;
269 }
271 /* called with StartIoLock held */
272 /* returns TRUE if something was put on the ring and notify might be required */
273 static BOOLEAN
274 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
275 srb_list_entry_t *srb_entry = srb->SrbExtension;
276 /* sector_number and block_count are the adjusted-to-512-byte-sector values */
277 ULONGLONG sector_number;
278 ULONG block_count;
279 blkif_shadow_t *shadow;
280 ULONG remaining, offset, length;
281 grant_ref_t gref;
282 PUCHAR ptr;
283 int i;
284 PVOID system_address;
286 //if (dump_mode) FUNCTION_ENTER();
288 //FUNCTION_MSG("aligned_buffer_in_use = %d\n", xvdd->aligned_buffer_in_use);
289 //FUNCTION_MSG("shadow_free = %d\n", xvdd->shadow_free);
291 XN_ASSERT(srb);
293 if (xvdd->device_state != DEVICE_STATE_ACTIVE) {
294 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
295 return FALSE;
296 }
298 if (!dump_mode) {
299 if (SxxxPortGetSystemAddress(xvdd, srb, &system_address) != STATUS_SUCCESS) {
300 FUNCTION_MSG("Failed to map DataBuffer\n");
301 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
302 return FALSE;
303 }
304 system_address = (PUCHAR)system_address + srb_entry->offset;
305 } else {
306 system_address = (PUCHAR)srb->DataBuffer + srb_entry->offset;
307 }
308 block_count = decode_cdb_length(srb);
309 sector_number = decode_cdb_sector(srb);
310 block_count *= xvdd->bytes_per_sector / 512;
311 sector_number *= xvdd->bytes_per_sector / 512;
313 XN_ASSERT(block_count * 512 == srb->DataTransferLength);
315 sector_number += srb_entry->offset / 512;
316 block_count -= srb_entry->offset / 512;
318 XN_ASSERT(block_count > 0);
320 /* look for pending writes that overlap this one */
321 /* we get warnings from drbd if we don't */
322 if (srb_entry->offset == 0) {
323 for (i = 0; i < MAX_SHADOW_ENTRIES; i++) {
324 PSCSI_REQUEST_BLOCK srb2;
325 ULONGLONG sector_number2;
326 ULONG block_count2;
328 srb2 = xvdd->shadows[i].srb;
329 if (!srb2)
330 continue;
331 if (decode_cdb_is_read(srb2))
332 continue;
333 block_count2 = decode_cdb_length(srb2);;
334 block_count2 *= xvdd->bytes_per_sector / 512;
335 sector_number2 = decode_cdb_sector(srb2);
336 sector_number2 *= xvdd->bytes_per_sector / 512;
338 if (sector_number < sector_number2 && sector_number + block_count <= sector_number2)
339 continue;
340 if (sector_number2 < sector_number && sector_number2 + block_count2 <= sector_number)
341 continue;
343 FUNCTION_MSG("Concurrent outstanding write detected (%I64d, %d) (%I64d, %d)\n",
344 sector_number, block_count, sector_number2, block_count2);
345 break;
346 }
347 if (i != MAX_SHADOW_ENTRIES) {
348 /* put the srb back at the start of the queue */
349 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
350 return FALSE;
351 }
352 }
354 shadow = get_shadow_from_freelist(xvdd);
355 if (!shadow) {
356 /* put the srb back at the start of the queue */
357 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
358 //if (dump_mode) FUNCTION_EXIT();
359 return FALSE;
360 }
361 XN_ASSERT(!shadow->aligned_buffer_in_use);
362 XN_ASSERT(!shadow->srb);
363 shadow->req.sector_number = sector_number;
364 shadow->req.handle = 0;
365 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
366 shadow->req.nr_segments = 0;
367 shadow->srb = srb;
368 shadow->length = 0;
369 shadow->system_address = system_address;
370 shadow->reset = FALSE;
372 if (!dump_mode) {
373 if ((ULONG_PTR)shadow->system_address & 511) {
374 xvdd->aligned_buffer_in_use = TRUE;
375 /* limit to aligned_buffer_size */
376 block_count = min(block_count, xvdd->aligned_buffer_size / 512);
377 ptr = (PUCHAR)xvdd->aligned_buffer;
378 if (!decode_cdb_is_read(srb))
379 memcpy(ptr, shadow->system_address, block_count * 512);
380 shadow->aligned_buffer_in_use = TRUE;
381 } else {
382 ptr = (PUCHAR)shadow->system_address;
383 shadow->aligned_buffer_in_use = FALSE;
384 }
385 } else {
386 XN_ASSERT(!((ULONG_PTR)shadow->system_address & 511));
387 ptr = shadow->system_address;
388 shadow->aligned_buffer_in_use = FALSE;
389 }
391 remaining = block_count * 512;
392 while (remaining > 0 && shadow->req.nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST) {
393 PHYSICAL_ADDRESS physical_address;
395 if (!dump_mode) {
396 physical_address = MmGetPhysicalAddress(ptr);
397 } else {
398 ULONG length;
399 physical_address = SxxxPortGetPhysicalAddress(xvdd, srb, ptr, &length);
400 //FUNCTION_MSG("physical_address = %08I64x\n", physical_address.QuadPart);
402 }
403 gref = XnGrantAccess(xvdd->handle,
404 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, INVALID_GRANT_REF, xvdd->grant_tag);
405 if (gref == INVALID_GRANT_REF) {
406 ULONG i;
407 for (i = 0; i < shadow->req.nr_segments; i++) {
408 XnEndAccess(xvdd->handle,
409 shadow->req.seg[i].gref, FALSE, xvdd->grant_tag);
410 }
411 if (shadow->aligned_buffer_in_use) {
412 shadow->aligned_buffer_in_use = FALSE;
413 xvdd->aligned_buffer_in_use = FALSE;
414 }
415 /* put the srb back at the start of the queue */
416 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
417 put_shadow_on_freelist(xvdd, shadow);
418 FUNCTION_MSG("Out of gref's. Deferring\n");
419 /* TODO: what if there are no requests currently in progress to kick the queue again?? timer? */
420 return FALSE;
421 }
422 offset = physical_address.LowPart & (PAGE_SIZE - 1);
423 length = min(PAGE_SIZE - offset, remaining);
424 XN_ASSERT((offset & 511) == 0);
425 XN_ASSERT((length & 511) == 0);
426 XN_ASSERT(offset + length <= PAGE_SIZE);
427 shadow->req.seg[shadow->req.nr_segments].gref = gref;
428 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset / 512);
429 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) / 512) - 1);
430 remaining -= length;
431 ptr += length;
432 shadow->length += length;
433 shadow->req.nr_segments++;
434 }
435 srb_entry->offset += shadow->length;
436 srb_entry->outstanding_requests++;
437 XenVbd_PutRequest(xvdd, &shadow->req);
438 if (srb_entry->offset < srb_entry->length) {
439 /* put the srb back at the start of the queue to continue on the next request */
440 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
441 }
442 //if (dump_mode)
443 //FUNCTION_EXIT();
444 return TRUE;
445 }
447 static ULONG
448 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
449 PMODE_PARAMETER_HEADER parameter_header = NULL;
450 PMODE_PARAMETER_HEADER10 parameter_header10 = NULL;
451 PMODE_PARAMETER_BLOCK param_block;
452 PMODE_FORMAT_PAGE format_page;
453 ULONG offset = 0;
454 UCHAR buffer[1024];
455 BOOLEAN valid_page = FALSE;
456 BOOLEAN cdb_llbaa;
457 BOOLEAN cdb_dbd;
458 UCHAR cdb_page_code;
459 USHORT cdb_allocation_length;
461 UNREFERENCED_PARAMETER(xvdd);
463 RtlZeroMemory(srb->DataBuffer, srb->DataTransferLength);
464 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
465 offset = 0;
467 switch (srb->Cdb[0]) {
468 case SCSIOP_MODE_SENSE:
469 cdb_llbaa = FALSE;
470 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
471 cdb_page_code = srb->Cdb[2] & 0x3f;
472 cdb_allocation_length = srb->Cdb[4];
473 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
474 parameter_header->MediumType = 0;
475 parameter_header->DeviceSpecificParameter = 0;
476 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ) {
477 FUNCTION_MSG(" Mode sense to a read only disk.\n");
478 parameter_header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
479 }
480 offset += sizeof(MODE_PARAMETER_HEADER);
481 break;
482 case SCSIOP_MODE_SENSE10:
483 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
484 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
485 cdb_page_code = srb->Cdb[2] & 0x3f;
486 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
487 parameter_header10 = (PMODE_PARAMETER_HEADER10)&buffer[offset];
488 parameter_header10->MediumType = 0;
489 parameter_header10->DeviceSpecificParameter = 0;
490 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ) {
491 FUNCTION_MSG(" Mode sense to a read only disk.\n");
492 parameter_header10->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
493 }
494 offset += sizeof(MODE_PARAMETER_HEADER10);
495 break;
496 default:
497 FUNCTION_MSG("SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]);
498 return FALSE;
499 }
501 if (!cdb_dbd) {
502 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
503 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK) {
504 if (xvdd->total_sectors >> 32) {
505 param_block->DensityCode = 0xff;
506 param_block->NumberOfBlocks[0] = 0xff;
507 param_block->NumberOfBlocks[1] = 0xff;
508 param_block->NumberOfBlocks[2] = 0xff;
509 } else {
510 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
511 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
512 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
513 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
514 }
515 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
516 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
517 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
518 }
519 offset += sizeof(MODE_PARAMETER_BLOCK);
520 }
521 switch (srb->Cdb[0])
522 {
523 case SCSIOP_MODE_SENSE:
524 parameter_header->BlockDescriptorLength = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER));
525 break;
526 case SCSIOP_MODE_SENSE10:
527 parameter_header10->BlockDescriptorLength[0] = (UCHAR)((offset - sizeof(MODE_PARAMETER_HEADER10)) >> 8);
528 parameter_header10->BlockDescriptorLength[1] = (UCHAR)(offset - sizeof(MODE_PARAMETER_HEADER10));
529 break;
530 }
531 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL)) {
532 valid_page = TRUE;
533 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
534 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
535 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
536 /* 256 sectors per track */
537 format_page->SectorsPerTrack[0] = 0x01;
538 format_page->SectorsPerTrack[1] = 0x00;
539 /* xxx bytes per sector */
540 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
541 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
542 format_page->HardSectorFormating = TRUE;
543 format_page->SoftSectorFormating = TRUE;
544 offset += sizeof(MODE_FORMAT_PAGE);
545 }
546 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_CACHING || cdb_page_code == MODE_SENSE_RETURN_ALL)) {
547 PMODE_CACHING_PAGE caching_page;
548 valid_page = TRUE;
549 caching_page = (PMODE_CACHING_PAGE)&buffer[offset];
550 caching_page->PageCode = MODE_PAGE_CACHING;
551 caching_page->PageLength = sizeof(MODE_CACHING_PAGE) - FIELD_OFFSET(MODE_CACHING_PAGE, PageLength);
552 // caching_page-> // all zeros is just fine... maybe
553 offset += sizeof(MODE_CACHING_PAGE);
554 }
555 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_MEDIUM_TYPES || cdb_page_code == MODE_SENSE_RETURN_ALL)) {
556 PUCHAR medium_types_page;
557 valid_page = TRUE;
558 medium_types_page = &buffer[offset];
559 medium_types_page[0] = MODE_PAGE_MEDIUM_TYPES;
560 medium_types_page[1] = 0x06;
561 medium_types_page[2] = 0;
562 medium_types_page[3] = 0;
563 medium_types_page[4] = 0;
564 medium_types_page[5] = 0;
565 medium_types_page[6] = 0;
566 medium_types_page[7] = 0;
567 offset += 8;
568 }
569 switch (srb->Cdb[0]) {
570 case SCSIOP_MODE_SENSE:
571 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
572 break;
573 case SCSIOP_MODE_SENSE10:
574 parameter_header10->ModeDataLength[0] = (UCHAR)((offset - 2) >> 8);
575 parameter_header10->ModeDataLength[1] = (UCHAR)(offset - 2);
576 break;
577 }
579 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL) {
580 srb->SrbStatus = SRB_STATUS_ERROR;
581 }
582 else if(offset < srb->DataTransferLength)
583 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
584 else
585 srb->SrbStatus = SRB_STATUS_SUCCESS;
586 srb->DataTransferLength = min(srb->DataTransferLength, offset);
587 srb->ScsiStatus = 0;
588 memcpy(srb->DataBuffer, buffer, srb->DataTransferLength);
590 //FUNCTION_EXIT();
592 return TRUE;
593 }
595 static BOOLEAN
596 XenVbd_ResetBus(PXENVBD_DEVICE_DATA xvdd, ULONG PathId) {
597 //srb_list_entry_t *srb_entry;
598 int i;
599 /* need to make sure that each SRB is only reset once */
600 LIST_ENTRY srb_reset_list;
601 PLIST_ENTRY list_entry;
603 UNREFERENCED_PARAMETER(PathId);
605 FUNCTION_ENTER();
607 if (dump_mode) {
608 FUNCTION_MSG("dump mode - doing nothing\n");
609 FUNCTION_EXIT();
610 return TRUE;
611 }
613 /* It appears that the StartIo spinlock is already held at this point */
615 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
617 xvdd->aligned_buffer_in_use = FALSE;
619 InitializeListHead(&srb_reset_list);
621 /* add all queued srbs to the list */
622 while((list_entry = RemoveHeadList(&xvdd->srb_list)) != &xvdd->srb_list) {
623 #if DBG
624 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
625 FUNCTION_MSG("adding queued SRB %p to reset list\n", srb_entry->srb);
626 #endif
627 InsertTailList(&srb_reset_list, list_entry);
628 }
630 /* add any in-flight srbs that aren't already on the list (could be multiple shadows per srb if it's been broken up */
631 for (i = 0; i < MAX_SHADOW_ENTRIES; i++) {
632 if (xvdd->shadows[i].srb) {
633 srb_list_entry_t *srb_entry = xvdd->shadows[i].srb->SrbExtension;
634 for (list_entry = srb_reset_list.Flink; list_entry != &srb_reset_list; list_entry = list_entry->Flink) {
635 if (list_entry == &srb_entry->list_entry)
636 break;
637 }
638 if (list_entry == &srb_reset_list) {
639 FUNCTION_MSG("adding in-flight SRB %p to reset list\n", srb_entry->srb);
640 InsertTailList(&srb_reset_list, &srb_entry->list_entry);
641 }
642 /* set reset here so that the interrupt won't do anything with the srb but will dispose of the shadow entry correctly */
643 xvdd->shadows[i].reset = TRUE;
644 xvdd->shadows[i].srb = NULL;
645 xvdd->shadows[i].aligned_buffer_in_use = FALSE;
646 }
647 }
649 while((list_entry = RemoveHeadList(&srb_reset_list)) != &srb_reset_list) {
650 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
651 srb_entry->outstanding_requests = 0;
652 srb_entry->srb->SrbStatus = SRB_STATUS_BUS_RESET;
653 FUNCTION_MSG("completing SRB %p with status SRB_STATUS_BUS_RESET\n", srb_entry->srb);
654 SxxxPortNotification(RequestComplete, xvdd, srb_entry->srb);
655 }
657 /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen normally but could in dump mode) */
658 XnNotify(xvdd->handle, xvdd->event_channel);
660 SxxxPortNotification(NextLuRequest, xvdd, 0, 0, 0);
661 FUNCTION_EXIT();
663 return TRUE;
664 }
666 /* called with StartIo lock held */
667 VOID
668 XenVbd_ProcessSrbList(PXENVBD_DEVICE_DATA xvdd) {
669 PUCHAR data_buffer;
670 #ifdef _NTSTORPORT_
671 PSCSI_PNP_REQUEST_BLOCK sprb;
672 PSCSI_POWER_REQUEST_BLOCK spwrb;
673 PMINIPORT_DUMP_POINTERS dump_pointers;
674 #endif
675 PCDB cdb;
676 ULONG data_transfer_length;
677 UCHAR srb_status;
678 ULONG notify = FALSE;
679 PSCSI_REQUEST_BLOCK srb;
680 srb_list_entry_t *srb_entry;
681 PSRB_IO_CONTROL sic;
682 ULONG prev_offset;
684 if (xvdd->device_state == DEVICE_STATE_ACTIVE) {
685 if (xvdd->new_total_sectors == -1L)
686 xvdd->new_total_sectors = xvdd->total_sectors;
687 if (xvdd->new_total_sectors != xvdd->total_sectors) {
688 xvdd->total_sectors = xvdd->new_total_sectors;
689 SxxxPortNotification(BusChangeDetected, xvdd, 0);
690 }
691 }
692 while(!xvdd->aligned_buffer_in_use && xvdd->shadow_free && (srb_entry = (srb_list_entry_t *)RemoveHeadList(&xvdd->srb_list)) != (srb_list_entry_t *)&xvdd->srb_list) {
693 srb = srb_entry->srb;
694 prev_offset = srb_entry->offset;
695 if (xvdd->device_state == DEVICE_STATE_INACTIVE) {
696 /* need to check again as may have been initialising when this srb was put on the list */
697 FUNCTION_MSG("Inactive Device (in ProcessSrbList)\n");
698 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
699 SxxxPortNotification(RequestComplete, xvdd, srb);
700 continue;
701 }
703 data_transfer_length = srb->DataTransferLength;
704 srb_status = SRB_STATUS_PENDING;
706 switch (srb->Function) {
707 case SRB_FUNCTION_EXECUTE_SCSI:
708 if (xvdd->device_state != DEVICE_STATE_ACTIVE) {
709 FUNCTION_MSG("Not yet active - state = %d\n", xvdd->device_state);
710 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
711 break;
712 }
713 cdb = (PCDB)srb->Cdb;
714 switch(cdb->CDB6GENERIC.OperationCode) {
715 case SCSIOP_TEST_UNIT_READY:
716 if (dump_mode)
717 FUNCTION_MSG("Command = TEST_UNIT_READY\n");
718 srb_status = SRB_STATUS_SUCCESS;
719 srb->ScsiStatus = 0;
720 break;
721 case SCSIOP_INQUIRY:
722 // if (dump_mode)
723 FUNCTION_MSG("Command = INQUIRY\n");
724 // FUNCTION_MSG("(LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]);
725 // FUNCTION_MSG("(Length = %d)\n", srb->DataTransferLength);
727 data_buffer = srb->DataBuffer;
728 RtlZeroMemory(data_buffer, srb->DataTransferLength);
729 srb_status = SRB_STATUS_SUCCESS;
730 switch (xvdd->device_type)
731 {
732 case XENVBD_DEVICETYPE_DISK:
733 if ((srb->Cdb[1] & 1) == 0) {
734 if (srb->Cdb[2]) {
735 srb_status = SRB_STATUS_ERROR;
736 } else {
737 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
738 id->DeviceType = DIRECT_ACCESS_DEVICE;
739 id->Versions = 5; /* SPC-3 */
740 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
741 id->HiSupport = 1; /* WHQL test says we should set this */
742 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
743 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
744 id->CommandQueue = 1;
745 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
746 memcpy(id->ProductId, SCSI_DISK_MODEL, 16); // product id
747 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
748 data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
749 }
750 } else {
751 switch (srb->Cdb[2]) {
752 case VPD_SUPPORTED_PAGES: /* list of pages we support */
753 FUNCTION_MSG("VPD_SUPPORTED_PAGES\n");
754 data_buffer[0] = DIRECT_ACCESS_DEVICE;
755 data_buffer[1] = VPD_SUPPORTED_PAGES;
756 data_buffer[2] = 0x00;
757 data_buffer[3] = 4;
758 data_buffer[4] = VPD_SUPPORTED_PAGES;
759 data_buffer[5] = VPD_SERIAL_NUMBER;
760 data_buffer[6] = VPD_DEVICE_IDENTIFIERS;
761 data_buffer[7] = VPD_BLOCK_LIMITS;
762 data_transfer_length = 8;
763 break;
764 case VPD_SERIAL_NUMBER: /* serial number */
765 FUNCTION_MSG("VPD_SERIAL_NUMBER\n");
766 data_buffer[0] = DIRECT_ACCESS_DEVICE;
767 data_buffer[1] = VPD_SERIAL_NUMBER;
768 data_buffer[2] = 0x00;
769 data_buffer[3] = (UCHAR)strlen(xvdd->serial_number);
770 if (data_transfer_length > 4) {
771 memcpy(&data_buffer[4], xvdd->serial_number, min(data_transfer_length - 4, strlen(xvdd->serial_number)));
772 }
773 data_transfer_length = 4 + (UCHAR)strlen(xvdd->serial_number);
774 break;
775 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
776 FUNCTION_MSG("VPD_DEVICE_IDENTIFIERS\n");
777 data_buffer[0] = DIRECT_ACCESS_DEVICE;
778 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
779 data_buffer[2] = 0x00;
780 data_buffer[3] = 2 * (4 + (UCHAR)strlen(xvdd->serial_number));
781 if (data_transfer_length >= 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number))) {
782 data_buffer[4] = 2; /* ASCII */
783 data_buffer[5] = 0; /* VendorId */
784 data_buffer[6] = 0; /* reserved */
785 data_buffer[7] = (UCHAR)strlen(xvdd->serial_number);
786 memcpy(&data_buffer[8], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
787 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 0] = 2; /* ASCII */
788 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 1] = 1; /* T10 VendorId */
789 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 2] = 0; /* Reserved */
790 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 3] = (UCHAR)strlen(xvdd->serial_number);
791 memcpy(&data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 4], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
792 }
793 data_transfer_length = 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number));
794 break;
795 case VPD_BLOCK_LIMITS: /* to indicate support for UNMAP (TRIM/DISCARD) */
796 FUNCTION_MSG("VPD_BLOCK_LIMITS\n");
797 // max descriptors = 1
798 // max sectors = 0xFFFFFFFF
799 // granularity = from xenbus
800 // alignment = from xenbus(?)
801 srb_status = SRB_STATUS_ERROR;
802 break;
803 default:
804 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
805 srb_status = SRB_STATUS_ERROR;
806 break;
807 }
808 }
809 break;
810 case XENVBD_DEVICETYPE_CDROM:
811 if ((srb->Cdb[1] & 1) == 0)
812 {
813 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
814 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
815 id->RemovableMedia = 1;
816 id->Versions = 3;
817 id->ResponseDataFormat = 0;
818 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
819 id->CommandQueue = 1;
820 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
821 memcpy(id->ProductId, SCSI_CDROM_MODEL, 16); // product id
822 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
823 data_transfer_length = sizeof(INQUIRYDATA);
824 }
825 else
826 {
827 switch (srb->Cdb[2])
828 {
829 case 0x00:
830 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
831 data_buffer[1] = 0x00;
832 data_buffer[2] = 0x00;
833 data_buffer[3] = 2;
834 data_buffer[4] = 0x00;
835 data_buffer[5] = 0x80;
836 data_transfer_length = 6;
837 break;
838 case 0x80:
839 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
840 data_buffer[1] = 0x80;
841 data_buffer[2] = 0x00;
842 data_buffer[3] = 8;
843 data_buffer[4] = 0x31;
844 data_buffer[5] = 0x32;
845 data_buffer[6] = 0x33;
846 data_buffer[7] = 0x34;
847 data_buffer[8] = 0x35;
848 data_buffer[9] = 0x36;
849 data_buffer[10] = 0x37;
850 data_buffer[11] = 0x38;
851 data_transfer_length = 12;
852 break;
853 default:
854 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
855 srb_status = SRB_STATUS_ERROR;
856 break;
857 }
858 }
859 break;
860 default:
861 FUNCTION_MSG("Unknown DeviceType %02x requested\n", xvdd->device_type);
862 srb_status = SRB_STATUS_ERROR;
863 break;
864 }
865 break;
866 case SCSIOP_READ_CAPACITY:
867 //if (dump_mode)
868 FUNCTION_MSG("Command = READ_CAPACITY\n");
869 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
870 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
871 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
872 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
873 data_buffer = srb->DataBuffer;
874 RtlZeroMemory(data_buffer, srb->DataTransferLength);
875 if ((xvdd->total_sectors - 1) >> 32) {
876 data_buffer[0] = 0xff;
877 data_buffer[1] = 0xff;
878 data_buffer[2] = 0xff;
879 data_buffer[3] = 0xff;
880 } else {
881 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
882 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
883 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
884 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
885 }
886 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
887 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
888 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
889 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
890 data_transfer_length = 8;
891 srb->ScsiStatus = 0;
892 srb_status = SRB_STATUS_SUCCESS;
893 break;
894 case SCSIOP_READ_CAPACITY16:
895 //if (dump_mode)
896 FUNCTION_MSG("Command = READ_CAPACITY16\n");
897 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
898 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
899 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
900 data_buffer = srb->DataBuffer;
901 RtlZeroMemory(data_buffer, srb->DataTransferLength);
902 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
903 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
904 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
905 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
906 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
907 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
908 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
909 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
910 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
911 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
912 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
913 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
914 data_buffer[12] = 0;
915 switch (xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector) {
916 case 1:
917 data_buffer[13] = 0; /* 512 byte hardware sectors */
918 break;
919 case 2:
920 data_buffer[13] = 1; /* 1024 byte hardware sectors */
921 break;
922 case 3:
923 data_buffer[13] = 2; /* 2048 byte hardware sectors */
924 break;
925 case 4:
926 data_buffer[13] = 3; /* 4096 byte hardware sectors */
927 break;
928 default:
929 data_buffer[13] = 0; /* 512 byte hardware sectors */
930 FUNCTION_MSG("Unknown logical blocks per physical block %d (%d / %d)\n", xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector, xvdd->hw_bytes_per_sector, xvdd->bytes_per_sector);
931 break;
932 }
933 data_buffer[14] = 0xC0; //0;
934 data_buffer[15] = 0;
935 data_transfer_length = 16;
936 srb->ScsiStatus = 0;
937 srb_status = SRB_STATUS_SUCCESS;
938 break;
939 case SCSIOP_MODE_SENSE:
940 case SCSIOP_MODE_SENSE10:
941 if (dump_mode)
942 FUNCTION_MSG("Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", srb->Cdb[1] & 0x08, srb->Cdb[2] & 0xC0, srb->Cdb[2] & 0x3F);
943 data_transfer_length = XenVbd_FillModePage(xvdd, srb);
944 srb_status = SRB_STATUS_SUCCESS;
945 break;
946 case SCSIOP_READ:
947 case SCSIOP_READ16:
948 case SCSIOP_WRITE:
949 case SCSIOP_WRITE16:
950 //FUNCTION_MSG("srb = %p\n", srb);
951 if (XenVbd_PutSrbOnRing(xvdd, srb)) {
952 notify = TRUE;
953 }
954 break;
955 case SCSIOP_WRITE_SAME:
956 case SCSIOP_WRITE_SAME16:
957 /* not yet supported */
958 FUNCTION_MSG("WRITE_SAME\n");
959 srb_status = SRB_STATUS_ERROR;
960 break;
961 case SCSIOP_UNMAP:
962 /* not yet supported */
963 FUNCTION_MSG("UNMAP\n");
964 srb_status = SRB_STATUS_ERROR;
965 break;
966 case SCSIOP_VERIFY:
967 case SCSIOP_VERIFY16:
968 // Should we do more here?
969 if (dump_mode)
970 FUNCTION_MSG("Command = VERIFY\n");
971 srb_status = SRB_STATUS_SUCCESS;
972 break;
973 case SCSIOP_REPORT_LUNS:
974 //if (dump_mode)
975 FUNCTION_MSG("Command = REPORT_LUNS\n");
976 switch (srb->Cdb[2]) {
977 case 1:
978 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
979 break;
980 default:
981 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
982 break;
983 }
984 FUNCTION_MSG(" ALLOCATION LENGTH = %d\n", (srb->Cdb[6] << 24)|(srb->Cdb[7] << 16)|(srb->Cdb[8] << 8)|(srb->Cdb[9]));
985 data_buffer = srb->DataBuffer;
986 RtlZeroMemory(data_buffer, srb->DataTransferLength);
987 data_buffer[3] = 8; /* 1 lun */
988 /* rest of the data is blank */
989 data_transfer_length = 16;
990 srb->ScsiStatus = 0;
991 srb_status = SRB_STATUS_SUCCESS;
992 break;
993 case SCSIOP_REQUEST_SENSE:
994 if (dump_mode)
995 FUNCTION_MSG("Command = REQUEST_SENSE\n");
996 data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
997 srb_status = SRB_STATUS_SUCCESS;
998 break;
999 case SCSIOP_READ_TOC:
1000 //if (dump_mode)
1001 FUNCTION_MSG("Command = READ_TOC\n");
1002 data_buffer = srb->DataBuffer;
1003 /*
1004 #define READ_TOC_FORMAT_TOC 0x00
1005 #define READ_TOC_FORMAT_SESSION 0x01
1006 #define READ_TOC_FORMAT_FULL_TOC 0x02
1007 #define READ_TOC_FORMAT_PMA 0x03
1008 #define READ_TOC_FORMAT_ATIP 0x04
1009 */
1010 switch (cdb->READ_TOC.Format2) {
1011 case READ_TOC_FORMAT_TOC:
1012 data_buffer[0] = 0; // length MSB
1013 data_buffer[1] = 10; // length LSB
1014 data_buffer[2] = 1; // First Track
1015 data_buffer[3] = 1; // Last Track
1016 data_buffer[4] = 0; // Reserved
1017 data_buffer[5] = 0x14; // current position data + uninterrupted data
1018 data_buffer[6] = 1; // last complete track
1019 data_buffer[7] = 0; // reserved
1020 data_buffer[8] = 0; // MSB Block
1021 data_buffer[9] = 0;
1022 data_buffer[10] = 0;
1023 data_buffer[11] = 0; // LSB Block
1024 data_transfer_length = 12;
1025 srb_status = SRB_STATUS_SUCCESS;
1026 break;
1027 case READ_TOC_FORMAT_SESSION:
1028 case READ_TOC_FORMAT_FULL_TOC:
1029 case READ_TOC_FORMAT_PMA:
1030 case READ_TOC_FORMAT_ATIP:
1031 srb_status = SRB_STATUS_ERROR;
1032 break;
1033 default:
1034 srb_status = SRB_STATUS_ERROR;
1035 break;
1037 break;
1038 case SCSIOP_START_STOP_UNIT:
1039 FUNCTION_MSG("Command = SCSIOP_START_STOP_UNIT\n");
1040 srb_status = SRB_STATUS_SUCCESS;
1041 break;
1042 case SCSIOP_RESERVE_UNIT:
1043 FUNCTION_MSG("Command = SCSIOP_RESERVE_UNIT\n");
1044 srb_status = SRB_STATUS_SUCCESS;
1045 break;
1046 case SCSIOP_RELEASE_UNIT:
1047 FUNCTION_MSG("Command = SCSIOP_RELEASE_UNIT\n");
1048 srb_status = SRB_STATUS_SUCCESS;
1049 break;
1050 case SCSIOP_SYNCHRONIZE_CACHE:
1051 FUNCTION_MSG("Command = SCSIOP_SYNCHRONIZE_CACHE\n");
1052 srb_status = SRB_STATUS_SUCCESS;
1053 break;
1054 default:
1055 FUNCTION_MSG("Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]);
1056 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1057 srb_status = SRB_STATUS_ERROR;
1058 break;
1060 if (srb_status == SRB_STATUS_ERROR) {
1061 FUNCTION_MSG("EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key);
1062 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE) {
1063 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1064 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1066 srb->SrbStatus = srb_status;
1067 srb->ScsiStatus = 0x02;
1068 XenVbd_MakeAutoSense(xvdd, srb);
1069 SxxxPortNotification(RequestComplete, xvdd, srb);
1070 } else if (srb_status != SRB_STATUS_PENDING) {
1071 if (srb->ScsiStatus != 0) {
1072 FUNCTION_MSG("ScsiStatus = 0x%02x\n", srb->ScsiStatus);
1074 if (data_transfer_length > srb->DataTransferLength)
1075 FUNCTION_MSG("data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength);
1077 if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength) {
1078 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1079 srb->DataTransferLength = data_transfer_length;
1080 } else {
1081 srb->SrbStatus = srb_status;
1083 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1084 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1085 SxxxPortNotification(RequestComplete, xvdd, srb);
1087 break;
1088 case SRB_FUNCTION_FLUSH:
1089 FUNCTION_MSG("SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1090 srb->SrbStatus = SRB_STATUS_SUCCESS;
1091 SxxxPortNotification(RequestComplete, xvdd, srb);
1092 break;
1093 #ifdef _NTSTORPORT_
1094 case SRB_FUNCTION_PNP:
1095 FUNCTION_MSG("SRB_FUNCTION_PNP\n");
1096 sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
1097 switch (sprb->PnPAction)
1099 case StorStartDevice:
1100 FUNCTION_MSG(" StorStartDevice\n");
1101 break;
1102 case StorRemoveDevice:
1103 FUNCTION_MSG(" StorRemoveDevice\n");
1104 break;
1105 case StorStopDevice:
1106 FUNCTION_MSG(" StorStopDevice\n");
1107 break;
1108 case StorQueryCapabilities:
1109 FUNCTION_MSG(" StorQueryCapabilities\n");
1110 break;
1111 case StorFilterResourceRequirements:
1112 FUNCTION_MSG(" StorFilterResourceRequirements\n");
1113 break;
1114 default:
1115 FUNCTION_MSG(" Stor%d\n", sprb->PnPAction);
1116 break;
1118 FUNCTION_MSG(" SrbPnPFlags = %08x\n", sprb->SrbPnPFlags);
1119 srb->SrbStatus = SRB_STATUS_SUCCESS;
1120 SxxxPortNotification(RequestComplete, xvdd, srb);
1121 break;
1123 case SRB_FUNCTION_POWER:
1124 FUNCTION_MSG("SRB_FUNCTION_POWER\n");
1125 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
1126 spwrb = (PSCSI_POWER_REQUEST_BLOCK)srb;
1127 if (spwrb->DevicePowerState == StorPowerDeviceD0) {
1128 FUNCTION_MSG("Entering D0\n");
1129 } else {
1130 FUNCTION_MSG("Entering D%d (%d)\n", spwrb->DevicePowerState - StorPowerDeviceD0, spwrb->DevicePowerState);
1131 switch (spwrb->PowerAction) {
1132 case StorPowerActionNone:
1133 FUNCTION_MSG(" StorPowerActionNone\n");
1134 break;
1135 case StorPowerActionReserved:
1136 FUNCTION_MSG(" StorPowerActionReserved\n");
1137 break;
1138 case StorPowerActionSleep:
1139 FUNCTION_MSG(" StorPowerActionSleep\n");
1140 break;
1141 case StorPowerActionHibernate:
1142 FUNCTION_MSG(" StorPowerActionHibernate\n");
1143 break;
1144 case StorPowerActionShutdown:
1145 FUNCTION_MSG(" StorPowerActionShutdown\n");
1146 break;
1147 case StorPowerActionShutdownReset:
1148 FUNCTION_MSG(" StorPowerActionShutdownReset\n");
1149 break;
1150 case StorPowerActionShutdownOff:
1151 FUNCTION_MSG(" StorPowerActionShutdownOff\n");
1152 break;
1153 case StorPowerActionWarmEject:
1154 FUNCTION_MSG(" StorPowerActionWarmEject\n");
1155 break;
1156 default:
1157 FUNCTION_MSG(" Stor%d\n", spwrb->PowerAction);
1158 break;
1161 xvdd->power_state = spwrb->DevicePowerState;
1162 xvdd->power_action = spwrb->PowerAction;
1163 srb->SrbStatus = SRB_STATUS_SUCCESS;
1164 SxxxPortNotification(RequestComplete, xvdd, srb);
1165 break;
1166 case SRB_FUNCTION_DUMP_POINTERS:
1167 FUNCTION_MSG("SRB_FUNCTION_DUMP_POINTERS\n");
1168 FUNCTION_MSG("DataTransferLength = %d\n", srb->DataTransferLength);
1169 dump_pointers = srb->DataBuffer;
1170 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1171 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1172 FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1173 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1174 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1175 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1176 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1177 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1178 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1179 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1180 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1181 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1182 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1183 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1184 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1185 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1186 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1188 dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
1189 dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
1190 RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
1191 dump_pointers->AdapterObject = NULL;
1192 dump_pointers->MappedRegisterBase = 0;
1193 dump_pointers->CommonBufferSize = 0;
1194 dump_pointers->MiniportPrivateDumpData = xvdd;
1195 dump_pointers->MaximumTransferLength = 4 * 1024 * 1024;
1196 dump_pointers->NumberOfPhysicalBreaks = dump_pointers->MaximumTransferLength >> PAGE_SHIFT;
1197 dump_pointers->AlignmentMask = 0;
1198 dump_pointers->NumberOfAccessRanges = 0;
1199 dump_pointers->NumberOfBuses = 1;
1200 dump_pointers->Master = TRUE;
1201 dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
1202 dump_pointers->MaximumNumberOfTargets = 2;
1204 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1205 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1206 //FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1207 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1208 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1209 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1210 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1211 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1212 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1213 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1214 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1215 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1216 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1217 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1218 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1219 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1220 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1222 srb->SrbStatus = SRB_STATUS_SUCCESS;
1223 SxxxPortNotification(RequestComplete, xvdd, srb);
1224 break;
1225 #endif
1226 case SRB_FUNCTION_SHUTDOWN:
1227 FUNCTION_MSG("SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1228 srb->SrbStatus = SRB_STATUS_SUCCESS;
1229 SxxxPortNotification(RequestComplete, xvdd, srb);
1230 break;
1231 case SRB_FUNCTION_RESET_BUS:
1232 case SRB_FUNCTION_RESET_DEVICE:
1233 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
1234 /* the path doesn't matter here - only ever one device*/
1235 FUNCTION_MSG("SRB_FUNCTION_RESET_XXX\n");
1236 XenVbd_ResetBus(xvdd, 0);
1237 srb->SrbStatus = SRB_STATUS_SUCCESS;
1238 SxxxPortNotification(RequestComplete, xvdd, srb);
1239 break;
1240 case SRB_FUNCTION_WMI:
1241 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1242 SxxxPortNotification(RequestComplete, xvdd, srb);
1243 break;
1244 case SRB_FUNCTION_IO_CONTROL:
1245 FUNCTION_MSG("SRB_FUNCTION_IO_CONTROL\n");
1246 sic = srb->DataBuffer;
1247 FUNCTION_MSG("ControlCode = %d\n", sic->ControlCode);
1248 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1249 SxxxPortNotification(RequestComplete, xvdd, srb);
1250 break;
1251 case 0x27:
1252 FUNCTION_MSG("SRB_FUNCTION_FREE_DUMP_POINTERS\n");
1253 srb->SrbStatus = SRB_STATUS_SUCCESS;
1254 SxxxPortNotification(RequestComplete, xvdd, srb);
1255 break;
1256 default:
1257 FUNCTION_MSG("Unhandled srb->Function = %08X\n", srb->Function);
1258 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1259 SxxxPortNotification(RequestComplete, xvdd, srb);
1260 break;
1262 if ((PLIST_ENTRY)srb_entry == xvdd->srb_list.Flink && srb_entry->offset == prev_offset) {
1263 FUNCTION_MSG("Same entry\n");
1264 /* same entry was put back onto the head of the list unchanged, so we can't progress */
1265 break;
1268 if (notify) {
1269 notify = FALSE;
1270 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
1271 if (notify) {
1272 XnNotify(xvdd->handle, xvdd->event_channel);
1275 return;