win-pvdrivers

view xenvbd_common/common_miniport.h @ 1044:9f476ac2fbe1

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