win-pvdrivers

annotate xenvbd_common/common_miniport.h @ 1025:aa2e51f67f7c

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