Exemplo n.º 1
0
NTSTATUS
ScsiPortPdoCreateClose(
    IN PDEVICE_OBJECT Pdo,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine handles creates and closes for bus device pdo's

Arguments:

    Pdo - a pointer to the physical device object
    Irp - a pointer to the io request packet

Return Value:

    status

--*/

{
    PLOGICAL_UNIT_EXTENSION logicalUnitExtension = Pdo->DeviceExtension;

    ULONG isRemoved;

    NTSTATUS status = STATUS_SUCCESS;

    PAGED_CODE();

    ASSERT_PDO(Pdo);

    isRemoved = SpAcquireRemoveLock(Pdo, Irp);

    if(IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_CREATE) {

        if(isRemoved) {
            status = STATUS_DEVICE_DOES_NOT_EXIST;
        } else if((logicalUnitExtension->LuFlags | LU_RESCAN_ACTIVE) ==
                    LU_RESCAN_ACTIVE) {

            //
            // This device object hasn't been verified to exist.  Fail the create
            //

            // status = STATUS_DEVICE_NOT_READY;
        }
    }

    Irp->IoStatus.Status = status;
    SpReleaseRemoveLock(Pdo, Irp);
    SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);

    return status;
}
Exemplo n.º 2
0
NTSTATUS
NTAPI
PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension)
{
    PPCI_INTERFACE CurrentInterface, *Interfaces;
    PPCI_PDO_EXTENSION PdoExtension;
    PPCI_ARBITER_INSTANCE ArbiterInterface;
    NTSTATUS Status;
    PCI_SIGNATURE ArbiterType;
    ASSERT_FDO(FdoExtension);

    /* Loop all the arbiters */
    for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_BusNumber; ArbiterType++)
    {
        /* Check if this is the extension for the Root PCI Bus */
        if (!PCI_IS_ROOT_FDO(FdoExtension))
        {
            /* Get the PDO extension */
            PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension;
            ASSERT_PDO(PdoExtension);

            /* Skip this bus if it does subtractive decode */
            if (PdoExtension->Dependent.type1.SubtractiveDecode)
            {
                DPRINT1("PCI Not creating arbiters for subtractive bus %u\n",
                        PdoExtension->Dependent.type1.SubtractiveDecode);
                continue;
            }
        }

        /* Query all the registered arbiter interfaces */
        Interfaces = PciInterfaces;
        while (*Interfaces)
        {
            /* Find the one that matches the arbiter currently being setup */
            CurrentInterface = *Interfaces;
            if (CurrentInterface->Signature == ArbiterType) break;
            Interfaces++;
        }

        /* Check if the required arbiter was not found in the list */
        if (!*Interfaces)
        {
            /* Skip this arbiter and try the next one */
            DPRINT1("PCI - FDO ext 0x%p no %s arbiter.\n",
                    FdoExtension,
                    PciArbiterNames[ArbiterType - PciArb_Io]);
            continue;
        }

        /* An arbiter was found, allocate an instance for it */
        Status = STATUS_INSUFFICIENT_RESOURCES;
        ArbiterInterface = ExAllocatePoolWithTag(PagedPool,
                                                 sizeof(PCI_ARBITER_INSTANCE),
                                                 PCI_POOL_TAG);
        if (!ArbiterInterface) break;

        /* Setup the instance */
        ArbiterInterface->BusFdoExtension = FdoExtension;
        ArbiterInterface->Interface = CurrentInterface;
        swprintf(ArbiterInterface->InstanceName,
                 L"PCI %S (b=%02x)",
                 PciArbiterNames[ArbiterType - PciArb_Io],
                 FdoExtension->BaseBus);

        /* Call the interface initializer for it */
        Status = CurrentInterface->Initializer(ArbiterInterface);
        if (!NT_SUCCESS(Status)) break;

        /* Link it with this FDO */
        PcipLinkSecondaryExtension(&FdoExtension->SecondaryExtension,
                                   &FdoExtension->SecondaryExtLock,
                                   &ArbiterInterface->Header,
                                   ArbiterType,
                                   PciArbiterDestructor);

        /* This arbiter is now initialized, move to the next one */
        DPRINT1("PCI - FDO ext 0x%p %S arbiter initialized (context 0x%p).\n",
                FdoExtension,
                L"ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name,
                ArbiterInterface);
        Status = STATUS_SUCCESS;
    }

    /* Return to caller */
    return Status;
}
Exemplo n.º 3
0
NTSTATUS
NTAPI
PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension,
                           IN PCM_RESOURCE_LIST Resources)
{
    PPCI_PDO_EXTENSION PdoExtension;
    //CM_RESOURCE_TYPE DesiredType;
    PVOID Instance;
    PCI_SIGNATURE ArbiterType;

    UNREFERENCED_PARAMETER(Resources);

    /* Arbiters should not already be initialized */
    if (DeviceExtension->ArbitersInitialized)
    {
        /* Duplicated start request, fail initialization */
        DPRINT1("PCI Warning hot start FDOx %p, resource ranges not checked.\n", DeviceExtension);
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    /* Check for non-root FDO */
    if (!PCI_IS_ROOT_FDO(DeviceExtension))
    {
        /* Grab the PDO */
        PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension;
        ASSERT_PDO(PdoExtension);

        /* Check if this is a subtractive bus */
        if (PdoExtension->Dependent.type1.SubtractiveDecode)
        {
            /* There is nothing to do regarding arbitration of resources */
            DPRINT1("PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", DeviceExtension);
            return STATUS_SUCCESS;
        }
    }

    /* Loop all arbiters */
    for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++)
    {
        /* Pick correct resource type for each arbiter */
        if (ArbiterType == PciArb_Io)
        {
            /* I/O Port */
            //DesiredType = CmResourceTypePort;
        }
        else if (ArbiterType == PciArb_Memory)
        {
            /* Device RAM */
            //DesiredType = CmResourceTypeMemory;
        }
        else
        {
            /* Ignore anything else */
            continue;
        }

        /* Find an arbiter of this type */
        Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension,
                                                 ArbiterType);
        if (Instance)
        {
            /*
             * Now we should initialize it, not yet implemented because Arb
             * library isn't yet implemented, not even the headers.
             */
            UNIMPLEMENTED;
            //while (TRUE);
        }
        else
        {
            /* The arbiter was not found, this is an error! */
            DPRINT1("PCI - FDO ext 0x%p %s arbiter (REQUIRED) is missing.\n",
                    DeviceExtension,
                    PciArbiterNames[ArbiterType - PciArb_Io]);
        }
    }

    /* Arbiters are now initialized */
    DeviceExtension->ArbitersInitialized = TRUE;
    return STATUS_SUCCESS;
}
Exemplo n.º 4
0
NTSTATUS
SpPagingPathNotificationCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP LowerIrp,
    IN PDEVICE_OBJECT Fdo
    )
{
    PIRP upperIrp = LowerIrp->AssociatedIrp.MasterIrp;

    PIO_STACK_LOCATION lowerStack = IoGetCurrentIrpStackLocation(LowerIrp);
    PIO_STACK_LOCATION upperStack = IoGetCurrentIrpStackLocation(upperIrp);

    PDEVICE_OBJECT pdo = upperStack->DeviceObject;

    PADAPTER_EXTENSION lowerExtension;
    PLOGICAL_UNIT_EXTENSION upperExtension;

    ASSERT(Fdo != NULL);
    ASSERT(pdo != NULL);

    DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: Completion of "
                   "paging notification irp %#p sent due to irp %#p\n",
                LowerIrp, upperIrp));

    lowerExtension = (PADAPTER_EXTENSION) Fdo->DeviceExtension;
    upperExtension = (PLOGICAL_UNIT_EXTENSION) pdo->DeviceExtension;

    ASSERT_FDO(lowerExtension->DeviceObject);
    ASSERT_PDO(upperExtension->DeviceObject);

    DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: irp status %#08lx\n",
                LowerIrp->IoStatus.Status));

    if(NT_SUCCESS(LowerIrp->IoStatus.Status)) {

        PUCHAR typeName = "INSERT TYPE HERE";
        PULONG lowerCount;
        PULONG upperCount;

        //
        // The parameters have already been erased from the lower irp stack
        // location - use the parameters from the upper once since they're
        // just a copy.
        //

        switch(upperStack->Parameters.UsageNotification.Type) {

            case DeviceUsageTypePaging: {

                lowerCount = &(lowerExtension->CommonExtension.PagingPathCount);
                upperCount = &(upperExtension->CommonExtension.PagingPathCount);
                typeName = "PagingPathCount";
                break;
            }

            case DeviceUsageTypeHibernation: {

                lowerCount = &(lowerExtension->CommonExtension.HibernatePathCount);
                upperCount = &(upperExtension->CommonExtension.HibernatePathCount);
                typeName = "HibernatePathCount";
                break;
            }

            case DeviceUsageTypeDumpFile: {

                lowerCount = &(lowerExtension->CommonExtension.DumpPathCount);
                upperCount = &(upperExtension->CommonExtension.DumpPathCount);
                typeName = "DumpPathCount";
                break;
            }

            default: {

                typeName = "unknown type";
                lowerCount = upperCount = NULL;
                break;
            }
        }

        if(lowerCount != NULL) {
            IoAdjustPagingPathCount(
                lowerCount,
                upperStack->Parameters.UsageNotification.InPath
                );
            DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
                           "Fdo %s count - %d\n",
                        typeName, *lowerCount));
            IoInvalidateDeviceState(lowerExtension->LowerPdo);
        }

        if(upperCount != NULL) {
            IoAdjustPagingPathCount(
                upperCount,
                upperStack->Parameters.UsageNotification.InPath
                );
            DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
                           "Pdo %s count - %d\n",
                        typeName, *upperCount));
            IoInvalidateDeviceState(upperExtension->DeviceObject);
        }
    }

    upperIrp->IoStatus = LowerIrp->IoStatus;

    SpReleaseRemoveLock(lowerExtension->CommonExtension.DeviceObject, LowerIrp);
    SpReleaseRemoveLock(upperExtension->CommonExtension.DeviceObject, upperIrp);

    IoMarkIrpPending(upperIrp);

    SpCompleteRequest(upperExtension->CommonExtension.DeviceObject,
                      upperIrp,
                      NULL,
                      IO_NO_INCREMENT);

    IoFreeIrp(LowerIrp);

    return STATUS_MORE_PROCESSING_REQUIRED;
}
Exemplo n.º 5
0
NTSTATUS
NTAPI
DiskQueryId(
    IN PDEVICE_OBJECT Pdo,
    IN BUS_QUERY_ID_TYPE IdType,
    IN PUNICODE_STRING UnicodeIdString
    )

/*++

Routine Description:

    This routine generates the PNP id's for the disk's "children".  If the
    specified ID isn't one that the routine can generate it must return
    STATUS_NOT_IMPLEMENTED so classpnp will know not to do anything with the
    PNP request's status.

    This routine allocates the buffer for the UnicodeIdString.  It is the
    caller's responsibility to free the buffer when it's done.

Arguments:

    Pdo - a pointer to the PDO we are to generate an ID for

    IdType - the type of ID to be generated

    UnicodeIdString - a string to put the results into.

Return Value:

    STATUS_SUCCCESS if successful

    STATUS_NOT_IMPLEMENTED if the IdType is not one supported by this routine

    error status otherwise.

--*/

{
    ANSI_STRING ansiIdString;

    //NTSTATUS status;

    PAGED_CODE();
    ASSERT_PDO(Pdo);

    if(IdType == BusQueryDeviceID) {

        if((Pdo->Characteristics & FILE_REMOVABLE_MEDIA) == 0) {
            RtlInitAnsiString(&ansiIdString, "STORAGE\\Partition");
            return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
        }

        RtlInitAnsiString(&ansiIdString,
                          "STORAGE\\RemovableMedia");

        return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
    }

    if(IdType == BusQueryInstanceID) {

        //PPHYSICAL_DEVICE_EXTENSION pdoExtension = Pdo->DeviceExtension;
        PCOMMON_DEVICE_EXTENSION commonExtension = Pdo->DeviceExtension;
        PDISK_DATA diskData = commonExtension->PartitionZeroExtension->CommonExtension.DriverData;

        UCHAR string[64];

        if((Pdo->Characteristics & FILE_REMOVABLE_MEDIA) == 0) {

            if (diskData->PartitionStyle == PARTITION_STYLE_MBR) {
                sprintf(string, "S%08lx_O%I64lx_L%I64lx",
                        diskData->Mbr.Signature,
                        commonExtension->StartingOffset,
                        commonExtension->PartitionLength);
            } else {
                sprintf(string,
                        "S%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xS_O%I64lx_L%I64lx",
                        diskData->Efi.DiskId.Data1,
                        diskData->Efi.DiskId.Data2,
                        diskData->Efi.DiskId.Data3,
                        diskData->Efi.DiskId.Data4[0],
                        diskData->Efi.DiskId.Data4[1],
                        diskData->Efi.DiskId.Data4[2],
                        diskData->Efi.DiskId.Data4[3],
                        diskData->Efi.DiskId.Data4[4],
                        diskData->Efi.DiskId.Data4[5],
                        diskData->Efi.DiskId.Data4[6],
                        diskData->Efi.DiskId.Data4[7],
                        commonExtension->StartingOffset,
                        commonExtension->PartitionLength);
            }
        } else {
            sprintf(string, "RM");
        }

        RtlInitAnsiString(&ansiIdString, string);

        return RtlAnsiStringToUnicodeString(UnicodeIdString, &ansiIdString, TRUE);
    }

    if((IdType == BusQueryHardwareIDs) || (IdType == BusQueryCompatibleIDs)) {

        RtlInitAnsiString(&ansiIdString, "STORAGE\\Volume");

        UnicodeIdString->MaximumLength = (USHORT) RtlAnsiStringToUnicodeSize(&ansiIdString) + sizeof(UNICODE_NULL);

        UnicodeIdString->Buffer = ExAllocatePoolWithTag(PagedPool,
                                                        UnicodeIdString->MaximumLength,
                                                        DISK_TAG_PNP_ID);

        if(UnicodeIdString->Buffer == NULL) {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(UnicodeIdString->Buffer, UnicodeIdString->MaximumLength);

        return RtlAnsiStringToUnicodeString(UnicodeIdString,
                                            &ansiIdString,
                                            FALSE);
    }

    return STATUS_NOT_IMPLEMENTED;
}
Exemplo n.º 6
0
NTSTATUS
NTAPI
PciAddDevice(IN PDRIVER_OBJECT DriverObject,
             IN PDEVICE_OBJECT PhysicalDeviceObject)
{
    PCM_RESOURCE_LIST Descriptor;
    PDEVICE_OBJECT AttachedTo;
    PPCI_FDO_EXTENSION FdoExtension;
    PPCI_FDO_EXTENSION ParentExtension;
    PPCI_PDO_EXTENSION PdoExtension;
    PDEVICE_OBJECT DeviceObject;
    UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
    PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
    NTSTATUS Status;
    HANDLE KeyHandle;
    UNICODE_STRING ValueName;
    ULONG ResultLength;
    PAGED_CODE();
    DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n",
            PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName);

    /* Zero out variables so failure path knows what to do */
    AttachedTo = NULL;
    FdoExtension = NULL;
    PdoExtension = NULL;
    DeviceObject = NULL;

    do
    {
        /* Check if there's already a device extension for this bus */
        ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject,
                                                       &PciGlobalLock);
        if (ParentExtension)
        {
            /* Make sure we find a real PDO */
            PdoExtension = PhysicalDeviceObject->DeviceExtension;
            ASSERT_PDO(PdoExtension);

            /* Make sure it's a PCI-to-PCI bridge */
            if ((PdoExtension->BaseClass != PCI_CLASS_BRIDGE_DEV) ||
                (PdoExtension->SubClass != PCI_SUBCLASS_BR_PCI_TO_PCI))
            {
                /* This should never happen */
                DPRINT1("PCI - PciAddDevice for Non-Root/Non-PCI-PCI bridge,\n"
                        "      Class %02x, SubClass %02x, will not add.\n",
                        PdoExtension->BaseClass,
                        PdoExtension->SubClass);
                ASSERT((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
                       (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));

                /* Enter the failure path */
                Status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }

            /* Subordinate bus on the bridge */
            DPRINT1("PCI - AddDevice (new bus is child of bus 0x%x).\n",
                    ParentExtension->BaseBus);

            /* Make sure PCI bus numbers are configured */
            if (!PciAreBusNumbersConfigured(PdoExtension))
            {
                /* This is a critical failure */
                DPRINT1("PCI - Bus numbers not configured for bridge (0x%x.0x%x.0x%x)\n",
                        ParentExtension->BaseBus,
                        PdoExtension->Slot.u.bits.DeviceNumber,
                        PdoExtension->Slot.u.bits.FunctionNumber);

                /* Enter the failure path */
                Status = STATUS_INVALID_DEVICE_REQUEST;
                break;
            }
        }

        /* Create the FDO for the bus */
        Status = IoCreateDevice(DriverObject,
                                sizeof(PCI_FDO_EXTENSION),
                                NULL,
                                FILE_DEVICE_BUS_EXTENDER,
                                0,
                                0,
                                &DeviceObject);
        if (!NT_SUCCESS(Status)) break;

        /* Initialize the extension for the FDO */
        FdoExtension = DeviceObject->DeviceExtension;
        PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension,
                                              DeviceObject,
                                              PhysicalDeviceObject);

        /* Attach to the root PDO */
        Status = STATUS_NO_SUCH_DEVICE;
        AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject,
                                                 PhysicalDeviceObject);
        ASSERT(AttachedTo != NULL);
        if (!AttachedTo) break;
        FdoExtension->AttachedDeviceObject = AttachedTo;

        /* Check if this is a child bus, or the root */
        if (ParentExtension)
        {
            /* The child inherits root data */
            FdoExtension->BaseBus = PdoExtension->Dependent.type1.SecondaryBus;
            FdoExtension->BusRootFdoExtension = ParentExtension->BusRootFdoExtension;
            PdoExtension->BridgeFdoExtension = FdoExtension;
            FdoExtension->ParentFdoExtension = ParentExtension;
        }
        else
        {
            /* Query the boot configuration */
            Status = PciGetDeviceProperty(PhysicalDeviceObject,
                                          DevicePropertyBootConfiguration,
                                          (PVOID*)&Descriptor);
            if (!NT_SUCCESS(Status))
            {
                /* No configuration has been set */
                Descriptor = NULL;
            }
            else
            {
                /* Root PDO in ReactOS does not assign boot resources */
                UNIMPLEMENTED_DBGBREAK("Encountered during setup\n");
                Descriptor = NULL;
            }

            if (Descriptor)
            {
                /* Root PDO in ReactOS does not assign boot resources */
                UNIMPLEMENTED_DBGBREAK();
            }
            else
            {
                /* Default configuration isn't the normal path on Windows */
                if (PciBreakOnDefault)
                {
                    /* If a second bus is found and there's still no data, crash */
                    KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
                                 0xDEAD0010u,
                                 (ULONG_PTR)DeviceObject,
                                 0,
                                 0);
                }

                /* Warn that a default configuration will be used, and set bus 0 */
                DPRINT1("PCI   Will use default configuration.\n");
                PciBreakOnDefault = TRUE;
                FdoExtension->BaseBus = 0;
            }

            /* This is the root bus */
            FdoExtension->BusRootFdoExtension = FdoExtension;
        }

        /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */
        Status = PciGetConfigHandlers(FdoExtension);
        if (!NT_SUCCESS(Status)) break;

        /* Initialize all the supported PCI arbiters */
        Status = PciInitializeArbiters(FdoExtension);
        if (!NT_SUCCESS(Status)) break;

        /* This is a real FDO, insert it into the list */
        FdoExtension->Fake = FALSE;
        PciInsertEntryAtTail(&PciFdoExtensionListHead,
                             FdoExtension,
                             &PciGlobalLock);

        /* Open the device registry key so that we can query the errata flags */
        IoOpenDeviceRegistryKey(DeviceObject,
                                PLUGPLAY_REGKEY_DEVICE,
                                KEY_ALL_ACCESS,
                                &KeyHandle),

        /* Open the value that contains errata flags for this bus instance */
        RtlInitUnicodeString(&ValueName, L"HackFlags");
        Status = ZwQueryValueKey(KeyHandle,
                                 &ValueName,
                                 KeyValuePartialInformation,
                                 ValueInfo,
                                 sizeof(Buffer),
                                 &ResultLength);
        ZwClose(KeyHandle);
        if (NT_SUCCESS(Status))
        {
            /* Make sure the data is of expected type and size */
            if ((ValueInfo->Type == REG_DWORD) &&
                (ValueInfo->DataLength == sizeof(ULONG)))
            {
                /* Read the flags for this bus */
                FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data;
            }
        }

        /* Query ACPI for PCI HotPlug Support */
        PciGetHotPlugParameters(FdoExtension);

        /* The Bus FDO is now initialized */
        DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        return STATUS_SUCCESS;
    } while (FALSE);

    /* This is the failure path */
    ASSERT(!NT_SUCCESS(Status));

    /* Check if the FDO extension exists */
    if (FdoExtension) DPRINT1("Should destroy secondaries\n");

    /* Delete device objects */
    if (AttachedTo) IoDetachDevice(AttachedTo);
    if (DeviceObject) IoDeleteDevice(DeviceObject);
    return Status;
}
Exemplo n.º 7
0
VOID
FASTCALL
SpCompleteRequest(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN OPTIONAL PSRB_DATA SrbData,
    IN CCHAR PriorityBoost
)

/*++

Routine Description:

    This routine is a wrapper around IoCompleteRequest.  It is used primarily
    for debugging purposes.  The routine will assert if the Irp being completed
    is still holding the release lock.

Arguments:


Return Value:

    none

--*/

{

    PADAPTER_EXTENSION adapterExtension = DeviceObject->DeviceExtension;
#if DBG
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PREMOVE_TRACKING_BLOCK *listEntry =
        &((PREMOVE_TRACKING_BLOCK) commonExtension->RemoveTrackingList);

    KIRQL oldIrql;

    KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
                      &oldIrql);

    while(*listEntry != NULL) {

        if((*listEntry)->Tag == Irp) {
            break;
        }

        listEntry = &((*listEntry)->NextBlock);
    }

    if(*listEntry != NULL) {

        DebugPrint((0, ">>>>SpCompleteRequest: Irp %#p completed while "
                    "still holding the remove lock\n",
                    Irp));
        DebugPrint((0, ">>>>SpReleaseRemoveLock: Lock acquired in file "
                    "%s on line %d\n", (*listEntry)->File, (*listEntry)->Line));
        ASSERT(FALSE);
    }

    KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql);

    if(ARGUMENT_PRESENT(SrbData)) {
        PLOGICAL_UNIT_EXTENSION logicalUnit;

        ASSERT_SRB_DATA(SrbData);
        ASSERT(SrbData->ScatterGatherList == NULL);

        ASSERT_SRB_DATA(SrbData);
        ASSERT(SrbData->CurrentIrp == Irp);

        logicalUnit = SrbData->LogicalUnit;

        ASSERT(logicalUnit != NULL);
        ASSERT(logicalUnit->CurrentUntaggedRequest != SrbData);
        ASSERT_PDO(logicalUnit->CommonExtension.DeviceObject);

        ASSERT(SrbData->RemappedMdl == NULL);
    }

#endif

    //
    // If the caller specified an SRB_DATA structure for the completion then
    // we will free it to the lookaside list, fix the OriginalIrp value in the
    // srb and release the queue-tag value assigned to the device.
    //

    if(ARGUMENT_PRESENT(SrbData)) {
        PLOGICAL_UNIT_EXTENSION logicalUnit;

        logicalUnit = SrbData->LogicalUnit;

        if((SrbData->CurrentSrb->Function == SRB_FUNCTION_LOCK_QUEUE) ||
                (SrbData->CurrentSrb->Function == SRB_FUNCTION_UNLOCK_QUEUE)) {
            ASSERT(SrbData->CurrentSrb == logicalUnit->LockRequest);
            logicalUnit->LockRequest = NULL;
        }

        SrbData->CurrentSrb->OriginalRequest = SrbData->CurrentIrp;
        SrbData->CurrentIrp = NULL;
        SrbData->CurrentSrb = NULL;

        ASSERT(SrbData->FreeRoutine != NULL);
        ASSERT((SrbData->FreeRoutine == SpFreeSrbData) ||
               (SrbData->FreeRoutine == SpFreeBypassSrbData));

        SrbData->FreeRoutine(logicalUnit->AdapterExtension, SrbData);
        SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject, Irp);
    }

    IoCompleteRequest(Irp, PriorityBoost);
    return;
}