ReactOS  0.4.13-dev-73-gcfe54aa
xferpkt.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 1999
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 
26 #ifdef ALLOC_PRAGMA
27  #pragma alloc_text(PAGE, InitializeTransferPackets)
28  #pragma alloc_text(PAGE, DestroyAllTransferPackets)
29  #pragma alloc_text(PAGE, SetupEjectionTransferPacket)
30  #pragma alloc_text(PAGE, SetupModeSenseTransferPacket)
31 #endif
32 
33 
36 
37 
38 /*
39  * InitializeTransferPackets
40  *
41  * Allocate/initialize TRANSFER_PACKETs and related resources.
42  */
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 }
133 
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 }
151 
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 }
187 
188 /*
189  * DestroyTransferPacket
190  *
191  */
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 }
216 
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 }
321 
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 }
361 
362 /*
363  * SetupReadWriteTransferPacket
364  *
365  * This function is called once to set up the first attempt to send a packet.
366  * It is not called before a retry, as SRB fields may be modified for the retry.
367  *
368  * Set up the Srb of the TRANSFER_PACKET for the transfer.
369  * The Irp is set up in SubmitTransferPacket because it must be reset
370  * for each packet submission.
371  */
373  PVOID Buf,
374  ULONG Len,
375  LARGE_INTEGER DiskLocation,
376  PIRP OriginalIrp)
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 }
454 
455 /*
456  * SubmitTransferPacket
457  *
458  * Set up the IRP for the TRANSFER_PACKET submission and send it down.
459  */
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 }
501 
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  */
528  InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information,
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);
649  if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
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 }
710 
711 /*
712  * SetupEjectionTransferPacket
713  *
714  * Set up a transferPacket for a synchronous Ejection Control transfer.
715  */
717  BOOLEAN PreventMediaRemoval,
718  PKEVENT SyncEventPtr,
719  PIRP OriginalIrp)
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 }
753 
754 /*
755  * SetupModeSenseTransferPacket
756  *
757  * Set up a transferPacket for a synchronous Mode Sense transfer.
758  */
760  PKEVENT SyncEventPtr,
761  PVOID ModeSenseBuffer,
762  UCHAR ModeSenseBufferLen,
763  UCHAR PageMode,
764  PIRP OriginalIrp)
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 }
802 
803 /*
804  * SetupDriveCapacityTransferPacket
805  *
806  * Set up a transferPacket for a synchronous Drive Capacity transfer.
807  */
809  PVOID ReadCapacityBuffer,
810  ULONG ReadCapacityBufferLen,
811  PKEVENT SyncEventPtr,
812  PIRP OriginalIrp)
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 }
846 
847 #if 0
848  /*
849  * SetupSendStartUnitTransferPacket
850  *
851  * Set up a transferPacket for a synchronous Send Start Unit transfer.
852  */
853  VOID SetupSendStartUnitTransferPacket( TRANSFER_PACKET *Pkt,
854  PIRP OriginalIrp)
855  {
857  PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
858  PCDB pCdb;
859 
860  PAGED_CODE();
861 
862  RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
863 
864  /*
865  * Initialize the SRB.
866  * Use a very long timeout value to give the drive time to spin up.
867  */
868  Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
871  Pkt->Srb.CdbLength = 6;
872  Pkt->Srb.OriginalRequest = Pkt->Irp;
874  Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
875  Pkt->Srb.Lun = 0;
876 
880 
881  pCdb = (PCDB)Pkt->Srb.Cdb;
882  pCdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
883  pCdb->START_STOP.Start = 1;
884  pCdb->START_STOP.Immediate = 0;
885  pCdb->START_STOP.LogicalUnitNumber = 0;
886 
887  Pkt->OriginalIrp = OriginalIrp;
888  Pkt->NumRetries = 0;
889  Pkt->SyncEventPtr = NULL;
891  }
892 #endif
static VOID SimpleInitSlistHdr(SLIST_ENTRY *SListHdr)
Definition: classp.h:478
struct _FOUR_BYTE * PFOUR_BYTE
#define SRB_FLAGS_DISABLE_AUTOSENSE
Definition: srb.h:391
VOID NTAPI ClassReleaseQueue(IN PDEVICE_OBJECT Fdo)
Definition: class.c:8160
VOID NTAPI ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp)
Definition: class.c:2246
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define IN
Definition: typedefs.h:38
NTSTATUS NTAPI InitializeTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:43
#define max(a, b)
Definition: svc.c:63
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define TRUE
Definition: types.h:120
* PSTORAGE_ADAPTER_DESCRIPTOR
Definition: ntddstor.h:476
#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:97
ULONG SrbFlags
Definition: srb.h:252
PVOID OriginalRequest
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:271
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:377
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
struct _CDB::_MEDIA_REMOVAL MEDIA_REMOVAL
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:63
static VOID SimplePushSlist(SLIST_ENTRY *SListHdr, SLIST_ENTRY *SListEntry)
Definition: classp.h:482
#define TEST_FLAG(Flags, Bit)
Definition: classpnp.h:156
_In_ PIRP Irp
Definition: csq.h:116
#define SRB_FLAGS_NO_QUEUE_FREEZE
Definition: srb.h:396
#define SCSIOP_MODE_SENSE
Definition: cdrw_hw.h:896
ULONG MaxWorkingSetTransferPackets
Definition: xferpkt.c:35
PVOID DataBuffer
Definition: srb.h:255
ULONG DataTransferLength
Definition: srb.h:253
struct _FUNCTIONAL_DEVICE_EXTENSION * PartitionZeroExtension
Definition: classpnp.h:575
VOID NTAPI SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp)
Definition: xferpkt.c:716
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:695
KSPIN_LOCK SpinLock
Definition: classp.h:456
BOOLEAN LoggedTURFailureSinceLastIO
Definition: classp.h:417
SCSI_REQUEST_BLOCK Srb
Definition: classp.h:353
ULONG NumTotalTransferPackets
Definition: classp.h:437
UCHAR CdbLength
Definition: srb.h:250
LIST_ENTRY AllPktsListEntry
Definition: classp.h:287
UCHAR QueueAction
Definition: srb.h:249
struct _CDB::_CDB10 CDB10
LIST_ENTRY AllTransferPacketsList
Definition: classp.h:434
#define InsertTailList(ListHead, Entry)
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
BOOLEAN NTAPI ExVerifySuite(SUITE_TYPE SuiteType)
Definition: sysinfo.c:377
ULONG TimeOutValue
Definition: srb.h:254
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
#define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise
Definition: classp.h:380
UCHAR SrbStatus
Definition: srb.h:243
#define SRB_STATUS(Status)
Definition: srb.h:381
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
ULONG NumRetries
Definition: classp.h:302
ULONG DbgPeakNumTransferPackets
Definition: classp.h:438
LARGE_INTEGER TargetLocationCopy
Definition: classp.h:339
#define PAGED_CODE()
Definition: video.h:57
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
#define SRB_FLAGS_DONT_START_NEXT_PACKET
Definition: srb.h:407
#define DEV_WRITE_CACHE
Definition: class2.h:21
#define DBGTRACE(dbgTraceLevel, args_in_parens)
Definition: debug.h:136
PIRP NTAPI DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData)
Definition: clntirp.c:45
PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
Definition: xferpkt.c:322
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
static SLIST_ENTRY * SimplePopSlist(SLIST_ENTRY *SListHdr)
Definition: classp.h:487
#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
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer
Definition: classp.h:376
VOID NTAPI SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp)
Definition: xferpkt.c:759
#define IO_DISK_INCREMENT
Definition: iotypes.h:567
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
PDEVICE_OBJECT Fdo
Definition: classp.h:290
UCHAR ScsiStatus
Definition: srb.h:244
#define SCSIOP_READ
Definition: cdrw_hw.h:905
VOID NTAPI ClasspPerfIncrementSuccessfulIo(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: utils.c:385
#define DBGTRAP(args_in_parens)
Definition: debug.h:137
struct _SENSE_DATA SENSE_DATA
VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:217
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
#define SCSIOP_WRITE
Definition: cdrw_hw.h:906
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
union _CDB * PCDB
#define NUM_DRIVECAPACITY_RETRIES
Definition: classp.h:76
#define NUM_LOCKMEDIAREMOVAL_RETRIES
Definition: classp.h:74
struct _CDB::_START_STOP START_STOP
BOOLEAN InLowMemRetry
Definition: classp.h:319
BOOLEAN NTAPI StepLowMemRetry(PTRANSFER_PACKET Pkt)
Definition: retry.c:304
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define MAXIMUM_RETRIES
Definition: class2.h:14
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 VOID InitializeSListHead(_Out_ PSLIST_HEADER SListHead)
Definition: rtlfuncs.h:3353
PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:152
struct _CDB::_MODE_SENSE MODE_SENSE
LIST_ENTRY DeferredClientIrpList
Definition: classp.h:443
#define MIN_INITIAL_TRANSFER_PACKETS
Definition: classp.h:374
BOOLEAN NTAPI RetryTransferPacket(PTRANSFER_PACKET Pkt)
Definition: retry.c:180
PIRP OriginalIrp
Definition: classp.h:296
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
UCHAR Function
Definition: srb.h:242
static __inline VOID FREE_PORT_ALLOCATED_SENSE_BUFFER(_In_ PFUNCTIONAL_DEVICE_EXTENSION FdoExtension, _In_ PSCSI_REQUEST_BLOCK Srb)
Definition: classpnp.h:1255
#define DBGCHECKRETURNEDPKT(_pkt)
Definition: debug.h:144
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
VOID NTAPI SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp)
Definition: xferpkt.c:808
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:389
struct _TRANSFER_PACKET * PTRANSFER_PACKET
#define Len
Definition: deflate.h:82
#define PSLIST_ENTRY
Definition: rtltypes.h:130
USHORT Length
Definition: srb.h:241
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define SRB_CLASS_FLAGS_PAGING
Definition: classpnp.h:21
#define NUM_MODESENSE_RETRIES
Definition: classp.h:75
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SRB_FLAGS_NO_DATA_TRANSFER
Definition: srb.h:394
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:378
VOID NTAPI SubmitTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:460
#define InterlockedDecrement
Definition: armddk.h:52
#define SCSIOP_MEDIUM_REMOVAL
Definition: cdrw_hw.h:902
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PKEVENT SyncEventPtr
Definition: classp.h:313
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
T MAX(T a, T b)
Definition: polytest.cpp:85
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define Int64ShrlMod32(a, b)
__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
VOID NTAPI ClassCompleteRequest(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN CCHAR PriorityBoost)
Definition: lock.c:376
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 START_UNIT_TIMEOUT
Definition: class2.c:34
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise
Definition: classp.h:379
VOID NTAPI SetupReadWriteTransferPacket(PTRANSFER_PACKET Pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp)
Definition: xferpkt.c:372
#define SRB_SIMPLE_TAG_REQUEST
Definition: srb.h:415
#define SRB_FLAGS_DATA_OUT
Definition: srb.h:393
ULONG NumFreeTransferPackets
Definition: classp.h:436
PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:574
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer
Definition: classp.h:375
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define SRB_FLAGS_ADAPTER_CACHE_ENABLE
Definition: srb.h:397
#define IRP_PAGING_IO
#define SL_WRITE_THROUGH
Definition: iotypes.h:1780
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define SLIST_ENTRY(type)
Definition: queue.h:102
PVOID SenseInfoBuffer
Definition: srb.h:256
PUCHAR BufPtrCopy
Definition: classp.h:337
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server
Definition: classp.h:378
unsigned int ULONG
Definition: retypes.h:1
SLIST_ENTRY SlistEntry
Definition: classp.h:286
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
VOID NTAPI DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
Definition: xferpkt.c:134
#define SRB_STATUS_SUCCESS
Definition: srb.h:333
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define DBGWARN(args_in_parens)
Definition: debug.h:134
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
return STATUS_SUCCESS
Definition: btrfs.c:2725
signed int * PLONG
Definition: retypes.h:5
static SERVICE_STATUS status
Definition: service.c:31
ULONG QueueSortKey
Definition: srb.h:262
#define SCSIOP_START_STOP_UNIT
Definition: cdrw_hw.h:897
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
BOOLEAN NTAPI InterpretTransferPacketError(PTRANSFER_PACKET Pkt)
Definition: retry.c:34
ULONG BufLenCopy
Definition: classp.h:338
#define IRP_SYNCHRONOUS_PAGING_IO
VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt)
Definition: xferpkt.c:192
LONGLONG QuadPart
Definition: typedefs.h:112
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:1846
Definition: ps.c:97