1 /* 2 * PROJECT: ReactOS Storage Stack 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: SCSI Port driver SCSI requests handling 5 * COPYRIGHT: Eric Kohl (eric.kohl@reactos.org) 6 * Aleksey Bragin (aleksey@reactos.org) 7 * 2020 Victor Perevertkin (victor.perevertkin@reactos.org) 8 */ 9 10 #include "scsiport.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 16 static 17 NTSTATUS 18 SpiStatusSrbToNt( 19 _In_ UCHAR SrbStatus) 20 { 21 switch (SRB_STATUS(SrbStatus)) 22 { 23 case SRB_STATUS_TIMEOUT: 24 case SRB_STATUS_COMMAND_TIMEOUT: 25 return STATUS_IO_TIMEOUT; 26 27 case SRB_STATUS_BAD_SRB_BLOCK_LENGTH: 28 case SRB_STATUS_BAD_FUNCTION: 29 return STATUS_INVALID_DEVICE_REQUEST; 30 31 case SRB_STATUS_NO_DEVICE: 32 case SRB_STATUS_INVALID_LUN: 33 case SRB_STATUS_INVALID_TARGET_ID: 34 case SRB_STATUS_NO_HBA: 35 return STATUS_DEVICE_DOES_NOT_EXIST; 36 37 case SRB_STATUS_DATA_OVERRUN: 38 return STATUS_BUFFER_OVERFLOW; 39 40 case SRB_STATUS_SELECTION_TIMEOUT: 41 return STATUS_DEVICE_NOT_CONNECTED; 42 43 default: 44 return STATUS_IO_DEVICE_ERROR; 45 } 46 47 return STATUS_IO_DEVICE_ERROR; 48 } 49 50 static 51 NTSTATUS 52 SpiHandleAttachRelease( 53 _In_ PSCSI_PORT_LUN_EXTENSION LunExtension, 54 _Inout_ PIRP Irp) 55 { 56 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = 57 LunExtension->Common.LowerDevice->DeviceExtension; 58 PDEVICE_OBJECT DeviceObject; 59 KIRQL Irql; 60 61 /* Get pointer to the SRB */ 62 PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp); 63 PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb; 64 65 /* Get spinlock */ 66 KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); 67 68 /* Release, if asked */ 69 if (Srb->Function == SRB_FUNCTION_RELEASE_DEVICE) 70 { 71 LunExtension->DeviceClaimed = FALSE; 72 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); 73 Srb->SrbStatus = SRB_STATUS_SUCCESS; 74 75 return STATUS_SUCCESS; 76 } 77 78 /* Attach, if not already claimed */ 79 if (LunExtension->DeviceClaimed) 80 { 81 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); 82 Srb->SrbStatus = SRB_STATUS_BUSY; 83 84 return STATUS_DEVICE_BUSY; 85 } 86 87 /* Save the device object */ 88 DeviceObject = LunExtension->Common.DeviceObject; 89 90 if (Srb->Function == SRB_FUNCTION_CLAIM_DEVICE) 91 LunExtension->DeviceClaimed = TRUE; 92 93 if (Srb->Function == SRB_FUNCTION_ATTACH_DEVICE) 94 LunExtension->Common.DeviceObject = Srb->DataBuffer; 95 96 Srb->DataBuffer = DeviceObject; 97 98 KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); 99 Srb->SrbStatus = SRB_STATUS_SUCCESS; 100 101 return STATUS_SUCCESS; 102 } 103 104 /********************************************************************** 105 * NAME INTERNAL 106 * ScsiPortDispatchScsi 107 * 108 * DESCRIPTION 109 * Answer requests for SCSI calls 110 * 111 * RUN LEVEL 112 * PASSIVE_LEVEL 113 * 114 * ARGUMENTS 115 * Standard dispatch arguments 116 * 117 * RETURNS 118 * NTSTATUS 119 */ 120 121 NTSTATUS 122 NTAPI 123 ScsiPortDispatchScsi( 124 _In_ PDEVICE_OBJECT DeviceObject, 125 _Inout_ PIRP Irp) 126 { 127 PSCSI_PORT_DEVICE_EXTENSION portExt; 128 PSCSI_PORT_LUN_EXTENSION lunExt; 129 PIO_STACK_LOCATION Stack; 130 PSCSI_REQUEST_BLOCK Srb; 131 KIRQL Irql; 132 NTSTATUS Status = STATUS_SUCCESS; 133 PIRP NextIrp, IrpList; 134 PKDEVICE_QUEUE_ENTRY Entry; 135 136 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp); 137 138 Stack = IoGetCurrentIrpStackLocation(Irp); 139 Srb = Stack->Parameters.Scsi.Srb; 140 lunExt = DeviceObject->DeviceExtension; 141 ASSERT(!lunExt->Common.IsFDO); 142 portExt = lunExt->Common.LowerDevice->DeviceExtension; 143 144 if (Srb == NULL) 145 { 146 DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n"); 147 Status = STATUS_UNSUCCESSFUL; 148 149 Irp->IoStatus.Status = Status; 150 Irp->IoStatus.Information = 0; 151 152 IoCompleteRequest(Irp, IO_NO_INCREMENT); 153 154 return Status; 155 } 156 157 DPRINT("Srb: %p, Srb->Function: %lu\n", Srb, Srb->Function); 158 159 Srb->PathId = lunExt->PathId; 160 Srb->TargetId = lunExt->TargetId; 161 Srb->Lun = lunExt->Lun; 162 163 if (lunExt == NULL) 164 { 165 DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n"); 166 Status = STATUS_NO_SUCH_DEVICE; 167 168 Srb->SrbStatus = SRB_STATUS_NO_DEVICE; 169 Irp->IoStatus.Status = Status; 170 Irp->IoStatus.Information = 0; 171 172 IoCompleteRequest(Irp, IO_NO_INCREMENT); 173 174 return Status; 175 } 176 177 switch (Srb->Function) 178 { 179 case SRB_FUNCTION_SHUTDOWN: 180 case SRB_FUNCTION_FLUSH: 181 DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n"); 182 if (portExt->CachesData == FALSE) 183 { 184 /* All success here */ 185 Srb->SrbStatus = SRB_STATUS_SUCCESS; 186 Irp->IoStatus.Status = STATUS_SUCCESS; 187 IoCompleteRequest(Irp, IO_NO_INCREMENT); 188 return STATUS_SUCCESS; 189 } 190 /* Fall through to a usual execute operation */ 191 192 case SRB_FUNCTION_EXECUTE_SCSI: 193 case SRB_FUNCTION_IO_CONTROL: 194 DPRINT(" SRB_FUNCTION_EXECUTE_SCSI or SRB_FUNCTION_IO_CONTROL\n"); 195 /* Mark IRP as pending in all cases */ 196 IoMarkIrpPending(Irp); 197 198 if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) 199 { 200 /* Start IO directly */ 201 IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL); 202 } 203 else 204 { 205 KIRQL oldIrql; 206 207 /* We need to be at DISPATCH_LEVEL */ 208 KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); 209 210 /* Insert IRP into the queue */ 211 if (!KeInsertByKeyDeviceQueue(&lunExt->DeviceQueue, 212 &Irp->Tail.Overlay.DeviceQueueEntry, 213 Srb->QueueSortKey)) 214 { 215 /* It means the queue is empty, and we just start this request */ 216 IoStartPacket(portExt->Common.DeviceObject, Irp, NULL, NULL); 217 } 218 219 /* Back to the old IRQL */ 220 KeLowerIrql(oldIrql); 221 } 222 return STATUS_PENDING; 223 224 case SRB_FUNCTION_CLAIM_DEVICE: 225 case SRB_FUNCTION_ATTACH_DEVICE: 226 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n"); 227 228 /* Reference device object and keep the device object */ 229 Status = SpiHandleAttachRelease(lunExt, Irp); 230 break; 231 232 case SRB_FUNCTION_RELEASE_DEVICE: 233 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n"); 234 235 /* Dereference device object and clear the device object */ 236 Status = SpiHandleAttachRelease(lunExt, Irp); 237 break; 238 239 case SRB_FUNCTION_RELEASE_QUEUE: 240 DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n"); 241 242 /* Guard with the spinlock */ 243 KeAcquireSpinLock(&portExt->SpinLock, &Irql); 244 245 if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE)) 246 { 247 DPRINT("Queue is not frozen really\n"); 248 249 KeReleaseSpinLock(&portExt->SpinLock, Irql); 250 Srb->SrbStatus = SRB_STATUS_SUCCESS; 251 Status = STATUS_SUCCESS; 252 break; 253 254 } 255 256 /* Unfreeze the queue */ 257 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE; 258 259 if (lunExt->SrbInfo.Srb == NULL) 260 { 261 /* Get next logical unit request. SpiGetNextRequestFromLun releases the lock. */ 262 SpiGetNextRequestFromLun(portExt, lunExt, &Irql); 263 } 264 else 265 { 266 DPRINT("The queue has active request\n"); 267 KeReleaseSpinLock(&portExt->SpinLock, Irql); 268 } 269 270 Srb->SrbStatus = SRB_STATUS_SUCCESS; 271 Status = STATUS_SUCCESS; 272 break; 273 274 case SRB_FUNCTION_FLUSH_QUEUE: 275 DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n"); 276 277 /* Guard with the spinlock */ 278 KeAcquireSpinLock(&portExt->SpinLock, &Irql); 279 280 if (!(lunExt->Flags & LUNEX_FROZEN_QUEUE)) 281 { 282 DPRINT("Queue is not frozen really\n"); 283 284 KeReleaseSpinLock(&portExt->SpinLock, Irql); 285 Status = STATUS_INVALID_DEVICE_REQUEST; 286 break; 287 } 288 289 /* Make sure there is no active request */ 290 ASSERT(lunExt->SrbInfo.Srb == NULL); 291 292 /* Compile a list from the device queue */ 293 IrpList = NULL; 294 while ((Entry = KeRemoveDeviceQueue(&lunExt->DeviceQueue)) != NULL) 295 { 296 NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); 297 298 /* Get the Srb */ 299 Stack = IoGetCurrentIrpStackLocation(NextIrp); 300 Srb = Stack->Parameters.Scsi.Srb; 301 302 /* Set statuse */ 303 Srb->SrbStatus = SRB_STATUS_REQUEST_FLUSHED; 304 NextIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; 305 306 /* Add then to the list */ 307 NextIrp->Tail.Overlay.ListEntry.Flink = (PLIST_ENTRY)IrpList; 308 IrpList = NextIrp; 309 } 310 311 /* Unfreeze the queue */ 312 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE; 313 314 /* Release the spinlock */ 315 KeReleaseSpinLock(&portExt->SpinLock, Irql); 316 317 /* Complete those requests */ 318 while (IrpList) 319 { 320 NextIrp = IrpList; 321 IrpList = (PIRP)NextIrp->Tail.Overlay.ListEntry.Flink; 322 323 IoCompleteRequest(NextIrp, 0); 324 } 325 326 Status = STATUS_SUCCESS; 327 break; 328 329 default: 330 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function); 331 Status = STATUS_NOT_IMPLEMENTED; 332 break; 333 } 334 335 Irp->IoStatus.Status = Status; 336 IoCompleteRequest(Irp, IO_NO_INCREMENT); 337 338 return Status; 339 } 340 341 VOID 342 SpiGetNextRequestFromLun( 343 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 344 _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, 345 _Inout_opt_ PKIRQL OldIrql 346 ) 347 { 348 PIO_STACK_LOCATION IrpStack; 349 PIRP NextIrp; 350 PKDEVICE_QUEUE_ENTRY Entry; 351 PSCSI_REQUEST_BLOCK Srb; 352 353 354 /* If LUN is not active or queue is more than maximum allowed */ 355 if (LunExtension->QueueCount >= LunExtension->MaxQueueCount || 356 !(LunExtension->Flags & SCSI_PORT_LU_ACTIVE)) 357 { 358 /* Release the spinlock and exit */ 359 if (OldIrql != NULL) 360 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql); 361 else 362 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 363 return; 364 } 365 366 /* Check if we can get a next request */ 367 if (LunExtension->Flags & 368 (LUNEX_NEED_REQUEST_SENSE | LUNEX_BUSY | 369 LUNEX_FULL_QUEUE | LUNEX_FROZEN_QUEUE | LUNEX_REQUEST_PENDING)) 370 { 371 /* Pending requests can only be started if the queue is empty */ 372 if (IsListEmpty(&LunExtension->SrbInfo.Requests) && 373 !(LunExtension->Flags & 374 (LUNEX_BUSY | LUNEX_FROZEN_QUEUE | LUNEX_FULL_QUEUE | LUNEX_NEED_REQUEST_SENSE))) 375 { 376 /* Make sure we have SRB */ 377 ASSERT(LunExtension->SrbInfo.Srb == NULL); 378 379 /* Clear active and pending flags */ 380 LunExtension->Flags &= ~(LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE); 381 382 /* Get next Irp, and clear pending requests list */ 383 NextIrp = LunExtension->PendingRequest; 384 LunExtension->PendingRequest = NULL; 385 386 /* Set attempt counter to zero */ 387 LunExtension->AttemptCount = 0; 388 389 /* Release the spinlock */ 390 if (OldIrql != NULL) 391 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql); 392 else 393 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 394 395 /* Start the next pending request */ 396 IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL); 397 398 return; 399 } 400 else 401 { 402 /* Release the spinlock, without clearing any flags and exit */ 403 if (OldIrql != NULL) 404 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql); 405 else 406 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 407 408 return; 409 } 410 } 411 412 /* Reset active flag */ 413 LunExtension->Flags &= ~SCSI_PORT_LU_ACTIVE; 414 415 /* Set attempt counter to zero */ 416 LunExtension->AttemptCount = 0; 417 418 /* Remove packet from the device queue */ 419 Entry = KeRemoveByKeyDeviceQueue(&LunExtension->DeviceQueue, LunExtension->SortKey); 420 421 if (Entry != NULL) 422 { 423 /* Get pointer to the next irp */ 424 NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry); 425 426 /* Get point to the SRB */ 427 IrpStack = IoGetCurrentIrpStackLocation(NextIrp); 428 Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1; 429 430 /* Set new key*/ 431 LunExtension->SortKey = Srb->QueueSortKey; 432 LunExtension->SortKey++; 433 434 /* Release the spinlock */ 435 if (OldIrql != NULL) 436 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql); 437 else 438 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 439 440 /* Start the next pending request */ 441 IoStartPacket(DeviceExtension->Common.DeviceObject, NextIrp, (PULONG)NULL, NULL); 442 } 443 else 444 { 445 /* Release the spinlock */ 446 if (OldIrql != NULL) 447 KeReleaseSpinLock(&DeviceExtension->SpinLock, *OldIrql); 448 else 449 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 450 } 451 } 452 453 IO_COMPLETION_ROUTINE SpiSenseCompletionRoutine; 454 455 NTSTATUS 456 NTAPI 457 SpiSenseCompletionRoutine( 458 _In_ PDEVICE_OBJECT DeviceObject, 459 _In_ PIRP Irp, 460 _In_opt_ PVOID Context) 461 { 462 PIO_STACK_LOCATION ioStack = IoGetNextIrpStackLocation(Irp); 463 PSCSI_PORT_LUN_EXTENSION lunExt = ioStack->DeviceObject->DeviceExtension; 464 PSCSI_PORT_DEVICE_EXTENSION portExt = lunExt->Common.LowerDevice->DeviceExtension; 465 PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)Context; 466 PSCSI_REQUEST_BLOCK InitialSrb; 467 PIRP InitialIrp; 468 469 DPRINT("SpiCompletionRoutine() entered, IRP %p \n", Irp); 470 471 if ((Srb->Function == SRB_FUNCTION_RESET_BUS) || 472 (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)) 473 { 474 /* Deallocate SRB and IRP and exit */ 475 ExFreePool(Srb); 476 IoFreeIrp(Irp); 477 478 return STATUS_MORE_PROCESSING_REQUIRED; 479 } 480 481 /* Get a pointer to the SRB and IRP which were initially sent */ 482 InitialSrb = *((PVOID *)(Srb+1)); 483 InitialIrp = InitialSrb->OriginalRequest; 484 485 if ((SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) || 486 (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)) 487 { 488 /* Sense data is OK */ 489 InitialSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; 490 491 /* Set length to be the same */ 492 InitialSrb->SenseInfoBufferLength = (UCHAR)Srb->DataTransferLength; 493 } 494 495 /* Make sure initial SRB's queue is frozen */ 496 ASSERT(InitialSrb->SrbStatus & SRB_STATUS_QUEUE_FROZEN); 497 498 // The queue is frozen, but the SRB had a SRB_FLAGS_NO_QUEUE_FREEZE => unfreeze the queue 499 if ((InitialSrb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE) && 500 (InitialSrb->SrbStatus & SRB_STATUS_QUEUE_FROZEN)) 501 { 502 KIRQL irql; 503 504 KeAcquireSpinLock(&portExt->SpinLock, &irql); 505 506 ASSERT(lunExt->Flags & LUNEX_FROZEN_QUEUE); 507 508 lunExt->Flags &= ~LUNEX_FROZEN_QUEUE; 509 lunExt->Flags &= ~LUNEX_NEED_REQUEST_SENSE; 510 511 // SpiGetNextRequestFromLun releases the lock 512 SpiGetNextRequestFromLun(portExt, lunExt, &irql); 513 514 InitialSrb->SrbStatus &= ~SRB_STATUS_QUEUE_FROZEN; 515 } 516 517 /* Complete this request */ 518 IoCompleteRequest(InitialIrp, IO_DISK_INCREMENT); 519 520 /* Deallocate everything (internal) */ 521 ExFreePool(Srb); 522 523 if (Irp->MdlAddress != NULL) 524 { 525 MmUnlockPages(Irp->MdlAddress); 526 IoFreeMdl(Irp->MdlAddress); 527 Irp->MdlAddress = NULL; 528 } 529 530 IoFreeIrp(Irp); 531 return STATUS_MORE_PROCESSING_REQUIRED; 532 } 533 534 static 535 VOID 536 SpiSendRequestSense( 537 _In_ PSCSI_PORT_LUN_EXTENSION LunExtension, 538 _In_ PSCSI_REQUEST_BLOCK InitialSrb) 539 { 540 PSCSI_REQUEST_BLOCK Srb; 541 PCDB Cdb; 542 PIRP Irp; 543 PIO_STACK_LOCATION IrpStack; 544 LARGE_INTEGER LargeInt; 545 PVOID *Ptr; 546 547 DPRINT("SpiSendRequestSense() entered, InitialSrb %p\n", InitialSrb); 548 549 /* Allocate Srb */ 550 Srb = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(PVOID), TAG_SCSIPORT); 551 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); 552 553 /* Allocate IRP */ 554 LargeInt.QuadPart = (LONGLONG) 1; 555 Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ, 556 LunExtension->Common.DeviceObject, 557 InitialSrb->SenseInfoBuffer, 558 InitialSrb->SenseInfoBufferLength, 559 &LargeInt, 560 NULL); 561 562 IoSetCompletionRoutine(Irp, 563 SpiSenseCompletionRoutine, 564 Srb, 565 TRUE, 566 TRUE, 567 TRUE); 568 569 if (!Srb) 570 { 571 DPRINT("SpiSendRequestSense() failed, Srb %p\n", Srb); 572 return; 573 } 574 575 IrpStack = IoGetNextIrpStackLocation(Irp); 576 IrpStack->MajorFunction = IRP_MJ_SCSI; 577 578 /* Put Srb address into Irp... */ 579 IrpStack->Parameters.Others.Argument1 = (PVOID)Srb; 580 581 /* ...and vice versa */ 582 Srb->OriginalRequest = Irp; 583 584 /* Save Srb */ 585 Ptr = (PVOID *)(Srb+1); 586 *Ptr = InitialSrb; 587 588 /* Build CDB for REQUEST SENSE */ 589 Srb->CdbLength = 6; 590 Cdb = (PCDB)Srb->Cdb; 591 592 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; 593 Cdb->CDB6INQUIRY.LogicalUnitNumber = 0; 594 Cdb->CDB6INQUIRY.Reserved1 = 0; 595 Cdb->CDB6INQUIRY.PageCode = 0; 596 Cdb->CDB6INQUIRY.IReserved = 0; 597 Cdb->CDB6INQUIRY.AllocationLength = (UCHAR)InitialSrb->SenseInfoBufferLength; 598 Cdb->CDB6INQUIRY.Control = 0; 599 600 /* Set address */ 601 Srb->TargetId = InitialSrb->TargetId; 602 Srb->Lun = InitialSrb->Lun; 603 Srb->PathId = InitialSrb->PathId; 604 605 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 606 Srb->Length = sizeof(SCSI_REQUEST_BLOCK); 607 608 /* Timeout will be 2 seconds */ 609 Srb->TimeOutValue = 2; 610 611 /* No auto request sense */ 612 Srb->SenseInfoBufferLength = 0; 613 Srb->SenseInfoBuffer = NULL; 614 615 /* Set necessary flags */ 616 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_BYPASS_FROZEN_QUEUE | 617 SRB_FLAGS_DISABLE_DISCONNECT; 618 619 // pass some InitialSrb flags 620 if (InitialSrb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER) 621 Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 622 623 if (InitialSrb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE) 624 Srb->SrbFlags |= SRB_FLAGS_BYPASS_LOCKED_QUEUE; 625 626 if (InitialSrb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE) 627 Srb->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE; 628 629 Srb->DataBuffer = InitialSrb->SenseInfoBuffer; 630 631 /* Fill the transfer length */ 632 Srb->DataTransferLength = InitialSrb->SenseInfoBufferLength; 633 634 /* Clear statuses */ 635 Srb->ScsiStatus = Srb->SrbStatus = 0; 636 Srb->NextSrb = 0; 637 638 /* Call the driver */ 639 (VOID)IoCallDriver(LunExtension->Common.DeviceObject, Irp); 640 641 DPRINT("SpiSendRequestSense() done\n"); 642 } 643 644 645 static 646 VOID 647 SpiProcessCompletedRequest( 648 _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 649 _Inout_ PSCSI_REQUEST_BLOCK_INFO SrbInfo, 650 _Out_ PBOOLEAN NeedToCallStartIo) 651 { 652 PSCSI_REQUEST_BLOCK Srb; 653 PSCSI_PORT_LUN_EXTENSION LunExtension; 654 LONG Result; 655 PIRP Irp; 656 //ULONG SequenceNumber; 657 658 Srb = SrbInfo->Srb; 659 Irp = Srb->OriginalRequest; 660 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); 661 662 /* Get Lun extension */ 663 LunExtension = IoStack->DeviceObject->DeviceExtension; 664 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 665 666 if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION && 667 DeviceExtension->MapBuffers && 668 Irp->MdlAddress) 669 { 670 /* MDL is shared if transfer is broken into smaller parts */ 671 Srb->DataBuffer = (PCCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) + 672 ((PCCHAR)Srb->DataBuffer - SrbInfo->DataOffset); 673 674 /* In case of data going in, flush the buffers */ 675 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) 676 { 677 KeFlushIoBuffers(Irp->MdlAddress, 678 TRUE, 679 FALSE); 680 } 681 } 682 683 /* Flush adapter if needed */ 684 if (SrbInfo->BaseOfMapRegister) 685 { 686 /* TODO: Implement */ 687 ASSERT(FALSE); 688 } 689 690 /* Clear the request */ 691 SrbInfo->Srb = NULL; 692 693 /* If disconnect is disabled... */ 694 if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) 695 { 696 /* Acquire the spinlock since we mess with flags */ 697 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 698 699 /* Set corresponding flag */ 700 DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED; 701 702 /* Clear the timer if needed */ 703 if (!(DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)) 704 DeviceExtension->TimerCount = -1; 705 706 /* Spinlock is not needed anymore */ 707 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 708 709 if (!(DeviceExtension->Flags & SCSI_PORT_REQUEST_PENDING) && 710 !(DeviceExtension->Flags & SCSI_PORT_DEVICE_BUSY) && 711 !(*NeedToCallStartIo)) 712 { 713 /* We're not busy, but we have a request pending */ 714 IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE); 715 } 716 } 717 718 /* Scatter/gather */ 719 if (Srb->SrbFlags & SRB_FLAGS_SGLIST_FROM_POOL) 720 { 721 /* TODO: Implement */ 722 ASSERT(FALSE); 723 } 724 725 /* Acquire spinlock (we're freeing SrbExtension) */ 726 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 727 728 /* Free it (if needed) */ 729 if (Srb->SrbExtension) 730 { 731 if (Srb->SenseInfoBuffer != NULL && DeviceExtension->SupportsAutoSense) 732 { 733 ASSERT(Srb->SenseInfoBuffer == NULL || SrbInfo->SaveSenseRequest != NULL); 734 735 if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) 736 { 737 /* Copy sense data to the buffer */ 738 RtlCopyMemory(SrbInfo->SaveSenseRequest, 739 Srb->SenseInfoBuffer, 740 Srb->SenseInfoBufferLength); 741 } 742 743 /* And restore the pointer */ 744 Srb->SenseInfoBuffer = SrbInfo->SaveSenseRequest; 745 } 746 747 /* Put it into the free srb extensions list */ 748 *((PVOID *)Srb->SrbExtension) = DeviceExtension->FreeSrbExtensions; 749 DeviceExtension->FreeSrbExtensions = Srb->SrbExtension; 750 } 751 752 /* Save transfer length in the IRP */ 753 Irp->IoStatus.Information = Srb->DataTransferLength; 754 755 //SequenceNumber = SrbInfo->SequenceNumber; 756 SrbInfo->SequenceNumber = 0; 757 758 /* Decrement the queue count */ 759 LunExtension->QueueCount--; 760 761 /* Free Srb, if needed*/ 762 if (Srb->QueueTag != SP_UNTAGGED) 763 { 764 /* Put it into the free list */ 765 SrbInfo->Requests.Blink = NULL; 766 SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo; 767 DeviceExtension->FreeSrbInfo = SrbInfo; 768 } 769 770 /* SrbInfo is not used anymore */ 771 SrbInfo = NULL; 772 773 if (DeviceExtension->Flags & SCSI_PORT_REQUEST_PENDING) 774 { 775 /* Clear the flag */ 776 DeviceExtension->Flags &= ~SCSI_PORT_REQUEST_PENDING; 777 778 /* Note the caller about StartIo */ 779 *NeedToCallStartIo = TRUE; 780 } 781 782 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) 783 { 784 /* Start the packet */ 785 Irp->IoStatus.Status = STATUS_SUCCESS; 786 787 if (!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) && 788 LunExtension->RequestTimeout == -1) 789 { 790 /* Start the next packet. SpiGetNextRequestFromLun will release the lock for us */ 791 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL); 792 } 793 else 794 { 795 /* Release the spinlock */ 796 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 797 } 798 799 DPRINT("IoCompleting request IRP 0x%p\n", Irp); 800 801 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 802 803 /* Decrement number of active requests, and analyze the result */ 804 Result = InterlockedDecrement(&DeviceExtension->ActiveRequestCounter); 805 806 if (Result < 0 && 807 !DeviceExtension->MapRegisters && 808 DeviceExtension->AdapterObject != NULL) 809 { 810 /* Nullify map registers */ 811 DeviceExtension->MapRegisterBase = NULL; 812 IoFreeAdapterChannel(DeviceExtension->AdapterObject); 813 } 814 815 /* Exit, we're done */ 816 return; 817 } 818 819 /* Decrement number of active requests, and analyze the result */ 820 Result = InterlockedDecrement(&DeviceExtension->ActiveRequestCounter); 821 822 if (Result < 0 && 823 !DeviceExtension->MapRegisters && 824 DeviceExtension->AdapterObject != NULL) 825 { 826 /* Result is negative, so this is a slave, free map registers */ 827 DeviceExtension->MapRegisterBase = NULL; 828 IoFreeAdapterChannel(DeviceExtension->AdapterObject); 829 } 830 831 /* Convert status */ 832 Irp->IoStatus.Status = SpiStatusSrbToNt(Srb->SrbStatus); 833 834 /* It's not a bypass, it's busy or the queue is full? */ 835 if ((Srb->ScsiStatus == SCSISTAT_BUSY || 836 Srb->SrbStatus == SRB_STATUS_BUSY || 837 Srb->ScsiStatus == SCSISTAT_QUEUE_FULL) && 838 !(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)) 839 { 840 841 DPRINT("Busy SRB status %x\n", Srb->SrbStatus); 842 843 /* Requeue, if needed */ 844 if (LunExtension->Flags & (LUNEX_FROZEN_QUEUE | LUNEX_BUSY)) 845 { 846 DPRINT("it's being requeued\n"); 847 848 Srb->SrbStatus = SRB_STATUS_PENDING; 849 Srb->ScsiStatus = 0; 850 851 if (!KeInsertByKeyDeviceQueue(&LunExtension->DeviceQueue, 852 &Irp->Tail.Overlay.DeviceQueueEntry, 853 Srb->QueueSortKey)) 854 { 855 /* It's a big f.ck up if we got here */ 856 Srb->SrbStatus = SRB_STATUS_ERROR; 857 Srb->ScsiStatus = SCSISTAT_BUSY; 858 859 ASSERT(FALSE); 860 goto Error; 861 } 862 863 /* Release the spinlock */ 864 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 865 866 } 867 else if (LunExtension->AttemptCount++ < 20) 868 { 869 /* LUN is still busy */ 870 Srb->ScsiStatus = 0; 871 Srb->SrbStatus = SRB_STATUS_PENDING; 872 873 LunExtension->BusyRequest = Irp; 874 LunExtension->Flags |= LUNEX_BUSY; 875 876 /* Release the spinlock */ 877 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 878 } 879 else 880 { 881 Error: 882 /* Freeze the queue*/ 883 Srb->SrbStatus |= SRB_STATUS_QUEUE_FROZEN; 884 LunExtension->Flags |= LUNEX_FROZEN_QUEUE; 885 886 /* "Unfull" the queue */ 887 LunExtension->Flags &= ~LUNEX_FULL_QUEUE; 888 889 /* Release the spinlock */ 890 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 891 892 /* Return status that the device is not ready */ 893 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; 894 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 895 } 896 897 return; 898 } 899 900 /* Start the next request, if LUN is idle, and this is sense request */ 901 if (((Srb->ScsiStatus != SCSISTAT_CHECK_CONDITION) || 902 (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) || 903 !Srb->SenseInfoBuffer || !Srb->SenseInfoBufferLength) 904 && (Srb->SrbFlags & SRB_FLAGS_NO_QUEUE_FREEZE)) 905 { 906 if (LunExtension->RequestTimeout == -1) 907 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL); 908 else 909 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 910 } 911 else 912 { 913 /* Freeze the queue */ 914 Srb->SrbStatus |= SRB_STATUS_QUEUE_FROZEN; 915 LunExtension->Flags |= LUNEX_FROZEN_QUEUE; 916 917 /* Do we need a request sense? */ 918 if (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION && 919 !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && 920 Srb->SenseInfoBuffer && Srb->SenseInfoBufferLength) 921 { 922 /* If LUN is busy, we have to requeue it in order to allow request sense */ 923 if (LunExtension->Flags & LUNEX_BUSY) 924 { 925 DPRINT("Requeuing busy request to allow request sense\n"); 926 927 if (!KeInsertByKeyDeviceQueue(&LunExtension->DeviceQueue, 928 &LunExtension->BusyRequest->Tail.Overlay.DeviceQueueEntry, 929 Srb->QueueSortKey)) 930 { 931 /* We should never get here */ 932 ASSERT(FALSE); 933 934 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 935 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 936 return; 937 938 } 939 940 /* Clear busy flags */ 941 LunExtension->Flags &= ~(LUNEX_FULL_QUEUE | LUNEX_BUSY); 942 } 943 944 /* Release the spinlock */ 945 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 946 947 /* Send RequestSense */ 948 SpiSendRequestSense(LunExtension, Srb); 949 950 /* Exit */ 951 return; 952 } 953 954 /* Release the spinlock */ 955 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 956 } 957 958 /* Complete the request */ 959 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 960 } 961 962 BOOLEAN 963 NTAPI 964 ScsiPortStartPacket( 965 _In_ PVOID Context) 966 { 967 PIO_STACK_LOCATION IrpStack; 968 PSCSI_REQUEST_BLOCK Srb; 969 PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context; 970 PSCSI_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension; 971 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 972 PSCSI_PORT_LUN_EXTENSION LunExtension; 973 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 974 BOOLEAN Result; 975 BOOLEAN StartTimer; 976 977 DPRINT("ScsiPortStartPacket() called\n"); 978 979 IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp); 980 Srb = IrpStack->Parameters.Scsi.Srb; 981 982 if (CommonExtension->IsFDO) // IsFDO 983 { 984 DeviceExtension = DeviceObject->DeviceExtension; 985 LunExtension = IrpStack->DeviceObject->DeviceExtension; 986 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 987 } 988 else 989 { 990 LunExtension = DeviceObject->DeviceExtension; 991 DeviceExtension = LunExtension->Common.LowerDevice->DeviceExtension; 992 } 993 994 /* Check if we are in a reset state */ 995 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET) 996 { 997 /* Mark the we've got requests while being in the reset state */ 998 DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET_REQUEST; 999 return TRUE; 1000 } 1001 1002 /* Set the time out value */ 1003 DeviceExtension->TimerCount = Srb->TimeOutValue; 1004 1005 /* We are busy */ 1006 DeviceExtension->Flags |= SCSI_PORT_DEVICE_BUSY; 1007 1008 if (LunExtension->RequestTimeout != -1) 1009 { 1010 /* Timer already active */ 1011 StartTimer = FALSE; 1012 } 1013 else 1014 { 1015 /* It hasn't been initialized yet */ 1016 LunExtension->RequestTimeout = Srb->TimeOutValue; 1017 StartTimer = TRUE; 1018 } 1019 1020 if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) 1021 { 1022 /* Handle bypass-requests */ 1023 1024 /* Is this an abort request? */ 1025 if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) 1026 { 1027 /* Get pointer to SRB info structure */ 1028 SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag); 1029 1030 /* Check if the request is still "active" */ 1031 if (SrbInfo == NULL || 1032 SrbInfo->Srb == NULL || 1033 !(SrbInfo->Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) 1034 { 1035 /* It's not, mark it as active then */ 1036 Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE; 1037 1038 if (StartTimer) 1039 LunExtension->RequestTimeout = -1; 1040 1041 DPRINT("Request has been already completed, but abort request came\n"); 1042 Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; 1043 1044 /* Notify about request complete */ 1045 ScsiPortNotification(RequestComplete, 1046 DeviceExtension->MiniPortDeviceExtension, 1047 Srb); 1048 1049 /* and about readiness for the next request */ 1050 ScsiPortNotification(NextRequest, 1051 DeviceExtension->MiniPortDeviceExtension); 1052 1053 /* They might ask for some work, so queue the DPC for them */ 1054 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 1055 1056 /* We're done in this branch */ 1057 return TRUE; 1058 } 1059 } 1060 else 1061 { 1062 /* Add number of queued requests */ 1063 LunExtension->QueueCount++; 1064 } 1065 1066 /* Bypass requests don't need request sense */ 1067 LunExtension->Flags &= ~LUNEX_NEED_REQUEST_SENSE; 1068 1069 /* Is disconnect disabled for this request? */ 1070 if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) 1071 { 1072 /* Set the corresponding flag */ 1073 DeviceExtension->Flags &= ~SCSI_PORT_DISCONNECT_ALLOWED; 1074 } 1075 1076 /* Transfer timeout value from Srb to Lun */ 1077 LunExtension->RequestTimeout = Srb->TimeOutValue; 1078 } 1079 else 1080 { 1081 if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) 1082 { 1083 /* It's a disconnect, so no more requests can go */ 1084 DeviceExtension->Flags &= ~SCSI_PORT_DISCONNECT_ALLOWED; 1085 } 1086 1087 LunExtension->Flags |= SCSI_PORT_LU_ACTIVE; 1088 1089 /* Increment queue count */ 1090 LunExtension->QueueCount++; 1091 1092 /* If it's tagged - special thing */ 1093 if (Srb->QueueTag != SP_UNTAGGED) 1094 { 1095 SrbInfo = &DeviceExtension->SrbInfo[Srb->QueueTag - 1]; 1096 1097 /* Chek for consistency */ 1098 ASSERT(SrbInfo->Requests.Blink == NULL); 1099 1100 /* Insert it into the list of requests */ 1101 InsertTailList(&LunExtension->SrbInfo.Requests, &SrbInfo->Requests); 1102 } 1103 } 1104 1105 /* Mark this Srb active */ 1106 Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE; 1107 1108 /* Call HwStartIo routine */ 1109 Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension, 1110 Srb); 1111 1112 /* If notification is needed, then request a DPC */ 1113 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 1114 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 1115 1116 return Result; 1117 } 1118 1119 BOOLEAN 1120 NTAPI 1121 SpiSaveInterruptData(IN PVOID Context) 1122 { 1123 PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context; 1124 PSCSI_PORT_LUN_EXTENSION LunExtension; 1125 PSCSI_REQUEST_BLOCK Srb; 1126 PSCSI_REQUEST_BLOCK_INFO SrbInfo, NextSrbInfo; 1127 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1128 BOOLEAN IsTimed; 1129 1130 /* Get pointer to the device extension */ 1131 DeviceExtension = InterruptContext->DeviceExtension; 1132 1133 /* If we don't have anything pending - return */ 1134 if (!(DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)) 1135 return FALSE; 1136 1137 /* Actually save the interrupt data */ 1138 *InterruptContext->InterruptData = DeviceExtension->InterruptData; 1139 1140 /* Clear the data stored in the device extension */ 1141 DeviceExtension->InterruptData.Flags &= 1142 (SCSI_PORT_RESET | SCSI_PORT_RESET_REQUEST | SCSI_PORT_DISABLE_INTERRUPTS); 1143 DeviceExtension->InterruptData.CompletedAbort = NULL; 1144 DeviceExtension->InterruptData.ReadyLun = NULL; 1145 DeviceExtension->InterruptData.CompletedRequests = NULL; 1146 1147 /* Loop through the list of completed requests */ 1148 SrbInfo = InterruptContext->InterruptData->CompletedRequests; 1149 1150 while (SrbInfo) 1151 { 1152 /* Make sure we have SRV */ 1153 ASSERT(SrbInfo->Srb); 1154 1155 /* Get SRB and LunExtension */ 1156 Srb = SrbInfo->Srb; 1157 1158 PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Srb->OriginalRequest); 1159 LunExtension = IoStack->DeviceObject->DeviceExtension; 1160 ASSERT(LunExtension && !LunExtension->Common.IsFDO); 1161 1162 /* We have to check special cases if request is unsuccessful*/ 1163 if (Srb->SrbStatus != SRB_STATUS_SUCCESS) 1164 { 1165 /* Check if we need request sense by a few conditions */ 1166 if (Srb->SenseInfoBuffer && Srb->SenseInfoBufferLength && 1167 Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION && 1168 !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) 1169 { 1170 if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) 1171 { 1172 /* It means: we tried to send REQUEST SENSE, but failed */ 1173 1174 Srb->ScsiStatus = 0; 1175 Srb->SrbStatus = SRB_STATUS_REQUEST_SENSE_FAILED; 1176 } 1177 else 1178 { 1179 /* Set the corresponding flag, so that REQUEST SENSE 1180 will be sent */ 1181 LunExtension->Flags |= LUNEX_NEED_REQUEST_SENSE; 1182 } 1183 1184 } 1185 1186 /* Check for a full queue */ 1187 if (Srb->ScsiStatus == SCSISTAT_QUEUE_FULL) 1188 { 1189 /* TODO: Implement when it's encountered */ 1190 ASSERT(FALSE); 1191 } 1192 } 1193 1194 /* Let's decide if we need to watch timeout or not */ 1195 if (Srb->QueueTag == SP_UNTAGGED) 1196 { 1197 IsTimed = TRUE; 1198 } 1199 else 1200 { 1201 if (LunExtension->SrbInfo.Requests.Flink == &SrbInfo->Requests) 1202 IsTimed = TRUE; 1203 else 1204 IsTimed = FALSE; 1205 1206 /* Remove it from the queue */ 1207 RemoveEntryList(&SrbInfo->Requests); 1208 } 1209 1210 if (IsTimed) 1211 { 1212 /* We have to maintain timeout counter */ 1213 if (IsListEmpty(&LunExtension->SrbInfo.Requests)) 1214 { 1215 LunExtension->RequestTimeout = -1; 1216 } 1217 else 1218 { 1219 NextSrbInfo = CONTAINING_RECORD(LunExtension->SrbInfo.Requests.Flink, 1220 SCSI_REQUEST_BLOCK_INFO, 1221 Requests); 1222 1223 Srb = NextSrbInfo->Srb; 1224 1225 /* Update timeout counter */ 1226 LunExtension->RequestTimeout = Srb->TimeOutValue; 1227 } 1228 } 1229 1230 SrbInfo = SrbInfo->CompletedRequests; 1231 } 1232 1233 return TRUE; 1234 } 1235 1236 VOID 1237 NTAPI 1238 ScsiPortDpcForIsr( 1239 _In_ PKDPC Dpc, 1240 _In_ PDEVICE_OBJECT DpcDeviceObject, 1241 _Inout_ PIRP DpcIrp, 1242 _In_opt_ PVOID DpcContext) 1243 { 1244 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DpcDeviceObject->DeviceExtension; 1245 SCSI_PORT_INTERRUPT_DATA InterruptData; 1246 SCSI_PORT_SAVE_INTERRUPT Context; 1247 PSCSI_PORT_LUN_EXTENSION LunExtension; 1248 BOOLEAN NeedToStartIo; 1249 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 1250 LARGE_INTEGER TimerValue; 1251 1252 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n", 1253 Dpc, DpcDeviceObject, DpcIrp, DpcContext); 1254 1255 /* We need to acquire spinlock */ 1256 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1257 1258 RtlZeroMemory(&InterruptData, sizeof(SCSI_PORT_INTERRUPT_DATA)); 1259 1260 TryAgain: 1261 1262 /* Interrupt structure must be snapshotted, and only then analyzed */ 1263 Context.InterruptData = &InterruptData; 1264 Context.DeviceExtension = DeviceExtension; 1265 1266 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0], 1267 SpiSaveInterruptData, 1268 &Context)) 1269 { 1270 /* Nothing - just return (don't forget to release the spinlock */ 1271 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1272 DPRINT("ScsiPortDpcForIsr() done\n"); 1273 return; 1274 } 1275 1276 /* If flush of adapters is needed - do it */ 1277 if (InterruptData.Flags & SCSI_PORT_FLUSH_ADAPTERS) 1278 { 1279 /* TODO: Implement */ 1280 ASSERT(FALSE); 1281 } 1282 1283 /* Check for IoMapTransfer */ 1284 if (InterruptData.Flags & SCSI_PORT_MAP_TRANSFER) 1285 { 1286 /* TODO: Implement */ 1287 ASSERT(FALSE); 1288 } 1289 1290 /* Check if timer is needed */ 1291 if (InterruptData.Flags & SCSI_PORT_TIMER_NEEDED) 1292 { 1293 /* Save the timer routine */ 1294 DeviceExtension->HwScsiTimer = InterruptData.HwScsiTimer; 1295 1296 if (InterruptData.MiniportTimerValue == 0) 1297 { 1298 /* Cancel the timer */ 1299 KeCancelTimer(&DeviceExtension->MiniportTimer); 1300 } 1301 else 1302 { 1303 /* Convert timer value */ 1304 TimerValue.QuadPart = Int32x32To64(InterruptData.MiniportTimerValue, -10); 1305 1306 /* Set the timer */ 1307 KeSetTimer(&DeviceExtension->MiniportTimer, 1308 TimerValue, 1309 &DeviceExtension->MiniportTimerDpc); 1310 } 1311 } 1312 1313 /* If it's ready for the next request */ 1314 if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY) 1315 { 1316 /* Check for a duplicate request (NextRequest+NextLuRequest) */ 1317 if ((DeviceExtension->Flags & 1318 (SCSI_PORT_DEVICE_BUSY | SCSI_PORT_DISCONNECT_ALLOWED)) == 1319 (SCSI_PORT_DEVICE_BUSY | SCSI_PORT_DISCONNECT_ALLOWED)) 1320 { 1321 /* Clear busy flag set by ScsiPortStartPacket() */ 1322 DeviceExtension->Flags &= ~SCSI_PORT_DEVICE_BUSY; 1323 1324 if (!(InterruptData.Flags & SCSI_PORT_RESET)) 1325 { 1326 /* Ready for next, and no reset is happening */ 1327 DeviceExtension->TimerCount = -1; 1328 } 1329 } 1330 else 1331 { 1332 /* Not busy, but not ready for the next request */ 1333 DeviceExtension->Flags &= ~SCSI_PORT_DEVICE_BUSY; 1334 InterruptData.Flags &= ~SCSI_PORT_NEXT_REQUEST_READY; 1335 } 1336 } 1337 1338 /* Any resets? */ 1339 if (InterruptData.Flags & SCSI_PORT_RESET_REPORTED) 1340 { 1341 /* Hold for a bit */ 1342 DeviceExtension->TimerCount = 4; 1343 } 1344 1345 /* Any ready LUN? */ 1346 if (InterruptData.ReadyLun != NULL) 1347 { 1348 1349 /* Process all LUNs from the list*/ 1350 while (TRUE) 1351 { 1352 /* Remove it from the list first (as processed) */ 1353 LunExtension = InterruptData.ReadyLun; 1354 InterruptData.ReadyLun = LunExtension->ReadyLun; 1355 LunExtension->ReadyLun = NULL; 1356 1357 /* Get next request for this LUN */ 1358 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, NULL); 1359 1360 /* Still ready requests exist? 1361 If yes - get spinlock, if no - stop here */ 1362 if (InterruptData.ReadyLun != NULL) 1363 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1364 else 1365 break; 1366 } 1367 } 1368 else 1369 { 1370 /* Release the spinlock */ 1371 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1372 } 1373 1374 /* If we ready for next packet, start it */ 1375 if (InterruptData.Flags & SCSI_PORT_NEXT_REQUEST_READY) 1376 IoStartNextPacket(DeviceExtension->Common.DeviceObject, FALSE); 1377 1378 NeedToStartIo = FALSE; 1379 1380 /* Loop the completed request list */ 1381 while (InterruptData.CompletedRequests) 1382 { 1383 /* Remove the request */ 1384 SrbInfo = InterruptData.CompletedRequests; 1385 InterruptData.CompletedRequests = SrbInfo->CompletedRequests; 1386 SrbInfo->CompletedRequests = NULL; 1387 1388 /* Process it */ 1389 SpiProcessCompletedRequest(DeviceExtension, 1390 SrbInfo, 1391 &NeedToStartIo); 1392 } 1393 1394 /* Loop abort request list */ 1395 while (InterruptData.CompletedAbort) 1396 { 1397 LunExtension = InterruptData.CompletedAbort; 1398 1399 /* Remove the request */ 1400 InterruptData.CompletedAbort = LunExtension->CompletedAbortRequests; 1401 1402 /* Get spinlock since we're going to change flags */ 1403 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1404 1405 /* TODO: Put SrbExtension to the list of free extensions */ 1406 ASSERT(FALSE); 1407 } 1408 1409 /* If we need - call StartIo routine */ 1410 if (NeedToStartIo) 1411 { 1412 /* Make sure CurrentIrp is not null! */ 1413 ASSERT(DpcDeviceObject->CurrentIrp != NULL); 1414 ScsiPortStartIo(DpcDeviceObject, DpcDeviceObject->CurrentIrp); 1415 } 1416 1417 /* Everything has been done, check */ 1418 if (InterruptData.Flags & SCSI_PORT_ENABLE_INT_REQUEST) 1419 { 1420 /* Synchronize using spinlock */ 1421 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1422 1423 /* Request an interrupt */ 1424 DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension); 1425 1426 ASSERT(DeviceExtension->Flags & SCSI_PORT_DISABLE_INT_REQUESET); 1427 1428 /* Should interrupts be enabled again? */ 1429 if (DeviceExtension->Flags & SCSI_PORT_DISABLE_INT_REQUESET) 1430 { 1431 /* Clear this flag */ 1432 DeviceExtension->Flags &= ~SCSI_PORT_DISABLE_INT_REQUESET; 1433 1434 /* Call a special routine to do this */ 1435 ASSERT(FALSE); 1436 #if 0 1437 KeSynchronizeExecution(DeviceExtension->Interrupt, 1438 SpiEnableInterrupts, 1439 DeviceExtension); 1440 #endif 1441 } 1442 1443 /* If we need a notification again - loop */ 1444 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED) 1445 goto TryAgain; 1446 1447 /* Release the spinlock */ 1448 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1449 } 1450 1451 DPRINT("ScsiPortDpcForIsr() done\n"); 1452 } 1453 1454 static 1455 PSCSI_REQUEST_BLOCK_INFO 1456 SpiAllocateSrbStructures( 1457 _Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, 1458 _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, 1459 _Inout_ PSCSI_REQUEST_BLOCK Srb) 1460 { 1461 PCHAR SrbExtension; 1462 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 1463 1464 /* Spinlock must be held while this function executes */ 1465 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1466 1467 /* Allocate SRB data structure */ 1468 if (DeviceExtension->NeedSrbDataAlloc) 1469 { 1470 /* Treat the abort request in a special way */ 1471 if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) 1472 { 1473 SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag); 1474 } 1475 else if (Srb->SrbFlags & 1476 (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) && 1477 !(Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) 1478 ) 1479 { 1480 /* Do not process tagged commands if need request sense is set */ 1481 if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) 1482 { 1483 ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING)); 1484 1485 LunExtension->PendingRequest = Srb->OriginalRequest; 1486 LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE; 1487 1488 /* Release the spinlock and return */ 1489 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1490 return NULL; 1491 } 1492 1493 ASSERT(LunExtension->SrbInfo.Srb == NULL); 1494 SrbInfo = DeviceExtension->FreeSrbInfo; 1495 1496 if (SrbInfo == NULL) 1497 { 1498 /* No SRB structures left in the list. We have to leave 1499 and wait while we are called again */ 1500 1501 DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING; 1502 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1503 return NULL; 1504 } 1505 1506 DeviceExtension->FreeSrbInfo = (PSCSI_REQUEST_BLOCK_INFO)SrbInfo->Requests.Flink; 1507 1508 /* QueueTag must never be 0, so +1 to it */ 1509 Srb->QueueTag = (UCHAR)(SrbInfo - DeviceExtension->SrbInfo) + 1; 1510 } 1511 else 1512 { 1513 /* Usual untagged command */ 1514 if ( 1515 (!IsListEmpty(&LunExtension->SrbInfo.Requests) || 1516 LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) && 1517 !(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) 1518 ) 1519 { 1520 /* Mark it as pending and leave */ 1521 ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING)); 1522 LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE; 1523 LunExtension->PendingRequest = Srb->OriginalRequest; 1524 1525 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1526 return(NULL); 1527 } 1528 1529 Srb->QueueTag = SP_UNTAGGED; 1530 SrbInfo = &LunExtension->SrbInfo; 1531 } 1532 } 1533 else 1534 { 1535 Srb->QueueTag = SP_UNTAGGED; 1536 SrbInfo = &LunExtension->SrbInfo; 1537 } 1538 1539 /* Allocate SRB extension structure */ 1540 if (DeviceExtension->NeedSrbExtensionAlloc) 1541 { 1542 /* Check the list of free extensions */ 1543 SrbExtension = DeviceExtension->FreeSrbExtensions; 1544 1545 /* If no free extensions... */ 1546 if (SrbExtension == NULL) 1547 { 1548 /* Free SRB data */ 1549 if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND && 1550 Srb->QueueTag != SP_UNTAGGED) 1551 { 1552 SrbInfo->Requests.Blink = NULL; 1553 SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo; 1554 DeviceExtension->FreeSrbInfo = SrbInfo; 1555 } 1556 1557 /* Return, in order to be called again later */ 1558 DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING; 1559 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1560 return NULL; 1561 } 1562 1563 /* Remove that free SRB extension from the list (since 1564 we're going to use it) */ 1565 DeviceExtension->FreeSrbExtensions = *((PVOID *)SrbExtension); 1566 1567 /* Spinlock can be released now */ 1568 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1569 1570 Srb->SrbExtension = SrbExtension; 1571 1572 if (Srb->SenseInfoBuffer != NULL && 1573 DeviceExtension->SupportsAutoSense) 1574 { 1575 /* Store pointer to the SenseInfo buffer */ 1576 SrbInfo->SaveSenseRequest = Srb->SenseInfoBuffer; 1577 1578 /* Does data fit the buffer? */ 1579 if (Srb->SenseInfoBufferLength > sizeof(SENSE_DATA)) 1580 { 1581 /* No, disabling autosense at all */ 1582 Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE; 1583 } 1584 else 1585 { 1586 /* Yes, update the buffer pointer */ 1587 Srb->SenseInfoBuffer = SrbExtension + DeviceExtension->SrbExtensionSize; 1588 } 1589 } 1590 } 1591 else 1592 { 1593 /* Cleanup... */ 1594 Srb->SrbExtension = NULL; 1595 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1596 } 1597 1598 return SrbInfo; 1599 } 1600 1601 VOID 1602 NTAPI 1603 ScsiPortStartIo( 1604 _Inout_ PDEVICE_OBJECT DeviceObject, 1605 _Inout_ PIRP Irp) 1606 { 1607 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; 1608 PSCSI_PORT_LUN_EXTENSION LunExtension; 1609 PIO_STACK_LOCATION IrpStack; 1610 PSCSI_REQUEST_BLOCK Srb; 1611 PSCSI_REQUEST_BLOCK_INFO SrbInfo; 1612 LONG CounterResult; 1613 NTSTATUS Status; 1614 1615 DPRINT("ScsiPortStartIo() called!\n"); 1616 1617 DeviceExtension = DeviceObject->DeviceExtension; 1618 IrpStack = IoGetCurrentIrpStackLocation(Irp); 1619 LunExtension = IrpStack->DeviceObject->DeviceExtension; 1620 1621 ASSERT(DeviceExtension->Common.IsFDO); 1622 ASSERT(!LunExtension->Common.IsFDO); 1623 1624 DPRINT("LunExtension %p DeviceExtension %p\n", LunExtension, DeviceExtension); 1625 1626 Srb = IrpStack->Parameters.Scsi.Srb; 1627 1628 /* Apply "default" flags */ 1629 Srb->SrbFlags |= DeviceExtension->SrbFlags; 1630 1631 if (DeviceExtension->NeedSrbDataAlloc || 1632 DeviceExtension->NeedSrbExtensionAlloc) 1633 { 1634 /* Allocate them */ 1635 SrbInfo = SpiAllocateSrbStructures(DeviceExtension, 1636 LunExtension, 1637 Srb); 1638 1639 /* Couldn't alloc one or both data structures, return */ 1640 if (SrbInfo == NULL) 1641 { 1642 /* We have to call IoStartNextPacket, because this request 1643 was not started */ 1644 if (LunExtension->Flags & LUNEX_REQUEST_PENDING) 1645 IoStartNextPacket(DeviceObject, FALSE); 1646 1647 return; 1648 } 1649 } 1650 else 1651 { 1652 /* No allocations are needed */ 1653 SrbInfo = &LunExtension->SrbInfo; 1654 Srb->SrbExtension = NULL; 1655 Srb->QueueTag = SP_UNTAGGED; 1656 } 1657 1658 /* Increase sequence number of SRB */ 1659 if (!SrbInfo->SequenceNumber) 1660 { 1661 /* Increase global sequence number */ 1662 DeviceExtension->SequenceNumber++; 1663 1664 /* Assign it */ 1665 SrbInfo->SequenceNumber = DeviceExtension->SequenceNumber; 1666 } 1667 1668 /* Check some special SRBs */ 1669 if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) 1670 { 1671 /* Some special handling */ 1672 DPRINT1("Abort command! Unimplemented now\n"); 1673 } 1674 else 1675 { 1676 SrbInfo->Srb = Srb; 1677 } 1678 1679 if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) 1680 { 1681 // Store the MDL virtual address in SrbInfo structure 1682 SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress); 1683 1684 if (DeviceExtension->MapBuffers) 1685 { 1686 /* Calculate offset within DataBuffer */ 1687 SrbInfo->DataOffset = MmGetSystemAddressForMdl(Irp->MdlAddress); 1688 Srb->DataBuffer = SrbInfo->DataOffset + 1689 (ULONG)((PUCHAR)Srb->DataBuffer - 1690 (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress)); 1691 } 1692 1693 if (DeviceExtension->AdapterObject) 1694 { 1695 /* Flush buffers */ 1696 KeFlushIoBuffers(Irp->MdlAddress, 1697 Srb->SrbFlags & SRB_FLAGS_DATA_IN ? TRUE : FALSE, 1698 TRUE); 1699 } 1700 1701 if (DeviceExtension->MapRegisters) 1702 { 1703 /* Calculate number of needed map registers */ 1704 SrbInfo->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES( 1705 Srb->DataBuffer, 1706 Srb->DataTransferLength); 1707 1708 /* Allocate adapter channel */ 1709 Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject, 1710 DeviceExtension->Common.DeviceObject, 1711 SrbInfo->NumberOfMapRegisters, 1712 SpiAdapterControl, 1713 SrbInfo); 1714 1715 if (!NT_SUCCESS(Status)) 1716 { 1717 DPRINT1("IoAllocateAdapterChannel() failed!\n"); 1718 1719 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; 1720 ScsiPortNotification(RequestComplete, 1721 DeviceExtension + 1, 1722 Srb); 1723 1724 ScsiPortNotification(NextRequest, 1725 DeviceExtension + 1); 1726 1727 /* Request DPC for that work */ 1728 IoRequestDpc(DeviceExtension->Common.DeviceObject, NULL, NULL); 1729 } 1730 1731 /* Control goes to SpiAdapterControl */ 1732 return; 1733 } 1734 } 1735 1736 /* Increase active request counter */ 1737 CounterResult = InterlockedIncrement(&DeviceExtension->ActiveRequestCounter); 1738 1739 if (CounterResult == 0 && 1740 DeviceExtension->AdapterObject != NULL && 1741 !DeviceExtension->MapRegisters) 1742 { 1743 IoAllocateAdapterChannel( 1744 DeviceExtension->AdapterObject, 1745 DeviceObject, 1746 DeviceExtension->PortCapabilities.MaximumPhysicalPages, 1747 ScsiPortAllocateAdapterChannel, 1748 LunExtension 1749 ); 1750 1751 return; 1752 } 1753 1754 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock); 1755 1756 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0], 1757 ScsiPortStartPacket, 1758 DeviceObject)) 1759 { 1760 DPRINT("Synchronization failed!\n"); 1761 1762 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; 1763 Irp->IoStatus.Information = 0; 1764 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1765 1766 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1767 } 1768 else 1769 { 1770 /* Release the spinlock only */ 1771 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock); 1772 } 1773 1774 1775 DPRINT("ScsiPortStartIo() done\n"); 1776 } 1777