ReactOS  0.4.15-dev-1049-g1062a29
xferpkt.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 2010
4 
5 Module Name:
6 
7  xferpkt.c
8 
9 Abstract:
10 
11  Packet routines for CLASSPNP
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 
20 Revision History:
21 
22 --*/
23 
24 #include "classp.h"
25 #include "debug.h"
26 
27 #ifdef DEBUG_USE_WPP
28 #include "xferpkt.tmh"
29 #endif
30 
31 #ifdef ALLOC_PRAGMA
32  #pragma alloc_text(PAGE, InitializeTransferPackets)
33  #pragma alloc_text(PAGE, DestroyAllTransferPackets)
34  #pragma alloc_text(PAGE, SetupEjectionTransferPacket)
35  #pragma alloc_text(PAGE, SetupModeSenseTransferPacket)
36  #pragma alloc_text(PAGE, CleanupTransferPacketToWorkingSetSizeWorker)
37  #pragma alloc_text(PAGE, ClasspSetupPopulateTokenTransferPacket)
38 #endif
39 
40 /*
41  * InitializeTransferPackets
42  *
43  * Allocate/initialize TRANSFER_PACKETs and related resources.
44  */
46 {
49  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
50  PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
51  PSTORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR devIoCapabilityDesc = NULL;
52  STORAGE_PROPERTY_ID propertyId;
53  OSVERSIONINFOEXW osVersionInfo;
54  ULONG hwMaxPages;
55  ULONG arraySize;
56  ULONG index;
57  ULONG maxOutstandingIOPerLUN;
58  ULONG minWorkingSetTransferPackets;
59  ULONG maxWorkingSetTransferPackets;
60 
62 
63  PAGED_CODE();
64 
65  //
66  // Precompute the maximum transfer length
67  //
68  NT_ASSERT(adapterDesc->MaximumTransferLength);
69 
70  hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
71 
72  fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
73  fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
74 
75  //
76  // Allocate per-node free packet lists
77  //
78  arraySize = KeQueryHighestNodeNumber() + 1;
79  fdoData->FreeTransferPacketsLists =
80  ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
81  sizeof(PNL_SLIST_HEADER) * arraySize,
83 
84  if (fdoData->FreeTransferPacketsLists == NULL) {
86  return status;
87  }
88 
89  for (index = 0; index < arraySize; index++) {
93  }
94 
96 
97  //
98  // Set the packet threshold numbers based on the Windows Client or Server SKU.
99  //
100 
101  osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
102  status = RtlGetVersion((POSVERSIONINFOW) &osVersionInfo);
103 
105 
106  //
107  // Retrieve info on IO capability supported by port drivers
108  //
109 
111  status = ClassGetDescriptor(fdoExt->CommonExtension.LowerDeviceObject,
112  &propertyId,
113  (PVOID *)&devIoCapabilityDesc);
114 
115  if (NT_SUCCESS(status) && (devIoCapabilityDesc != NULL)) {
116  maxOutstandingIOPerLUN = devIoCapabilityDesc->LunMaxIoCount;
117  FREE_POOL(devIoCapabilityDesc);
118 
119 #if DBG
120  fdoData->MaxOutstandingIOPerLUN = maxOutstandingIOPerLUN;
121 #endif
122 
123  } else {
124  maxOutstandingIOPerLUN = MAX_OUTSTANDING_IO_PER_LUN_DEFAULT;
125 
126 #if DBG
127  fdoData->MaxOutstandingIOPerLUN = 0;
128 #endif
129 
130  }
131 
132  //
133  // StorageDeviceIoCapabilityProperty support is optional so
134  // ignore any failures.
135  //
136 
138 
139 
140  if ((osVersionInfo.wProductType != VER_NT_DOMAIN_CONTROLLER) &&
141  (osVersionInfo.wProductType != VER_NT_SERVER)) {
142 
143  // this is Client SKU
144 
145  minWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Client;
146 
147  // Note: the reason we use max here is to guarantee a reasonable large max number
148  // in the case where the port driver may return a very small supported outstanding
149  // IOs. For example, even EMMC drive only reports 1 outstanding IO supported, we
150  // may still want to set this value to be at least
151  // MAX_WORKINGSET_TRANSFER_PACKETS_Client.
152  maxWorkingSetTransferPackets = max(MAX_WORKINGSET_TRANSFER_PACKETS_Client,
153  2 * maxOutstandingIOPerLUN);
154 
155  } else {
156 
157  // this is Server SKU
158  // Note: the addition max here to make sure we set the min to be at least
159  // MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound no matter what maxOutstandingIOPerLUN
160  // reported. We shouldn't set this value to be smaller than client system.
161  // In other words, the minWorkingSetTransferPackets for server will always between
162  // MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound and MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound
163 
164  minWorkingSetTransferPackets =
167  maxOutstandingIOPerLUN));
168 
169  maxWorkingSetTransferPackets = max(MAX_WORKINGSET_TRANSFER_PACKETS_Server,
170  2 * maxOutstandingIOPerLUN);
171  }
172 
173 
174  fdoData->LocalMinWorkingSetTransferPackets = minWorkingSetTransferPackets;
175  fdoData->LocalMaxWorkingSetTransferPackets = maxWorkingSetTransferPackets;
176 
177  //
178  // Allow class driver to override the settings
179  //
180  if (commonExt->DriverExtension->WorkingSet != NULL) {
181  PCLASS_WORKING_SET workingSet = commonExt->DriverExtension->WorkingSet;
182 
183  // override only if non-zero
184  if (workingSet->XferPacketsWorkingSetMinimum != 0)
185  {
186  fdoData->LocalMinWorkingSetTransferPackets = workingSet->XferPacketsWorkingSetMinimum;
187  // adjust maximum upwards if needed
189  {
191  }
192  }
193  // override only if non-zero
194  if (workingSet->XferPacketsWorkingSetMaximum != 0)
195  {
196  fdoData->LocalMaxWorkingSetTransferPackets = workingSet->XferPacketsWorkingSetMaximum;
197  // adjust minimum downwards if needed
199  {
201  }
202  }
203  // that's all the adjustments required/allowed
204  } // end working set size special code
205 
206  for (index = 0; index < arraySize; index++) {
208  PTRANSFER_PACKET pkt = NewTransferPacket(Fdo);
209  if (pkt) {
211  pkt->AllocateNode = index;
212  EnqueueFreeTransferPacket(Fdo, pkt);
213  } else {
215  break;
216  }
217  }
219  }
220 
221  //
222  // Pre-initialize our SCSI_REQUEST_BLOCK template with all
223  // the constant fields. This will save a little time for each xfer.
224  // NOTE: a CdbLength field of 10 may not always be appropriate
225  //
226 
227  if (NT_SUCCESS(status)) {
228  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
229  ULONG ByteSize = 0;
230 
231  #if (NTDDI_VERSION >= NTDDI_WINBLUE)
232  if ((fdoExt->MiniportDescriptor != NULL) &&
233  (fdoExt->MiniportDescriptor->Size >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_MINIPORT_DESCRIPTOR, ExtraIoInfoSupported)) &&
234  (fdoExt->MiniportDescriptor->ExtraIoInfoSupported == TRUE)) {
236  fdoExt->AdapterDescriptor->AddressType,
238  &ByteSize,
239  2,
242  );
243  } else {
245  fdoExt->AdapterDescriptor->AddressType,
247  &ByteSize,
248  1,
250  );
251  }
252  #else
254  fdoExt->AdapterDescriptor->AddressType,
256  &ByteSize,
257  1,
259  );
260  #endif
261  if (NT_SUCCESS(status)) {
263  } else {
264  NT_ASSERT(FALSE);
265  }
266  } else {
267  fdoData->SrbTemplate = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SCSI_REQUEST_BLOCK), '-brs');
268  if (fdoData->SrbTemplate == NULL) {
270  } else {
271  RtlZeroMemory(fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
272  fdoData->SrbTemplate->Length = sizeof(SCSI_REQUEST_BLOCK);
273  fdoData->SrbTemplate->Function = SRB_FUNCTION_EXECUTE_SCSI;
274  }
275  }
276  }
277 
278  if (status == STATUS_SUCCESS) {
281  SrbSetCdbLength(fdoData->SrbTemplate, 10);
282  }
283 
284  return status;
285 }
286 
287 
289 {
291  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
292  TRANSFER_PACKET *pkt;
293  ULONG index;
294  ULONG arraySize;
295 
296  PAGED_CODE();
297 
298  //
299  // fdoData->FreeTransferPacketsLists could be NULL if
300  // there was an error during start device.
301  //
302  if (fdoData->FreeTransferPacketsLists != NULL) {
303 
305 
306  arraySize = KeQueryHighestNodeNumber() + 1;
307  for (index = 0; index < arraySize; index++) {
309  while (pkt) {
313  }
314 
316  }
317  }
318 
319  FREE_POOL(fdoData->SrbTemplate);
320 }
321 
323 #ifdef _MSC_VER
324 #pragma warning(suppress:28195) // This function may not allocate memory in some error cases.
325 #endif
326 PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo)
327 {
329  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
330  PTRANSFER_PACKET newPkt = NULL;
331  ULONG transferLength = (ULONG)-1;
333 
334  if (NT_SUCCESS(status)) {
335  status = RtlULongAdd(fdoData->HwMaxXferLen, PAGE_SIZE, &transferLength);
336  if (!NT_SUCCESS(status)) {
337 
338  TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_RW, "Integer overflow in calculating transfer packet size."));
340  }
341  }
342 
343  /*
344  * Allocate the actual packet.
345  */
346  if (NT_SUCCESS(status)) {
347  newPkt = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(TRANSFER_PACKET), 'pnPC');
348  if (newPkt == NULL) {
349  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate transfer packet."));
351  } else {
352  RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET));
354  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
355 #if (NTDDI_VERSION >= NTDDI_WINBLUE)
356  if ((fdoExt->MiniportDescriptor != NULL) &&
357  (fdoExt->MiniportDescriptor->Size >= RTL_SIZEOF_THROUGH_FIELD(STORAGE_MINIPORT_DESCRIPTOR, ExtraIoInfoSupported)) &&
358  (fdoExt->MiniportDescriptor->ExtraIoInfoSupported == TRUE)) {
360  fdoExt->AdapterDescriptor->AddressType,
362  NULL,
363  2,
366  );
367  } else {
369  fdoExt->AdapterDescriptor->AddressType,
371  NULL,
372  1,
374  );
375  }
376 #else
378  fdoExt->AdapterDescriptor->AddressType,
380  NULL,
381  1,
383  );
384 #endif
385  } else {
386 #ifdef _MSC_VER
387 #pragma prefast(suppress:6014, "The allocated memory that Pkt->Srb points to will be freed in DestroyTransferPacket().")
388 #endif
389  newPkt->Srb = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SCSI_REQUEST_BLOCK), '-brs');
390  if (newPkt->Srb == NULL) {
392  }
393 
394  }
395 
396  if (status != STATUS_SUCCESS)
397  {
398  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate SRB."));
399  FREE_POOL(newPkt);
400  }
401  }
402  }
403 
404  /*
405  * Allocate Irp for the packet.
406  */
407  if (NT_SUCCESS(status) && newPkt != NULL) {
408  newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE);
409  if (newPkt->Irp == NULL) {
410  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate IRP for transfer packet."));
412  }
413  }
414 
415  /*
416  * Allocate a MDL. Add one page to the length to insure an extra page
417  * entry is allocated if the buffer does not start on page boundaries.
418  */
419  if (NT_SUCCESS(status) && newPkt != NULL) {
420 
421  NT_ASSERT(transferLength != (ULONG)-1);
422 
423  newPkt->PartialMdl = IoAllocateMdl(NULL,
424  transferLength,
425  FALSE,
426  FALSE,
427  NULL);
428  if (newPkt->PartialMdl == NULL) {
429  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate MDL for transfer packet."));
431  } else {
432  NT_ASSERT(newPkt->PartialMdl->Size >= (CSHORT)(sizeof(MDL) + BYTES_TO_PAGES(fdoData->HwMaxXferLen) * sizeof(PFN_NUMBER)));
433  }
434 
435  }
436 
437  /*
438  * Allocate per-packet retry history, if required
439  */
440  if (NT_SUCCESS(status) &&
441  (fdoData->InterpretSenseInfo != NULL) &&
442  (newPkt != NULL)
443  ) {
444  // attempt to allocate also the history
445  ULONG historyByteCount = 0;
446 
447  // SAL annotation and ClassInitializeEx() should both catch this case
448  NT_ASSERT(fdoData->InterpretSenseInfo->HistoryCount != 0);
449  _Analysis_assume_(fdoData->InterpretSenseInfo->HistoryCount != 0);
450 
451  historyByteCount = sizeof(SRB_HISTORY_ITEM) * fdoData->InterpretSenseInfo->HistoryCount;
452  historyByteCount += sizeof(SRB_HISTORY) - sizeof(SRB_HISTORY_ITEM);
453 
454  newPkt->RetryHistory = (PSRB_HISTORY)ExAllocatePoolWithTag(NonPagedPoolNx, historyByteCount, 'hrPC');
455 
456  if (newPkt->RetryHistory == NULL) {
457  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "Failed to allocate MDL for transfer packet."));
459  } else {
460  // call this routine directly once since it's the first initialization of
461  // the structure and the internal maximum count field is not yet setup.
462  HistoryInitializeRetryLogs(newPkt->RetryHistory, fdoData->InterpretSenseInfo->HistoryCount);
463  }
464  }
465 
466  /*
467  * Enqueue the packet in our static AllTransferPacketsList
468  * (just so we can find it during debugging if its stuck somewhere).
469  */
470  if (NT_SUCCESS(status) && newPkt != NULL)
471  {
472  KIRQL oldIrql;
473  newPkt->Fdo = Fdo;
474 #if DBG
475  newPkt->DbgPktId = InterlockedIncrement((volatile LONG *)&fdoData->DbgMaxPktId);
476 #endif
477  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
479  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
480 
481  } else {
482  // free any resources acquired above (in reverse order)
483  if (newPkt != NULL) {
484  FREE_POOL(newPkt->RetryHistory);
485  if (newPkt->PartialMdl != NULL) { IoFreeMdl(newPkt->PartialMdl); }
486  if (newPkt->Irp != NULL) { IoFreeIrp(newPkt->Irp); }
487  if (newPkt->Srb != NULL) { FREE_POOL(newPkt->Srb); }
488  FREE_POOL(newPkt);
489  }
490  }
491 
492  return newPkt;
493 }
494 
495 
496 /*
497  * DestroyTransferPacket
498  *
499  */
501 {
503  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
504  KIRQL oldIrql;
505 
506  NT_ASSERT(!Pkt->SlistEntry.Next);
507 // NT_ASSERT(!Pkt->OriginalIrp);
508 
509  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
510 
511  /*
512  * Delete the packet from our all-packets queue.
513  */
518 
519  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
520 
522  IoFreeIrp(Pkt->Irp);
524  FREE_POOL(Pkt->Srb);
525  FREE_POOL(Pkt);
526 }
527 
528 
530 {
532  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
533  ULONG allocateNode;
534  KIRQL oldIrql;
535 
536  NT_ASSERT(!Pkt->SlistEntry.Next);
537 
538  allocateNode = Pkt->AllocateNode;
540  InterlockedIncrement((volatile LONG *)&(fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets));
541 
542  /*
543  * If the total number of packets is larger than LocalMinWorkingSetTransferPackets,
544  * that means that we've been in stress. If all those packets are now
545  * free, then we are now out of stress and can free the extra packets.
546  * Attempt to free down to LocalMaxWorkingSetTransferPackets immediately, and
547  * down to LocalMinWorkingSetTransferPackets lazily (one at a time).
548  * However, since we're at DPC, do this is a work item. If the device is removed
549  * or we are unable to allocate the work item, do NOT free more than
550  * MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE. Subsequent IO completions will end up freeing
551  * up the rest, even if it is MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE at a time.
552  */
553  if (fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets >=
554  fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets) {
555 
556  /*
557  * 1. Immediately snap down to our UPPER threshold.
558  */
559  if (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
561 
562  ULONG isRemoved;
563  PIO_WORKITEM workItem = NULL;
564 
565  workItem = IoAllocateWorkItem(Fdo);
566 
567  //
568  // Acquire a remove lock in order to make sure the device object and its
569  // private data structures will exist when the workitem fires.
570  // The remove lock will be released by the workitem (CleanupTransferPacketToWorkingSetSize).
571  //
572  isRemoved = ClassAcquireRemoveLock(Fdo, (PIRP)workItem);
573 
574  if (workItem && !isRemoved) {
575 
576  TracePrint((TRACE_LEVEL_INFORMATION,
577  TRACE_FLAG_GENERAL,
578  "EnqueueFreeTransferPacket: Device (%p), queuing work item to clean up free transfer packets.\n",
579  Fdo));
580 
581  //
582  // Queue a work item to trim down the total number of transfer packets to with the
583  // working size.
584  //
586 
587  } else {
588 
589  if (workItem) {
590  IoFreeWorkItem(workItem);
591  }
592 
593  if (isRemoved != REMOVE_COMPLETE) {
594  ClassReleaseRemoveLock(Fdo, (PIRP)workItem);
595  }
596 
597  TracePrint((TRACE_LEVEL_ERROR,
598  TRACE_FLAG_GENERAL,
599  "EnqueueFreeTransferPacket: Device (%p), Failed to allocate memory for the work item.\n",
600  Fdo));
601 
602  CleanupTransferPacketToWorkingSetSize(Fdo, TRUE, allocateNode);
603  }
604  }
605 
606  /*
607  * 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time).
608  */
609  if (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
611  /*
612  * Check the counter again with lock held. This eliminates a race condition
613  * while still allowing us to not grab the spinlock in the common codepath.
614  *
615  * Note that the spinlock does not synchronize with threads dequeuing free
616  * packets to send (DequeueFreeTransferPacket does that with a lightweight
617  * interlocked exchange); the spinlock prevents multiple threads in this function
618  * from deciding to free too many extra packets at once.
619  */
620  PTRANSFER_PACKET pktToDelete = NULL;
621 
622  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "Exiting stress, lazily freeing one of %d/%d packets from node %d.",
623  fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets,
625  allocateNode));
626 
627  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
628  if ((fdoData->FreeTransferPacketsLists[allocateNode].NumFreeTransferPackets >=
629  fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets) &&
630  (fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets >
632 
633  pktToDelete = DequeueFreeTransferPacketEx(Fdo, FALSE, allocateNode);
634  if (pktToDelete) {
635  InterlockedDecrement((volatile LONG *)&(fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets));
636  } else {
637  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,
638  "Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2). Node=%d",
640  Fdo,
641  fdoData->FreeTransferPacketsLists[allocateNode].NumTotalTransferPackets,
642  allocateNode));
643  }
644  }
645  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
646 
647  if (pktToDelete) {
648  DestroyTransferPacket(pktToDelete);
649  }
650  }
651 
652  }
653 
654 }
655 
657 {
658  return DequeueFreeTransferPacketEx(Fdo, AllocIfNeeded, KeGetCurrentNodeNumber());
659 }
660 
662  _In_ PDEVICE_OBJECT Fdo,
663  _In_ BOOLEAN AllocIfNeeded,
664  _In_ ULONG Node)
665 {
666  PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
667  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
668  PTRANSFER_PACKET pkt;
669  PSLIST_ENTRY slistEntry;
670 
672 
673  if (slistEntry) {
674  slistEntry->Next = NULL;
675  pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
677 
678  // when dequeuing the packet, also reset the history data
680 
681  } else {
682  if (AllocIfNeeded) {
683  /*
684  * We are in stress and have run out of lookaside packets.
685  * In order to service the current transfer,
686  * allocate an extra packet.
687  * We will free it lazily when we are out of stress.
688  */
689  pkt = NewTransferPacket(Fdo);
690  if (pkt) {
695  } else {
696  TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "DequeueFreeTransferPacket: packet allocation failed"));
697  }
698  } else {
699  pkt = NULL;
700  }
701  }
702 
703  return pkt;
704 }
705 
706 
707 
708 /*
709  * SetupReadWriteTransferPacket
710  *
711  * This function is called once to set up the first attempt to send a packet.
712  * It is not called before a retry, as SRB fields may be modified for the retry.
713  *
714  * Set up the Srb of the TRANSFER_PACKET for the transfer.
715  * The Irp is set up in SubmitTransferPacket because it must be reset
716  * for each packet submission.
717  */
719  PVOID Buf,
720  ULONG Len,
721  LARGE_INTEGER DiskLocation,
723 {
725  PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
726  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
728  UCHAR majorFunc = origCurSp->MajorFunction;
729  LARGE_INTEGER logicalBlockAddr;
730  ULONG numTransferBlocks;
731  PCDB pCdb;
732  ULONG srbLength;
733  ULONG timeoutValue = fdoExt->TimeOutValue;
734 
735  logicalBlockAddr.QuadPart = Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
736  numTransferBlocks = Len >> fdoExt->SectorShift;
737 
738  /*
739  * This field is useful when debugging, since low-memory conditions are
740  * handled differently for CDROM (which is the only driver using StartIO)
741  */
743 
744  /*
745  * Slap the constant SRB fields in from our pre-initialized template.
746  * We'll then only have to fill in the unique fields for this transfer.
747  * Tell lower drivers to sort the SRBs by the logical block address
748  * so that disk seeks are minimized.
749  */
750  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
751  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
752  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
753  } else {
754  srbLength = fdoData->SrbTemplate->Length;
755  }
756  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
757  SrbSetDataBuffer(Pkt->Srb, Buf);
759  SrbSetQueueSortKey(Pkt->Srb, logicalBlockAddr.LowPart);
760  if (logicalBlockAddr.QuadPart > 0xFFFFFFFF) {
761  //
762  // If the requested LBA is more than max ULONG set the
763  // QueueSortKey to the maximum value, so that these
764  // requests can be added towards the end of the queue.
765  //
766 
767  SrbSetQueueSortKey(Pkt->Srb, 0xFFFFFFFF);
768  }
771 
772 
773  SrbSetTimeOutValue(Pkt->Srb, timeoutValue);
774 
775  /*
776  * Arrange values in CDB in big-endian format.
777  */
778  pCdb = SrbGetCdb(Pkt->Srb);
779  if (pCdb) {
780  if (TEST_FLAG(fdoExt->DeviceFlags, DEV_USE_16BYTE_CDB)) {
781  REVERSE_BYTES_QUAD(&pCdb->CDB16.LogicalBlock, &logicalBlockAddr);
782  REVERSE_BYTES(&pCdb->CDB16.TransferLength, &numTransferBlocks);
783  pCdb->CDB16.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ16 : SCSIOP_WRITE16;
784  SrbSetCdbLength(Pkt->Srb, 16);
785  } else {
786  pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte3;
787  pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte2;
788  pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte1;
789  pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr.LowPart)->Byte0;
790  pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
791  pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
792  pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
793  }
794  }
795 
796  /*
797  * Set SRB and IRP flags
798  */
799  SrbAssignSrbFlags(Pkt->Srb, fdoExt->SrbFlags);
800  if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
803  }
805 
806  /*
807  * Allow caching only if this is not a write-through request.
808  * If write-through and caching is enabled on the device, force
809  * media access.
810  * Ignore SL_WRITE_THROUGH for reads; it's only set because the file handle was opened with WRITE_THROUGH.
811  */
812  if ((majorFunc == IRP_MJ_WRITE) && TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH) && pCdb) {
813  pCdb->CDB10.ForceUnitAccess = fdoExt->CdbForceUnitAccess;
814  } else {
816  }
817 
818  /*
819  * Remember the buf and len in the SRB because miniports
820  * can overwrite SRB.DataTransferLength and we may need it again
821  * for the retry.
822  */
823  Pkt->BufPtrCopy = Buf;
824  Pkt->BufLenCopy = Len;
825  Pkt->TargetLocationCopy = DiskLocation;
826 
828  Pkt->NumRetries = fdoData->MaxNumberOfIoRetries;
829  Pkt->SyncEventPtr = NULL;
831 #if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
834 #endif
835 
836 
837  if (pCdb) {
838  DBGLOGFLUSHINFO(fdoData, TRUE, (BOOLEAN)(pCdb->CDB10.ForceUnitAccess), FALSE);
839  } else {
840  DBGLOGFLUSHINFO(fdoData, TRUE, FALSE, FALSE);
841  }
842 }
843 
844 
845 /*
846  * SubmitTransferPacket
847  *
848  * Set up the IRP for the TRANSFER_PACKET submission and send it down.
849  */
851 {
852  PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
853  PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
855  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExtension->PrivateFdoData;
856  BOOLEAN idleRequest = FALSE;
857  PIO_STACK_LOCATION nextSp;
858 
859  NT_ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
860 
861  /*
862  * Attach the SRB to the IRP.
863  * The reused IRP's stack location has to be rewritten for each retry
864  * call because IoCompleteRequest clears the stack locations.
865  */
867 
868 
869  nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
870  nextSp->MajorFunction = IRP_MJ_SCSI;
871  nextSp->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)Pkt->Srb;
872 
873  SrbSetScsiStatus(Pkt->Srb, 0);
874  Pkt->Srb->SrbStatus = 0;
876 
878  /*
879  * Only dereference the "original IRP"'s stack location
880  * if its a real client irp (as opposed to a static irp
881  * we're using just for result status for one of the non-IO scsi commands).
882  *
883  * For read/write, propagate the storage-specific IRP stack location flags
884  * (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
885  */
887  nextSp->Flags = origCurSp->Flags;
888  }
889 
890  //
891  // If the request is not split, we can use the original IRP MDL. If the
892  // request needs to be split, we need to use a partial MDL. The partial MDL
893  // is needed because more than one driver might be mapping the same MDL
894  // and this causes problems.
895  //
896  if (Pkt->UsePartialMdl == FALSE) {
897  Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
898  } else {
900  Pkt->Irp->MdlAddress = Pkt->PartialMdl;
901  }
902 
903 
906 
907  //
908  // Set the original irp here for SFIO.
909  //
911 
912  //
913  // No need to lock for IdlePrioritySupported, since it will
914  // be modified only at initialization time.
915  //
916  if (fdoData->IdlePrioritySupported == TRUE) {
917  idleRequest = ClasspIsIdleRequest(Pkt->OriginalIrp);
918  if (idleRequest) {
920  } else {
922  }
923  }
924 
926  return IoCallDriver(nextDevObj, Pkt->Irp);
927 }
928 
929 
930 NTSTATUS
931 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
933 {
936  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
937  BOOLEAN packetDone = FALSE;
938  BOOLEAN idleRequest = FALSE;
939  ULONG transferLength;
940  LARGE_INTEGER completionTime;
941  ULONGLONG lastIoCompletionTime;
942 
943  UNREFERENCED_PARAMETER(NullFdo);
944 
945  /*
946  * Put all the assertions and spew in here so we don't have to look at them.
947  */
948  DBGLOGRETURNPACKET(pkt);
949  DBGCHECKRETURNEDPKT(pkt);
951 
952 
953  completionTime = ClasspGetCurrentTime();
954 
955  //
956  // Record the time at which the last IO completed while snapping the old
957  // value to be used later. This can occur on multiple threads and hence
958  // could be overwritten with an older value. This is OK because this value
959  // is maintained as a heuristic.
960  //
961 
962 #ifdef _WIN64
963  lastIoCompletionTime = ReadULong64NoFence((volatile ULONG64*)&fdoData->LastIoCompletionTime.QuadPart);
964  WriteULong64NoFence((volatile ULONG64*)&fdoData->LastIoCompletionTime.QuadPart,
965  completionTime.QuadPart);
966 #else
967  lastIoCompletionTime = InterlockedExchangeNoFence64((volatile LONG64*)&fdoData->LastIoCompletionTime.QuadPart,
968  completionTime.QuadPart);
969 #endif
970 
971  if (fdoData->IdlePrioritySupported == TRUE) {
972  idleRequest = ClasspIsIdleRequest(pkt->OriginalIrp);
973  if (idleRequest) {
975  NT_ASSERT(fdoData->ActiveIdleIoCount >= 0);
976  } else {
977  fdoData->LastNonIdleIoTime = completionTime;
979  NT_ASSERT(fdoData->ActiveIoCount >= 0);
980  }
981  }
982 
983  //
984  // If partial MDL was used, unmap the pages. When the packet is retried, the
985  // MDL will be recreated. If the packet is done, the MDL will be ready to be reused.
986  //
987  if (pkt->UsePartialMdl) {
989  }
990 
991  if (SRB_STATUS(pkt->Srb->SrbStatus) == SRB_STATUS_SUCCESS) {
992 
993  NT_ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
994 
995  transferLength = SrbGetDataTransferLength(pkt->Srb);
996 
998 
999  /*
1000  * The port driver should not have allocated a sense buffer
1001  * if the SRB succeeded.
1002  */
1003  NT_ASSERT(!PORT_ALLOCATED_SENSE_EX(fdoExt, pkt->Srb));
1004 
1005  /*
1006  * Add this packet's transferred length to the original IRP's.
1007  */
1009  (LONG)transferLength);
1010 
1011 
1012  if ((pkt->InLowMemRetry) ||
1013  (pkt->DriverUsesStartIO && pkt->LowMemRetry_remainingBufLen > 0)) {
1014  packetDone = StepLowMemRetry(pkt);
1015  } else {
1016  packetDone = TRUE;
1017  }
1018 
1019  }
1020  else {
1021  /*
1022  * The packet failed. We may retry it if possible.
1023  */
1024  BOOLEAN shouldRetry;
1025 
1026  /*
1027  * Make sure IRP status matches SRB error status (since we propagate it).
1028  */
1029  if (NT_SUCCESS(Irp->IoStatus.Status)){
1030  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1031  }
1032 
1033  /*
1034  * The packet failed.
1035  * So when sending the packet down we either saw either an error or STATUS_PENDING,
1036  * and so we returned STATUS_PENDING for the original IRP.
1037  * So now we must mark the original irp pending to match that, _regardless_ of
1038  * whether we actually switch threads here by retrying.
1039  * (We also have to mark the irp pending if the lower driver marked the irp pending;
1040  * that is dealt with farther down).
1041  */
1044  }
1045 
1046  /*
1047  * Interpret the SRB error (to a meaningful IRP status)
1048  * and determine if we should retry this packet.
1049  * This call looks at the returned SENSE info to figure out what to do.
1050  */
1051  shouldRetry = InterpretTransferPacketError(pkt);
1052 
1053  /*
1054  * If the SRB queue is locked-up, release it.
1055  * Do this after calling the error handler.
1056  */
1057  if (pkt->Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN){
1058  ClassReleaseQueue(pkt->Fdo);
1059  }
1060 
1061 
1062  if (NT_SUCCESS(Irp->IoStatus.Status)){
1063  /*
1064  * The error was recovered above in the InterpretTransferPacketError() call.
1065  */
1066 
1067  NT_ASSERT(!shouldRetry);
1068 
1069  /*
1070  * In the case of a recovered error,
1071  * add the transfer length to the original Irp as we would in the success case.
1072  */
1075 
1076  if ((pkt->InLowMemRetry) ||
1077  (pkt->DriverUsesStartIO && pkt->LowMemRetry_remainingBufLen > 0)) {
1078  packetDone = StepLowMemRetry(pkt);
1079  } else {
1080  packetDone = TRUE;
1081  }
1082  } else {
1083  if (shouldRetry && (pkt->NumRetries > 0)){
1084  packetDone = RetryTransferPacket(pkt);
1085  } else if (shouldRetry && (pkt->RetryHistory != NULL)){
1086  // don't limit retries if class driver has custom interpretation routines
1087  packetDone = RetryTransferPacket(pkt);
1088  } else {
1089  packetDone = TRUE;
1090  }
1091  }
1092  }
1093 
1094  /*
1095  * If the packet is completed, put it back in the free list.
1096  * If it is the last packet servicing the original request, complete the original irp.
1097  */
1098  if (packetDone){
1099  LONG numPacketsRemaining;
1100  PIRP deferredIrp;
1101  PDEVICE_OBJECT Fdo = pkt->Fdo;
1102  UCHAR uniqueAddr = 0;
1103 
1104  /*
1105  * In case a remove is pending, bump the lock count so we don't get freed
1106  * right after we complete the original irp.
1107  */
1108  ClassAcquireRemoveLock(Fdo, (PVOID)&uniqueAddr);
1109 
1110 
1111  /*
1112  * Sometimes the port driver can allocates a new 'sense' buffer
1113  * to report transfer errors, e.g. when the default sense buffer
1114  * is too small. If so, it is up to us to free it.
1115  * Now that we're done using the sense info, free it if appropriate.
1116  * Then clear the sense buffer so it doesn't pollute future errors returned in this packet.
1117  */
1118  if (PORT_ALLOCATED_SENSE_EX(fdoExt, pkt->Srb)) {
1119  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "Freeing port-allocated sense buffer for pkt %ph.", pkt));
1123  } else {
1126  }
1127 
1128  RtlZeroMemory(&pkt->SrbErrorSenseData, sizeof(pkt->SrbErrorSenseData));
1129 
1130  /*
1131  * Call IoSetMasterIrpStatus to set appropriate status
1132  * for the Master IRP.
1133  */
1135 
1136  if (!NT_SUCCESS(Irp->IoStatus.Status)){
1137  /*
1138  * If the original I/O originated in user space (i.e. it is thread-queued),
1139  * and the error is user-correctable (e.g. media is missing, for removable media),
1140  * alert the user.
1141  * Since this is only one of possibly several packets completing for the original IRP,
1142  * we may do this more than once for a single request. That's ok; this allows
1143  * us to test each returned status with IoIsErrorUserInduced().
1144  */
1145  if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
1147  pkt->OriginalIrp->Tail.Overlay.Thread){
1148 
1150  }
1151  }
1152 
1153  /*
1154  * We use a field in the original IRP to count
1155  * down the transfer pieces as they complete.
1156  */
1157  numPacketsRemaining = InterlockedDecrement(
1158  (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
1159 
1160  if (numPacketsRemaining > 0){
1161  /*
1162  * More transfer pieces remain for the original request.
1163  * Wait for them to complete before completing the original irp.
1164  */
1165  } else {
1166 
1167  /*
1168  * All the transfer pieces are done.
1169  * Complete the original irp if appropriate.
1170  */
1171  NT_ASSERT(numPacketsRemaining == 0);
1173 
1175  KIRQL oldIrql;
1176 
1177  if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
1180  }
1182 
1183  /*
1184  * We submitted all the downward irps, including this last one, on the thread
1185  * that the OriginalIrp came in on. So the OriginalIrp is completing on a
1186  * different thread iff this last downward irp is completing on a different thread.
1187  * If BlkCache is loaded, for example, it will often complete
1188  * requests out of the cache on the same thread, therefore not marking the downward
1189  * irp pending and not requiring us to do so here. If the downward request is completing
1190  * on the same thread, then by not marking the OriginalIrp pending we can save an APC
1191  * and get extra perf benefit out of BlkCache.
1192  * Note that if the packet ever cycled due to retry or LowMemRetry,
1193  * we set the pending bit in those codepaths.
1194  */
1195  if (pkt->Irp->PendingReturned){
1197  }
1198 
1199 
1201 
1202  //
1203  // Drop the count only after completing the request, to give
1204  // Mm some amount of time to issue its next critical request
1205  //
1206 
1208  {
1209  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
1210 
1212  {
1213  fdoData->MaxInterleavedNormalIo = 0;
1214  } else {
1216  }
1217 
1218  fdoData->NumHighPriorityPagingIo--;
1219 
1220  if (fdoData->NumHighPriorityPagingIo == 0)
1221  {
1222  LARGE_INTEGER period;
1223 
1224  //
1225  // Exiting throttle mode
1226  //
1227 
1229 
1230  period.QuadPart = fdoData->ThrottleStopTime.QuadPart - fdoData->ThrottleStartTime.QuadPart;
1232  }
1233 
1234  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
1235  }
1236 
1237  if (idleRequest) {
1238  ClasspCompleteIdleRequest(fdoExt);
1239  }
1240 
1241  /*
1242  * We may have been called by one of the class drivers (e.g. cdrom)
1243  * via the legacy API ClassSplitRequest.
1244  * This is the only case for which the packet engine is called for an FDO
1245  * with a StartIo routine; in that case, we have to call IoStartNextPacket
1246  * now that the original irp has been completed.
1247  */
1248  if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
1250  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
1251  } else {
1252  KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
1253  IoStartNextPacket(Fdo, TRUE); // yes, some IO is now cancellable
1254  KeLowerIrql(oldIrql);
1255  }
1256  }
1257  }
1258  }
1259 
1260  /*
1261  * If the packet was synchronous, write the final result back to the issuer's status buffer
1262  * and signal his event.
1263  */
1264  if (pkt->SyncEventPtr){
1265  KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
1266  pkt->SyncEventPtr = NULL;
1267  }
1268 
1269  /*
1270  * If the operation isn't a normal read/write, but needs to do more
1271  * operation-specific processing, call the operation's continuation
1272  * routine. The operation may create and queue another transfer packet
1273  * within this routine, but pkt is still freed after returning from the
1274  * continuation routine.
1275  */
1276  if (pkt->ContinuationRoutine != NULL){
1278  pkt->ContinuationRoutine = NULL;
1279  }
1280 
1281  /*
1282  * Free the completed packet.
1283  */
1284  pkt->UsePartialMdl = FALSE;
1285 // pkt->OriginalIrp = NULL;
1286  pkt->InLowMemRetry = FALSE;
1287  EnqueueFreeTransferPacket(Fdo, pkt);
1288 
1289  /*
1290  * Now that we have freed some resources,
1291  * try again to send one of the previously deferred irps.
1292  */
1293  deferredIrp = DequeueDeferredClientIrp(Fdo);
1294  if (deferredIrp){
1295  ServiceTransferRequest(Fdo, deferredIrp, TRUE);
1296  }
1297 
1298  ClassReleaseRemoveLock(Fdo, (PVOID)&uniqueAddr);
1299  }
1300 
1302 }
1303 
1304 
1305 /*
1306  * SetupEjectionTransferPacket
1307  *
1308  * Set up a transferPacket for a synchronous Ejection Control transfer.
1309  */
1311  BOOLEAN PreventMediaRemoval,
1312  PKEVENT SyncEventPtr,
1313  PIRP OriginalIrp)
1314 {
1316  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1317  PCDB pCdb;
1318  ULONG srbLength;
1319 
1320  PAGED_CODE();
1321 
1322  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1323  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1324  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1325  } else {
1326  srbLength = fdoData->SrbTemplate->Length;
1327  }
1328  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1329 
1331  SrbSetCdbLength(Pkt->Srb, 6);
1336 
1338 
1339  pCdb = SrbGetCdb(Pkt->Srb);
1340  if (pCdb) {
1341  pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
1342  pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
1343  }
1344 
1345  Pkt->BufPtrCopy = NULL;
1346  Pkt->BufLenCopy = 0;
1347 
1350  Pkt->SyncEventPtr = SyncEventPtr;
1352 }
1353 
1354 
1355 /*
1356  * SetupModeSenseTransferPacket
1357  *
1358  * Set up a transferPacket for a synchronous Mode Sense transfer.
1359  */
1361  PKEVENT SyncEventPtr,
1362  PVOID ModeSenseBuffer,
1363  UCHAR ModeSenseBufferLen,
1364  UCHAR PageMode,
1365  UCHAR SubPage,
1366  PIRP OriginalIrp,
1367  UCHAR PageControl)
1368 
1369 {
1371  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1372  PCDB pCdb;
1373  ULONG srbLength;
1374 
1375  PAGED_CODE();
1376 
1377  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1378  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1379  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1380  } else {
1381  srbLength = fdoData->SrbTemplate->Length;
1382  }
1383  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1384 
1386  SrbSetCdbLength(Pkt->Srb, 6);
1391  SrbSetDataBuffer(Pkt->Srb, ModeSenseBuffer);
1392  SrbSetDataTransferLength(Pkt->Srb, ModeSenseBufferLen);
1393 
1394 
1396 
1397  pCdb = SrbGetCdb(Pkt->Srb);
1398  if (pCdb) {
1399  pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
1400  pCdb->MODE_SENSE.PageCode = PageMode;
1401  pCdb->MODE_SENSE.SubPageCode = SubPage;
1402  pCdb->MODE_SENSE.Pc = PageControl;
1403  pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
1404  }
1405 
1406  Pkt->BufPtrCopy = ModeSenseBuffer;
1407  Pkt->BufLenCopy = ModeSenseBufferLen;
1408 
1411  Pkt->SyncEventPtr = SyncEventPtr;
1413 }
1414 
1415 /*
1416  * SetupModeSelectTransferPacket
1417  *
1418  * Set up a transferPacket for a synchronous Mode Select transfer.
1419  */
1421  PKEVENT SyncEventPtr,
1422  PVOID ModeSelectBuffer,
1423  UCHAR ModeSelectBufferLen,
1424  BOOLEAN SavePages,
1425  PIRP OriginalIrp)
1426 
1427 {
1429  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1430  PCDB pCdb;
1431  ULONG srbLength;
1432 
1433  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1434  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1435  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1436  } else {
1437  srbLength = fdoData->SrbTemplate->Length;
1438  }
1439  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1440 
1442  SrbSetCdbLength(Pkt->Srb, 6);
1447  SrbSetDataBuffer(Pkt->Srb, ModeSelectBuffer);
1448  SrbSetDataTransferLength(Pkt->Srb, ModeSelectBufferLen);
1449 
1451 
1452  pCdb = SrbGetCdb(Pkt->Srb);
1453  if (pCdb) {
1454  pCdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
1455  pCdb->MODE_SELECT.SPBit = SavePages;
1456  pCdb->MODE_SELECT.PFBit = 1;
1457  pCdb->MODE_SELECT.ParameterListLength = (UCHAR)ModeSelectBufferLen;
1458  }
1459 
1460  Pkt->BufPtrCopy = ModeSelectBuffer;
1461  Pkt->BufLenCopy = ModeSelectBufferLen;
1462 
1465  Pkt->SyncEventPtr = SyncEventPtr;
1467 }
1468 
1469 
1470 /*
1471  * SetupDriveCapacityTransferPacket
1472  *
1473  * Set up a transferPacket for a synchronous Drive Capacity transfer.
1474  */
1476  PVOID ReadCapacityBuffer,
1477  ULONG ReadCapacityBufferLen,
1478  PKEVENT SyncEventPtr,
1479  PIRP OriginalIrp,
1480  BOOLEAN Use16ByteCdb)
1481 {
1483  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1484  PCDB pCdb;
1485  ULONG srbLength;
1486  ULONG timeoutValue = fdoExt->TimeOutValue;
1487 
1488  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1489  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1490  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1491  } else {
1492  srbLength = fdoData->SrbTemplate->Length;
1493  }
1494  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1495 
1500 
1501 
1502  SrbSetTimeOutValue(Pkt->Srb, timeoutValue);
1503  SrbSetDataBuffer(Pkt->Srb, ReadCapacityBuffer);
1504  SrbSetDataTransferLength(Pkt->Srb, ReadCapacityBufferLen);
1505 
1507 
1508  pCdb = SrbGetCdb(Pkt->Srb);
1509  if (pCdb) {
1510  if (Use16ByteCdb == TRUE) {
1511  NT_ASSERT(ReadCapacityBufferLen >= sizeof(READ_CAPACITY_DATA_EX));
1512  SrbSetCdbLength(Pkt->Srb, 16);
1513  pCdb->CDB16.OperationCode = SCSIOP_READ_CAPACITY16;
1514  REVERSE_BYTES(&pCdb->CDB16.TransferLength, &ReadCapacityBufferLen);
1515  pCdb->AsByte[1] = 0x10; // Service Action
1516  } else {
1517  SrbSetCdbLength(Pkt->Srb, 10);
1518  pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
1519  }
1520  }
1521 
1522  Pkt->BufPtrCopy = ReadCapacityBuffer;
1523  Pkt->BufLenCopy = ReadCapacityBufferLen;
1524 
1527 #if !defined(__REACTOS__) && NTDDI_VERSION >= NTDDI_WINBLUE
1529 #endif
1530 
1531  Pkt->SyncEventPtr = SyncEventPtr;
1533 }
1534 
1535 
1536 #if 0
1537  /*
1538  * SetupSendStartUnitTransferPacket
1539  *
1540  * Set up a transferPacket for a synchronous Send Start Unit transfer.
1541  */
1542  VOID SetupSendStartUnitTransferPacket( TRANSFER_PACKET *Pkt,
1543  PIRP OriginalIrp)
1544  {
1546  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1547  PCDB pCdb;
1548 
1549  PAGED_CODE();
1550 
1552 
1553  /*
1554  * Initialize the SRB.
1555  * Use a very long timeout value to give the drive time to spin up.
1556  */
1557  Pkt->Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1558  Pkt->Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1559  Pkt->Srb->TimeOutValue = START_UNIT_TIMEOUT;
1560  Pkt->Srb->CdbLength = 6;
1561  Pkt->Srb->OriginalRequest = Pkt->Irp;
1562  Pkt->Srb->SenseInfoBuffer = &Pkt->SrbErrorSenseData;
1563  Pkt->Srb->SenseInfoBufferLength = sizeof(Pkt->SrbErrorSenseData);
1564  Pkt->Srb->Lun = 0;
1565 
1569 
1570  pCdb = (PCDB)Pkt->Srb->Cdb;
1571  pCdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
1572  pCdb->START_STOP.Start = 1;
1573  pCdb->START_STOP.Immediate = 0;
1574  pCdb->START_STOP.LogicalUnitNumber = 0;
1575 
1577  Pkt->NumRetries = 0;
1578  Pkt->SyncEventPtr = NULL;
1580  }
1581 #endif
1582 
1583 
1584 VOID
1585 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1587  _In_ PVOID Fdo,
1590  )
1591 {
1593 
1594  PAGED_CODE();
1595 
1597 
1598  //
1599  // Release the remove lock acquired in EnqueueFreeTransferPacket
1600  //
1602 
1603  if (IoWorkItem != NULL) {
1605  }
1606 }
1607 
1608 
1609 VOID
1611  _In_ PDEVICE_OBJECT Fdo,
1612  _In_ BOOLEAN LimitNumPktToDelete,
1613  _In_ ULONG Node
1614  )
1615 
1616 /*
1617 Routine Description:
1618 
1619  This function frees the resources for the free transfer packets attempting
1620  to bring them down within the working set size.
1621 
1622 Arguments:
1623  Fdo: The FDO that represents the device whose transfer packet size needs to be trimmed.
1624  LimitNumPktToDelete: Flag to indicate if the number of packets freed in one call should be capped.
1625  Node: NUMA node transfer packet is associated with.
1626 
1627 --*/
1628 
1629 {
1630  PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
1631  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
1632  KIRQL oldIrql;
1633  SINGLE_LIST_ENTRY pktList;
1634  PSINGLE_LIST_ENTRY slistEntry;
1635  PTRANSFER_PACKET pktToDelete;
1636  ULONG requiredNumPktToDelete = fdoData->FreeTransferPacketsLists[Node].NumTotalTransferPackets -
1638 
1639  if (LimitNumPktToDelete) {
1640  requiredNumPktToDelete = MIN(requiredNumPktToDelete, MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE);
1641  }
1642 
1643  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW, "CleanupTransferPacketToWorkingSetSize (%p): Exiting stress, block freeing %d packets.", Fdo, requiredNumPktToDelete));
1644 
1645  /*
1646  * Check the counter again with lock held. This eliminates a race condition
1647  * while still allowing us to not grab the spinlock in the common codepath.
1648  *
1649  * Note that the spinlock does not synchronize with threads dequeuing free
1650  * packets to send (DequeueFreeTransferPacket does that with a lightweight
1651  * interlocked exchange); the spinlock prevents multiple threads in this function
1652  * from deciding to free too many extra packets at once.
1653  */
1654  SimpleInitSlistHdr(&pktList);
1655  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
1658  (requiredNumPktToDelete--)){
1659 
1660  pktToDelete = DequeueFreeTransferPacketEx(Fdo, FALSE, Node);
1661  if (pktToDelete){
1662  SimplePushSlist(&pktList,
1663  (PSINGLE_LIST_ENTRY)&pktToDelete->SlistEntry);
1665  } else {
1666  TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_RW,
1667  "Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1). Node=%d",
1669  Fdo,
1671  Node));
1672  break;
1673  }
1674  }
1675  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
1676 
1677  slistEntry = SimplePopSlist(&pktList);
1678  while (slistEntry) {
1679  pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
1680  DestroyTransferPacket(pktToDelete);
1681  slistEntry = SimplePopSlist(&pktList);
1682  }
1683 
1684  return;
1685 }
1686 
1687 
1691 VOID
1692 ClasspSetupPopulateTokenTransferPacket(
1693  _In_ __drv_aliasesMem POFFLOAD_READ_CONTEXT OffloadReadContext,
1695  _In_ ULONG Length,
1696  _In_reads_bytes_(Length) PUCHAR PopulateTokenBuffer,
1699  )
1700 
1701 /*++
1702 
1703 Routine description:
1704 
1705  This routine is called once to set up a packet for PopulateToken.
1706  It builds up the SRB by setting the appropriate fields.
1707 
1708 Arguments:
1709 
1710  Pkt - The transfer packet to be sent down to the lower driver
1711  SyncEventPtr - The event that gets signaled once the IRP contained in the packet completes
1712  Length - Length of the buffer being sent as part of the command
1713  PopulateTokenBuffer - The buffer that contains the LBA ranges information for the PopulateToken operation
1714  OriginalIrp - The Io request to be processed
1715  ListIdentifier - The identifier that will be used to correlate a subsequent command to retrieve the token
1716 
1717 Return Value:
1718 
1719  Nothing
1720 
1721 --*/
1722 
1723 {
1725  PCLASS_PRIVATE_FDO_DATA fdoData;
1726  PCDB pCdb;
1727  ULONG srbLength;
1728 
1729  PAGED_CODE();
1730 
1731  TracePrint((TRACE_LEVEL_VERBOSE,
1732  TRACE_FLAG_IOCTL,
1733  "ClasspSetupPopulateTokenTransferPacket (%p): Entering function. Irp %p\n",
1734  Pkt->Fdo,
1735  OriginalIrp));
1736 
1737  fdoExt = Pkt->Fdo->DeviceExtension;
1738  fdoData = fdoExt->PrivateFdoData;
1739 
1740  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1741  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1742  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1743  } else {
1744  srbLength = fdoData->SrbTemplate->Length;
1745  }
1746  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1747 
1749  SrbSetCdbLength(Pkt->Srb, 16);
1754  SrbSetDataBuffer(Pkt->Srb, PopulateTokenBuffer);
1756 
1758 
1759  pCdb = SrbGetCdb(Pkt->Srb);
1760  if (pCdb) {
1761  pCdb->TOKEN_OPERATION.OperationCode = SCSIOP_POPULATE_TOKEN;
1762  pCdb->TOKEN_OPERATION.ServiceAction = SERVICE_ACTION_POPULATE_TOKEN;
1763 
1764  REVERSE_BYTES(&pCdb->TOKEN_OPERATION.ListIdentifier, &ListIdentifier);
1765  REVERSE_BYTES(&pCdb->TOKEN_OPERATION.ParameterListLength, &Length);
1766  }
1767 
1768  Pkt->BufPtrCopy = PopulateTokenBuffer;
1769  Pkt->BufLenCopy = Length;
1770 
1774 
1776  Pkt->ContinuationContext = OffloadReadContext;
1777 
1778  TracePrint((TRACE_LEVEL_VERBOSE,
1779  TRACE_FLAG_IOCTL,
1780  "ClasspSetupPopulateTokenTransferPacket (%p): Exiting function with Irp %p\n",
1781  Pkt->Fdo,
1782  OriginalIrp));
1783 
1784  return;
1785 }
1786 
1787 
1791 VOID
1792 ClasspSetupReceivePopulateTokenInformationTransferPacket(
1793  _In_ POFFLOAD_READ_CONTEXT OffloadReadContext,
1795  _In_ ULONG Length,
1796  _In_reads_bytes_(Length) PUCHAR ReceivePopulateTokenInformationBuffer,
1799  )
1800 
1801 /*++
1802 
1803 Routine description:
1804 
1805  This routine is called once to set up a packet for read token retrieval.
1806  It builds up the SRB by setting the appropriate fields.
1807 
1808 Arguments:
1809 
1810  Pkt - The transfer packet to be sent down to the lower driver
1811  Length - Length of the buffer being sent as part of the command
1812  ReceivePopulateTokenInformationBuffer - The buffer into which the target will pass back the token
1813  OriginalIrp - The Io request to be processed
1814  ListIdentifier - The identifier that will be used to correlate this command with its corresponding previous populate token operation
1815 
1816 Return Value:
1817 
1818  Nothing
1819 
1820 --*/
1821 
1822 {
1824  PCLASS_PRIVATE_FDO_DATA fdoData;
1825  PCDB pCdb;
1826  ULONG srbLength;
1827 
1828  TracePrint((TRACE_LEVEL_VERBOSE,
1829  TRACE_FLAG_IOCTL,
1830  "ClasspSetupReceivePopulateTokenInformationTransferPacket (%p): Entering function. Irp %p\n",
1831  Pkt->Fdo,
1832  OriginalIrp));
1833 
1834  fdoExt = Pkt->Fdo->DeviceExtension;
1835  fdoData = fdoExt->PrivateFdoData;
1836 
1837  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1838  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1839  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1840  } else {
1841  srbLength = fdoData->SrbTemplate->Length;
1842  }
1843  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1844 
1846  SrbSetCdbLength(Pkt->Srb, 16);
1851  SrbSetDataBuffer(Pkt->Srb, ReceivePopulateTokenInformationBuffer);
1853 
1855 
1856  pCdb = SrbGetCdb(Pkt->Srb);
1857  if (pCdb) {
1860 
1861  REVERSE_BYTES(&pCdb->RECEIVE_TOKEN_INFORMATION.ListIdentifier, &ListIdentifier);
1862  REVERSE_BYTES(&pCdb->RECEIVE_TOKEN_INFORMATION.AllocationLength, &Length);
1863  }
1864 
1865  Pkt->BufPtrCopy = ReceivePopulateTokenInformationBuffer;
1866  Pkt->BufLenCopy = Length;
1867 
1871 
1873  Pkt->ContinuationContext = OffloadReadContext;
1874 
1875  TracePrint((TRACE_LEVEL_VERBOSE,
1876  TRACE_FLAG_IOCTL,
1877  "ClasspSetupReceivePopulateTokenInformationTransferPacket (%p): Exiting function with Irp %p\n",
1878  Pkt->Fdo,
1879  OriginalIrp));
1880 
1881  return;
1882 }
1883 
1884 
1888 VOID
1889 ClasspSetupWriteUsingTokenTransferPacket(
1890  _In_ __drv_aliasesMem POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1892  _In_ ULONG Length,
1893  _In_reads_bytes_ (Length) PUCHAR WriteUsingTokenBuffer,
1896  )
1897 
1898 /*++
1899 
1900 Routine description:
1901 
1902  This routine is called once to set up a packet for WriteUsingToken.
1903  It builds up the SRB by setting the appropriate fields. It is not called
1904  before a retry as the SRB fields may be modified for the retry.
1905 
1906  The IRP is set up in SubmitTransferPacket because it must be reset for
1907  each packet submission.
1908 
1909 Arguments:
1910 
1911  Pkt - The transfer packet to be sent down to the lower driver
1912  Length - Length of the buffer being sent as part of the command
1913  WriteUsingTokenBuffer - The buffer that contains the read token and the write LBA ranges information for the WriteUsingToken operation
1914  OriginalIrp - The Io request to be processed
1915  ListIdentifier - The identifier that will be used to correlate a subsequent command to retrieve extended results in case of command failure
1916 
1917 Return Value:
1918 
1919  Nothing
1920 
1921 --*/
1922 
1923 {
1925  PCLASS_PRIVATE_FDO_DATA fdoData;
1926  PCDB pCdb;
1927  ULONG srbLength;
1928 
1929  TracePrint((TRACE_LEVEL_VERBOSE,
1930  TRACE_FLAG_IOCTL,
1931  "ClasspSetupWriteUsingTokenTransferPacket (%p): Entering function. Irp %p\n",
1932  Pkt->Fdo,
1933  OriginalIrp));
1934 
1935  fdoExt = Pkt->Fdo->DeviceExtension;
1936  fdoData = fdoExt->PrivateFdoData;
1937 
1938  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
1939  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
1940  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
1941  } else {
1942  srbLength = fdoData->SrbTemplate->Length;
1943  }
1944  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
1945 
1947  SrbSetCdbLength(Pkt->Srb, 16);
1952  SrbSetDataBuffer(Pkt->Srb, WriteUsingTokenBuffer);
1954 
1956 
1957  pCdb = SrbGetCdb(Pkt->Srb);
1958  if (pCdb) {
1959  pCdb->TOKEN_OPERATION.OperationCode = SCSIOP_WRITE_USING_TOKEN;
1960  pCdb->TOKEN_OPERATION.ServiceAction = SERVICE_ACTION_WRITE_USING_TOKEN;
1961 
1962  REVERSE_BYTES(&pCdb->TOKEN_OPERATION.ParameterListLength, &Length);
1963  REVERSE_BYTES(&pCdb->TOKEN_OPERATION.ListIdentifier, &ListIdentifier);
1964  }
1965 
1966  Pkt->BufPtrCopy = WriteUsingTokenBuffer;
1967  Pkt->BufLenCopy = Length;
1968 
1972 
1974  Pkt->ContinuationContext = OffloadWriteContext;
1975 
1976  TracePrint((TRACE_LEVEL_VERBOSE,
1977  TRACE_FLAG_IOCTL,
1978  "ClasspSetupWriteUsingTokenTransferPacket (%p): Exiting function with Irp %p\n",
1979  Pkt->Fdo,
1980  OriginalIrp));
1981 
1982  return;
1983 }
1984 
1985 
1989 VOID
1990 ClasspSetupReceiveWriteUsingTokenInformationTransferPacket(
1991  _In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext,
1993  _In_ ULONG Length,
1994  _In_reads_bytes_ (Length) PUCHAR ReceiveWriteUsingTokenInformationBuffer,
1997  )
1998 
1999 /*++
2000 
2001 Routine description:
2002 
2003  This routine is called once to set up a packet for extended results for
2004  WriteUsingToken operation. It builds up the SRB by setting the appropriate fields.
2005 
2006 Arguments:
2007 
2008  Pkt - The transfer packet to be sent down to the lower driver
2009  SyncEventPtr - The event that gets signaled once the IRP contained in the packet completes
2010  Length - Length of the buffer being sent as part of the command
2011  ReceiveWriteUsingTokenInformationBuffer - The buffer into which the target will pass back the extended results
2012  OriginalIrp - The Io request to be processed
2013  ListIdentifier - The identifier that will be used to correlate this command with its corresponding previous write using token operation
2014 
2015 Return Value:
2016 
2017  Nothing
2018 
2019 --*/
2020 
2021 {
2023  PCLASS_PRIVATE_FDO_DATA fdoData;
2024  PCDB pCdb;
2025  ULONG srbLength;
2026 
2027  TracePrint((TRACE_LEVEL_VERBOSE,
2028  TRACE_FLAG_IOCTL,
2029  "ClasspSetupReceiveWriteUsingTokenInformationTransferPacket (%p): Entering function. Irp %p\n",
2030  Pkt->Fdo,
2031  OriginalIrp));
2032 
2033  fdoExt = Pkt->Fdo->DeviceExtension;
2034  fdoData = fdoExt->PrivateFdoData;
2035 
2036  if (fdoExt->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) {
2037  srbLength = ((PSTORAGE_REQUEST_BLOCK) fdoData->SrbTemplate)->SrbLength;
2038  NT_ASSERT(((PSTORAGE_REQUEST_BLOCK) Pkt->Srb)->SrbLength >= srbLength);
2039  } else {
2040  srbLength = fdoData->SrbTemplate->Length;
2041  }
2042  RtlCopyMemory(Pkt->Srb, fdoData->SrbTemplate, srbLength); // copies _contents_ of SRB blocks
2043 
2045  SrbSetCdbLength(Pkt->Srb, 16);
2050  SrbSetDataBuffer(Pkt->Srb, ReceiveWriteUsingTokenInformationBuffer);
2052 
2054 
2055  pCdb = SrbGetCdb(Pkt->Srb);
2056  if (pCdb) {
2059 
2060  REVERSE_BYTES(&pCdb->RECEIVE_TOKEN_INFORMATION.AllocationLength, &Length);
2061  REVERSE_BYTES(&pCdb->RECEIVE_TOKEN_INFORMATION.ListIdentifier, &ListIdentifier);
2062  }
2063 
2064  Pkt->BufPtrCopy = ReceiveWriteUsingTokenInformationBuffer;
2065  Pkt->BufLenCopy = Length;
2066 
2070 
2072  Pkt->ContinuationContext = OffloadWriteContext;
2073 
2074  TracePrint((TRACE_LEVEL_VERBOSE,
2075  TRACE_FLAG_IOCTL,
2076  "ClasspSetupReceiveWriteUsingTokenInformationTransferPacket (%p): Exiting function with Irp %p\n",
2077  Pkt->Fdo,
2078  OriginalIrp));
2079 
2080  return;
2081 }
2082 
2083 
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
NTSTATUS SubmitTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:850
VOID ClasspWriteUsingTokenTransferPacketDone(_In_ PVOID Context)
Definition: class.c:15519
#define SCSIOP_WRITE_USING_TOKEN
Definition: scsi.h:341
__inline VOID ClasspSrbSetOriginalIrp(_In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb, _In_ PIRP Irp)
Definition: classp.h:2530
struct _FOUR_BYTE * PFOUR_BYTE
#define SRB_TYPE_STORAGE_REQUEST_BLOCK
Definition: srb.h:655
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:391
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:269
#define _IRQL_requires_same_
Definition: no_sal2.h:652
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:39
#define max(a, b)
Definition: svc.c:63
VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, UCHAR SubPage, PIRP OriginalIrp, UCHAR PageControl)
Definition: xferpkt.c:1360
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
NTKRNLVISTAAPI VOID IoSetMasterIrpStatus(_Inout_ PIRP MasterIrp, _In_ NTSTATUS Status)
Definition: io.c:131
FORCEINLINE UCHAR SrbGetSenseInfoBufferLength(_In_ PVOID Srb)
Definition: srbhelper.h:638
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
VOID ClasspCompleteIdleRequest(PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: clntirp.c:713
_In_ PTRANSFER_PACKET Pkt
Definition: classp.h:1754
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:599
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:100
FORCEINLINE VOID SrbAssignSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:946
BOOLEAN DriverUsesStartIO
Definition: classp.h:543
FORCEINLINE VOID SrbSetOriginalRequest(_In_ PVOID Srb, _In_opt_ PVOID OriginalRequest)
Definition: srbhelper.h:710
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:158
FORCEINLINE ULONG SrbGetSrbFlags(_In_ PVOID Srb)
Definition: srbhelper.h:927
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
PSTORAGE_REQUEST_BLOCK_HEADER SrbTemplate
Definition: classp.h:790
FORCEINLINE VOID SrbSetDataTransferLength(_In_ PVOID Srb, _In_ ULONG DataTransferLength)
Definition: srbhelper.h:784
IO_PAGING_PRIORITY FASTCALL IoGetPagingIoPriority(IN PIRP Irp)
Definition: irp.c:1748
#define DBGLOGFLUSHINFO(_fdoData, _isIO, _isFUA, _isFlush)
Definition: debug.h:129
Definition: ntbasedef.h:629
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
struct _SCSI_REQUEST_BLOCK * PSCSI_REQUEST_BLOCK
#define REMOVE_COMPLETE
Definition: classpnp.h:98
LARGE_INTEGER ThrottleStartTime
Definition: classp.h:836
PDRIVER_STARTIO ClassStartIo
Definition: class2.h:93
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:159
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define TRUE
Definition: types.h:120
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_LowerBound
Definition: classp.h:634
#define MAX_CLEANUP_TRANSFER_PACKETS_AT_ONCE
Definition: classp.h:639
#define HISTORYINITIALIZERETRYLOGS(_packet)
Definition: classp.h:2330
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG ClassMaxInterleavePerCriticalIo
Definition: class.c:88
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:599
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2813
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:873
DECLSPEC_CACHEALIGN SLIST_HEADER SListHeader
Definition: classp.h:644
KSPIN_LOCK SpinLock
Definition: classp.h:795
UCHAR NumThinProvisioningRetries
Definition: classp.h:517
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3465
#define NUM_WRITE_USING_TOKEN_RETRIES
Definition: classp.h:205
VOID NTAPI ClassReleaseQueue(_In_ PDEVICE_OBJECT Fdo)
Definition: class.c:11589
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:753
__inline VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
Definition: classp.h:1215
VOID ClasspReceiveWriteUsingTokenInformationTransferPacketDone(_In_ POFFLOAD_WRITE_CONTEXT OffloadWriteContext)
Definition: class.c:16071
#define MIN_WORKINGSET_TRANSFER_PACKETS_Client
Definition: classp.h:631
_In_opt_ PVOID _In_ PIO_WORKITEM IoWorkItem
Definition: iotypes.h:503
ULONG LocalMinWorkingSetTransferPackets
Definition: classp.h:711
PSTORAGE_REQUEST_BLOCK_HEADER Srb
Definition: classp.h:580
PIRP DequeueDeferredClientIrp(PDEVICE_OBJECT Fdo)
Definition: clntirp.c:113
UCHAR NumIoTimeoutRetries
Definition: classp.h:518
VOID SetupModeSelectTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSelectBuffer, UCHAR ModeSelectBufferLen, BOOLEAN SavePages, PIRP OriginalIrp)
Definition: xferpkt.c:1420
IO_STATUS_BLOCK IoStatus
PCONTINUATION_ROUTINE ContinuationRoutine
Definition: classp.h:608
FORCEINLINE PCDB SrbGetCdb(_In_ PVOID Srb)
Definition: srbhelper.h:583
#define SCSIOP_WRITE16
Definition: scsi.h:915
NTKRNLVISTAAPI USHORT NTAPI KeGetCurrentNodeNumber(VOID)
LIST_ENTRY AllPktsListEntry
Definition: classp.h:499
struct _CDB::_CDB10 CDB10
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:771
#define InsertTailList(ListHead, Entry)
FORCEINLINE VOID SrbSetSenseInfoBufferLength(_In_ PVOID Srb, _In_ UCHAR SenseInfoBufferLength)
Definition: srbhelper.h:675
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
FORCEINLINE PVOID SrbGetDataBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:728
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
#define DEV_USE_16BYTE_CDB
Definition: classpnp.h:183
PIO_WORKITEM NTAPI IoAllocateWorkItem(IN PDEVICE_OBJECT DeviceObject)
Definition: iowork.c:75
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
UCHAR NumRetries
Definition: classp.h:516
* PSTORAGE_DEVICE_IO_CAPABILITY_DESCRIPTOR
Definition: ntddstor.h:695
VOID NTAPI IoFreeWorkItem(IN PIO_WORKITEM IoWorkItem)
Definition: iowork.c:64
#define SRB_STATUS(Status)
Definition: srb.h:381
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
LARGE_INTEGER TargetLocationCopy
Definition: classp.h:564
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
#define SRB_FLAGS_DONT_START_NEXT_PACKET
Definition: srb.h:407
#define _In_opt_
Definition: no_sal2.h:213
LARGE_INTEGER LastIoCompletionTime
Definition: classp.h:940
struct _CDB::_CDB16 CDB16
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IRP_MJ_SCSI
T MIN(T a, T b)
Definition: polytest.cpp:79
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET Pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
Definition: xferpkt.c:718
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
#define _IRQL_requires_min_(irql)
Definition: no_sal2.h:651
__inline VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1211
ULONG DbgPeakNumTransferPackets
Definition: classp.h:647
ULONG PFN_NUMBER
Definition: ke.h:8
__inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2560
LARGE_INTEGER ThrottleStopTime
Definition: classp.h:841
#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
FORCEINLINE VOID SrbSetScsiStatus(_In_ PVOID Srb, _In_ UCHAR ScsiStatus)
Definition: srbhelper.h:1056
#define FALSE
Definition: types.h:117
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP _In_ ULONG ListIdentifier
Definition: classp.h:1757
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
#define InterlockedExchangeNoFence64
Definition: interlocked.h:174
long LONG
Definition: pedump.c:60
PVOID DefaultStorageRequestBlockAllocateRoutine(_In_ CLONG ByteSize)
Definition: srblib.c:28
NTKRNLVISTAAPI VOID NTAPI IoQueueWorkItemEx(_Inout_ PIO_WORKITEM IoWorkItem, _In_ PIO_WORKITEM_ROUTINE_EX WorkerRoutine, _In_ WORK_QUEUE_TYPE QueueType, _In_opt_ __drv_aliasesMem PVOID Context)
Definition: io.c:55
#define SERVICE_ACTION_POPULATE_TOKEN
Definition: scsi.h:442
union node Node
Definition: types.h:1255
DECLSPEC_CACHEALIGN ULONG NumFreeTransferPackets
Definition: classp.h:645
PDEVICE_OBJECT Fdo
Definition: classp.h:503
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define VER_NT_DOMAIN_CONTROLLER
#define SCSIOP_READ16
Definition: scsi.h:914
NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
Definition: xferpkt.c:932
#define __drv_aliasesMem
Definition: btrfs_drv.h:205
PVOID DeviceExtension
Definition: env_spec_w32.h:418
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
unsigned char BOOLEAN
VOID NTAPI ClassReleaseRemoveLock(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PIRP Tag)
Definition: lock.c:251
smooth NULL
Definition: ftsmooth.c:416
* PSTORAGE_REQUEST_BLOCK
Definition: srb.h:652
union _CDB * PCDB
struct _CDB::_RECEIVE_TOKEN_INFORMATION RECEIVE_TOKEN_INFORMATION
#define NUM_DRIVECAPACITY_RETRIES
Definition: classp.h:161
#define NUM_LOCKMEDIAREMOVAL_RETRIES
Definition: classp.h:158
VOID(* PCONTINUATION_ROUTINE)(_In_ PVOID Context)
Definition: classp.h:492
GLuint index
Definition: glext.h:6031
struct _CDB::_START_STOP START_STOP
BOOLEAN InLowMemRetry
Definition: classp.h:544
__drv_allocatesMem(Mem)
Definition: xferpkt.c:322
#define InterlockedExchangeAdd
Definition: interlocked.h:181
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
FORCEINLINE ULONG SrbGetDataTransferLength(_In_ PVOID Srb)
Definition: srbhelper.h:765
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
struct _CDB::_MODE_SELECT MODE_SELECT
struct _CDB::_MODE_SENSE MODE_SENSE
FORCEINLINE VOID SrbSetCdbLength(_In_ PVOID Srb, _In_ UCHAR CdbLength)
Definition: srbhelper.h:1093
LIST_ENTRY DeferredClientIrpList
Definition: classp.h:777
#define MIN_INITIAL_TRANSFER_PACKETS
Definition: classp.h:630
#define NUM_POPULATE_TOKEN_RETRIES
Definition: classp.h:204
enum _IO_PAGING_PRIORITY IO_PAGING_PRIORITY
VOID NTAPI CleanupTransferPacketToWorkingSetSizeWorker(_In_ PVOID Fdo, _In_opt_ PVOID Context, _In_ PIO_WORKITEM IoWorkItem)
Definition: xferpkt.c:1586
int64_t LONG64
Definition: typedefs.h:68
PVOID ContinuationContext
Definition: classp.h:609
BOOLEAN UsePartialMdl
Definition: classp.h:595
PIRP OriginalIrp
Definition: classp.h:509
VOID ClasspPerfIncrementSuccessfulIo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:486
#define NUM_MODESELECT_RETRIES
Definition: classp.h:160
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define SERVICE_ACTION_RECEIVE_TOKEN_INFORMATION
Definition: scsi.h:447
uint64_t ULONGLONG
Definition: typedefs.h:67
PSRB_HISTORY RetryHistory
Definition: classp.h:598
FORCEINLINE VOID SrbSetTimeOutValue(_In_ PVOID Srb, _In_ ULONG TimeOutValue)
Definition: srbhelper.h:821
PSTORAGE_ADAPTER_DESCRIPTOR AdapterDescriptor
Definition: classpnp.h:877
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
struct _CDB::_TOKEN_OPERATION TOKEN_OPERATION
#define SENSE_BUFFER_SIZE_EX
Definition: scsi.h:596
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
struct _TRANSFER_PACKET * PTRANSFER_PACKET
#define HISTORYLOGSENDPACKET(_packet)
Definition: classp.h:2345
ULONG NumTotalTransferPackets
Definition: classp.h:646
__inline LARGE_INTEGER ClasspGetCurrentTime(VOID)
Definition: classp.h:1280
#define Len
Definition: deflate.h:82
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:673
#define PSLIST_ENTRY
Definition: rtltypes.h:134
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned __int64 ULONG64
Definition: imports.h:198
#define BYTES_TO_PAGES(Size)
#define SRB_CLASS_FLAGS_PAGING
Definition: classpnp.h:21
PPNL_SLIST_HEADER FreeTransferPacketsLists
Definition: classp.h:772
#define NUM_MODESENSE_RETRIES
Definition: classp.h:159
#define DBGLOGSENDPACKET(_pkt)
Definition: debug.h:127
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp, BOOLEAN Use16ByteCdb)
Definition: xferpkt.c:1475
#define CLASS_TAG_PRIVATE_DATA
Definition: classp.h:189
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
MDL
Definition: mmtypes.h:117
#define index(s, c)
Definition: various.h:29
BOOLEAN IdlePrioritySupported
Definition: classp.h:808
#define InterlockedDecrement
Definition: armddk.h:52
FORCEINLINE VOID SrbSetRequestAttribute(_In_ PVOID Srb, _In_ UCHAR RequestAttribute)
Definition: srbhelper.h:1131
#define SCSIOP_RECEIVE_ROD_TOKEN_INFORMATION
Definition: scsi.h:343
PCLASS_DRIVER_EXTENSION DriverExtension
Definition: classpnp.h:600
#define SCSIOP_READ_CAPACITY16
Definition: scsi.h:364
struct _SRB_HISTORY_ITEM SRB_HISTORY_ITEM
__inline BOOLEAN ClasspIsIdleRequest(PIRP Irp)
Definition: classp.h:1268
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
PCLASS_WORKING_SET WorkingSet
Definition: classpnp.h:588
#define SERVICE_ACTION_WRITE_USING_TOKEN
Definition: scsi.h:443
#define SCSIOP_POPULATE_TOKEN
Definition: scsi.h:340
ULONG LowPart
Definition: typedefs.h:106
#define HISTORYLOGRETURNEDPACKET(_packet)
Definition: classp.h:2357
ULONG NumHighPriorityPagingIo
Definition: classp.h:826
#define PAGE_SIZE
Definition: env_spec_w32.h:49
NTSTATUS ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp, BOOLEAN PostToDpc)
Definition: class.c:3341
PKEVENT SyncEventPtr
Definition: classp.h:535
#define FREE_POOL(_PoolPtr)
Definition: classpnp.h:63
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
NTSTATUS CreateStorageRequestBlock(_Inout_ PSTORAGE_REQUEST_BLOCK *Srb, _In_ USHORT AddressType, _In_opt_ PSRB_ALLOCATE_ROUTINE AllocateRoutine, _Inout_opt_ ULONG *ByteSize, _In_ ULONG NumSrbExData,...)
Definition: srblib.c:249
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2691
#define MmPrepareMdlForReuse(_Mdl)
struct _OSVERSIONINFOEXW OSVERSIONINFOEXW
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:157
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
T MAX(T a, T b)
Definition: polytest.cpp:85
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
UCHAR MaxNumberOfIoRetries
Definition: classp.h:976
LARGE_INTEGER LongestThrottlePeriod
Definition: classp.h:846
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define Int64ShrlMod32(a, b)
#define _In_
Definition: no_sal2.h:204
__inline BOOLEAN PORT_ALLOCATED_SENSE_EX(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSTORAGE_REQUEST_BLOCK_HEADER Srb)
Definition: classp.h:2547
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2789
ULONG LowMemRetry_remainingBufLen
Definition: classp.h:546
#define InterlockedIncrement
Definition: armddk.h:53
VOID DestroyTransferPacket(_In_ __drv_freesMem(mem) PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:500
#define DBGCHECKRETURNEDPKT(_pkt)
Definition: debug.h:126
FORCEINLINE PVOID SrbGetSenseInfoBuffer(_In_ PVOID Srb)
Definition: srbhelper.h:619
VOID CleanupTransferPacketToWorkingSetSize(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN LimitNumPktToDelete, _In_ ULONG Node)
Definition: xferpkt.c:1610
#define START_UNIT_TIMEOUT
Definition: class2.c:30
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server_UpperBound
Definition: classp.h:633
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define min(a, b)
Definition: monoChain.cc:55
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:393
PTRANSFER_PACKET DequeueFreeTransferPacketEx(_In_ PDEVICE_OBJECT Fdo, _In_ BOOLEAN AllocIfNeeded, _In_ ULONG Node)
Definition: xferpkt.c:661
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:598
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
VOID ClasspPopulateTokenTransferPacketDone(_In_ PVOID Context)
Definition: class.c:14166
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define __drv_freesMem(kind)
Definition: driverspecs.h:254
BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt)
Definition: retry.c:40
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
Definition: srb.h:397
VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:288
#define IRP_PAGING_IO
#define SL_WRITE_THROUGH
Definition: iotypes.h:1804
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
VOID HistoryInitializeRetryLogs(_Out_ PSRB_HISTORY History, ULONG HistoryCount)
Definition: history.c:36
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define VER_NT_SERVER
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:706
VOID SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp)
Definition: xferpkt.c:1310
Definition: mem.c:156
PMDL PartialMdl
Definition: classp.h:596
FORCEINLINE VOID SrbSetDataBuffer(_In_ PVOID Srb, _In_opt_ __drv_aliasesMem PVOID DataBuffer)
Definition: srbhelper.h:747
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:45
PUCHAR BufPtrCopy
Definition: classp.h:562
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
CLASS_INIT_DATA InitData
Definition: classpnp.h:577
__inline SINGLE_LIST_ENTRY * SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
Definition: classp.h:1220
struct tagContext Context
Definition: acpixf.h:1034
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:635
unsigned int ULONG
Definition: retypes.h:1
SLIST_ENTRY SlistEntry
Definition: classp.h:500
FORCEINLINE VOID SrbSetSenseInfoBuffer(_In_ PVOID Srb, _In_opt_ PVOID SenseInfoBuffer)
Definition: srbhelper.h:657
FORCEINLINE VOID SrbSetSrbFlags(_In_ PVOID Srb, _In_ ULONG Flags)
Definition: srbhelper.h:964
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static int priority
Definition: timer.c:163
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
SENSE_DATA_EX SrbErrorSenseData
Definition: classp.h:570
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define MAX_WORKINGSET_TRANSFER_PACKETS_Client
Definition: classp.h:632
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
ULONG MaxInterleavedNormalIo
Definition: classp.h:831
PCLASS_INTERPRET_SENSE_INFO2 InterpretSenseInfo
Definition: classp.h:958
NTKRNLVISTAAPI USHORT NTAPI KeQueryHighestNodeNumber(VOID)
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:656
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3107
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:393
short CSHORT
Definition: umtypes.h:127
VOID NTAPI ClassCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ CCHAR PriorityBoost)
Definition: lock.c:401
signed int * PLONG
Definition: retypes.h:5
FORCEINLINE VOID SrbSetQueueSortKey(_In_ PVOID Srb, _In_ ULONG QueueSortKey)
Definition: srbhelper.h:839
static SERVICE_STATUS status
Definition: service.c:31
#define DBGLOGRETURNPACKET(_pkt)
Definition: debug.h:128
struct _SRB_HISTORY * PSRB_HISTORY
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define MAX_OUTSTANDING_IO_PER_LUN_DEFAULT
Definition: classp.h:638
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, __drv_aliasesMem PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:529
ULONG AllocateNode
Definition: classp.h:611
VOID ClasspReceivePopulateTokenInformationTransferPacketDone(_In_ PVOID Context)
Definition: class.c:14504
_IRQL_requires_max_(APC_LEVEL)
Definition: xferpkt.c:1688
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
LARGE_INTEGER LastNonIdleIoTime
Definition: classp.h:935
UCHAR AsByte[16]
Definition: scsi.h:1988
#define REVERSE_BYTES_QUAD(Destination, Source)
Definition: scsi.h:3452
ULONG BufLenCopy
Definition: classp.h:563
#define IRP_SYNCHRONOUS_PAGING_IO
LONGLONG QuadPart
Definition: typedefs.h:114
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt)
Definition: retry.c:453
Definition: dlist.c:348
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:510
#define PAGED_CODE()
#define SCSIOP_MODE_SELECT
Definition: cdrw_hw.h:891
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847
#define NT_ASSERT
Definition: rtlfuncs.h:3312
ULONG LocalMaxWorkingSetTransferPackets
Definition: classp.h:712
Definition: ps.c:97