[STORAGE] Storage driver cleanup part 1
[reactos.git] / drivers / storage / classpnp / xferpkt.c
diff --git a/drivers/storage/classpnp/xferpkt.c b/drivers/storage/classpnp/xferpkt.c
deleted file mode 100644 (file)
index 865ae7f..0000000
+++ /dev/null
@@ -1,892 +0,0 @@
-/*++
-
-Copyright (C) Microsoft Corporation, 1991 - 1999
-
-Module Name:
-
-    xferpkt.c
-
-Abstract:
-
-    Packet routines for CLASSPNP
-
-Environment:
-
-    kernel mode only
-
-Notes:
-
-
-Revision History:
-
---*/
-
-#include "classp.h"
-
-#ifdef ALLOC_PRAGMA
-    #pragma alloc_text(PAGE, InitializeTransferPackets)
-    #pragma alloc_text(PAGE, DestroyAllTransferPackets)
-    #pragma alloc_text(PAGE, SetupEjectionTransferPacket)
-    #pragma alloc_text(PAGE, SetupModeSenseTransferPacket)
-#endif
-
-
-ULONG MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
-ULONG MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
-
-
-/*
- *  InitializeTransferPackets
- *
- *      Allocate/initialize TRANSFER_PACKETs and related resources.
- */
-NTSTATUS NTAPI InitializeTransferPackets(PDEVICE_OBJECT Fdo)
-{
-    PCOMMON_DEVICE_EXTENSION commonExt = Fdo->DeviceExtension;
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
-    ULONG hwMaxPages;
-    NTSTATUS status = STATUS_SUCCESS;
-
-    PAGED_CODE();
-    
-    /*
-     *  Precompute the maximum transfer length
-     */
-    ASSERT(adapterDesc->MaximumTransferLength);
-    ASSERT(adapterDesc->MaximumPhysicalPages);
-    hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
-
-#if defined(_AMD64_SIMULATOR_)
-
-    //
-    // The simulator appears to have a problem with large transfers.
-    //
-
-    if (hwMaxPages > 4) {
-        hwMaxPages = 4;
-    }
-
-#endif
-
-    fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
-    fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
-
-    fdoData->NumTotalTransferPackets = 0;
-    fdoData->NumFreeTransferPackets = 0;
-    InitializeSListHead(&fdoData->FreeTransferPacketsList);
-    InitializeListHead(&fdoData->AllTransferPacketsList);
-    InitializeListHead(&fdoData->DeferredClientIrpList);
-        
-    /*
-     *  Set the packet threshold numbers based on the Windows SKU.
-     */
-    if (ExVerifySuite(Personal)){
-        // this is Windows Personal
-        MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
-        MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
-    }
-    else if (ExVerifySuite(Enterprise) || ExVerifySuite(DataCenter)){
-        // this is Advanced Server or Datacenter
-        MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise;
-        MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise;
-    }
-    else if (ExVerifySuite(TerminalServer)){
-        // this is standard Server or Pro with terminal server
-        MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Server;
-        MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Server;
-    }
-    else {
-        // this is Professional without terminal server
-        MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
-        MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
-    }
-
-    while (fdoData->NumFreeTransferPackets < MIN_INITIAL_TRANSFER_PACKETS){
-        PTRANSFER_PACKET pkt = NewTransferPacket(Fdo);
-        if (pkt){
-            InterlockedIncrement((PLONG)&fdoData->NumTotalTransferPackets);
-            EnqueueFreeTransferPacket(Fdo, pkt);
-        }
-        else {
-            status = STATUS_INSUFFICIENT_RESOURCES;
-            break;
-        }
-    }
-    fdoData->DbgPeakNumTransferPackets = fdoData->NumTotalTransferPackets;
-    
-    /*
-     *  Pre-initialize our SCSI_REQUEST_BLOCK template with all
-     *  the constant fields.  This will save a little time for each xfer.
-     *  NOTE: a CdbLength field of 10 may not always be appropriate
-     */
-    RtlZeroMemory(&fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
-    fdoData->SrbTemplate.Length = sizeof(SCSI_REQUEST_BLOCK);
-    fdoData->SrbTemplate.Function = SRB_FUNCTION_EXECUTE_SCSI;
-    fdoData->SrbTemplate.QueueAction = SRB_SIMPLE_TAG_REQUEST;
-    fdoData->SrbTemplate.SenseInfoBufferLength = sizeof(SENSE_DATA);
-    fdoData->SrbTemplate.CdbLength = 10;
-
-    return status;
-}
-
-VOID NTAPI DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    TRANSFER_PACKET *pkt;
-
-    PAGED_CODE();
-    
-    ASSERT(IsListEmpty(&fdoData->DeferredClientIrpList));
-
-    while ((pkt = DequeueFreeTransferPacket(Fdo, FALSE))){
-        DestroyTransferPacket(pkt);
-        InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);    
-    }
-
-    ASSERT(fdoData->NumTotalTransferPackets == 0);
-}
-
-PTRANSFER_PACKET NTAPI NewTransferPacket(PDEVICE_OBJECT Fdo)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    PTRANSFER_PACKET newPkt;
-
-    newPkt = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSFER_PACKET), 'pnPC');
-    if (newPkt){
-        RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET)); // just to be sure
-
-        /*
-         *  Allocate resources for the packet.
-         */
-        newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE);
-        if (newPkt->Irp){
-            KIRQL oldIrql;
-            
-            newPkt->Fdo = Fdo;
-
-            /*
-             *  Enqueue the packet in our static AllTransferPacketsList
-             *  (just so we can find it during debugging if its stuck somewhere).
-             */
-            KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
-            InsertTailList(&fdoData->AllTransferPacketsList, &newPkt->AllPktsListEntry);
-            KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
-        }
-        else {
-            ExFreePool(newPkt);
-            newPkt = NULL;
-        }
-    }
-
-    return newPkt;
-}
-
-/*
- *  DestroyTransferPacket
- *
- */
-VOID NTAPI DestroyTransferPacket(PTRANSFER_PACKET Pkt)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    KIRQL oldIrql;
-
-    ASSERT(!Pkt->SlistEntry.Next);
-    ASSERT(!Pkt->OriginalIrp);
-
-    KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
-
-    /*
-     *  Delete the packet from our all-packets queue.
-     */
-    ASSERT(!IsListEmpty(&Pkt->AllPktsListEntry));
-    ASSERT(!IsListEmpty(&fdoData->AllTransferPacketsList));
-    RemoveEntryList(&Pkt->AllPktsListEntry);
-    InitializeListHead(&Pkt->AllPktsListEntry);
-
-    KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
-
-    IoFreeIrp(Pkt->Irp);
-    ExFreePool(Pkt);
-}
-
-VOID NTAPI EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    KIRQL oldIrql;
-    ULONG newNumPkts;
-    
-    ASSERT(!Pkt->SlistEntry.Next);
-
-    InterlockedPushEntrySList(&fdoData->FreeTransferPacketsList, &Pkt->SlistEntry);
-    newNumPkts = InterlockedIncrement((PLONG)&fdoData->NumFreeTransferPackets);
-    ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets);
-
-    /*
-     *  If the total number of packets is larger than MinWorkingSetTransferPackets,
-     *  that means that we've been in stress.  If all those packets are now
-     *  free, then we are now out of stress and can free the extra packets.
-     *  Free down to MaxWorkingSetTransferPackets immediately, and
-     *  down to MinWorkingSetTransferPackets lazily (one at a time).
-     */
-    if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){
-
-        /*
-         *  1.  Immediately snap down to our UPPER threshold.
-         */
-        if (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets){
-            SLIST_ENTRY pktList;
-            PSLIST_ENTRY slistEntry;
-            PTRANSFER_PACKET pktToDelete;
-
-            DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets));
-
-            /*
-             *  Check the counter again with lock held.  This eliminates a race condition
-             *  while still allowing us to not grab the spinlock in the common codepath.
-             *
-             *  Note that the spinlock does not synchronize with threads dequeuing free
-             *  packets to send (DequeueFreeTransferPacket does that with a lightweight
-             *  interlocked exchange); the spinlock prevents multiple threads in this function
-             *  from deciding to free too many extra packets at once.
-             */
-            SimpleInitSlistHdr(&pktList);
-            KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
-            while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) && 
-                   (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets)){
-                   
-                pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);   
-                if (pktToDelete){
-                    SimplePushSlist(&pktList, &pktToDelete->SlistEntry);
-                    InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);    
-                }
-                else {
-                    DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
-                    break;
-                }
-            }
-            KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
-
-            while ((slistEntry = SimplePopSlist(&pktList))){
-                pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
-                DestroyTransferPacket(pktToDelete);
-            }
-
-        }
-
-        /*
-         *  2.  Lazily work down to our LOWER threshold (by only freeing one packet at a time).
-         */
-        if (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets){
-            /*
-             *  Check the counter again with lock held.  This eliminates a race condition
-             *  while still allowing us to not grab the spinlock in the common codepath.
-             *
-             *  Note that the spinlock does not synchronize with threads dequeuing free
-             *  packets to send (DequeueFreeTransferPacket does that with a lightweight
-             *  interlocked exchange); the spinlock prevents multiple threads in this function
-             *  from deciding to free too many extra packets at once.
-             */
-            PTRANSFER_PACKET pktToDelete = NULL; 
-
-            DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets));
-            
-            KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
-            if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
-                (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets)){
-                
-                pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
-                if (pktToDelete){
-                    InterlockedDecrement((PLONG)&fdoData->NumTotalTransferPackets);    
-                }
-                else {
-                    DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
-                }
-            }
-            KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
-
-            if (pktToDelete){
-                DestroyTransferPacket(pktToDelete);
-            }
-        }
-
-    }
-  
-}
-
-PTRANSFER_PACKET NTAPI DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    PTRANSFER_PACKET pkt;
-    PSLIST_ENTRY slistEntry;
-    //KIRQL oldIrql;
-
-    slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
-    if (slistEntry){
-        slistEntry->Next = NULL;
-        pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
-        ASSERT(fdoData->NumFreeTransferPackets > 0);
-        InterlockedDecrement((PLONG)&fdoData->NumFreeTransferPackets);
-    }
-    else {
-        if (AllocIfNeeded){
-            /*
-             *  We are in stress and have run out of lookaside packets.
-             *  In order to service the current transfer, 
-             *  allocate an extra packet.  
-             *  We will free it lazily when we are out of stress.
-             */
-            pkt = NewTransferPacket(Fdo);
-            if (pkt){
-                InterlockedIncrement((PLONG)&fdoData->NumTotalTransferPackets);
-                fdoData->DbgPeakNumTransferPackets = max(fdoData->DbgPeakNumTransferPackets, fdoData->NumTotalTransferPackets);
-            }
-            else {
-                DBGWARN(("DequeueFreeTransferPacket: packet allocation failed"));
-            }
-        }
-        else {
-            pkt = NULL;
-        }
-    }
-    
-    return pkt;
-}
-
-/*
- *  SetupReadWriteTransferPacket
- *
- *        This function is called once to set up the first attempt to send a packet.
- *        It is not called before a retry, as SRB fields may be modified for the retry.
- *
- *      Set up the Srb of the TRANSFER_PACKET for the transfer.
- *        The Irp is set up in SubmitTransferPacket because it must be reset
- *        for each packet submission.
- */
-VOID NTAPI SetupReadWriteTransferPacket(PTRANSFER_PACKET Pkt, 
-                                        PVOID Buf, 
-                                        ULONG Len, 
-                                        LARGE_INTEGER DiskLocation,
-                                        PIRP OriginalIrp)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp);
-    UCHAR majorFunc = origCurSp->MajorFunction;
-    ULONG logicalBlockAddr;
-    ULONG numTransferBlocks;
-    PCDB pCdb;
-  
-    logicalBlockAddr = (ULONG)Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
-    numTransferBlocks = Len >> fdoExt->SectorShift;
-
-    /*
-     *  Slap the constant SRB fields in from our pre-initialized template.
-     *  We'll then only have to fill in the unique fields for this transfer.
-     *  Tell lower drivers to sort the SRBs by the logical block address 
-     *  so that disk seeks are minimized.
-     */
-    Pkt->Srb = fdoData->SrbTemplate;    // copies _contents_ of SRB blocks
-    Pkt->Srb.DataBuffer = Buf;
-    Pkt->Srb.DataTransferLength = Len;
-    Pkt->Srb.QueueSortKey = logicalBlockAddr;  
-    Pkt->Srb.OriginalRequest = Pkt->Irp;
-    Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
-    Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0);
-    Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue;
-
-    /*
-     *  Arrange values in CDB in big-endian format.
-     */
-    pCdb = (PCDB)Pkt->Srb.Cdb;
-    pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte3;
-    pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte2;
-    pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte1;
-    pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte0;
-    pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
-    pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
-    pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
-
-    /*
-     *  Set SRB and IRP flags    
-     */
-    Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
-    if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
-        TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){
-        SET_FLAG(Pkt->Srb.SrbFlags, SRB_CLASS_FLAGS_PAGING);
-    }
-    SET_FLAG(Pkt->Srb.SrbFlags, (majorFunc==IRP_MJ_READ) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT);
-
-    /*
-     *  Allow caching only if this is not a write-through request.
-     *  If write-through and caching is enabled on the device, force
-     *  media access.
-     */
-    if (TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)){
-        if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE)){
-            pCdb->CDB10.ForceUnitAccess = TRUE;
-        }
-    }
-    else {
-        SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
-    } 
-
-    /*
-     *  Remember the buf and len in the SRB because miniports
-     *  can overwrite SRB.DataTransferLength and we may need it again
-     *  for the retry.
-     */
-    Pkt->BufPtrCopy = Buf;
-    Pkt->BufLenCopy = Len;
-    Pkt->TargetLocationCopy = DiskLocation;
-    
-    Pkt->OriginalIrp = OriginalIrp;
-    Pkt->NumRetries = MAXIMUM_RETRIES;    
-    Pkt->SyncEventPtr = NULL;
-    Pkt->CompleteOriginalIrpWhenLastPacketCompletes = TRUE;
-}
-
-/*
- *  SubmitTransferPacket
- *
- *        Set up the IRP for the TRANSFER_PACKET submission and send it down.
- */
-VOID NTAPI SubmitTransferPacket(PTRANSFER_PACKET Pkt)
-{
-    PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
-    PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
-    PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
-    
-    ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
-
-    /*
-     *  Attach the SRB to the IRP.
-     *  The reused IRP's stack location has to be rewritten for each retry
-     *  call because IoCompleteRequest clears the stack locations.
-     */
-    IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED);
-    nextSp->MajorFunction = IRP_MJ_SCSI;
-    nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
-    Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
-    if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){
-        /*
-         *  Only dereference the "original IRP"'s stack location
-         *  if its a real client irp (as opposed to a static irp 
-         *  we're using just for result status for one of the non-IO scsi commands).
-         *
-         *  For read/write, propagate the storage-specific IRP stack location flags
-         *  (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
-         */
-        PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
-        nextSp->Flags = origCurSp->Flags;
-    }
-
-    /*
-     *  Write MDL address to new IRP. In the port driver the SRB DataBuffer
-     *  field is used as the actual buffer pointer within the MDL, 
-     *  so the same MDL can be used for each partial transfer. 
-     *  This saves having to build a new MDL for each partial transfer.
-     */
-    Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
-    
-    IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE);
-    IoCallDriver(nextDevObj, Pkt->Irp);
-}
-
-NTSTATUS NTAPI TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
-{
-    PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
-    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-    PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(pkt->OriginalIrp);
-    BOOLEAN packetDone = FALSE;
-
-    /*
-     *  Put all the assertions and spew in here so we don't have to look at them.
-     */
-    DBGCHECKRETURNEDPKT(pkt);    
-    
-    if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
-        
-        fdoData->LoggedTURFailureSinceLastIO = FALSE;
-        
-        /*
-         *  The port driver should not have allocated a sense buffer
-         *  if the SRB succeeded.
-         */
-        ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));
-
-        /*
-         *  Add this packet's transferred length to the original IRP's.
-         */
-        InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information, 
-                              (LONG)pkt->Srb.DataTransferLength);
-
-        if (pkt->InLowMemRetry){
-            packetDone = StepLowMemRetry(pkt);
-        }
-        else {
-            packetDone = TRUE;
-        }
-        
-    }
-    else {
-        /*
-         *  The packet failed.  We may retry it if possible.
-         */
-        BOOLEAN shouldRetry;
-        
-        /*
-         *  Make sure IRP status matches SRB error status (since we propagate it).
-         */
-        if (NT_SUCCESS(Irp->IoStatus.Status)){
-            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-        }
-
-        /*
-         *  Interpret the SRB error (to a meaningful IRP status)
-         *  and determine if we should retry this packet.
-         *  This call looks at the returned SENSE info to figure out what to do.
-         */
-        shouldRetry = InterpretTransferPacketError(pkt);
-
-        /*
-         *  Sometimes the port driver can allocates a new 'sense' buffer
-         *  to report transfer errors, e.g. when the default sense buffer
-         *  is too small.  If so, it is up to us to free it.
-         *  Now that we're done interpreting the sense info, free it if appropriate.
-         */
-        if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
-            DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
-            FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
-            pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
-            pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
-        }
-
-        /*
-         *  If the SRB queue is locked-up, release it.
-         *  Do this after calling the error handler.
-         */
-        if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
-            ClassReleaseQueue(pkt->Fdo);
-        }
-        
-        if (shouldRetry && (pkt->NumRetries > 0)){           
-            packetDone = RetryTransferPacket(pkt);
-        }
-        else {
-            packetDone = TRUE;
-        }
-        
-    }
-
-    /*
-     *  If the packet is completed, put it back in the free list.
-     *  If it is the last packet servicing the original request, complete the original irp.
-     */
-    if (packetDone){
-        LONG numPacketsRemaining;
-        PIRP deferredIrp;
-        PDEVICE_OBJECT Fdo = pkt->Fdo;
-        UCHAR uniqueAddr;
-        
-        /*
-         *  In case a remove is pending, bump the lock count so we don't get freed
-         *  right after we complete the original irp.
-         */
-        ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);        
-
-        /*
-         *  The original IRP should get an error code
-         *  if any one of the packets failed.
-         */
-        if (!NT_SUCCESS(Irp->IoStatus.Status)){
-            pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
-
-            /*
-             *  If the original I/O originated in user space (i.e. it is thread-queued), 
-             *  and the error is user-correctable (e.g. media is missing, for removable media),
-             *  alert the user.
-             *  Since this is only one of possibly several packets completing for the original IRP,
-             *  we may do this more than once for a single request.  That's ok; this allows
-             *  us to test each returned status with IoIsErrorUserInduced().
-             */
-            if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
-                pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
-                pkt->OriginalIrp->Tail.Overlay.Thread){
-
-                IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, pkt->Fdo);
-            }
-        }
-
-        /*
-         *  We use a field in the original IRP to count
-         *  down the transfer pieces as they complete.
-         */
-        numPacketsRemaining = InterlockedDecrement(
-            (PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
-            
-        if (numPacketsRemaining > 0){
-            /*
-             *  More transfer pieces remain for the original request.
-             *  Wait for them to complete before completing the original irp.
-             */
-        }
-        else {
-
-            /*
-             *  All the transfer pieces are done.
-             *  Complete the original irp if appropriate.
-             */
-            ASSERT(numPacketsRemaining == 0);
-            if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){  
-                if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
-                    ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
-                    ClasspPerfIncrementSuccessfulIo(fdoExt);
-                }
-                ClassReleaseRemoveLock(pkt->Fdo, pkt->OriginalIrp);
-
-                ClassCompleteRequest(pkt->Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);
-
-                /*
-                 *  We may have been called by one of the class drivers (e.g. cdrom)
-                 *  via the legacy API ClassSplitRequest.  
-                 *  This is the only case for which the packet engine is called for an FDO
-                 *  with a StartIo routine; in that case, we have to call IoStartNextPacket
-                 *  now that the original irp has been completed.
-                 */
-                if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
-                    if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
-                        DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
-                    }
-                    else {
-                        KIRQL oldIrql;
-                        KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
-                        IoStartNextPacket(pkt->Fdo, FALSE);
-                        KeLowerIrql(oldIrql);
-                    }
-                }              
-            }            
-        }
-
-        /*
-         *  If the packet was synchronous, write the final
-         *  result back to the issuer's status buffer and
-         *  signal his event.
-         */
-        if (pkt->SyncEventPtr){
-            KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
-            pkt->SyncEventPtr = NULL;
-        }
-
-        /*
-         *  Free the completed packet.
-         */
-        pkt->OriginalIrp = NULL;
-        pkt->InLowMemRetry = FALSE;
-        EnqueueFreeTransferPacket(pkt->Fdo, pkt);
-
-        /*
-         *  Now that we have freed some resources,
-         *  try again to send one of the previously deferred irps.
-         */
-        deferredIrp = DequeueDeferredClientIrp(fdoData);
-        if (deferredIrp){
-            DBGWARN(("... retrying deferred irp %xh.", deferredIrp)); 
-            ServiceTransferRequest(pkt->Fdo, deferredIrp);
-        }
-
-        ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);        
-    }
-
-    return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-/*
- *  SetupEjectionTransferPacket
- *
- *      Set up a transferPacket for a synchronous Ejection Control transfer.
- */
-VOID NTAPI SetupEjectionTransferPacket(   TRANSFER_PACKET *Pkt,
-                                        BOOLEAN PreventMediaRemoval,
-                                        PKEVENT SyncEventPtr,
-                                        PIRP OriginalIrp)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-    PCDB pCdb;
-
-    PAGED_CODE();
-
-    RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
-    
-    Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-    Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-    Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;   
-    Pkt->Srb.CdbLength = 6;
-    Pkt->Srb.OriginalRequest = Pkt->Irp;
-    Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
-    Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
-    Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
-
-    Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
-
-    pCdb = (PCDB)Pkt->Srb.Cdb;
-    pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
-    pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
-
-    Pkt->BufPtrCopy = NULL;
-    Pkt->BufLenCopy = 0;
-
-    Pkt->OriginalIrp = OriginalIrp;
-    Pkt->NumRetries = NUM_LOCKMEDIAREMOVAL_RETRIES;          
-    Pkt->SyncEventPtr = SyncEventPtr;
-    Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
-}
-
-/*
- *  SetupModeSenseTransferPacket
- *
- *      Set up a transferPacket for a synchronous Mode Sense transfer.
- */
-VOID NTAPI SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt,
-                                        PKEVENT SyncEventPtr,
-                                        PVOID ModeSenseBuffer,
-                                        UCHAR ModeSenseBufferLen,
-                                        UCHAR PageMode,
-                                        PIRP OriginalIrp)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-    PCDB pCdb;
-
-    PAGED_CODE();
-
-    RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
-    
-    Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-    Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-    Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;   
-    Pkt->Srb.CdbLength = 6;
-    Pkt->Srb.OriginalRequest = Pkt->Irp;
-    Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
-    Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
-    Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
-    Pkt->Srb.DataBuffer = ModeSenseBuffer;
-    Pkt->Srb.DataTransferLength = ModeSenseBufferLen;
-
-    Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);    
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
-
-    pCdb = (PCDB)Pkt->Srb.Cdb;
-    pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
-    pCdb->MODE_SENSE.PageCode = PageMode;
-    pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
-
-    Pkt->BufPtrCopy = ModeSenseBuffer;
-    Pkt->BufLenCopy = ModeSenseBufferLen;
-        
-    Pkt->OriginalIrp = OriginalIrp;
-    Pkt->NumRetries = NUM_MODESENSE_RETRIES;          
-    Pkt->SyncEventPtr = SyncEventPtr;
-    Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
-}
-
-/*
- *  SetupDriveCapacityTransferPacket
- *
- *      Set up a transferPacket for a synchronous Drive Capacity transfer.
- */
-VOID NTAPI SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt,
-                                            PVOID ReadCapacityBuffer,
-                                            ULONG ReadCapacityBufferLen,
-                                            PKEVENT SyncEventPtr,
-                                            PIRP OriginalIrp)
-{
-    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-    PCDB pCdb;
-
-    RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
-    
-    Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-    Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-    Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;   
-    Pkt->Srb.CdbLength = 10;
-    Pkt->Srb.OriginalRequest = Pkt->Irp;
-    Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
-    Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
-    Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
-    Pkt->Srb.DataBuffer = ReadCapacityBuffer;
-    Pkt->Srb.DataTransferLength = ReadCapacityBufferLen;
-
-    Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);    
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
-    SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
-
-    pCdb = (PCDB)Pkt->Srb.Cdb;
-    pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
-
-    Pkt->BufPtrCopy = ReadCapacityBuffer;
-    Pkt->BufLenCopy = ReadCapacityBufferLen;
-
-    Pkt->OriginalIrp = OriginalIrp;
-    Pkt->NumRetries = NUM_DRIVECAPACITY_RETRIES;          
-    Pkt->SyncEventPtr = SyncEventPtr;
-    Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
-}
-
-#if 0
-    /*
-     *  SetupSendStartUnitTransferPacket
-     *
-     *      Set up a transferPacket for a synchronous Send Start Unit transfer.
-     */
-    VOID SetupSendStartUnitTransferPacket(   TRANSFER_PACKET *Pkt,
-                                                    PIRP OriginalIrp)
-    {
-        PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
-        PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
-        PCDB pCdb;
-
-        PAGED_CODE();
-
-        RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
-
-        /*
-         *  Initialize the SRB.
-         *  Use a very long timeout value to give the drive time to spin up.
-         */
-        Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
-        Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
-        Pkt->Srb.TimeOutValue = START_UNIT_TIMEOUT;
-        Pkt->Srb.CdbLength = 6;
-        Pkt->Srb.OriginalRequest = Pkt->Irp;
-        Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
-        Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
-        Pkt->Srb.Lun = 0;
-        
-        SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER);    
-        SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_AUTOSENSE);
-        SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
-
-        pCdb = (PCDB)Pkt->Srb.Cdb;
-        pCdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
-        pCdb->START_STOP.Start = 1;
-        pCdb->START_STOP.Immediate = 0;
-        pCdb->START_STOP.LogicalUnitNumber = 0;
-
-        Pkt->OriginalIrp = OriginalIrp;
-        Pkt->NumRetries = 0;          
-        Pkt->SyncEventPtr = NULL;
-        Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
-    }
-#endif