ReactOS  0.4.15-dev-3217-gc6d1646
scsi.c
Go to the documentation of this file.
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
19  _In_ UCHAR SrbStatus)
20 {
21  switch (SRB_STATUS(SrbStatus))
22  {
23  case SRB_STATUS_TIMEOUT:
25  return STATUS_IO_TIMEOUT;
26 
30 
34  case SRB_STATUS_NO_HBA:
36 
39 
42 
43  default:
45  }
46 
48 }
49 
50 static
53  _In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
55 {
56  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
57  LunExtension->Common.LowerDevice->DeviceExtension;
59  KIRQL Irql;
60 
61  /* Get pointer to the SRB */
63  PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;
64 
65  /* Get spinlock */
66  KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
67 
68  /* Release, if asked */
70  {
71  LunExtension->DeviceClaimed = FALSE;
72  KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
74 
75  return STATUS_SUCCESS;
76  }
77 
78  /* Attach, if not already claimed */
79  if (LunExtension->DeviceClaimed)
80  {
81  KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
83 
84  return STATUS_DEVICE_BUSY;
85  }
86 
87  /* Save the device object */
88  DeviceObject = LunExtension->Common.DeviceObject;
89 
91  LunExtension->DeviceClaimed = TRUE;
92 
94  LunExtension->Common.DeviceObject = Srb->DataBuffer;
95 
97 
98  KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
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
125  _Inout_ PIRP Irp)
126 {
131  KIRQL Irql;
133  PIRP NextIrp, IrpList;
135 
136  DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
137 
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");
148 
149  Irp->IoStatus.Status = Status;
150  Irp->IoStatus.Information = 0;
151 
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");
167 
169  Irp->IoStatus.Status = Status;
170  Irp->IoStatus.Information = 0;
171 
173 
174  return Status;
175  }
176 
177  switch (Srb->Function)
178  {
180  case SRB_FUNCTION_FLUSH:
181  DPRINT(" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
182  if (portExt->CachesData == FALSE)
183  {
184  /* All success here */
186  Irp->IoStatus.Status = STATUS_SUCCESS;
188  return STATUS_SUCCESS;
189  }
190  /* Fall through to a usual execute operation */
191 
194  DPRINT(" SRB_FUNCTION_EXECUTE_SCSI or SRB_FUNCTION_IO_CONTROL\n");
195  /* Mark IRP as pending in all cases */
197 
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 */
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 
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 
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 
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);
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 
272  break;
273 
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);
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 */
300  Srb = Stack->Parameters.Scsi.Srb;
301 
302  /* Set statuse */
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 
327  break;
328 
329  default:
330  DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
332  break;
333  }
334 
335  Irp->IoStatus.Status = Status;
337 
338  return Status;
339 }
340 
341 VOID
343  _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
344  _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
346 )
347 {
348  PIO_STACK_LOCATION IrpStack;
349  PIRP NextIrp;
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 &
370  {
371  /* Pending requests can only be started if the queue is empty */
372  if (IsListEmpty(&LunExtension->SrbInfo.Requests) &&
373  !(LunExtension->Flags &
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
459  _In_ PIRP Irp,
461 {
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) ||
473  {
474  /* Deallocate SRB and IRP and exit */
475  ExFreePool(Srb);
476  IoFreeIrp(Irp);
477 
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 
487  {
488  /* Sense data is OK */
489  InitialSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
490 
491  /* Set length to be the same */
493  }
494 
495  /* Make sure initial SRB's queue is 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 */
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);
532 }
533 
534 static
535 VOID
537  _In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
538  _In_ PSCSI_REQUEST_BLOCK InitialSrb)
539 {
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 */
552 
553  /* Allocate IRP */
554  LargeInt.QuadPart = (LONGLONG) 1;
556  LunExtension->Common.DeviceObject,
557  InitialSrb->SenseInfoBuffer,
558  InitialSrb->SenseInfoBufferLength,
559  &LargeInt,
560  NULL);
561 
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 */
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 
606  Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
607 
608  /* Timeout will be 2 seconds */
609  Srb->TimeOutValue = 2;
610 
611  /* No auto request sense */
614 
615  /* Set necessary flags */
618 
619  // pass some InitialSrb flags
620  if (InitialSrb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER)
622 
623  if (InitialSrb->SrbFlags & SRB_FLAGS_BYPASS_LOCKED_QUEUE)
625 
626  if (InitialSrb->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
648  _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
650  _Out_ PBOOLEAN NeedToCallStartIo)
651 {
653  PSCSI_PORT_LUN_EXTENSION LunExtension;
654  LONG Result;
655  PIRP Irp;
656  //ULONG SequenceNumber;
657 
658  Srb = SrbInfo->Srb;
661 
662  /* Get Lun extension */
663  LunExtension = IoStack->DeviceObject->DeviceExtension;
664  ASSERT(LunExtension && !LunExtension->Common.IsFDO);
665 
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 */
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... */
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 */
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 
736  {
737  /* Copy sense data to the buffer */
738  RtlCopyMemory(SrbInfo->SaveSenseRequest,
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 
783  {
784  /* Start the packet */
785  Irp->IoStatus.Status = STATUS_SUCCESS;
786 
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 
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 ||
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 
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 */
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;
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*/
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;
895  }
896 
897  return;
898  }
899 
900  /* Start the next request, if LUN is idle, and this is sense request */
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 */
915  LunExtension->Flags |= LUNEX_FROZEN_QUEUE;
916 
917  /* Do we need a request sense? */
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);
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 */
960 }
961 
962 BOOLEAN
963 NTAPI
966 {
967  PIO_STACK_LOCATION IrpStack;
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 
1021  {
1022  /* Handle bypass-requests */
1023 
1024  /* Is this an abort request? */
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 */
1037 
1038  if (StartTimer)
1039  LunExtension->RequestTimeout = -1;
1040 
1041  DPRINT("Request has been already completed, but abort request came\n");
1043 
1044  /* Notify about request complete */
1046  DeviceExtension->MiniPortDeviceExtension,
1047  Srb);
1048 
1049  /* and about readiness for the next request */
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? */
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  {
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 */
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
1122 {
1123  PSCSI_PORT_SAVE_INTERRUPT InterruptContext = Context;
1124  PSCSI_PORT_LUN_EXTENSION LunExtension;
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 &=
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 
1159  LunExtension = IoStack->DeviceObject->DeviceExtension;
1160  ASSERT(LunExtension && !LunExtension->Common.IsFDO);
1161 
1162  /* We have to check special cases if request is unsuccessful*/
1164  {
1165  /* Check if we need request sense by a few conditions */
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;
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 */
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,
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
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;
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],
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 &
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
1457  _Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1458  _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension,
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 */
1472  {
1473  SrbInfo = SpiGetSrbData(DeviceExtension, LunExtension, Srb->QueueTag);
1474  }
1475  else if (Srb->SrbFlags &
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) &&
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 
1530  SrbInfo = &LunExtension->SrbInfo;
1531  }
1532  }
1533  else
1534  {
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 */
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 */
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
1605  _Inout_ PIRP Irp)
1606 {
1607  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1608  PSCSI_PORT_LUN_EXTENSION LunExtension;
1609  PIO_STACK_LOCATION IrpStack;
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)
1646 
1647  return;
1648  }
1649  }
1650  else
1651  {
1652  /* No allocations are needed */
1653  SrbInfo = &LunExtension->SrbInfo;
1654  Srb->SrbExtension = NULL;
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 */
1670  {
1671  /* Some special handling */
1672  DPRINT1("Abort command! Unimplemented now\n");
1673  }
1674  else
1675  {
1676  SrbInfo->Srb = Srb;
1677  }
1678 
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,
1698  TRUE);
1699  }
1700 
1701  if (DeviceExtension->MapRegisters)
1702  {
1703  /* Calculate number of needed map registers */
1705  Srb->DataBuffer,
1707 
1708  /* Allocate adapter channel */
1709  Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject,
1710  DeviceExtension->Common.DeviceObject,
1711  SrbInfo->NumberOfMapRegisters,
1713  SrbInfo);
1714 
1715  if (!NT_SUCCESS(Status))
1716  {
1717  DPRINT1("IoAllocateAdapterChannel() failed!\n");
1718 
1721  DeviceExtension + 1,
1722  Srb);
1723 
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  {
1744  DeviceExtension->AdapterObject,
1745  DeviceObject,
1746  DeviceExtension->PortCapabilities.MaximumPhysicalPages,
1748  LunExtension
1749  );
1750 
1751  return;
1752  }
1753 
1754  KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
1755 
1756  if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0],
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 
1767  }
1768  else
1769  {
1770  /* Release the spinlock only */
1771  KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
1772  }
1773 
1774 
1775  DPRINT("ScsiPortStartIo() done\n");
1776 }
struct _LIST_ENTRY * PLIST_ENTRY
struct _SCSI_REQUEST_BLOCK_INFO * CompletedRequests
Definition: scsiport.h:129
signed char * PCHAR
Definition: retypes.h:7
#define SRB_STATUS_INVALID_REQUEST
Definition: srb.h:338
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:391
#define SCSISTAT_BUSY
Definition: cdrw_hw.h:1081
#define SRB_FLAGS_UNSPECIFIED_DIRECTION
Definition: srb.h:395
#define IN
Definition: typedefs.h:39
KDEVICE_QUEUE DeviceQueue
Definition: scsiport.h:160
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
BOOLEAN NTAPI ScsiPortStartPacket(_In_ PVOID Context)
Definition: scsi.c:964
#define LUNEX_FULL_QUEUE
Definition: scsiport.h:49
ULONG SrbFlags
Definition: srb.h:252
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:107
PVOID SrbExtension
Definition: srb.h:259
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
PVOID OriginalRequest
Definition: srb.h:258
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
UCHAR Cdb[16]
Definition: srb.h:271
struct _Entry Entry
Definition: kefuncs.h:627
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define _Out_
Definition: ms_sal.h:345
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define MmGetMdlVirtualAddress(_Mdl)
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:379
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define SRB_FLAGS_IS_ACTIVE
Definition: srb.h:399
struct _DEVICE_OBJECT * PDEVICE_OBJECT
PVOID DataBuffer
Definition: srb.h:255
#define SRB_STATUS_ABORT_FAILED
Definition: srb.h:335
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
IO_SCSI_CAPABILITIES PortCapabilities
Definition: scsiport.c:79
#define SCSI_PORT_LU_ACTIVE
Definition: scsiport.h:30
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG DataTransferLength
Definition: srb.h:253
#define SCSI_PORT_DISABLE_INTERRUPTS
Definition: scsiport.h:41
PDEVICE_OBJECT LowerDevice
Definition: scsiport.h:139
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
VOID NTAPI KeAcquireSpinLockAtDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:198
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
#define SRB_STATUS_REQUEST_FLUSHED
Definition: srb.h:353
#define LUNEX_REQUEST_PENDING
Definition: scsiport.h:50
#define TAG_SCSIPORT
Definition: scsiport.h:21
VOID NTAPI KeAcquireSpinLock(PKSPIN_LOCK SpinLock, PKIRQL OldIrql)
Definition: spinlock.c:50
#define SRB_STATUS_COMMAND_TIMEOUT
Definition: srb.h:343
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
UCHAR CdbLength
Definition: srb.h:250
#define SRB_FUNCTION_FLUSH_QUEUE
Definition: srb.h:321
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:340
PSCSI_REQUEST_BLOCK_INFO CompletedRequests
Definition: scsiport.h:197
#define SRB_FUNCTION_RELEASE_QUEUE
Definition: srb.h:311
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1426
KIRQL irql
Definition: wave.h:1
#define SRB_FUNCTION_CLAIM_DEVICE
Definition: srb.h:308
#define SCSISTAT_CHECK_CONDITION
Definition: cdrw_hw.h:1079
IO_STATUS_BLOCK IoStatus
struct _SCSI_REQUEST_BLOCK * NextSrb
Definition: srb.h:257
#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH
Definition: srb.h:352
#define InsertTailList(ListHead, Entry)
if(dx==0 &&dy==0)
Definition: linetemp.h:174
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
#define SCSI_PORT_RESET
Definition: scsiport.h:35
ULONG TimeOutValue
Definition: srb.h:254
#define SRB_STATUS_INVALID_TARGET_ID
Definition: srb.h:355
#define SCSI_PORT_NOTIFICATION_NEEDED
Definition: scsiport.h:31
_Out_ PKIRQL Irql
Definition: csq.h:179
UCHAR SrbStatus
Definition: srb.h:243
#define SRB_STATUS(Status)
Definition: srb.h:381
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
IO_COMPLETION_ROUTINE SpiSenseCompletionRoutine
Definition: scsi.c:453
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define SP_UNTAGGED
Definition: srb.h:225
#define IRP_MJ_SCSI
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
#define SRB_STATUS_ERROR
Definition: srb.h:336
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:636
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
return STATUS_NOT_IMPLEMENTED
#define SRB_STATUS_REQUEST_SENSE_FAILED
Definition: srb.h:347
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
IO_ALLOCATION_ACTION NTAPI SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID MapRegisterBase, PVOID Context)
Definition: scsiport.c:2039
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
long LONG
Definition: pedump.c:60
#define SRB_FLAGS_SGLIST_FROM_POOL
Definition: srb.h:401
#define SCSI_PORT_NEXT_REQUEST_READY
Definition: scsiport.c:54
UCHAR ScsiStatus
Definition: srb.h:244
static NTSTATUS SpiHandleAttachRelease(_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PIRP Irp)
Definition: scsi.c:52
VOID SpiGetNextRequestFromLun(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_opt_ PKIRQL OldIrql)
Definition: scsi.c:342
#define SRB_FLAGS_BYPASS_FROZEN_QUEUE
Definition: srb.h:390
Definition: bl.h:897
#define SRB_FLAGS_BYPASS_LOCKED_QUEUE
Definition: srb.h:402
NTSTATUS NTAPI ScsiPortDispatchScsi(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: scsi.c:123
BOOLEAN NTAPI KeInsertByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry, IN ULONG SortKey)
Definition: devqueue.c:83
#define SRB_STATUS_PENDING
Definition: srb.h:332
VOID NTAPI IoStartPacket(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PULONG Key, IN PDRIVER_CANCEL CancelFunction)
Definition: device.c:1876
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
#define SRB_FUNCTION_RELEASE_DEVICE
Definition: srb.h:313
struct _SCSI_REQUEST_BLOCK_INFO * PSCSI_REQUEST_BLOCK_INFO
#define SRB_STATUS_NO_HBA
Definition: srb.h:348
union _CDB * PCDB
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define _In_
Definition: ms_sal.h:308
#define IoCompleteRequest
Definition: irp.c:1240
void * PVOID
Definition: retypes.h:9
UCHAR QueueTag
Definition: srb.h:248
UCHAR TargetId
Definition: srb.h:246
static VOID SpiSendRequestSense(_In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _In_ PSCSI_REQUEST_BLOCK InitialSrb)
Definition: scsi.c:536
#define SRB_STATUS_BUSY
Definition: srb.h:337
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID NTAPI IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
Definition: dma.c:103
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define SRB_FUNCTION_FLUSH
Definition: srb.h:315
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
KIRQL OldIrql
Definition: mm.h:1502
Status
Definition: gdiplustypes.h:24
#define SCSI_PORT_RESET_REQUEST
Definition: scsiport.h:36
int64_t LONGLONG
Definition: typedefs.h:68
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define SRB_STATUS_BAD_FUNCTION
Definition: srb.h:356
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
NTSTATUS NTAPI IoAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context)
Definition: adapter.c:30
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_SUCH_DEVICE
Definition: udferr_usr.h:136
#define SCSI_PORT_MAP_TRANSFER
Definition: scsiport.h:34
SCSI_REQUEST_BLOCK_INFO SrbInfo
Definition: scsiport.h:174
#define LUNEX_NEED_REQUEST_SENSE
Definition: scsiport.h:47
UCHAR Function
Definition: srb.h:242
VOID NTAPI KeReleaseSpinLockFromDpcLevel(IN PKSPIN_LOCK SpinLock)
Definition: spinlock.c:221
FORCEINLINE VOID IoRequestDpc(_Inout_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Irp, _In_opt_ __drv_aliasesMem PVOID Context)
Definition: iofuncs.h:2750
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
PIRP NTAPI IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:750
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:156
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
BOOL Error
Definition: chkdsk.c:66
PSCSI_PORT_INTERRUPT_DATA InterruptData
Definition: scsiport.h:208
USHORT Length
Definition: srb.h:241
VOID NTAPI ScsiPortStartIo(_Inout_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
Definition: scsi.c:1603
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:349
struct _IRP * PIRP
#define SCSISTAT_QUEUE_FULL
Definition: cdrw_hw.h:1086
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
VOID NTAPI ScsiPortDpcForIsr(_In_ PKDPC Dpc, _In_ PDEVICE_OBJECT DpcDeviceObject, _Inout_ PIRP DpcIrp, _In_opt_ PVOID DpcContext)
Definition: scsi.c:1238
#define SCSI_PORT_DISABLE_INT_REQUESET
Definition: scsiport.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define SRB_FLAGS_DISABLE_DISCONNECT
Definition: srb.h:388
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN NTAPI SpiSaveInterruptData(IN PVOID Context)
Definition: scsi.c:1121
char * PBOOLEAN
Definition: retypes.h:11
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
#define SRB_FUNCTION_ATTACH_DEVICE
Definition: srb.h:312
VOID __cdecl ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, IN ...)
Definition: scsiport.c:1316
PSCSI_PORT_LUN_EXTENSION CompletedAbort
Definition: scsiport.h:198
#define InterlockedDecrement
Definition: armddk.h:52
Definition: ketypes.h:687
#define SRB_FUNCTION_IO_CONTROL
Definition: srb.h:309
#define VOID
Definition: acefi.h:82
#define _Inout_opt_
Definition: ms_sal.h:379
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
struct _SCSI_PORT_LUN_EXTENSION * CompletedAbortRequests
Definition: scsiport.h:172
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:342
#define SRB_FUNCTION_RESET_BUS
Definition: srb.h:318
#define SCSI_PORT_ENABLE_INT_REQUEST
Definition: scsiport.h:42
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
PSCSI_REQUEST_BLOCK Srb
Definition: scsiport.h:119
#define SRB_STATUS_INVALID_LUN
Definition: srb.h:354
#define SRB_FUNCTION_ABORT_COMMAND
Definition: srb.h:316
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
static VOID SpiProcessCompletedRequest(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_REQUEST_BLOCK_INFO SrbInfo, _Out_ PBOOLEAN NeedToCallStartIo)
Definition: scsi.c:647
IO_ALLOCATION_ACTION NTAPI ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context)
Definition: scsiport.c:3022
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
UCHAR SenseInfoBufferLength
Definition: srb.h:251
#define SRB_FUNCTION_SHUTDOWN
Definition: srb.h:314
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:170
#define InterlockedIncrement
Definition: armddk.h:53
PADAPTER_OBJECT AdapterObject
Definition: scsiport.c:87
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
UCHAR PathId
Definition: srb.h:245
Definition: ketypes.h:566
#define SRB_STATUS_TIMEOUT
Definition: srb.h:341
#define STATUS_DEVICE_BUSY
Definition: udferr_usr.h:129
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue)
Definition: devqueue.c:153
PHW_INTERRUPT HwInterrupt
Definition: scsiport.c:83
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
VOID NTAPI KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
Definition: spinlock.c:27
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
#define SCSI_PORT_FLUSH_ADAPTERS
Definition: scsiport.h:33
struct _SCSI_PORT_LUN_EXTENSION * ReadyLun
Definition: scsiport.h:171
PKDEVICE_QUEUE_ENTRY NTAPI KeRemoveByKeyDeviceQueue(IN PKDEVICE_QUEUE DeviceQueue, IN ULONG SortKey)
Definition: devqueue.c:197
#define DPRINT1
Definition: precomp.h:8
SCSI_PORT_COMMON_EXTENSION Common
Definition: scsiport.h:146
#define IRP_MJ_READ
Definition: rdpdr.c:46
PVOID SenseInfoBuffer
Definition: srb.h:256
struct tagContext Context
Definition: acpixf.h:1034
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
PSCSI_PORT_LUN_EXTENSION ReadyLun
Definition: scsiport.h:199
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
PSCSI_REQUEST_BLOCK_INFO SpiGetSrbData(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _In_ PSCSI_PORT_LUN_EXTENSION LunExtension, _In_ UCHAR QueueTag)
Definition: pdo.c:102
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define SCSI_PORT_DEVICE_BUSY
Definition: scsiport.h:29
#define MmGetSystemAddressForMdl(Mdl)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
BOOLEAN NTAPI KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext OPTIONAL)
Definition: interrupt.c:165
#define SCSIOP_REQUEST_SENSE
Definition: cdrw_hw.h:870
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _CDB::_CDB6INQUIRY CDB6INQUIRY
#define DPRINT
Definition: sndvol32.h:71
VOID NTAPI KeLowerIrql(KIRQL NewIrql)
Definition: spinlock.c:39
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
#define SCSI_PORT_TIMER_NEEDED
Definition: scsiport.h:43
#define SCSI_PORT_DISCONNECT_ALLOWED
Definition: scsiport.h:39
#define LUNEX_BUSY
Definition: scsiport.h:48
#define SCSI_PORT_RESET_REPORTED
Definition: scsiport.h:37
IoMarkIrpPending(Irp)
static NTSTATUS SpiStatusSrbToNt(_In_ UCHAR SrbStatus)
Definition: scsi.c:18
struct _SCSI_PORT_DEVICE_EXTENSION * DeviceExtension
Definition: scsiport.h:209
ULONG QueueSortKey
Definition: srb.h:262
base of all file and directory entries
Definition: entries.h:82
#define LUNEX_FROZEN_QUEUE
Definition: scsiport.h:46
#define Int32x32To64(a, b)
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:387
LONGLONG QuadPart
Definition: typedefs.h:114
#define SCSI_PORT_REQUEST_PENDING
Definition: scsiport.h:38
static PSCSI_REQUEST_BLOCK_INFO SpiAllocateSrbStructures(_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_ PSCSI_REQUEST_BLOCK Srb)
Definition: scsi.c:1456
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847