ReactOS  0.4.15-dev-338-g3dad100
xferpkt.c File Reference
#include "classp.h"
Include dependency graph for xferpkt.c:

Go to the source code of this file.

Functions

NTSTATUS NTAPI InitializeTransferPackets (PDEVICE_OBJECT Fdo)
 
VOID NTAPI DestroyAllTransferPackets (PDEVICE_OBJECT Fdo)
 
PTRANSFER_PACKET NTAPI NewTransferPacket (PDEVICE_OBJECT Fdo)
 
VOID NTAPI DestroyTransferPacket (PTRANSFER_PACKET Pkt)
 
VOID NTAPI EnqueueFreeTransferPacket (PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
 
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket (PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
 
VOID NTAPI SetupReadWriteTransferPacket (PTRANSFER_PACKET Pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
 
VOID NTAPI SubmitTransferPacket (PTRANSFER_PACKET Pkt)
 
NTSTATUS NTAPI TransferPktComplete (IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
 
VOID NTAPI SetupEjectionTransferPacket (TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp)
 
VOID NTAPI SetupModeSenseTransferPacket (TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp)
 
VOID NTAPI SetupDriveCapacityTransferPacket (TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp)
 

Variables

ULONG MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer
 
ULONG MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer
 

Function Documentation

◆ DequeueFreeTransferPacket()

PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket ( PDEVICE_OBJECT  Fdo,
BOOLEAN  AllocIfNeeded 
)

Definition at line 322 of file xferpkt.c.

323 {
325  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
326  PTRANSFER_PACKET pkt;
327  PSLIST_ENTRY slistEntry;
328  //KIRQL oldIrql;
329 
330  slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
331  if (slistEntry){
332  slistEntry->Next = NULL;
333  pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
334  ASSERT(fdoData->NumFreeTransferPackets > 0);
336  }
337  else {
338  if (AllocIfNeeded){
339  /*
340  * We are in stress and have run out of lookaside packets.
341  * In order to service the current transfer,
342  * allocate an extra packet.
343  * We will free it lazily when we are out of stress.
344  */
345  pkt = NewTransferPacket(Fdo);
346  if (pkt){
349  }
350  else {
351  DBGWARN(("DequeueFreeTransferPacket: packet allocation failed"));
352  }
353  }
354  else {
355  pkt = NULL;
356  }
357  }
358 
359  return pkt;
360 }
#define max(a, b)
Definition: svc.c:63
ULONG NumTotalTransferPackets
Definition: classp.h:437
ULONG DbgPeakNumTransferPackets
Definition: classp.h:438
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
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
PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:152
#define PSLIST_ENTRY
Definition: rtltypes.h:130
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedDecrement
Definition: armddk.h:52
#define InterlockedIncrement
Definition: armddk.h:53
SLIST_HEADER FreeTransferPacketsList
Definition: classp.h:435
#define DBGWARN(args_in_parens)
Definition: debug.h:134
ULONG NumFreeTransferPackets
Definition: classp.h:436
signed int * PLONG
Definition: retypes.h:5

Referenced by ClassModeSense(), ClassReadDriveCapacity(), DestroyAllTransferPackets(), EnqueueFreeTransferPacket(), and ServiceTransferRequest().

◆ DestroyAllTransferPackets()

VOID NTAPI DestroyAllTransferPackets ( PDEVICE_OBJECT  Fdo)

Definition at line 134 of file xferpkt.c.

135 {
137  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
138  TRANSFER_PACKET *pkt;
139 
140  PAGED_CODE();
141 
143 
144  while ((pkt = DequeueFreeTransferPacket(Fdo, FALSE))){
147  }
148 
149  ASSERT(fdoData->NumTotalTransferPackets == 0);
150 }
ULONG NumTotalTransferPackets
Definition: classp.h:437
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:322
PVOID DeviceExtension
Definition: env_spec_w32.h:418
LIST_ENTRY DeferredClientIrpList
Definition: classp.h:443
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedDecrement
Definition: armddk.h:52
signed int * PLONG
Definition: retypes.h:5
VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:192
#define PAGED_CODE()

Referenced by ClassRemoveDevice().

◆ DestroyTransferPacket()

VOID NTAPI DestroyTransferPacket ( PTRANSFER_PACKET  Pkt)

Definition at line 192 of file xferpkt.c.

193 {
195  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
196  KIRQL oldIrql;
197 
198  ASSERT(!Pkt->SlistEntry.Next);
199  ASSERT(!Pkt->OriginalIrp);
200 
201  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
202 
203  /*
204  * Delete the packet from our all-packets queue.
205  */
210 
211  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
212 
213  IoFreeIrp(Pkt->Irp);
214  ExFreePool(Pkt);
215 }
KSPIN_LOCK SpinLock
Definition: classp.h:456
LIST_ENTRY AllPktsListEntry
Definition: classp.h:287
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:434
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
PDEVICE_OBJECT Fdo
Definition: classp.h:290
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PIRP OriginalIrp
Definition: classp.h:296
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
SLIST_ENTRY SlistEntry
Definition: classp.h:286
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by DestroyAllTransferPackets(), and EnqueueFreeTransferPacket().

◆ EnqueueFreeTransferPacket()

VOID NTAPI EnqueueFreeTransferPacket ( PDEVICE_OBJECT  Fdo,
PTRANSFER_PACKET  Pkt 
)

Definition at line 217 of file xferpkt.c.

218 {
220  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
221  KIRQL oldIrql;
222  ULONG newNumPkts;
223 
224  ASSERT(!Pkt->SlistEntry.Next);
225 
227  newNumPkts = InterlockedIncrement((PLONG)&fdoData->NumFreeTransferPackets);
228  ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets);
229 
230  /*
231  * If the total number of packets is larger than MinWorkingSetTransferPackets,
232  * that means that we've been in stress. If all those packets are now
233  * free, then we are now out of stress and can free the extra packets.
234  * Free down to MaxWorkingSetTransferPackets immediately, and
235  * down to MinWorkingSetTransferPackets lazily (one at a time).
236  */
237  if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){
238 
239  /*
240  * 1. Immediately snap down to our UPPER threshold.
241  */
243  SLIST_ENTRY pktList;
244  PSLIST_ENTRY slistEntry;
245  PTRANSFER_PACKET pktToDelete;
246 
247  DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets));
248 
249  /*
250  * Check the counter again with lock held. This eliminates a race condition
251  * while still allowing us to not grab the spinlock in the common codepath.
252  *
253  * Note that the spinlock does not synchronize with threads dequeuing free
254  * packets to send (DequeueFreeTransferPacket does that with a lightweight
255  * interlocked exchange); the spinlock prevents multiple threads in this function
256  * from deciding to free too many extra packets at once.
257  */
258  SimpleInitSlistHdr(&pktList);
259  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
260  while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
262 
263  pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
264  if (pktToDelete){
265  SimplePushSlist(&pktList, &pktToDelete->SlistEntry);
267  }
268  else {
269  DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
270  break;
271  }
272  }
273  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
274 
275  while ((slistEntry = SimplePopSlist(&pktList))){
276  pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
277  DestroyTransferPacket(pktToDelete);
278  }
279 
280  }
281 
282  /*
283  * 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time).
284  */
286  /*
287  * Check the counter again with lock held. This eliminates a race condition
288  * while still allowing us to not grab the spinlock in the common codepath.
289  *
290  * Note that the spinlock does not synchronize with threads dequeuing free
291  * packets to send (DequeueFreeTransferPacket does that with a lightweight
292  * interlocked exchange); the spinlock prevents multiple threads in this function
293  * from deciding to free too many extra packets at once.
294  */
295  PTRANSFER_PACKET pktToDelete = NULL;
296 
297  DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets));
298 
299  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
300  if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
302 
303  pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
304  if (pktToDelete){
306  }
307  else {
308  DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
309  }
310  }
311  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
312 
313  if (pktToDelete){
314  DestroyTransferPacket(pktToDelete);
315  }
316  }
317 
318  }
319 
320 }
static VOID SimpleInitSlistHdr(SLIST_ENTRY *SListHdr)
Definition: classp.h:478
static VOID SimplePushSlist(SLIST_ENTRY *SListHdr, SLIST_ENTRY *SListEntry)
Definition: classp.h:482
ULONG MaxWorkingSetTransferPackets
Definition: xferpkt.c:35
KSPIN_LOCK SpinLock
Definition: classp.h:456
ULONG NumTotalTransferPackets
Definition: classp.h:437
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:322
static SLIST_ENTRY * SimplePopSlist(SLIST_ENTRY *SListHdr)
Definition: classp.h:487
UCHAR KIRQL
Definition: env_spec_w32.h:591
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
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
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define PSLIST_ENTRY
Definition: rtltypes.h:130
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define InterlockedDecrement
Definition: armddk.h:52
#define DBGTRACE(dbgTraceLevel, args_in_parens)
Definition: debug.h:136
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
#define InterlockedIncrement
Definition: armddk.h:53
SLIST_HEADER FreeTransferPacketsList
Definition: classp.h:435
ULONG MinWorkingSetTransferPackets
Definition: xferpkt.c:34
ULONG NumFreeTransferPackets
Definition: classp.h:436
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define SLIST_ENTRY(type)
Definition: queue.h:102
unsigned int ULONG
Definition: retypes.h:1
SLIST_ENTRY SlistEntry
Definition: classp.h:286
signed int * PLONG
Definition: retypes.h:5
VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:192

Referenced by InitializeTransferPackets(), ServiceTransferRequest(), and TransferPktComplete().

◆ InitializeTransferPackets()

NTSTATUS NTAPI InitializeTransferPackets ( PDEVICE_OBJECT  Fdo)

Definition at line 43 of file xferpkt.c.

44 {
47  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
48  PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
49  ULONG hwMaxPages;
51 
52  PAGED_CODE();
53 
54  /*
55  * Precompute the maximum transfer length
56  */
57  ASSERT(adapterDesc->MaximumTransferLength);
58  ASSERT(adapterDesc->MaximumPhysicalPages);
59  hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
60 
61 #if defined(_AMD64_SIMULATOR_)
62 
63  //
64  // The simulator appears to have a problem with large transfers.
65  //
66 
67  if (hwMaxPages > 4) {
68  hwMaxPages = 4;
69  }
70 
71 #endif
72 
73  fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
74  fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
75 
76  fdoData->NumTotalTransferPackets = 0;
77  fdoData->NumFreeTransferPackets = 0;
81 
82  /*
83  * Set the packet threshold numbers based on the Windows SKU.
84  */
85  if (ExVerifySuite(Personal)){
86  // this is Windows Personal
89  }
91  // this is Advanced Server or Datacenter
94  }
95  else if (ExVerifySuite(TerminalServer)){
96  // this is standard Server or Pro with terminal server
99  }
100  else {
101  // this is Professional without terminal server
104  }
105 
108  if (pkt){
110  EnqueueFreeTransferPacket(Fdo, pkt);
111  }
112  else {
114  break;
115  }
116  }
118 
119  /*
120  * Pre-initialize our SCSI_REQUEST_BLOCK template with all
121  * the constant fields. This will save a little time for each xfer.
122  * NOTE: a CdbLength field of 10 may not always be appropriate
123  */
124  RtlZeroMemory(&fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
125  fdoData->SrbTemplate.Length = sizeof(SCSI_REQUEST_BLOCK);
128  fdoData->SrbTemplate.SenseInfoBufferLength = sizeof(SENSE_DATA);
129  fdoData->SrbTemplate.CdbLength = 10;
130 
131  return status;
132 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:476
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:377
ULONG MaxWorkingSetTransferPackets
Definition: xferpkt.c:35
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:575
LONG NTSTATUS
Definition: precomp.h:26
ULONG NumTotalTransferPackets
Definition: classp.h:437
UCHAR CdbLength
Definition: srb.h:250
UCHAR QueueAction
Definition: srb.h:249
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:434
BOOLEAN NTAPI ExVerifySuite(SUITE_TYPE SuiteType)
Definition: sysinfo.c:377
#define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise
Definition: classp.h:380
ULONG DbgPeakNumTransferPackets
Definition: classp.h:438
T MIN(T a, T b)
Definition: polytest.cpp:79
#define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer
Definition: classp.h:376
struct _SENSE_DATA SENSE_DATA
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:217
PVOID DeviceExtension
Definition: env_spec_w32.h:418
FORCEINLINE VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:152
LIST_ENTRY DeferredClientIrpList
Definition: classp.h:443
#define MIN_INITIAL_TRANSFER_PACKETS
Definition: classp.h:374
UCHAR Function
Definition: srb.h:242
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
T MAX(T a, T b)
Definition: polytest.cpp:85
UCHAR SenseInfoBufferLength
Definition: srb.h:251
SCSI_REQUEST_BLOCK SrbTemplate
Definition: classp.h:454
#define InterlockedIncrement
Definition: armddk.h:53
SLIST_HEADER FreeTransferPacketsList
Definition: classp.h:435
ULONG MinWorkingSetTransferPackets
Definition: xferpkt.c:34
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise
Definition: classp.h:379
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
ULONG NumFreeTransferPackets
Definition: classp.h:436
#define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer
Definition: classp.h:375
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:378
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
return STATUS_SUCCESS
Definition: btrfs.c:3014
signed int * PLONG
Definition: retypes.h:5
static SERVICE_STATUS status
Definition: service.c:31
#define PAGED_CODE()
Definition: ps.c:97

Referenced by ClassPnpStartDevice().

◆ NewTransferPacket()

PTRANSFER_PACKET NTAPI NewTransferPacket ( PDEVICE_OBJECT  Fdo)

Definition at line 152 of file xferpkt.c.

153 {
155  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
156  PTRANSFER_PACKET newPkt;
157 
158  newPkt = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSFER_PACKET), 'pnPC');
159  if (newPkt){
160  RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET)); // just to be sure
161 
162  /*
163  * Allocate resources for the packet.
164  */
165  newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE);
166  if (newPkt->Irp){
167  KIRQL oldIrql;
168 
169  newPkt->Fdo = Fdo;
170 
171  /*
172  * Enqueue the packet in our static AllTransferPacketsList
173  * (just so we can find it during debugging if its stuck somewhere).
174  */
175  KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
177  KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
178  }
179  else {
180  ExFreePool(newPkt);
181  newPkt = NULL;
182  }
183  }
184 
185  return newPkt;
186 }
KSPIN_LOCK SpinLock
Definition: classp.h:456
LIST_ENTRY AllPktsListEntry
Definition: classp.h:287
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:434
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
PDEVICE_OBJECT Fdo
Definition: classp.h:290
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

Referenced by DequeueFreeTransferPacket(), and InitializeTransferPackets().

◆ SetupDriveCapacityTransferPacket()

VOID NTAPI SetupDriveCapacityTransferPacket ( TRANSFER_PACKET Pkt,
PVOID  ReadCapacityBuffer,
ULONG  ReadCapacityBufferLen,
PKEVENT  SyncEventPtr,
PIRP  OriginalIrp 
)

Definition at line 808 of file xferpkt.c.

813 {
815  PCDB pCdb;
816 
817  RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
818 
819  Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
822  Pkt->Srb.CdbLength = 10;
823  Pkt->Srb.OriginalRequest = Pkt->Irp;
825  Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
826  Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
827  Pkt->Srb.DataBuffer = ReadCapacityBuffer;
828  Pkt->Srb.DataTransferLength = ReadCapacityBufferLen;
829 
830  Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
834 
835  pCdb = (PCDB)Pkt->Srb.Cdb;
836  pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
837 
838  Pkt->BufPtrCopy = ReadCapacityBuffer;
839  Pkt->BufLenCopy = ReadCapacityBufferLen;
840 
841  Pkt->OriginalIrp = OriginalIrp;
843  Pkt->SyncEventPtr = SyncEventPtr;
845 }
ULONG SrbFlags
Definition: srb.h:252
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
PVOID DataBuffer
Definition: srb.h:255
ULONG DataTransferLength
Definition: srb.h:253
Definition: cdrw_hw.h:28
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
UCHAR CdbLength
Definition: srb.h:250
UCHAR QueueAction
Definition: srb.h:249
struct _CDB::_CDB10 CDB10
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
ULONG TimeOutValue
Definition: srb.h:254
ULONG NumRetries
Definition: classp.h:302
PDEVICE_OBJECT Fdo
Definition: classp.h:290
struct _SENSE_DATA SENSE_DATA
PVOID DeviceExtension
Definition: env_spec_w32.h:418
union _CDB * PCDB
#define NUM_DRIVECAPACITY_RETRIES
Definition: classp.h:76
PIRP OriginalIrp
Definition: classp.h:296
UCHAR Function
Definition: srb.h:242
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
PKEVENT SyncEventPtr
Definition: classp.h:313
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
UCHAR SenseInfoBufferLength
Definition: srb.h:251
SENSE_DATA SrbErrorSenseData
Definition: classp.h:345
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
PVOID SenseInfoBuffer
Definition: srb.h:256
PUCHAR BufPtrCopy
Definition: classp.h:337
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ULONG BufLenCopy
Definition: classp.h:338
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297

Referenced by ClassReadDriveCapacity().

◆ SetupEjectionTransferPacket()

VOID NTAPI SetupEjectionTransferPacket ( TRANSFER_PACKET Pkt,
BOOLEAN  PreventMediaRemoval,
PKEVENT  SyncEventPtr,
PIRP  OriginalIrp 
)

Definition at line 716 of file xferpkt.c.

720 {
722  PCDB pCdb;
723 
724  PAGED_CODE();
725 
726  RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
727 
728  Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
731  Pkt->Srb.CdbLength = 6;
732  Pkt->Srb.OriginalRequest = Pkt->Irp;
734  Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
735  Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
736 
737  Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
740 
741  pCdb = (PCDB)Pkt->Srb.Cdb;
742  pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
743  pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
744 
745  Pkt->BufPtrCopy = NULL;
746  Pkt->BufLenCopy = 0;
747 
748  Pkt->OriginalIrp = OriginalIrp;
750  Pkt->SyncEventPtr = SyncEventPtr;
752 }
ULONG SrbFlags
Definition: srb.h:252
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
Definition: cdrw_hw.h:28
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
UCHAR CdbLength
Definition: srb.h:250
UCHAR QueueAction
Definition: srb.h:249
ULONG TimeOutValue
Definition: srb.h:254
ULONG NumRetries
Definition: classp.h:302
PDEVICE_OBJECT Fdo
Definition: classp.h:290
struct _SENSE_DATA SENSE_DATA
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
union _CDB * PCDB
#define NUM_LOCKMEDIAREMOVAL_RETRIES
Definition: classp.h:74
PIRP OriginalIrp
Definition: classp.h:296
UCHAR Function
Definition: srb.h:242
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
PKEVENT SyncEventPtr
Definition: classp.h:313
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
UCHAR SenseInfoBufferLength
Definition: srb.h:251
SENSE_DATA SrbErrorSenseData
Definition: classp.h:345
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
PVOID SenseInfoBuffer
Definition: srb.h:256
PUCHAR BufPtrCopy
Definition: classp.h:337
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ULONG BufLenCopy
Definition: classp.h:338
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297
#define PAGED_CODE()

◆ SetupModeSenseTransferPacket()

VOID NTAPI SetupModeSenseTransferPacket ( TRANSFER_PACKET Pkt,
PKEVENT  SyncEventPtr,
PVOID  ModeSenseBuffer,
UCHAR  ModeSenseBufferLen,
UCHAR  PageMode,
PIRP  OriginalIrp 
)

Definition at line 759 of file xferpkt.c.

765 {
767  PCDB pCdb;
768 
769  PAGED_CODE();
770 
771  RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
772 
773  Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
776  Pkt->Srb.CdbLength = 6;
777  Pkt->Srb.OriginalRequest = Pkt->Irp;
779  Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
780  Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
781  Pkt->Srb.DataBuffer = ModeSenseBuffer;
782  Pkt->Srb.DataTransferLength = ModeSenseBufferLen;
783 
784  Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
788 
789  pCdb = (PCDB)Pkt->Srb.Cdb;
790  pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
791  pCdb->MODE_SENSE.PageCode = PageMode;
792  pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
793 
794  Pkt->BufPtrCopy = ModeSenseBuffer;
795  Pkt->BufLenCopy = ModeSenseBufferLen;
796 
797  Pkt->OriginalIrp = OriginalIrp;
799  Pkt->SyncEventPtr = SyncEventPtr;
801 }
ULONG SrbFlags
Definition: srb.h:252
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
PVOID DataBuffer
Definition: srb.h:255
ULONG DataTransferLength
Definition: srb.h:253
Definition: cdrw_hw.h:28
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
UCHAR CdbLength
Definition: srb.h:250
UCHAR QueueAction
Definition: srb.h:249
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
ULONG TimeOutValue
Definition: srb.h:254
ULONG NumRetries
Definition: classp.h:302
PDEVICE_OBJECT Fdo
Definition: classp.h:290
struct _SENSE_DATA SENSE_DATA
PVOID DeviceExtension
Definition: env_spec_w32.h:418
union _CDB * PCDB
struct _CDB::_MODE_SENSE MODE_SENSE
PIRP OriginalIrp
Definition: classp.h:296
UCHAR Function
Definition: srb.h:242
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define NUM_MODESENSE_RETRIES
Definition: classp.h:75
unsigned char UCHAR
Definition: xmlstorage.h:181
PKEVENT SyncEventPtr
Definition: classp.h:313
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
UCHAR SenseInfoBufferLength
Definition: srb.h:251
SENSE_DATA SrbErrorSenseData
Definition: classp.h:345
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
PVOID SenseInfoBuffer
Definition: srb.h:256
PUCHAR BufPtrCopy
Definition: classp.h:337
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ULONG BufLenCopy
Definition: classp.h:338
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297
#define PAGED_CODE()

Referenced by ClassModeSense().

◆ SetupReadWriteTransferPacket()

VOID NTAPI SetupReadWriteTransferPacket ( PTRANSFER_PACKET  Pkt,
PVOID  Buf,
ULONG  Len,
LARGE_INTEGER  DiskLocation,
PIRP  OriginalIrp 
)

Definition at line 372 of file xferpkt.c.

377 {
379  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
380  PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp);
381  UCHAR majorFunc = origCurSp->MajorFunction;
382  ULONG logicalBlockAddr;
383  ULONG numTransferBlocks;
384  PCDB pCdb;
385 
386  logicalBlockAddr = (ULONG)Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
387  numTransferBlocks = Len >> fdoExt->SectorShift;
388 
389  /*
390  * Slap the constant SRB fields in from our pre-initialized template.
391  * We'll then only have to fill in the unique fields for this transfer.
392  * Tell lower drivers to sort the SRBs by the logical block address
393  * so that disk seeks are minimized.
394  */
395  Pkt->Srb = fdoData->SrbTemplate; // copies _contents_ of SRB blocks
396  Pkt->Srb.DataBuffer = Buf;
397  Pkt->Srb.DataTransferLength = Len;
398  Pkt->Srb.QueueSortKey = logicalBlockAddr;
399  Pkt->Srb.OriginalRequest = Pkt->Irp;
401  Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0);
402  Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue;
403 
404  /*
405  * Arrange values in CDB in big-endian format.
406  */
407  pCdb = (PCDB)Pkt->Srb.Cdb;
408  pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte3;
409  pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte2;
410  pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte1;
411  pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte0;
412  pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
413  pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
414  pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
415 
416  /*
417  * Set SRB and IRP flags
418  */
419  Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
420  if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
421  TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){
423  }
425 
426  /*
427  * Allow caching only if this is not a write-through request.
428  * If write-through and caching is enabled on the device, force
429  * media access.
430  */
431  if (TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)){
432  if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE)){
433  pCdb->CDB10.ForceUnitAccess = TRUE;
434  }
435  }
436  else {
438  }
439 
440  /*
441  * Remember the buf and len in the SRB because miniports
442  * can overwrite SRB.DataTransferLength and we may need it again
443  * for the retry.
444  */
445  Pkt->BufPtrCopy = Buf;
446  Pkt->BufLenCopy = Len;
447  Pkt->TargetLocationCopy = DiskLocation;
448 
449  Pkt->OriginalIrp = OriginalIrp;
450  Pkt->NumRetries = MAXIMUM_RETRIES;
451  Pkt->SyncEventPtr = NULL;
453 }
struct _FOUR_BYTE * PFOUR_BYTE
#define TRUE
Definition: types.h:120
ULONG SrbFlags
Definition: srb.h:252
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:156
PVOID DataBuffer
Definition: srb.h:255
ULONG DataTransferLength
Definition: srb.h:253
Definition: cdrw_hw.h:28
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
struct _CDB::_CDB10 CDB10
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
ULONG TimeOutValue
Definition: srb.h:254
ULONG NumRetries
Definition: classp.h:302
LARGE_INTEGER TargetLocationCopy
Definition: classp.h:339
#define DEV_WRITE_CACHE
Definition: class2.h:21
PDEVICE_OBJECT Fdo
Definition: classp.h:290
#define SCSIOP_READ
Definition: cdrw_hw.h:905
PVOID DeviceExtension
Definition: env_spec_w32.h:418
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
smooth NULL
Definition: ftsmooth.c:416
union _CDB * PCDB
#define MAXIMUM_RETRIES
Definition: class2.h:14
PIRP OriginalIrp
Definition: classp.h:296
#define Len
Definition: deflate.h:82
#define SRB_CLASS_FLAGS_PAGING
Definition: classpnp.h:21
unsigned char UCHAR
Definition: xmlstorage.h:181
PKEVENT SyncEventPtr
Definition: classp.h:313
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
#define Int64ShrlMod32(a, b)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
SENSE_DATA SrbErrorSenseData
Definition: classp.h:345
SCSI_REQUEST_BLOCK SrbTemplate
Definition: classp.h:454
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:393
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
Definition: srb.h:397
#define IRP_PAGING_IO
#define SL_WRITE_THROUGH
Definition: iotypes.h:1781
#define IRP_MJ_READ
Definition: rdpdr.c:46
PVOID SenseInfoBuffer
Definition: srb.h:256
PUCHAR BufPtrCopy
Definition: classp.h:337
unsigned int ULONG
Definition: retypes.h:1
ULONG QueueSortKey
Definition: srb.h:262
ULONG BufLenCopy
Definition: classp.h:338
#define IRP_SYNCHRONOUS_PAGING_IO
LONGLONG QuadPart
Definition: typedefs.h:113
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297

Referenced by ServiceTransferRequest(), and StepLowMemRetry().

◆ SubmitTransferPacket()

VOID NTAPI SubmitTransferPacket ( PTRANSFER_PACKET  Pkt)

Definition at line 460 of file xferpkt.c.

461 {
462  PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
463  PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
465 
466  ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
467 
468  /*
469  * Attach the SRB to the IRP.
470  * The reused IRP's stack location has to be rewritten for each retry
471  * call because IoCompleteRequest clears the stack locations.
472  */
474  nextSp->MajorFunction = IRP_MJ_SCSI;
475  nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
476  Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
478  /*
479  * Only dereference the "original IRP"'s stack location
480  * if its a real client irp (as opposed to a static irp
481  * we're using just for result status for one of the non-IO scsi commands).
482  *
483  * For read/write, propagate the storage-specific IRP stack location flags
484  * (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
485  */
487  nextSp->Flags = origCurSp->Flags;
488  }
489 
490  /*
491  * Write MDL address to new IRP. In the port driver the SRB DataBuffer
492  * field is used as the actual buffer pointer within the MDL,
493  * so the same MDL can be used for each partial transfer.
494  * This saves having to build a new MDL for each partial transfer.
495  */
496  Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
497 
499  IoCallDriver(nextDevObj, Pkt->Irp);
500 }
#define TRUE
Definition: types.h:120
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
UCHAR SrbStatus
Definition: srb.h:243
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
#define IRP_MJ_SCSI
PDEVICE_OBJECT Fdo
Definition: classp.h:290
UCHAR ScsiStatus
Definition: srb.h:244
NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
Definition: xferpkt.c:502
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PIRP OriginalIrp
Definition: classp.h:296
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:574
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297

Referenced by ClassModeSense(), ClassReadDriveCapacity(), ServiceTransferRequest(), StepLowMemRetry(), and TransferPacketRetryTimerDpc().

◆ TransferPktComplete()

NTSTATUS NTAPI TransferPktComplete ( IN PDEVICE_OBJECT  NullFdo,
IN PIRP  Irp,
IN PVOID  Context 
)

Definition at line 502 of file xferpkt.c.

503 {
506  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
508  BOOLEAN packetDone = FALSE;
509 
510  /*
511  * Put all the assertions and spew in here so we don't have to look at them.
512  */
513  DBGCHECKRETURNEDPKT(pkt);
514 
516 
518 
519  /*
520  * The port driver should not have allocated a sense buffer
521  * if the SRB succeeded.
522  */
523  ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));
524 
525  /*
526  * Add this packet's transferred length to the original IRP's.
527  */
529  (LONG)pkt->Srb.DataTransferLength);
530 
531  if (pkt->InLowMemRetry){
532  packetDone = StepLowMemRetry(pkt);
533  }
534  else {
535  packetDone = TRUE;
536  }
537 
538  }
539  else {
540  /*
541  * The packet failed. We may retry it if possible.
542  */
543  BOOLEAN shouldRetry;
544 
545  /*
546  * Make sure IRP status matches SRB error status (since we propagate it).
547  */
548  if (NT_SUCCESS(Irp->IoStatus.Status)){
549  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
550  }
551 
552  /*
553  * Interpret the SRB error (to a meaningful IRP status)
554  * and determine if we should retry this packet.
555  * This call looks at the returned SENSE info to figure out what to do.
556  */
557  shouldRetry = InterpretTransferPacketError(pkt);
558 
559  /*
560  * Sometimes the port driver can allocates a new 'sense' buffer
561  * to report transfer errors, e.g. when the default sense buffer
562  * is too small. If so, it is up to us to free it.
563  * Now that we're done interpreting the sense info, free it if appropriate.
564  */
565  if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
566  DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
567  FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
569  pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
570  }
571 
572  /*
573  * If the SRB queue is locked-up, release it.
574  * Do this after calling the error handler.
575  */
577  ClassReleaseQueue(pkt->Fdo);
578  }
579 
580  if (shouldRetry && (pkt->NumRetries > 0)){
581  packetDone = RetryTransferPacket(pkt);
582  }
583  else {
584  packetDone = TRUE;
585  }
586 
587  }
588 
589  /*
590  * If the packet is completed, put it back in the free list.
591  * If it is the last packet servicing the original request, complete the original irp.
592  */
593  if (packetDone){
594  LONG numPacketsRemaining;
595  PIRP deferredIrp;
596  PDEVICE_OBJECT Fdo = pkt->Fdo;
597  UCHAR uniqueAddr;
598 
599  /*
600  * In case a remove is pending, bump the lock count so we don't get freed
601  * right after we complete the original irp.
602  */
603  ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);
604 
605  /*
606  * The original IRP should get an error code
607  * if any one of the packets failed.
608  */
609  if (!NT_SUCCESS(Irp->IoStatus.Status)){
610  pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
611 
612  /*
613  * If the original I/O originated in user space (i.e. it is thread-queued),
614  * and the error is user-correctable (e.g. media is missing, for removable media),
615  * alert the user.
616  * Since this is only one of possibly several packets completing for the original IRP,
617  * we may do this more than once for a single request. That's ok; this allows
618  * us to test each returned status with IoIsErrorUserInduced().
619  */
620  if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
622  pkt->OriginalIrp->Tail.Overlay.Thread){
623 
625  }
626  }
627 
628  /*
629  * We use a field in the original IRP to count
630  * down the transfer pieces as they complete.
631  */
632  numPacketsRemaining = InterlockedDecrement(
633  (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
634 
635  if (numPacketsRemaining > 0){
636  /*
637  * More transfer pieces remain for the original request.
638  * Wait for them to complete before completing the original irp.
639  */
640  }
641  else {
642 
643  /*
644  * All the transfer pieces are done.
645  * Complete the original irp if appropriate.
646  */
647  ASSERT(numPacketsRemaining == 0);
650  ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
652  }
654 
656 
657  /*
658  * We may have been called by one of the class drivers (e.g. cdrom)
659  * via the legacy API ClassSplitRequest.
660  * This is the only case for which the packet engine is called for an FDO
661  * with a StartIo routine; in that case, we have to call IoStartNextPacket
662  * now that the original irp has been completed.
663  */
664  if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
666  DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
667  }
668  else {
669  KIRQL oldIrql;
670  KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
671  IoStartNextPacket(pkt->Fdo, FALSE);
672  KeLowerIrql(oldIrql);
673  }
674  }
675  }
676  }
677 
678  /*
679  * If the packet was synchronous, write the final
680  * result back to the issuer's status buffer and
681  * signal his event.
682  */
683  if (pkt->SyncEventPtr){
684  KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
685  pkt->SyncEventPtr = NULL;
686  }
687 
688  /*
689  * Free the completed packet.
690  */
691  pkt->OriginalIrp = NULL;
692  pkt->InLowMemRetry = FALSE;
693  EnqueueFreeTransferPacket(pkt->Fdo, pkt);
694 
695  /*
696  * Now that we have freed some resources,
697  * try again to send one of the previously deferred irps.
698  */
699  deferredIrp = DequeueDeferredClientIrp(fdoData);
700  if (deferredIrp){
701  DBGWARN(("... retrying deferred irp %xh.", deferredIrp));
702  ServiceTransferRequest(pkt->Fdo, deferredIrp);
703  }
704 
705  ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);
706  }
707 
709 }
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define ClassAcquireRemoveLock(devobj, tag)
Definition: classpnp.h:97
ULONG SrbFlags
Definition: srb.h:252
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:156
_In_ PIRP Irp
Definition: csq.h:116
ULONG DataTransferLength
Definition: srb.h:253
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:695
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:417
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
IO_STATUS_BLOCK IoStatus
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
UCHAR SrbStatus
Definition: srb.h:243
#define SRB_STATUS(Status)
Definition: srb.h:381
ULONG NumRetries
Definition: classp.h:302
#define SRB_FLAGS_DONT_START_NEXT_PACKET
Definition: srb.h:407
PIRP NTAPI DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: clntirp.c:45
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
long LONG
Definition: pedump.c:60
PDEVICE_OBJECT Fdo
Definition: classp.h:290
VOID NTAPI ClasspPerfIncrementSuccessfulIo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:385
struct _SENSE_DATA SENSE_DATA
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:217
PVOID DeviceExtension
Definition: env_spec_w32.h:418
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static __inline BOOLEAN PORT_ALLOCATED_SENSE(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: classpnp.h:1244
BOOLEAN InLowMemRetry
Definition: classp.h:319
BOOLEAN NTAPI StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:304
#define InterlockedExchangeAdd
Definition: interlocked.h:181
BOOLEAN NTAPI RetryTransferPacket(PTRANSFER_PACKET Pkt)
Definition: retry.c:180
PIRP OriginalIrp
Definition: classp.h:296
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static __inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: classpnp.h:1255
struct _TRANSFER_PACKET * PTRANSFER_PACKET
VOID NTAPI ClassReleaseQueue(IN PDEVICE_OBJECT Fdo)
Definition: class.c:8160
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
#define InterlockedDecrement
Definition: armddk.h:52
#define DBGTRACE(dbgTraceLevel, args_in_parens)
Definition: debug.h:136
PKEVENT SyncEventPtr
Definition: classp.h:313
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
UCHAR SenseInfoBufferLength
Definition: srb.h:251
SENSE_DATA SrbErrorSenseData
Definition: classp.h:345
#define DBGCHECKRETURNEDPKT(_pkt)
Definition: debug.h:144
#define DBGWARN(args_in_parens)
Definition: debug.h:134
VOID NTAPI ClassCompleteRequest(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CCHAR PriorityBoost)
Definition: lock.c:376
#define DBGTRAP(args_in_parens)
Definition: debug.h:137
PVOID SenseInfoBuffer
Definition: srb.h:256
unsigned int ULONG
Definition: retypes.h:1
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
VOID NTAPI ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp)
Definition: class.c:2246
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
signed int * PLONG
Definition: retypes.h:5
BOOLEAN NTAPI InterpretTransferPacketError(PTRANSFER_PACKET Pkt)
Definition: retry.c:34
VOID NTAPI ClassReleaseRemoveLock(IN PDEVICE_OBJECT DeviceObject, IN OPTIONAL PIRP Tag)
Definition: lock.c:212
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes
Definition: classp.h:297
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: device.c:1847

Referenced by SubmitTransferPacket().

Variable Documentation

◆ MaxWorkingSetTransferPackets

ULONG MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer

Definition at line 35 of file xferpkt.c.

Referenced by EnqueueFreeTransferPacket(), and InitializeTransferPackets().

◆ MinWorkingSetTransferPackets

ULONG MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer

Definition at line 34 of file xferpkt.c.

Referenced by EnqueueFreeTransferPacket(), and InitializeTransferPackets().