win-pvdrivers

view xenvbd_common/common_miniport.h @ 1025:aa2e51f67f7c

Fix hibernate under Win8. Change debugprints.
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 19 15:14:53 2013 +1100 (2013-02-19)
parents 9c6af8d0bdb6
children 306c10cdcba1
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 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) {
685 srb = srb_entry->srb;
686 prev_offset = srb_entry->offset;
687 if (xvdd->device_state == DEVICE_STATE_INACTIVE) {
688 /* need to check again as may have been initialising when this srb was put on the list */
689 FUNCTION_MSG("Inactive Device (in ProcessSrbList)\n");
690 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
691 SxxxPortNotification(RequestComplete, xvdd, srb);
692 continue;
693 }
695 data_transfer_length = srb->DataTransferLength;
696 srb_status = SRB_STATUS_PENDING;
698 switch (srb->Function) {
699 case SRB_FUNCTION_EXECUTE_SCSI:
700 if (xvdd->device_state != DEVICE_STATE_ACTIVE) {
701 FUNCTION_MSG("Not yet active - state = %d\n", xvdd->device_state);
702 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
703 break;
704 }
705 cdb = (PCDB)srb->Cdb;
706 switch(cdb->CDB6GENERIC.OperationCode) {
707 case SCSIOP_TEST_UNIT_READY:
708 if (dump_mode)
709 FUNCTION_MSG("Command = TEST_UNIT_READY\n");
710 srb_status = SRB_STATUS_SUCCESS;
711 srb->ScsiStatus = 0;
712 break;
713 case SCSIOP_INQUIRY:
714 // if (dump_mode)
715 FUNCTION_MSG("Command = INQUIRY\n");
716 // FUNCTION_MSG("(LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]);
717 // FUNCTION_MSG("(Length = %d)\n", srb->DataTransferLength);
719 data_buffer = srb->DataBuffer;
720 RtlZeroMemory(data_buffer, srb->DataTransferLength);
721 srb_status = SRB_STATUS_SUCCESS;
722 switch (xvdd->device_type)
723 {
724 case XENVBD_DEVICETYPE_DISK:
725 if ((srb->Cdb[1] & 1) == 0) {
726 if (srb->Cdb[2]) {
727 srb_status = SRB_STATUS_ERROR;
728 } else {
729 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
730 id->DeviceType = DIRECT_ACCESS_DEVICE;
731 id->Versions = 5; /* SPC-3 */
732 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
733 id->HiSupport = 1; /* WHQL test says we should set this */
734 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
735 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
736 id->CommandQueue = 1;
737 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
738 memcpy(id->ProductId, SCSI_DISK_MODEL, 16); // product id
739 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
740 data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
741 }
742 } else {
743 switch (srb->Cdb[2]) {
744 case VPD_SUPPORTED_PAGES: /* list of pages we support */
745 FUNCTION_MSG("VPD_SUPPORTED_PAGES\n");
746 data_buffer[0] = DIRECT_ACCESS_DEVICE;
747 data_buffer[1] = VPD_SUPPORTED_PAGES;
748 data_buffer[2] = 0x00;
749 data_buffer[3] = 4;
750 data_buffer[4] = VPD_SUPPORTED_PAGES;
751 data_buffer[5] = VPD_SERIAL_NUMBER;
752 data_buffer[6] = VPD_DEVICE_IDENTIFIERS;
753 data_buffer[7] = VPD_BLOCK_LIMITS;
754 data_transfer_length = 8;
755 break;
756 case VPD_SERIAL_NUMBER: /* serial number */
757 FUNCTION_MSG("VPD_SERIAL_NUMBER\n");
758 data_buffer[0] = DIRECT_ACCESS_DEVICE;
759 data_buffer[1] = VPD_SERIAL_NUMBER;
760 data_buffer[2] = 0x00;
761 data_buffer[3] = (UCHAR)strlen(xvdd->serial_number);
762 if (data_transfer_length > 4) {
763 memcpy(&data_buffer[4], xvdd->serial_number, min(data_transfer_length - 4, strlen(xvdd->serial_number)));
764 }
765 data_transfer_length = 4 + (UCHAR)strlen(xvdd->serial_number);
766 break;
767 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
768 FUNCTION_MSG("VPD_DEVICE_IDENTIFIERS\n");
769 data_buffer[0] = DIRECT_ACCESS_DEVICE;
770 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
771 data_buffer[2] = 0x00;
772 data_buffer[3] = 2 * (4 + (UCHAR)strlen(xvdd->serial_number));
773 if (data_transfer_length >= 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number))) {
774 data_buffer[4] = 2; /* ASCII */
775 data_buffer[5] = 0; /* VendorId */
776 data_buffer[6] = 0; /* reserved */
777 data_buffer[7] = (UCHAR)strlen(xvdd->serial_number);
778 memcpy(&data_buffer[8], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
779 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 0] = 2; /* ASCII */
780 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 1] = 1; /* T10 VendorId */
781 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 2] = 0; /* Reserved */
782 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 3] = (UCHAR)strlen(xvdd->serial_number);
783 memcpy(&data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 4], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
784 }
785 data_transfer_length = 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number));
786 break;
787 case VPD_BLOCK_LIMITS: /* to indicate support for UNMAP (TRIM/DISCARD) */
788 FUNCTION_MSG("VPD_BLOCK_LIMITS\n");
789 // max descriptors = 1
790 // max sectors = 0xFFFFFFFF
791 // granularity = from xenbus
792 // alignment = from xenbus(?)
793 srb_status = SRB_STATUS_ERROR;
794 break;
795 default:
796 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
797 srb_status = SRB_STATUS_ERROR;
798 break;
799 }
800 }
801 break;
802 case XENVBD_DEVICETYPE_CDROM:
803 if ((srb->Cdb[1] & 1) == 0)
804 {
805 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
806 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
807 id->RemovableMedia = 1;
808 id->Versions = 3;
809 id->ResponseDataFormat = 0;
810 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
811 id->CommandQueue = 1;
812 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
813 memcpy(id->ProductId, SCSI_CDROM_MODEL, 16); // product id
814 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
815 data_transfer_length = sizeof(INQUIRYDATA);
816 }
817 else
818 {
819 switch (srb->Cdb[2])
820 {
821 case 0x00:
822 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
823 data_buffer[1] = 0x00;
824 data_buffer[2] = 0x00;
825 data_buffer[3] = 2;
826 data_buffer[4] = 0x00;
827 data_buffer[5] = 0x80;
828 data_transfer_length = 6;
829 break;
830 case 0x80:
831 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
832 data_buffer[1] = 0x80;
833 data_buffer[2] = 0x00;
834 data_buffer[3] = 8;
835 data_buffer[4] = 0x31;
836 data_buffer[5] = 0x32;
837 data_buffer[6] = 0x33;
838 data_buffer[7] = 0x34;
839 data_buffer[8] = 0x35;
840 data_buffer[9] = 0x36;
841 data_buffer[10] = 0x37;
842 data_buffer[11] = 0x38;
843 data_transfer_length = 12;
844 break;
845 default:
846 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
847 srb_status = SRB_STATUS_ERROR;
848 break;
849 }
850 }
851 break;
852 default:
853 FUNCTION_MSG("Unknown DeviceType %02x requested\n", xvdd->device_type);
854 srb_status = SRB_STATUS_ERROR;
855 break;
856 }
857 break;
858 case SCSIOP_READ_CAPACITY:
859 //if (dump_mode)
860 FUNCTION_MSG("Command = READ_CAPACITY\n");
861 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
862 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
863 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
864 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
865 data_buffer = srb->DataBuffer;
866 RtlZeroMemory(data_buffer, srb->DataTransferLength);
867 if ((xvdd->total_sectors - 1) >> 32) {
868 data_buffer[0] = 0xff;
869 data_buffer[1] = 0xff;
870 data_buffer[2] = 0xff;
871 data_buffer[3] = 0xff;
872 } else {
873 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
874 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
875 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
876 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
877 }
878 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
879 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
880 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
881 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
882 data_transfer_length = 8;
883 srb->ScsiStatus = 0;
884 srb_status = SRB_STATUS_SUCCESS;
885 break;
886 case SCSIOP_READ_CAPACITY16:
887 //if (dump_mode)
888 FUNCTION_MSG("Command = READ_CAPACITY16\n");
889 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
890 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
891 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
892 data_buffer = srb->DataBuffer;
893 RtlZeroMemory(data_buffer, srb->DataTransferLength);
894 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
895 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
896 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
897 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
898 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
899 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
900 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
901 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
902 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
903 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
904 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
905 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
906 data_buffer[12] = 0;
907 switch (xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector) {
908 case 1:
909 data_buffer[13] = 0; /* 512 byte hardware sectors */
910 break;
911 case 2:
912 data_buffer[13] = 1; /* 1024 byte hardware sectors */
913 break;
914 case 3:
915 data_buffer[13] = 2; /* 2048 byte hardware sectors */
916 break;
917 case 4:
918 data_buffer[13] = 3; /* 4096 byte hardware sectors */
919 break;
920 default:
921 data_buffer[13] = 0; /* 512 byte hardware sectors */
922 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);
923 break;
924 }
925 data_buffer[14] = 0xC0; //0;
926 data_buffer[15] = 0;
927 data_transfer_length = 16;
928 srb->ScsiStatus = 0;
929 srb_status = SRB_STATUS_SUCCESS;
930 break;
931 case SCSIOP_MODE_SENSE:
932 case SCSIOP_MODE_SENSE10:
933 if (dump_mode)
934 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);
935 data_transfer_length = XenVbd_FillModePage(xvdd, srb);
936 srb_status = SRB_STATUS_SUCCESS;
937 break;
938 case SCSIOP_READ:
939 case SCSIOP_READ16:
940 case SCSIOP_WRITE:
941 case SCSIOP_WRITE16:
942 //FUNCTION_MSG("srb = %p\n", srb);
943 if (XenVbd_PutSrbOnRing(xvdd, srb)) {
944 notify = TRUE;
945 }
946 break;
947 case SCSIOP_WRITE_SAME:
948 case SCSIOP_WRITE_SAME16:
949 /* not yet supported */
950 FUNCTION_MSG("WRITE_SAME\n");
951 srb_status = SRB_STATUS_ERROR;
952 break;
953 case SCSIOP_UNMAP:
954 /* not yet supported */
955 FUNCTION_MSG("UNMAP\n");
956 srb_status = SRB_STATUS_ERROR;
957 break;
958 case SCSIOP_VERIFY:
959 case SCSIOP_VERIFY16:
960 // Should we do more here?
961 if (dump_mode)
962 FUNCTION_MSG("Command = VERIFY\n");
963 srb_status = SRB_STATUS_SUCCESS;
964 break;
965 case SCSIOP_REPORT_LUNS:
966 //if (dump_mode)
967 FUNCTION_MSG("Command = REPORT_LUNS\n");
968 switch (srb->Cdb[2]) {
969 case 1:
970 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
971 break;
972 default:
973 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
974 break;
975 }
976 FUNCTION_MSG(" ALLOCATION LENGTH = %d\n", (srb->Cdb[6] << 24)|(srb->Cdb[7] << 16)|(srb->Cdb[8] << 8)|(srb->Cdb[9]));
977 data_buffer = srb->DataBuffer;
978 RtlZeroMemory(data_buffer, srb->DataTransferLength);
979 data_buffer[3] = 8; /* 1 lun */
980 /* rest of the data is blank */
981 data_transfer_length = 16;
982 srb->ScsiStatus = 0;
983 srb_status = SRB_STATUS_SUCCESS;
984 break;
985 case SCSIOP_REQUEST_SENSE:
986 if (dump_mode)
987 FUNCTION_MSG("Command = REQUEST_SENSE\n");
988 data_transfer_length = XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
989 srb_status = SRB_STATUS_SUCCESS;
990 break;
991 case SCSIOP_READ_TOC:
992 //if (dump_mode)
993 FUNCTION_MSG("Command = READ_TOC\n");
994 data_buffer = srb->DataBuffer;
995 /*
996 #define READ_TOC_FORMAT_TOC 0x00
997 #define READ_TOC_FORMAT_SESSION 0x01
998 #define READ_TOC_FORMAT_FULL_TOC 0x02
999 #define READ_TOC_FORMAT_PMA 0x03
1000 #define READ_TOC_FORMAT_ATIP 0x04
1001 */
1002 switch (cdb->READ_TOC.Format2) {
1003 case READ_TOC_FORMAT_TOC:
1004 data_buffer[0] = 0; // length MSB
1005 data_buffer[1] = 10; // length LSB
1006 data_buffer[2] = 1; // First Track
1007 data_buffer[3] = 1; // Last Track
1008 data_buffer[4] = 0; // Reserved
1009 data_buffer[5] = 0x14; // current position data + uninterrupted data
1010 data_buffer[6] = 1; // last complete track
1011 data_buffer[7] = 0; // reserved
1012 data_buffer[8] = 0; // MSB Block
1013 data_buffer[9] = 0;
1014 data_buffer[10] = 0;
1015 data_buffer[11] = 0; // LSB Block
1016 data_transfer_length = 12;
1017 srb_status = SRB_STATUS_SUCCESS;
1018 break;
1019 case READ_TOC_FORMAT_SESSION:
1020 case READ_TOC_FORMAT_FULL_TOC:
1021 case READ_TOC_FORMAT_PMA:
1022 case READ_TOC_FORMAT_ATIP:
1023 srb_status = SRB_STATUS_ERROR;
1024 break;
1025 default:
1026 srb_status = SRB_STATUS_ERROR;
1027 break;
1029 break;
1030 case SCSIOP_START_STOP_UNIT:
1031 FUNCTION_MSG("Command = SCSIOP_START_STOP_UNIT\n");
1032 srb_status = SRB_STATUS_SUCCESS;
1033 break;
1034 case SCSIOP_RESERVE_UNIT:
1035 FUNCTION_MSG("Command = SCSIOP_RESERVE_UNIT\n");
1036 srb_status = SRB_STATUS_SUCCESS;
1037 break;
1038 case SCSIOP_RELEASE_UNIT:
1039 FUNCTION_MSG("Command = SCSIOP_RELEASE_UNIT\n");
1040 srb_status = SRB_STATUS_SUCCESS;
1041 break;
1042 case SCSIOP_SYNCHRONIZE_CACHE:
1043 FUNCTION_MSG("Command = SCSIOP_SYNCHRONIZE_CACHE\n");
1044 srb_status = SRB_STATUS_SUCCESS;
1045 break;
1046 default:
1047 FUNCTION_MSG("Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]);
1048 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1049 srb_status = SRB_STATUS_ERROR;
1050 break;
1052 if (srb_status == SRB_STATUS_ERROR) {
1053 FUNCTION_MSG("EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key);
1054 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE) {
1055 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1056 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1058 srb->SrbStatus = srb_status;
1059 srb->ScsiStatus = 0x02;
1060 XenVbd_MakeAutoSense(xvdd, srb);
1061 SxxxPortNotification(RequestComplete, xvdd, srb);
1062 } else if (srb_status != SRB_STATUS_PENDING) {
1063 if (srb->ScsiStatus != 0) {
1064 FUNCTION_MSG("ScsiStatus = 0x%02x\n", srb->ScsiStatus);
1066 if (data_transfer_length > srb->DataTransferLength)
1067 FUNCTION_MSG("data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength);
1069 if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength) {
1070 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1071 srb->DataTransferLength = data_transfer_length;
1072 } else {
1073 srb->SrbStatus = srb_status;
1075 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1076 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1077 SxxxPortNotification(RequestComplete, xvdd, srb);
1079 break;
1080 case SRB_FUNCTION_FLUSH:
1081 FUNCTION_MSG("SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1082 srb->SrbStatus = SRB_STATUS_SUCCESS;
1083 SxxxPortNotification(RequestComplete, xvdd, srb);
1084 break;
1085 #ifdef _NTSTORPORT_
1086 case SRB_FUNCTION_PNP:
1087 FUNCTION_MSG("SRB_FUNCTION_PNP\n");
1088 sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
1089 switch (sprb->PnPAction)
1091 case StorStartDevice:
1092 FUNCTION_MSG(" StorStartDevice\n");
1093 break;
1094 case StorRemoveDevice:
1095 FUNCTION_MSG(" StorRemoveDevice\n");
1096 break;
1097 case StorStopDevice:
1098 FUNCTION_MSG(" StorStopDevice\n");
1099 break;
1100 case StorQueryCapabilities:
1101 FUNCTION_MSG(" StorQueryCapabilities\n");
1102 break;
1103 case StorFilterResourceRequirements:
1104 FUNCTION_MSG(" StorFilterResourceRequirements\n");
1105 break;
1106 default:
1107 FUNCTION_MSG(" Stor%d\n", sprb->PnPAction);
1108 break;
1110 FUNCTION_MSG(" SrbPnPFlags = %08x\n", sprb->SrbPnPFlags);
1111 srb->SrbStatus = SRB_STATUS_SUCCESS;
1112 SxxxPortNotification(RequestComplete, xvdd, srb);
1113 break;
1115 case SRB_FUNCTION_POWER:
1116 FUNCTION_MSG("SRB_FUNCTION_POWER\n");
1117 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
1118 spwrb = (PSCSI_POWER_REQUEST_BLOCK)srb;
1119 if (spwrb->DevicePowerState == StorPowerDeviceD0) {
1120 FUNCTION_MSG("Entering D0\n");
1121 } else {
1122 FUNCTION_MSG("Entering D%d (%d)\n", spwrb->DevicePowerState - StorPowerDeviceD0, spwrb->DevicePowerState);
1123 switch (spwrb->PowerAction) {
1124 case StorPowerActionNone:
1125 FUNCTION_MSG(" StorPowerActionNone\n");
1126 break;
1127 case StorPowerActionReserved:
1128 FUNCTION_MSG(" StorPowerActionReserved\n");
1129 break;
1130 case StorPowerActionSleep:
1131 FUNCTION_MSG(" StorPowerActionSleep\n");
1132 break;
1133 case StorPowerActionHibernate:
1134 FUNCTION_MSG(" StorPowerActionHibernate\n");
1135 break;
1136 case StorPowerActionShutdown:
1137 FUNCTION_MSG(" StorPowerActionShutdown\n");
1138 break;
1139 case StorPowerActionShutdownReset:
1140 FUNCTION_MSG(" StorPowerActionShutdownReset\n");
1141 break;
1142 case StorPowerActionShutdownOff:
1143 FUNCTION_MSG(" StorPowerActionShutdownOff\n");
1144 break;
1145 case StorPowerActionWarmEject:
1146 FUNCTION_MSG(" StorPowerActionWarmEject\n");
1147 break;
1148 default:
1149 FUNCTION_MSG(" Stor%d\n", spwrb->PowerAction);
1150 break;
1153 xvdd->power_state = spwrb->DevicePowerState;
1154 xvdd->power_action = spwrb->PowerAction;
1155 srb->SrbStatus = SRB_STATUS_SUCCESS;
1156 SxxxPortNotification(RequestComplete, xvdd, srb);
1157 break;
1158 case SRB_FUNCTION_DUMP_POINTERS:
1159 FUNCTION_MSG("SRB_FUNCTION_DUMP_POINTERS\n");
1160 FUNCTION_MSG("DataTransferLength = %d\n", srb->DataTransferLength);
1161 dump_pointers = srb->DataBuffer;
1162 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1163 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1164 FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1165 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1166 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1167 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1168 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1169 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1170 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1171 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1172 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1173 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1174 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1175 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1176 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1177 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1178 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1180 dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
1181 dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
1182 RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
1183 dump_pointers->AdapterObject = NULL;
1184 dump_pointers->MappedRegisterBase = 0;
1185 dump_pointers->CommonBufferSize = 0;
1186 dump_pointers->MiniportPrivateDumpData = xvdd;
1187 dump_pointers->MaximumTransferLength = 4 * 1024 * 1024;
1188 dump_pointers->NumberOfPhysicalBreaks = dump_pointers->MaximumTransferLength >> PAGE_SHIFT;
1189 dump_pointers->AlignmentMask = 0;
1190 dump_pointers->NumberOfAccessRanges = 0;
1191 dump_pointers->NumberOfBuses = 1;
1192 dump_pointers->Master = TRUE;
1193 dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
1194 dump_pointers->MaximumNumberOfTargets = 2;
1196 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1197 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1198 //FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1199 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1200 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1201 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1202 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1203 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1204 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1205 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1206 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1207 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1208 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1209 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1210 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1211 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1212 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1214 srb->SrbStatus = SRB_STATUS_SUCCESS;
1215 SxxxPortNotification(RequestComplete, xvdd, srb);
1216 break;
1217 #endif
1218 case SRB_FUNCTION_SHUTDOWN:
1219 FUNCTION_MSG("SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1220 srb->SrbStatus = SRB_STATUS_SUCCESS;
1221 SxxxPortNotification(RequestComplete, xvdd, srb);
1222 break;
1223 case SRB_FUNCTION_RESET_BUS:
1224 case SRB_FUNCTION_RESET_DEVICE:
1225 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
1226 /* the path doesn't matter here - only ever one device*/
1227 FUNCTION_MSG("SRB_FUNCTION_RESET_XXX\n");
1228 XenVbd_ResetBus(xvdd, 0);
1229 srb->SrbStatus = SRB_STATUS_SUCCESS;
1230 SxxxPortNotification(RequestComplete, xvdd, srb);
1231 break;
1232 case SRB_FUNCTION_WMI:
1233 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1234 SxxxPortNotification(RequestComplete, xvdd, srb);
1235 break;
1236 case SRB_FUNCTION_IO_CONTROL:
1237 FUNCTION_MSG("SRB_FUNCTION_IO_CONTROL\n");
1238 sic = srb->DataBuffer;
1239 FUNCTION_MSG("ControlCode = %d\n", sic->ControlCode);
1240 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1241 SxxxPortNotification(RequestComplete, xvdd, srb);
1242 break;
1243 case 0x27:
1244 FUNCTION_MSG("SRB_FUNCTION_FREE_DUMP_POINTERS\n");
1245 srb->SrbStatus = SRB_STATUS_SUCCESS;
1246 SxxxPortNotification(RequestComplete, xvdd, srb);
1247 break;
1248 default:
1249 FUNCTION_MSG("Unhandled srb->Function = %08X\n", srb->Function);
1250 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1251 SxxxPortNotification(RequestComplete, xvdd, srb);
1252 break;
1254 if ((PLIST_ENTRY)srb_entry == xvdd->srb_list.Flink && srb_entry->offset == prev_offset) {
1255 FUNCTION_MSG("Same entry\n");
1256 /* same entry was put back onto the head of the list unchanged, so we can't progress */
1257 break;
1260 if (notify) {
1261 notify = FALSE;
1262 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
1263 if (notify) {
1264 XnNotify(xvdd->handle, xvdd->event_channel);
1267 return;