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