win-pvdrivers

view xenvbd_common/common_miniport.h @ 1088:53eb8a11ea2f

fix sector size detection
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 24 15:43:51 2013 +1100 (2013-12-24)
parents 4de2eb034713
children 27bd2a5a4704
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 switch (srb->Cdb[0]) {
68 case SCSIOP_READ:
69 case SCSIOP_WRITE:
70 return ((ULONG)(UCHAR)srb->Cdb[7] << 8) | (ULONG)(UCHAR)srb->Cdb[8];
71 case SCSIOP_READ16:
72 case SCSIOP_WRITE16:
73 return ((ULONG)(UCHAR)srb->Cdb[10] << 24) | ((ULONG)(UCHAR)srb->Cdb[11] << 16) | ((ULONG)(UCHAR)srb->Cdb[12] << 8) | (ULONG)(UCHAR)srb->Cdb[13];
74 default:
75 FUNCTION_MSG("Unknown SCSIOP function %02x\n", srb->Cdb[0]);
76 return 0;
77 }
78 }
80 static blkif_response_t *
81 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i) {
82 return RING_GET_RESPONSE(&xvdd->ring, i);
83 }
85 static VOID
86 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req) {
87 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
88 xvdd->ring.req_prod_pvt++;
89 }
91 static VOID
92 XenVbd_PutSrbOnList(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb) {
93 srb_list_entry_t *srb_entry = srb->SrbExtension;
94 srb_entry->srb = srb;
95 srb_entry->outstanding_requests = 0;
96 srb_entry->length = srb->DataTransferLength;
97 srb_entry->offset = 0;
98 srb_entry->error = FALSE;
99 InsertTailList(&xvdd->srb_list, (PLIST_ENTRY)srb_entry);
100 }
102 static __inline ULONGLONG
103 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
104 {
105 ULONGLONG sector;
107 switch (srb->Cdb[0]) {
108 case SCSIOP_READ:
109 case SCSIOP_WRITE:
110 sector = ((ULONG)(UCHAR)srb->Cdb[2] << 24) | ((ULONG)(UCHAR)srb->Cdb[3] << 16) | ((ULONG)(UCHAR)srb->Cdb[4] << 8) | (ULONG)(UCHAR)srb->Cdb[5];
111 break;
112 case SCSIOP_READ16:
113 case SCSIOP_WRITE16:
114 sector = ((ULONGLONG)(UCHAR)srb->Cdb[2] << 56) | ((ULONGLONG)(UCHAR)srb->Cdb[3] << 48)
115 | ((ULONGLONG)(UCHAR)srb->Cdb[4] << 40) | ((ULONGLONG)(UCHAR)srb->Cdb[5] << 32)
116 | ((ULONGLONG)(UCHAR)srb->Cdb[6] << 24) | ((ULONGLONG)(UCHAR)srb->Cdb[7] << 16)
117 | ((ULONGLONG)(UCHAR)srb->Cdb[8] << 8) | ((ULONGLONG)(UCHAR)srb->Cdb[9]);
118 //FUNCTION_MSG("sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector);
119 break;
120 default:
121 FUNCTION_MSG("Unknown SCSIOP function %02x\n", srb->Cdb[0]);
122 sector = 0;
123 break;
124 }
125 return sector;
126 }
128 static __inline BOOLEAN
129 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
130 {
131 switch (srb->Cdb[0])
132 {
133 case SCSIOP_READ:
134 case SCSIOP_READ16:
135 return TRUE;
136 case SCSIOP_WRITE:
137 case SCSIOP_WRITE16:
138 return FALSE;
139 default:
140 FUNCTION_MSG("Unknown SCSIOP function %02x\n", srb->Cdb[0]);
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 UCHAR
456 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, PULONG data_transfer_length) {
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->ScsiStatus = 0; // TODO: make this something meaningful
589 *data_transfer_length = 0;
590 return SRB_STATUS_ERROR;
591 }
592 srb->ScsiStatus = 0;
593 memcpy(srb->DataBuffer, buffer, min(srb->DataTransferLength, offset));
594 *data_transfer_length = offset;
596 return SRB_STATUS_SUCCESS;
597 }
599 static BOOLEAN
600 XenVbd_ResetBus(PXENVBD_DEVICE_DATA xvdd, ULONG PathId) {
601 //srb_list_entry_t *srb_entry;
602 int i;
603 /* need to make sure that each SRB is only reset once */
604 LIST_ENTRY srb_reset_list;
605 PLIST_ENTRY list_entry;
607 UNREFERENCED_PARAMETER(PathId);
609 FUNCTION_ENTER();
611 if (dump_mode) {
612 FUNCTION_MSG("dump mode - doing nothing\n");
613 FUNCTION_EXIT();
614 return TRUE;
615 }
617 /* It appears that the StartIo spinlock is already held at this point */
619 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
621 xvdd->aligned_buffer_in_use = FALSE;
623 InitializeListHead(&srb_reset_list);
625 /* add all queued srbs to the list */
626 while((list_entry = RemoveHeadList(&xvdd->srb_list)) != &xvdd->srb_list) {
627 #if DBG
628 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
629 FUNCTION_MSG("adding queued SRB %p to reset list\n", srb_entry->srb);
630 #endif
631 InsertTailList(&srb_reset_list, list_entry);
632 }
634 /* add any in-flight srbs that aren't already on the list (could be multiple shadows per srb if it's been broken up */
635 for (i = 0; i < MAX_SHADOW_ENTRIES; i++) {
636 if (xvdd->shadows[i].srb) {
637 srb_list_entry_t *srb_entry = xvdd->shadows[i].srb->SrbExtension;
638 for (list_entry = srb_reset_list.Flink; list_entry != &srb_reset_list; list_entry = list_entry->Flink) {
639 if (list_entry == &srb_entry->list_entry)
640 break;
641 }
642 if (list_entry == &srb_reset_list) {
643 FUNCTION_MSG("adding in-flight SRB %p to reset list\n", srb_entry->srb);
644 InsertTailList(&srb_reset_list, &srb_entry->list_entry);
645 }
646 /* set reset here so that the interrupt won't do anything with the srb but will dispose of the shadow entry correctly */
647 xvdd->shadows[i].reset = TRUE;
648 xvdd->shadows[i].srb = NULL;
649 xvdd->shadows[i].aligned_buffer_in_use = FALSE;
650 }
651 }
653 while((list_entry = RemoveHeadList(&srb_reset_list)) != &srb_reset_list) {
654 srb_list_entry_t *srb_entry = CONTAINING_RECORD(list_entry, srb_list_entry_t, list_entry);
655 srb_entry->outstanding_requests = 0;
656 srb_entry->srb->SrbStatus = SRB_STATUS_BUS_RESET;
657 FUNCTION_MSG("completing SRB %p with status SRB_STATUS_BUS_RESET\n", srb_entry->srb);
658 SxxxPortNotification(RequestComplete, xvdd, srb_entry->srb);
659 }
661 /* send a notify to Dom0 just in case it was missed for some reason (which should _never_ happen normally but could in dump mode) */
662 XnNotify(xvdd->handle, xvdd->event_channel);
664 SxxxPortNotification(NextRequest, xvdd);
665 FUNCTION_EXIT();
667 return TRUE;
668 }
670 /* called with StartIo lock held */
671 VOID
672 XenVbd_ProcessSrbList(PXENVBD_DEVICE_DATA xvdd) {
673 PUCHAR data_buffer;
674 #ifdef _NTSTORPORT_
675 PSCSI_PNP_REQUEST_BLOCK sprb;
676 PSCSI_POWER_REQUEST_BLOCK spwrb;
677 PMINIPORT_DUMP_POINTERS dump_pointers;
678 #endif
679 PCDB cdb;
680 ULONG data_transfer_length;
681 UCHAR srb_status;
682 ULONG notify = FALSE;
683 PSCSI_REQUEST_BLOCK srb;
684 srb_list_entry_t *srb_entry;
685 PSRB_IO_CONTROL sic;
686 ULONG prev_offset;
688 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) {
689 srb = srb_entry->srb;
690 prev_offset = srb_entry->offset;
691 if (xvdd->device_state == DEVICE_STATE_INACTIVE) {
692 /* need to check again as may have been initialising when this srb was put on the list */
693 FUNCTION_MSG("Inactive Device (in ProcessSrbList)\n");
694 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
695 SxxxPortNotification(RequestComplete, xvdd, srb);
696 continue;
697 }
698 data_transfer_length = srb->DataTransferLength;
699 srb_status = SRB_STATUS_PENDING;
701 switch (srb->Function) {
702 case SRB_FUNCTION_EXECUTE_SCSI:
703 if (xvdd->device_state != DEVICE_STATE_ACTIVE) {
704 FUNCTION_MSG("Not yet active - state = %d\n", xvdd->device_state);
705 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
706 break;
707 }
708 if (xvdd->new_total_sectors != xvdd->total_sectors) {
709 if (xvdd->new_total_sectors == -1L) {
710 xvdd->new_total_sectors = xvdd->total_sectors;
711 } else {
712 FUNCTION_MSG("Resize detected. Setting UNIT_ATTENTION\n");
713 xvdd->total_sectors = xvdd->new_total_sectors;
714 xvdd->last_sense_key = SCSI_SENSE_UNIT_ATTENTION;
715 xvdd->last_additional_sense_code = SCSI_ADSENSE_PARAMETERS_CHANGED;
716 xvdd->last_additional_sense_code_qualifier = 0x09; /* capacity changed */
717 }
718 }
719 cdb = (PCDB)srb->Cdb;
720 if (xvdd->cac && cdb->CDB6GENERIC.OperationCode != SCSIOP_REQUEST_SENSE) {
721 FUNCTION_MSG("Waiting for REQUEST_SENSE\n");
722 InsertHeadList(&xvdd->srb_list, (PLIST_ENTRY)srb->SrbExtension);
723 break;
724 }
725 switch(cdb->CDB6GENERIC.OperationCode) {
726 case SCSIOP_TEST_UNIT_READY:
727 if (dump_mode)
728 FUNCTION_MSG("Command = TEST_UNIT_READY\n");
729 srb_status = SRB_STATUS_SUCCESS;
730 srb->ScsiStatus = 0;
731 break;
732 case SCSIOP_INQUIRY:
733 // if (dump_mode)
734 FUNCTION_MSG("Command = INQUIRY\n");
735 // FUNCTION_MSG("(LUN = %d, EVPD = %d, Page Code = %02X)\n", srb->Cdb[1] >> 5, srb->Cdb[1] & 1, srb->Cdb[2]);
736 // FUNCTION_MSG("(Length = %d)\n", srb->DataTransferLength);
738 data_buffer = srb->DataBuffer;
739 RtlZeroMemory(data_buffer, srb->DataTransferLength);
740 srb_status = SRB_STATUS_SUCCESS;
741 srb->ScsiStatus = 0;
742 switch (xvdd->device_type) {
743 case XENVBD_DEVICETYPE_DISK:
744 if ((srb->Cdb[1] & 1) == 0) {
745 if (srb->Cdb[2]) {
746 srb_status = SRB_STATUS_ERROR;
747 } else {
748 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
749 id->DeviceType = DIRECT_ACCESS_DEVICE;
750 id->Versions = 5; /* SPC-3 */
751 id->ResponseDataFormat = 2; /* not sure about this but WHQL complains otherwise */
752 id->HiSupport = 1; /* WHQL test says we should set this */
753 //id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
754 id->AdditionalLength = sizeof(INQUIRYDATA) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength) - 1;
755 id->CommandQueue = 1;
756 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
757 memcpy(id->ProductId, SCSI_DISK_MODEL, 16); // product id
758 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
759 data_transfer_length = FIELD_OFFSET(INQUIRYDATA, VendorSpecific);
760 }
761 } else {
762 switch (srb->Cdb[2]) {
763 case VPD_SUPPORTED_PAGES: /* list of pages we support */
764 FUNCTION_MSG("VPD_SUPPORTED_PAGES - length = %d\n", srb->DataTransferLength);
765 data_buffer[0] = DIRECT_ACCESS_DEVICE;
766 data_buffer[1] = VPD_SUPPORTED_PAGES;
767 data_buffer[2] = 0x00;
768 data_buffer[3] = 4;
769 data_buffer[4] = VPD_SUPPORTED_PAGES;
770 data_buffer[5] = VPD_SERIAL_NUMBER;
771 data_buffer[6] = VPD_DEVICE_IDENTIFIERS;
772 data_buffer[7] = VPD_BLOCK_LIMITS;
773 data_transfer_length = 8;
774 break;
775 case VPD_SERIAL_NUMBER: /* serial number */
776 FUNCTION_MSG("VPD_SERIAL_NUMBER\n");
777 data_buffer[0] = DIRECT_ACCESS_DEVICE;
778 data_buffer[1] = VPD_SERIAL_NUMBER;
779 data_buffer[2] = 0x00;
780 data_buffer[3] = (UCHAR)strlen(xvdd->serial_number);
781 if (data_transfer_length > 4) {
782 memcpy(&data_buffer[4], xvdd->serial_number, min(data_transfer_length - 4, strlen(xvdd->serial_number)));
783 }
784 data_transfer_length = 4 + (UCHAR)strlen(xvdd->serial_number);
785 break;
786 case VPD_DEVICE_IDENTIFIERS: /* identification - we don't support any so just return zero */
787 FUNCTION_MSG("VPD_DEVICE_IDENTIFIERS\n");
788 data_buffer[0] = DIRECT_ACCESS_DEVICE;
789 data_buffer[1] = VPD_DEVICE_IDENTIFIERS;
790 data_buffer[2] = 0x00;
791 data_buffer[3] = 2 * (4 + (UCHAR)strlen(xvdd->serial_number));
792 if (data_transfer_length >= 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number))) {
793 data_buffer[4] = 2; /* ASCII */
794 data_buffer[5] = 0; /* VendorId */
795 data_buffer[6] = 0; /* reserved */
796 data_buffer[7] = (UCHAR)strlen(xvdd->serial_number);
797 memcpy(&data_buffer[8], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
798 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 0] = 2; /* ASCII */
799 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 1] = 1; /* T10 VendorId */
800 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 2] = 0; /* Reserved */
801 data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 3] = (UCHAR)strlen(xvdd->serial_number);
802 memcpy(&data_buffer[8 + (UCHAR)strlen(xvdd->serial_number) + 4], xvdd->serial_number, (UCHAR)strlen(xvdd->serial_number));
803 }
804 data_transfer_length = 4 + 2 * (4 + (ULONG)strlen(xvdd->serial_number));
805 break;
806 case VPD_BLOCK_LIMITS: /* to indicate support for UNMAP (TRIM/DISCARD) */
807 FUNCTION_MSG("VPD_BLOCK_LIMITS\n");
808 // max descriptors = 1
809 // max sectors = 0xFFFFFFFF
810 // granularity = from xenbus
811 // alignment = from xenbus(?)
812 srb_status = SRB_STATUS_ERROR;
813 break;
814 default:
815 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
816 srb_status = SRB_STATUS_ERROR;
817 break;
818 }
819 }
820 break;
821 case XENVBD_DEVICETYPE_CDROM:
822 if ((srb->Cdb[1] & 1) == 0)
823 {
824 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
825 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
826 id->RemovableMedia = 1;
827 id->Versions = 3;
828 id->ResponseDataFormat = 0;
829 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
830 id->CommandQueue = 1;
831 memcpy(id->VendorId, SCSI_DEVICE_MANUFACTURER, 8); // vendor id
832 memcpy(id->ProductId, SCSI_CDROM_MODEL, 16); // product id
833 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
834 data_transfer_length = sizeof(INQUIRYDATA);
835 }
836 else
837 {
838 switch (srb->Cdb[2])
839 {
840 case 0x00:
841 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
842 data_buffer[1] = 0x00;
843 data_buffer[2] = 0x00;
844 data_buffer[3] = 2;
845 data_buffer[4] = 0x00;
846 data_buffer[5] = 0x80;
847 data_transfer_length = 6;
848 break;
849 case 0x80:
850 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
851 data_buffer[1] = 0x80;
852 data_buffer[2] = 0x00;
853 data_buffer[3] = 8;
854 data_buffer[4] = 0x31;
855 data_buffer[5] = 0x32;
856 data_buffer[6] = 0x33;
857 data_buffer[7] = 0x34;
858 data_buffer[8] = 0x35;
859 data_buffer[9] = 0x36;
860 data_buffer[10] = 0x37;
861 data_buffer[11] = 0x38;
862 data_transfer_length = 12;
863 break;
864 default:
865 FUNCTION_MSG("Unknown Page %02x requested\n", srb->Cdb[2]);
866 srb_status = SRB_STATUS_ERROR;
867 break;
868 }
869 }
870 break;
871 default:
872 FUNCTION_MSG("Unknown DeviceType %02x requested\n", xvdd->device_type);
873 srb_status = SRB_STATUS_ERROR;
874 break;
875 }
876 break;
877 case SCSIOP_READ_CAPACITY:
878 //if (dump_mode)
879 FUNCTION_MSG("Command = READ_CAPACITY\n");
880 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
881 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
882 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
883 data_buffer = srb->DataBuffer;
884 RtlZeroMemory(data_buffer, srb->DataTransferLength);
885 if ((xvdd->total_sectors - 1) >> 32) {
886 data_buffer[0] = 0xff;
887 data_buffer[1] = 0xff;
888 data_buffer[2] = 0xff;
889 data_buffer[3] = 0xff;
890 } else {
891 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
892 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
893 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
894 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
895 }
896 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
897 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
898 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
899 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
900 data_transfer_length = 8;
901 srb->ScsiStatus = 0;
902 srb_status = SRB_STATUS_SUCCESS;
903 break;
904 case SCSIOP_READ_CAPACITY16:
905 //if (dump_mode)
906 FUNCTION_MSG("Command = READ_CAPACITY16\n");
907 //FUNCTION_MSG(" LUN = %d, RelAdr = %d\n", srb->Cdb[1] >> 4, srb->Cdb[1] & 1);
908 //FUNCTION_MSG(" LBA = %02x%02x%02x%02x\n", srb->Cdb[2], srb->Cdb[3], srb->Cdb[4], srb->Cdb[5]);
909 //FUNCTION_MSG(" PMI = %d\n", srb->Cdb[8] & 1);
910 data_buffer = srb->DataBuffer;
911 RtlZeroMemory(data_buffer, srb->DataTransferLength);
912 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
913 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
914 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
915 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
916 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
917 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
918 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
919 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
920 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
921 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
922 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
923 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
924 data_buffer[12] = 0;
925 switch (xvdd->hw_bytes_per_sector / xvdd->bytes_per_sector) {
926 case 1:
927 data_buffer[13] = 0; /* 512 byte hardware sectors */
928 break;
929 case 2:
930 data_buffer[13] = 1; /* 1024 byte hardware sectors */
931 break;
932 case 4:
933 data_buffer[13] = 2; /* 2048 byte hardware sectors */
934 break;
935 case 8:
936 data_buffer[13] = 3; /* 4096 byte hardware sectors */
937 break;
938 default:
939 data_buffer[13] = 0; /* 512 byte hardware sectors */
940 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);
941 break;
942 }
943 data_buffer[14] = 0xC0; //0;
944 data_buffer[15] = 0;
945 data_transfer_length = 16;
946 srb->ScsiStatus = 0;
947 srb_status = SRB_STATUS_SUCCESS;
948 break;
949 case SCSIOP_MODE_SENSE:
950 case SCSIOP_MODE_SENSE10:
951 if (dump_mode)
952 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);
953 srb_status = XenVbd_FillModePage(xvdd, srb, &data_transfer_length);
954 break;
955 case SCSIOP_READ:
956 case SCSIOP_READ16:
957 case SCSIOP_WRITE:
958 case SCSIOP_WRITE16:
959 if (XenVbd_PutSrbOnRing(xvdd, srb)) {
960 notify = TRUE;
961 }
962 break;
963 case SCSIOP_WRITE_SAME:
964 case SCSIOP_WRITE_SAME16:
965 /* not yet supported */
966 FUNCTION_MSG("WRITE_SAME\n");
967 srb_status = SRB_STATUS_ERROR;
968 break;
969 case SCSIOP_UNMAP:
970 /* not yet supported */
971 FUNCTION_MSG("UNMAP\n");
972 srb_status = SRB_STATUS_ERROR;
973 break;
974 case SCSIOP_VERIFY:
975 case SCSIOP_VERIFY16:
976 // Should we do more here?
977 if (dump_mode)
978 FUNCTION_MSG("Command = VERIFY\n");
979 srb_status = SRB_STATUS_SUCCESS;
980 break;
981 case SCSIOP_REPORT_LUNS:
982 //if (dump_mode)
983 FUNCTION_MSG("Command = REPORT_LUNS\n");
984 switch (srb->Cdb[2]) {
985 case 1:
986 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
987 break;
988 default:
989 FUNCTION_MSG(" SELECT REPORT = %d\n", srb->Cdb[2] & 255);
990 break;
991 }
992 FUNCTION_MSG(" ALLOCATION LENGTH = %d\n", (srb->Cdb[6] << 24)|(srb->Cdb[7] << 16)|(srb->Cdb[8] << 8)|(srb->Cdb[9]));
993 data_buffer = srb->DataBuffer;
994 RtlZeroMemory(data_buffer, srb->DataTransferLength);
995 data_buffer[3] = 8; /* 1 lun */
996 /* rest of the data is blank */
997 data_transfer_length = 16;
998 srb->ScsiStatus = 0;
999 srb_status = SRB_STATUS_SUCCESS;
1000 break;
1001 case SCSIOP_REQUEST_SENSE:
1002 if (dump_mode)
1003 FUNCTION_MSG("Command = REQUEST_SENSE\n");
1004 data_transfer_length = XenVbd_MakeSense(xvdd, srb);
1005 srb_status = SRB_STATUS_SUCCESS;
1006 break;
1007 case SCSIOP_READ_TOC:
1008 //if (dump_mode)
1009 FUNCTION_MSG("Command = READ_TOC\n");
1010 data_buffer = srb->DataBuffer;
1011 /*
1012 #define READ_TOC_FORMAT_TOC 0x00
1013 #define READ_TOC_FORMAT_SESSION 0x01
1014 #define READ_TOC_FORMAT_FULL_TOC 0x02
1015 #define READ_TOC_FORMAT_PMA 0x03
1016 #define READ_TOC_FORMAT_ATIP 0x04
1017 */
1018 switch (cdb->READ_TOC.Format2) {
1019 case READ_TOC_FORMAT_TOC:
1020 data_buffer[0] = 0; // length MSB
1021 data_buffer[1] = 10; // length LSB
1022 data_buffer[2] = 1; // First Track
1023 data_buffer[3] = 1; // Last Track
1024 data_buffer[4] = 0; // Reserved
1025 data_buffer[5] = 0x14; // current position data + uninterrupted data
1026 data_buffer[6] = 1; // last complete track
1027 data_buffer[7] = 0; // reserved
1028 data_buffer[8] = 0; // MSB Block
1029 data_buffer[9] = 0;
1030 data_buffer[10] = 0;
1031 data_buffer[11] = 0; // LSB Block
1032 data_transfer_length = 12;
1033 srb_status = SRB_STATUS_SUCCESS;
1034 break;
1035 case READ_TOC_FORMAT_SESSION:
1036 case READ_TOC_FORMAT_FULL_TOC:
1037 case READ_TOC_FORMAT_PMA:
1038 case READ_TOC_FORMAT_ATIP:
1039 srb_status = SRB_STATUS_ERROR;
1040 break;
1041 default:
1042 srb_status = SRB_STATUS_ERROR;
1043 break;
1045 break;
1046 case SCSIOP_START_STOP_UNIT:
1047 FUNCTION_MSG("Command = SCSIOP_START_STOP_UNIT\n");
1048 srb_status = SRB_STATUS_SUCCESS;
1049 break;
1050 case SCSIOP_RESERVE_UNIT:
1051 FUNCTION_MSG("Command = SCSIOP_RESERVE_UNIT\n");
1052 srb_status = SRB_STATUS_SUCCESS;
1053 break;
1054 case SCSIOP_RELEASE_UNIT:
1055 FUNCTION_MSG("Command = SCSIOP_RELEASE_UNIT\n");
1056 srb_status = SRB_STATUS_SUCCESS;
1057 break;
1058 case SCSIOP_SYNCHRONIZE_CACHE:
1059 FUNCTION_MSG("Command = SCSIOP_SYNCHRONIZE_CACHE\n");
1060 srb_status = SRB_STATUS_SUCCESS;
1061 break;
1062 default:
1063 FUNCTION_MSG("Unhandled EXECUTE_SCSI Command = %02X\n", srb->Cdb[0]);
1064 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1065 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1066 xvdd->last_additional_sense_code_qualifier = 0;
1067 srb_status = SRB_STATUS_ERROR;
1068 break;
1070 if (srb_status == SRB_STATUS_ERROR) {
1071 FUNCTION_MSG("EXECUTE_SCSI Command = %02X returned error %02x\n", srb->Cdb[0], xvdd->last_sense_key);
1072 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE) {
1073 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1074 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1075 xvdd->last_additional_sense_code_qualifier = 0;
1077 srb->SrbStatus = srb_status;
1078 XenVbd_MakeAutoSense(xvdd, srb);
1079 SxxxPortNotification(RequestComplete, xvdd, srb);
1080 } else if (srb_status != SRB_STATUS_PENDING) {
1081 if (srb->ScsiStatus != 0) {
1082 FUNCTION_MSG("ScsiStatus = 0x%02x\n", srb->ScsiStatus);
1084 if (data_transfer_length > srb->DataTransferLength)
1085 FUNCTION_MSG("data_transfer_length too big - %d > %d\n", data_transfer_length, srb->DataTransferLength);
1086 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1087 srb->DataTransferLength = data_transfer_length;
1088 if (srb_status == SRB_STATUS_SUCCESS && data_transfer_length < srb->DataTransferLength) {
1089 FUNCTION_MSG("data_transfer_length too small - %d < %d\n", data_transfer_length, srb->DataTransferLength);
1090 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
1091 srb->DataTransferLength = data_transfer_length;
1092 } else {
1093 srb->SrbStatus = srb_status;
1095 XenVbd_MakeAutoSense(xvdd, srb);
1096 SxxxPortNotification(RequestComplete, xvdd, srb);
1098 break;
1099 case SRB_FUNCTION_FLUSH:
1100 FUNCTION_MSG("SRB_FUNCTION_FLUSH %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1101 srb->SrbStatus = SRB_STATUS_SUCCESS;
1102 SxxxPortNotification(RequestComplete, xvdd, srb);
1103 break;
1104 #ifdef _NTSTORPORT_
1105 case SRB_FUNCTION_PNP:
1106 FUNCTION_MSG("SRB_FUNCTION_PNP\n");
1107 sprb = (PSCSI_PNP_REQUEST_BLOCK)srb;
1108 switch (sprb->PnPAction)
1110 case StorStartDevice:
1111 FUNCTION_MSG(" StorStartDevice\n");
1112 break;
1113 case StorRemoveDevice:
1114 FUNCTION_MSG(" StorRemoveDevice\n");
1115 break;
1116 case StorStopDevice:
1117 FUNCTION_MSG(" StorStopDevice\n");
1118 break;
1119 case StorQueryCapabilities:
1120 FUNCTION_MSG(" StorQueryCapabilities\n");
1121 break;
1122 case StorFilterResourceRequirements:
1123 FUNCTION_MSG(" StorFilterResourceRequirements\n");
1124 break;
1125 default:
1126 FUNCTION_MSG(" Stor%d\n", sprb->PnPAction);
1127 break;
1129 FUNCTION_MSG(" SrbPnPFlags = %08x\n", sprb->SrbPnPFlags);
1130 srb->SrbStatus = SRB_STATUS_SUCCESS;
1131 SxxxPortNotification(RequestComplete, xvdd, srb);
1132 break;
1134 case SRB_FUNCTION_POWER:
1135 FUNCTION_MSG("SRB_FUNCTION_POWER\n");
1136 FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());
1137 spwrb = (PSCSI_POWER_REQUEST_BLOCK)srb;
1138 if (spwrb->DevicePowerState == StorPowerDeviceD0) {
1139 FUNCTION_MSG("Entering D0\n");
1140 } else {
1141 FUNCTION_MSG("Entering D%d (%d)\n", spwrb->DevicePowerState - StorPowerDeviceD0, spwrb->DevicePowerState);
1142 switch (spwrb->PowerAction) {
1143 case StorPowerActionNone:
1144 FUNCTION_MSG(" StorPowerActionNone\n");
1145 break;
1146 case StorPowerActionReserved:
1147 FUNCTION_MSG(" StorPowerActionReserved\n");
1148 break;
1149 case StorPowerActionSleep:
1150 FUNCTION_MSG(" StorPowerActionSleep\n");
1151 break;
1152 case StorPowerActionHibernate:
1153 FUNCTION_MSG(" StorPowerActionHibernate\n");
1154 break;
1155 case StorPowerActionShutdown:
1156 FUNCTION_MSG(" StorPowerActionShutdown\n");
1157 break;
1158 case StorPowerActionShutdownReset:
1159 FUNCTION_MSG(" StorPowerActionShutdownReset\n");
1160 break;
1161 case StorPowerActionShutdownOff:
1162 FUNCTION_MSG(" StorPowerActionShutdownOff\n");
1163 break;
1164 case StorPowerActionWarmEject:
1165 FUNCTION_MSG(" StorPowerActionWarmEject\n");
1166 break;
1167 default:
1168 FUNCTION_MSG(" Stor%d\n", spwrb->PowerAction);
1169 break;
1172 xvdd->power_state = spwrb->DevicePowerState;
1173 xvdd->power_action = spwrb->PowerAction;
1174 srb->SrbStatus = SRB_STATUS_SUCCESS;
1175 SxxxPortNotification(RequestComplete, xvdd, srb);
1176 break;
1177 case SRB_FUNCTION_DUMP_POINTERS:
1178 FUNCTION_MSG("SRB_FUNCTION_DUMP_POINTERS\n");
1179 FUNCTION_MSG("DataTransferLength = %d\n", srb->DataTransferLength);
1180 dump_pointers = srb->DataBuffer;
1181 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1182 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1183 FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1184 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1185 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1186 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1187 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1188 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1189 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1190 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1191 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1192 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1193 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1194 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1195 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1196 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1197 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1199 dump_pointers->Version = DUMP_MINIPORT_VERSION_1;
1200 dump_pointers->Size = sizeof(MINIPORT_DUMP_POINTERS);
1201 RtlStringCchCopyW(dump_pointers->DriverName, DUMP_MINIPORT_NAME_LENGTH, L"xenvbd.sys");
1202 dump_pointers->AdapterObject = NULL;
1203 dump_pointers->MappedRegisterBase = 0;
1204 dump_pointers->CommonBufferSize = 0;
1205 dump_pointers->MiniportPrivateDumpData = xvdd;
1206 dump_pointers->MaximumTransferLength = 4 * 1024 * 1024;
1207 dump_pointers->NumberOfPhysicalBreaks = dump_pointers->MaximumTransferLength >> PAGE_SHIFT;
1208 dump_pointers->AlignmentMask = 0;
1209 dump_pointers->NumberOfAccessRanges = 0;
1210 dump_pointers->NumberOfBuses = 1;
1211 dump_pointers->Master = TRUE;
1212 dump_pointers->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
1213 dump_pointers->MaximumNumberOfTargets = 2;
1215 FUNCTION_MSG(" Version = %d\n", dump_pointers->Version);
1216 FUNCTION_MSG(" Size = %d\n", dump_pointers->Size);
1217 //FUNCTION_MSG(" DriverName = %S\n", dump_pointers->DriverName);
1218 FUNCTION_MSG(" AdapterObject = %p\n", dump_pointers->AdapterObject);
1219 FUNCTION_MSG(" MappedRegisterBase = %d\n", dump_pointers->MappedRegisterBase);
1220 FUNCTION_MSG(" CommonBufferSize = %d\n", dump_pointers->CommonBufferSize);
1221 FUNCTION_MSG(" MiniportPrivateDumpData = %p\n", dump_pointers->MiniportPrivateDumpData);
1222 FUNCTION_MSG(" SystemIoBusNumber = %d\n", dump_pointers->SystemIoBusNumber);
1223 FUNCTION_MSG(" AdapterInterfaceType = %d\n", dump_pointers->AdapterInterfaceType);
1224 FUNCTION_MSG(" MaximumTransferLength = %d\n", dump_pointers->MaximumTransferLength);
1225 FUNCTION_MSG(" NumberOfPhysicalBreaks = %d\n", dump_pointers->NumberOfPhysicalBreaks);
1226 FUNCTION_MSG(" AlignmentMask = %d\n", dump_pointers->AlignmentMask);
1227 FUNCTION_MSG(" NumberOfAccessRanges = %d\n", dump_pointers->NumberOfAccessRanges);
1228 FUNCTION_MSG(" NumberOfBuses = %d\n", dump_pointers->NumberOfBuses);
1229 FUNCTION_MSG(" Master = %d\n", dump_pointers->Master);
1230 FUNCTION_MSG(" MapBuffers = %d\n", dump_pointers->MapBuffers);
1231 FUNCTION_MSG(" MaximumNumberOfTargets = %d\n", dump_pointers->MaximumNumberOfTargets);
1233 srb->SrbStatus = SRB_STATUS_SUCCESS;
1234 SxxxPortNotification(RequestComplete, xvdd, srb);
1235 break;
1236 #endif
1237 case SRB_FUNCTION_SHUTDOWN:
1238 FUNCTION_MSG("SRB_FUNCTION_SHUTDOWN %p, xvdd->shadow_free = %d\n", srb, xvdd->shadow_free);
1239 srb->SrbStatus = SRB_STATUS_SUCCESS;
1240 SxxxPortNotification(RequestComplete, xvdd, srb);
1241 break;
1242 case SRB_FUNCTION_RESET_BUS:
1243 case SRB_FUNCTION_RESET_DEVICE:
1244 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
1245 /* the path doesn't matter here - only ever one device*/
1246 FUNCTION_MSG("SRB_FUNCTION_RESET_XXX\n");
1247 XenVbd_ResetBus(xvdd, 0);
1248 srb->SrbStatus = SRB_STATUS_SUCCESS;
1249 SxxxPortNotification(RequestComplete, xvdd, srb);
1250 break;
1251 case SRB_FUNCTION_WMI:
1252 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1253 SxxxPortNotification(RequestComplete, xvdd, srb);
1254 break;
1255 case SRB_FUNCTION_IO_CONTROL:
1256 FUNCTION_MSG("SRB_FUNCTION_IO_CONTROL\n");
1257 sic = srb->DataBuffer;
1258 FUNCTION_MSG("ControlCode = %d\n", sic->ControlCode);
1259 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1260 SxxxPortNotification(RequestComplete, xvdd, srb);
1261 break;
1262 case 0x27:
1263 FUNCTION_MSG("SRB_FUNCTION_FREE_DUMP_POINTERS\n");
1264 srb->SrbStatus = SRB_STATUS_SUCCESS;
1265 SxxxPortNotification(RequestComplete, xvdd, srb);
1266 break;
1267 default:
1268 FUNCTION_MSG("Unhandled srb->Function = %08X\n", srb->Function);
1269 srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1270 SxxxPortNotification(RequestComplete, xvdd, srb);
1271 break;
1273 if ((PLIST_ENTRY)srb_entry == xvdd->srb_list.Flink && srb_entry->offset == prev_offset) {
1274 FUNCTION_MSG("Same entry\n");
1275 /* same entry was put back onto the head of the list unchanged, so we can't progress */
1276 break;
1279 if (notify) {
1280 notify = FALSE;
1281 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
1282 if (notify) {
1283 XnNotify(xvdd->handle, xvdd->event_channel);
1286 return;