Пример #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;
}
Пример #2
0
NTSTATUS
ScsiPortDispatchUnimplemented(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

{
    PCOMMON_EXTENSION commonExtension;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG isRemoved;

    isRemoved = SpAcquireRemoveLock(DeviceObject, Irp);
    if(isRemoved) {
        Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
        SpReleaseRemoveLock(DeviceObject, Irp);
        SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);
        return STATUS_DEVICE_DOES_NOT_EXIST;
    }

    commonExtension = DeviceObject->DeviceExtension;

    DebugPrint((0, "ScsiPortDispatchUnimplemented: request %#p\n", Irp));
    DebugPrint((1, "/t/tFunction Code (%d, %d)\n",
                   irpStack->MajorFunction,
                   irpStack->MinorFunction));
    DebugPrint((1, "/t/tFor %s %#p\n",
                   (commonExtension->IsPdo ? "PDO" : "FDO"),
                   DeviceObject));

    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

    SpReleaseRemoveLock(DeviceObject, Irp);
    SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);

    return STATUS_INVALID_DEVICE_REQUEST;

}
Пример #3
0
VOID
SpWaitForRemoveLock(
    IN PDEVICE_OBJECT DeviceObject,
    IN PVOID LockTag
    )
{
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;

    PAGED_CODE();

    //
    // Mark the thing as removing
    //

    commonExtension->IsRemoved = REMOVE_PENDING;

    //
    // Release our outstanding lock.
    //

    SpReleaseRemoveLock(DeviceObject, LockTag);

    DebugPrint((1, "SpWaitForRemoveLock - Reference count is now %d\n",
                commonExtension->RemoveLock));

    KeWaitForSingleObject(&(commonExtension->RemoveEvent),
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

    DebugPrint((1, "SpWaitForRemoveLock - removing device %#p\n",
                DeviceObject));

    return;
}
Пример #4
0
NTSTATUS
ScsiPortPdoScsi(
    IN PDEVICE_OBJECT Pdo,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine dispatches SRB's for a particular target device.  It will fill
    in the Port, Path, Target and Lun values and then forward the request
    through to the FDO for the bus

Arguments:

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

Return Value:

    status

--*/

{
    PLOGICAL_UNIT_EXTENSION lun = Pdo->DeviceExtension;

    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);

#if DBG
    PDRIVER_OBJECT lowerDriverObject =
                        lun->CommonExtension.LowerDeviceObject->DriverObject;
#endif

    PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;

    ULONG isRemoved;

    PSRB_DATA srbData;
    BOOLEAN isLock = FALSE;

    NTSTATUS status;

    isRemoved = SpAcquireRemoveLock(Pdo, Irp);

    if(isRemoved &&
       !IS_CLEANUP_REQUEST(irpStack) &&
       (srb->Function != SRB_FUNCTION_CLAIM_DEVICE)) {

        Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;

        SpReleaseRemoveLock(Pdo, Irp);
        SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
        return STATUS_DEVICE_DOES_NOT_EXIST;
    }

    srb->PathId = lun->PathId;
    srb->TargetId = lun->TargetId;
    srb->Lun = lun->Lun;

    //
    // NOTICE:  The SCSI-II specification indicates that this field should be
    // zero; however, some target controllers ignore the logical unit number
    // in the INDENTIFY message and only look at the logical unit number field
    // in the CDB.
    //

    srb->Cdb[1] |= srb->Lun << 5;

    //
    // Queue tags should be assigned only by the StartIo routine.  Set it to
    // a benign value here so we can tell later on that we don't have to
    // clear the tag value in the bitmap.
    //

    srb->QueueTag = SP_UNTAGGED;

#if DBG
    ASSERT(lowerDriverObject->MajorFunction[IRP_MJ_SCSI] != NULL);
    ASSERT(lowerDriverObject->MajorFunction[IRP_MJ_SCSI] == ScsiPortGlobalDispatch);
#endif

    switch(srb->Function) {


        case SRB_FUNCTION_ABORT_COMMAND: {

            //
            // BUGBUG - abort is broken.  We'll need to either yank it out
            // or figure out how to recode it internally.  Abort commands
            // are going to need their own SRB_DATA structure since that
            // contains the pointer back to the original irp.
            //

            ASSERT(FALSE);
            status = STATUS_NOT_SUPPORTED;
            break;

        }

        case SRB_FUNCTION_CLAIM_DEVICE:
        case SRB_FUNCTION_REMOVE_DEVICE: {

            status = SpClaimLogicalUnit(
                        lun->CommonExtension.LowerDeviceObject->DeviceExtension,
                        lun,
                        Irp,
                        FALSE);
            break;
        }

        case SRB_FUNCTION_UNLOCK_QUEUE: 
        case SRB_FUNCTION_LOCK_QUEUE: {

            BOOLEAN lock;

            lock = (srb->Function == SRB_FUNCTION_LOCK_QUEUE);

            //
            // This srb function is only valid as part of a power up request
            // and will be ignored if the power state is D0.
            //

            DebugPrint((2, "ScsiPortPdoScsi: called to %s queue %#p\n",
                           lock ? "lock" : "unlock", 
                           lun));

            ASSERT(lun->LockRequest == NULL);

            CLEAR_FLAG(srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
            SET_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE);

            isLock = TRUE;

            //
            // Throw this request down so it gets processed as a real
            // request.  We need to get the completion dpc to start
            // things running again.  there are too many flags to set
            // to do it from here.
            //

            DebugPrint((2, "ScsiPortPdoScsi: %s %#p into "
                           "queue %#p ... issuing request\n",
                        lock ? "lock" : "unlock", srb, lun));

            srbData = SpAllocateBypassSrbData(lun);
            ASSERT(srbData != NULL);

            goto RunSrb;
        }

        case SRB_FUNCTION_RELEASE_QUEUE:
        case SRB_FUNCTION_FLUSH_QUEUE: {

            srbData = SpAllocateBypassSrbData(lun);
            ASSERT(srbData != NULL);

            goto RunSrb;
        }

        default: {

            if(TEST_FLAG(srb->SrbFlags, (SRB_FLAGS_BYPASS_LOCKED_QUEUE |
                                         SRB_FLAGS_BYPASS_FROZEN_QUEUE))) {
                
                srbData = SpAllocateBypassSrbData(lun);
                ASSERT(srbData != NULL);
            } else {
                srbData = SpAllocateSrbData( lun->AdapterExtension, Irp);

                if(srbData == NULL) {
    
                    //
                    // There wasn't an SRB_DATA block available for this
                    // request so it's been queued waiting for resources -
                    // leave the logical unit remove-locked and return pending.
                    //
    
                    DebugPrint((1, "ScsiPortPdoScsi: Insufficient resources "
                                   "to allocate SRB_DATA structure\n"));
                    return STATUS_PENDING;
                }
            }
RunSrb:
            srbData->CurrentIrp = Irp;
            srbData->CurrentSrb = srb;
            srbData->LogicalUnit = lun;

            srb->OriginalRequest = srbData;
            return SpDispatchRequest(lun, Irp);
        }
    }

    Irp->IoStatus.Status = status;
    SpReleaseRemoveLock(Pdo, Irp);
    SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
    return status;
}
Пример #5
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;
}
Пример #6
0
NTSTATUS
ScsiPortPdoDeviceControl(
    IN PDEVICE_OBJECT Pdo,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine handles device control requests for scsi target devices

Arguments:

    Pdo - a pointer to the physical device object

    Irp - a pointer to the io request packet

Return Value:

    status

--*/

{
    PLOGICAL_UNIT_EXTENSION physicalExtension = Pdo->DeviceExtension;
    PCOMMON_EXTENSION commonExtension = Pdo->DeviceExtension;

    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

    NTSTATUS status;
    BOOLEAN completeRequest = TRUE;

    ULONG isRemoved;

    isRemoved = SpAcquireRemoveLock(Pdo, Irp);
    if(isRemoved) {

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

    ASSERT(commonExtension->IsPdo);

    Irp->IoStatus.Status = 0;

    switch(ioControlCode) {

        case IOCTL_STORAGE_QUERY_PROPERTY: {

            //
            // Validate the query
            //

            PSTORAGE_PROPERTY_QUERY query = Irp->AssociatedIrp.SystemBuffer;

            if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
               sizeof(STORAGE_PROPERTY_QUERY)) {

                status = STATUS_INVALID_PARAMETER;
                break;
            }

            status = ScsiPortQueryProperty(Pdo, Irp);

            return status;

            break;
        }

        case IOCTL_SCSI_GET_ADDRESS: {

            PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;

            if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
               sizeof(SCSI_ADDRESS)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            scsiAddress->Length = sizeof(PSCSI_ADDRESS);
            scsiAddress->PortNumber = (UCHAR) physicalExtension->PortNumber;
            scsiAddress->PathId = physicalExtension->PathId;
            scsiAddress->TargetId = physicalExtension->TargetId;
            scsiAddress->Lun = physicalExtension->Lun;

            Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
            status = STATUS_SUCCESS;
            break;
        }

        //
        // XXX - need to handle
        //
        // IOCTL_STORAGE_PASS_THROUGH
        // IOCTL_STORAGE_PASS_THROUGH_DIRECT
        //

        case IOCTL_SCSI_PASS_THROUGH:
        case IOCTL_SCSI_PASS_THROUGH_DIRECT: {

            PSCSI_PASS_THROUGH srbControl = Irp->AssociatedIrp.SystemBuffer;

            if(irpStack->Parameters.DeviceIoControl.InputBufferLength <
               sizeof(SCSI_PASS_THROUGH)) {

                status = STATUS_BUFFER_TOO_SMALL;
                break;
            }

            srbControl->PathId = physicalExtension->PathId;
            srbControl->TargetId = physicalExtension->TargetId;
            srbControl->Lun = physicalExtension->Lun;

            //
            // Fall through to the default handler
            //

        }

        default: {

            IoSkipCurrentIrpStackLocation(Irp);
            SpReleaseRemoveLock(Pdo, Irp);
            status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
            completeRequest = FALSE;
        }

    }

    if(completeRequest) {

        Irp->IoStatus.Status = status;
        SpReleaseRemoveLock(Pdo, Irp);
        SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
    }
    return status;
}
Пример #7
0
NTSTATUS
ScsiPortPdoPnp(
    IN PDEVICE_OBJECT LogicalUnit,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine handles pnp-power requests.  Currently it will just be
    successful

Arguments:

    LogicalUnit - pointer to the physical device object
    Irp - pointer to the io request packet

Return Value:

    status

--*/

{
    PLOGICAL_UNIT_EXTENSION logicalUnitExtension = LogicalUnit->DeviceExtension;
    PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;

    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);

    static ULONG i = 0;

    NTSTATUS status = STATUS_SUCCESS;

    ULONG isRemoved;

    PAGED_CODE();

    isRemoved = SpAcquireRemoveLock(LogicalUnit, Irp);

#if 0
    if(isRemoved != ) {

        ASSERT(isRemoved != REMOVE_PENDING);

        status = STATUS_DEVICE_DOES_NOT_EXIST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
#else
    ASSERT(isRemoved != REMOVE_COMPLETE);
#endif

    switch(irpStack->MinorFunction) {

        case IRP_MN_QUERY_PNP_DEVICE_STATE: {

            //
            // If the device is in the paging path then mark it as
            // not-disableable.
            //

            PPNP_DEVICE_STATE deviceState = 
                (PPNP_DEVICE_STATE) &(Irp->IoStatus.Information);

            DebugPrint((1, "ScsiPortPdoPnp: QUERY_DEVICE_STATE for PDO %#x\n", LogicalUnit));

            if(commonExtension->PagingPathCount != 0) {
                SET_FLAG((*deviceState), PNP_DEVICE_NOT_DISABLEABLE);
                DebugPrint((1, "ScsiPortPdoPnp: QUERY_DEVICE_STATE: %#x - not disableable\n",
                            LogicalUnit));
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            SpReleaseRemoveLock(LogicalUnit, Irp);
            SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
            return STATUS_SUCCESS;
        }

        case IRP_MN_START_DEVICE: {

            if(commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) {
                Irp->IoStatus.Status = STATUS_SUCCESS;
                break;
            }

            if(commonExtension->IsInitialized == FALSE) {
                status = ScsiPortInitDevice(LogicalUnit);
            }

            if(NT_SUCCESS(status)) {
                commonExtension->IsInitialized = TRUE;
                status = ScsiPortStartDevice(LogicalUnit);
            }

            if(NT_SUCCESS(status)) {
                commonExtension->CurrentPnpState = IRP_MN_START_DEVICE;
                commonExtension->PreviousPnpState = 0xff;
            }

            Irp->IoStatus.Status = status;

            break;
        }

        case IRP_MN_QUERY_ID: {

            UCHAR rawIdString[64] = "UNKNOWN ID TYPE";
            ANSI_STRING ansiIdString;
            UNICODE_STRING unicodeIdString;
            BOOLEAN multiStrings;

            PINQUIRYDATA inquiryData = &(logicalUnitExtension->InquiryData);

            //
            // We've been asked for the id of one of the physical device objects
            //

            DebugPrint((2, "ScsiPortPnp: got IRP_MN_QUERY_ID\n"));

            RtlInitUnicodeString(&unicodeIdString, NULL);
            RtlInitAnsiString(&ansiIdString, NULL);

            switch(irpStack->Parameters.QueryId.IdType) {

                case BusQueryDeviceID: {

                    status = ScsiPortGetDeviceId(LogicalUnit, &unicodeIdString);
                    multiStrings = FALSE;

                    break;
                }

                case BusQueryInstanceID: {

                    status = ScsiPortGetInstanceId(LogicalUnit, &unicodeIdString);
                    multiStrings = FALSE;

                    break;
                }

                case BusQueryHardwareIDs: {

                    status = ScsiPortGetHardwareIds(
                                &(logicalUnitExtension->InquiryData), 
                                &unicodeIdString);
                    multiStrings = TRUE;
                    break;
                }

                case BusQueryCompatibleIDs: {

                    status = ScsiPortGetCompatibleIds( 
                                &(logicalUnitExtension->InquiryData), 
                                &unicodeIdString);
                    multiStrings = TRUE;

                    break;
                }

                default: {

                    status = Irp->IoStatus.Status;
                    Irp->IoStatus.Information = 0;

                    break;

                }
            }

            Irp->IoStatus.Status = status;

            if(NT_SUCCESS(status)) {
            
                PWCHAR idString;
                
                //
                // fix up all invalid characters
                //                 
                idString = unicodeIdString.Buffer;
                while (*idString) {
                
                    if ((*idString <= L' ')  || 
                        (*idString > (WCHAR)0x7F) || 
                        (*idString == L',')) {
                        *idString = L'_';
                    }
                    idString++;
                    
                    if ((*idString == L'\0') && multiStrings) {
                        idString++;
                    }
                }            
            
                Irp->IoStatus.Information = (ULONG_PTR) unicodeIdString.Buffer;
            } else {
                Irp->IoStatus.Information = (ULONG_PTR) NULL;
            }

            SpReleaseRemoveLock(LogicalUnit, Irp);
            SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);

            return status;
            break;
        }

        case IRP_MN_QUERY_RESOURCES:
        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: {

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = (ULONG_PTR) NULL;
            SpReleaseRemoveLock(LogicalUnit, Irp);
            SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
            return STATUS_SUCCESS;
        }

        case IRP_MN_SURPRISE_REMOVAL:
        case IRP_MN_REMOVE_DEVICE: {

            BOOLEAN destroyed;

            //
            // Release the lock for this IRP before going in.
            //

            if(commonExtension->IsRemoved == NO_REMOVE) {
                commonExtension->IsRemoved = REMOVE_PENDING;
            }

            SpReleaseRemoveLock(LogicalUnit, Irp);

            destroyed = SpRemoveLogicalUnit(LogicalUnit, 
                                            irpStack->MinorFunction);

            if(destroyed) {
                commonExtension->PreviousPnpState =
                    commonExtension->CurrentPnpState;
                commonExtension->CurrentPnpState = irpStack->MinorFunction;
            } else {
                commonExtension->CurrentPnpState = 0xff;
                commonExtension->PreviousPnpState = irpStack->MinorFunction;
            }

            status = STATUS_SUCCESS;
            Irp->IoStatus.Status = status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return status;
        }

        case IRP_MN_QUERY_DEVICE_TEXT: {

            Irp->IoStatus.Status =
                SpQueryDeviceText(
                    LogicalUnit,
                    irpStack->Parameters.QueryDeviceText.DeviceTextType,
                    irpStack->Parameters.QueryDeviceText.LocaleId,
                    (PWSTR *) &Irp->IoStatus.Information
                    );

            break;
        }

        case IRP_MN_QUERY_CAPABILITIES: {

            PDEVICE_CAPABILITIES capabilities =
                irpStack->Parameters.DeviceCapabilities.Capabilities;

            PSCSIPORT_DEVICE_TYPE deviceType = NULL;

            capabilities->RawDeviceOK = 1;

            deviceType = SpGetDeviceTypeInfo(
                            logicalUnitExtension->InquiryData.DeviceType
                            );

            if((deviceType != NULL) && (deviceType->IsStorage)) {
                capabilities->SilentInstall = 1;
            }

            capabilities->Address = logicalUnitExtension->TargetId;

            Irp->IoStatus.Status = STATUS_SUCCESS;
            break;
        }

        case IRP_MN_QUERY_STOP_DEVICE:
        case IRP_MN_QUERY_REMOVE_DEVICE: {

            if ((commonExtension->PagingPathCount != 0) ||
                (logicalUnitExtension->IsLegacyClaim == TRUE)) {
                Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
            } else {
                Irp->IoStatus.Status = STATUS_SUCCESS;

                commonExtension->PreviousPnpState =
                    commonExtension->CurrentPnpState;
                commonExtension->CurrentPnpState = irpStack->MinorFunction;
            }
            break;
        }

        case IRP_MN_CANCEL_STOP_DEVICE: {

            if(commonExtension->CurrentPnpState == IRP_MN_QUERY_STOP_DEVICE) {
                commonExtension->CurrentPnpState =
                    commonExtension->PreviousPnpState;
                commonExtension->PreviousPnpState = 0xff;
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            break;
        }

        case IRP_MN_CANCEL_REMOVE_DEVICE: {

            if(commonExtension->CurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE) {
                commonExtension->CurrentPnpState =
                    commonExtension->PreviousPnpState;
                commonExtension->PreviousPnpState = 0xff;
            }

            Irp->IoStatus.Status = STATUS_SUCCESS;
            break;
        }

        case IRP_MN_STOP_DEVICE: {

            ASSERT(commonExtension->CurrentPnpState == IRP_MN_QUERY_STOP_DEVICE);

            status = ScsiPortStopDevice(LogicalUnit);

            ASSERT(NT_SUCCESS(status));

            Irp->IoStatus.Status = status;
            Irp->IoStatus.Information = (ULONG_PTR) NULL;

            if(NT_SUCCESS(status)) {
                commonExtension->CurrentPnpState = IRP_MN_STOP_DEVICE;
                commonExtension->PreviousPnpState = 0xff;
            }

            SpReleaseRemoveLock(LogicalUnit, Irp);
            SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);

            return status;
        }

        case IRP_MN_QUERY_DEVICE_RELATIONS: {

            PDEVICE_RELATIONS deviceRelations;

            if(irpStack->Parameters.QueryDeviceRelations.Type !=
               TargetDeviceRelation) {

                break;
            }

            //
            // DEVICE_RELATIONS definition contains one object pointer.
            //

            deviceRelations = ExAllocatePoolWithTag(
                                PagedPool,
                                sizeof(DEVICE_RELATIONS),
                                SCSIPORT_TAG_DEVICE_RELATIONS);

            if(deviceRelations == NULL) {

                Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            RtlZeroMemory(deviceRelations, sizeof(DEVICE_RELATIONS));

            deviceRelations->Count = 1;
            deviceRelations->Objects[0] = LogicalUnit;

            ObReferenceObject(deviceRelations->Objects[0]);

            Irp->IoStatus.Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;

            break;
        }

        case IRP_MN_DEVICE_USAGE_NOTIFICATION: {

            PIRP newIrp;
            PIO_STACK_LOCATION nextStack;

            DebugPrint((1, "Pdo - IRP_MN_DEVICE_USAGE_NOTIFICATION %#p received for "
                           "logical unit %#p\n",
                        Irp,
                        LogicalUnit));

            newIrp = IoAllocateIrp(
                        commonExtension->LowerDeviceObject->StackSize,
                        FALSE);

            if(newIrp == NULL) {

                Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                break;
            }

            newIrp->AssociatedIrp.MasterIrp = Irp;

            newIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;

            nextStack = IoGetNextIrpStackLocation(newIrp);
            *nextStack = *IoGetCurrentIrpStackLocation(Irp);

            IoSetCompletionRoutine(newIrp,
                                   SpPagingPathNotificationCompletion,
                                   commonExtension->LowerDeviceObject,
                                   TRUE,
                                   TRUE,
                                   TRUE);

            status = IoCallDriver(commonExtension->LowerDeviceObject,
                                  newIrp);
            return status;
            break;
        }
    }

    SpReleaseRemoveLock(LogicalUnit, Irp);

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

    return status;
}
Пример #8
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;
}
Пример #9
0
NTSTATUS
SpWmiPassToMiniPort(
    IN     PDEVICE_OBJECT  DeviceObject,
    IN     UCHAR           WmiMinorCode,
    IN OUT PWMI_PARAMETERS WmiParameters
    )
/*++

Routine Description:

   This function pass a WMI request to the miniport driver for processing.
   It creates an SRB which is processed normally by the port driver.  This
   call is synchronous.

   Callers of SpWmiPassToMiniPort must be running at IRQL PASSIVE_LEVEL.

Arguments:

   DeviceObject  - Pointer to the functional or physical device object.

   WmiMinorCode  - WMI action to perform.

   WmiParameters - WMI parameters.

Return Value:

   An NTSTATUS code describing the result of handling the WMI request.
   Complete the IRP with this status.

Notes:

   If this WMI request is completed with STATUS_SUCCESS, the WmiParameters
   BufferSize field will reflect the actual size of the WMI return buffer.

--*/
{
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PADAPTER_EXTENSION fdoExtension;
    SCSI_WMI_REQUEST_BLOCK   srb;
    LARGE_INTEGER            startingOffset;
    PLOGICAL_UNIT_EXTENSION  logicalUnit;

    ULONG                    commonBufferSize;
    PUCHAR                   commonBuffer;
    PHYSICAL_ADDRESS         physicalAddress;
    PVOID                    removeTag = (PVOID)((ULONG_PTR)WmiParameters+3);
    PWNODE_HEADER            wnode;

    NTSTATUS status;

    PAGED_CODE();

    startingOffset.QuadPart = (LONGLONG) 1;

    //
    // Zero out the SRB.
    //
    RtlZeroMemory(&srb, sizeof(SCSI_WMI_REQUEST_BLOCK));

    //
    // Initialize the SRB for a WMI request.
    //
    if (commonExtension->IsPdo) {                                       // [PDO]

        //
        // Set the logical unit addressing from this PDO's device extension.
        //
        logicalUnit = DeviceObject->DeviceExtension;

        SpAcquireRemoveLock(DeviceObject, removeTag);

        srb.PathId      = logicalUnit->PathId;
        srb.TargetId    = logicalUnit->TargetId;
        srb.Lun         = logicalUnit->Lun;

        fdoExtension = logicalUnit->AdapterExtension;

    } else {                                                            // [FDO]

        //
        // Set the logical unit addressing to the first logical unit.  This is
        // merely used for addressing purposes for adapter requests only.
        // NOTE: SpFindSafeLogicalUnit will acquire the remove lock
        //

        logicalUnit = SpFindSafeLogicalUnit(DeviceObject,
                                            0xff,
                                            removeTag);

        if (logicalUnit == NULL) {
            return(STATUS_DEVICE_DOES_NOT_EXIST);
        }

        fdoExtension = DeviceObject->DeviceExtension;

        srb.WMIFlags    = SRB_WMI_FLAGS_ADAPTER_REQUEST;
        srb.PathId      = logicalUnit->PathId;
        srb.TargetId    = logicalUnit->TargetId;
        srb.Lun         = logicalUnit->Lun;
    }

    //
    // HACK - allocate a chunk of common buffer for the actual request to
    // get processed in. We need to determine the size of buffer to allocate
    // this is the larger of the input or output buffers
    //

    if (WmiMinorCode == IRP_MN_EXECUTE_METHOD)
    {
        wnode = (PWNODE_HEADER)WmiParameters->Buffer;
        commonBufferSize = (WmiParameters->BufferSize > wnode->BufferSize) ?
                            WmiParameters->BufferSize :
                            wnode->BufferSize;
    } else {
        commonBufferSize = WmiParameters->BufferSize;
    }
                        
    commonBuffer = HalAllocateCommonBuffer(fdoExtension->DmaAdapterObject,
                                           commonBufferSize,
                                           &physicalAddress,
                                           FALSE);

    if(commonBuffer == NULL) {
        DebugPrint((1, "SpWmiPassToMiniPort: Unable to allocate %#x bytes of "
                       "common buffer\n", commonBufferSize));
        
        SpReleaseRemoveLock(logicalUnit->DeviceObject, removeTag);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    try {
        KEVENT event;
        PIRP irp;
        PMDL mdl;
        PIO_STACK_LOCATION irpStack;

        RtlCopyMemory(commonBuffer, WmiParameters->Buffer, commonBufferSize);
    
        srb.DataBuffer         = commonBuffer;       // [already non-paged]
        srb.DataTransferLength = WmiParameters->BufferSize;
        srb.Function           = SRB_FUNCTION_WMI;
        srb.Length             = sizeof(SCSI_REQUEST_BLOCK);
        srb.WMISubFunction     = WmiMinorCode;
        srb.DataPath           = WmiParameters->DataPath;
        srb.SrbFlags           = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;
        srb.TimeOutValue       = 10;                                // [ten seconds]
    
        //
        // Note that the value in DataBuffer may be used regardless of the value
        // of the MapBuffers field.
        //
    
        //
        // Initialize the notification event.
        //

        KeInitializeEvent(&event, NotificationEvent, FALSE);
    
        //
        // Build IRP for this request.
        // Note we do this synchronously for two reasons.  If it was done
        // asynchonously then the completion code would have to make a special
        // check to deallocate the buffer.  Second if a completion routine were
        // used then an additional IRP stack location would be needed.
        //

        irp = IoAllocateIrp(logicalUnit->DeviceObject->StackSize, FALSE);

        if(irp == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
        }

        mdl = IoAllocateMdl(commonBuffer,
                            WmiParameters->BufferSize,
                            FALSE,
                            FALSE,
                            irp);

        if(mdl == NULL) {
            IoFreeIrp(irp);
            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
        }

        MmBuildMdlForNonPagedPool(mdl);

        srb.OriginalRequest = irp;
    
        irpStack = IoGetNextIrpStackLocation(irp);
    
        //
        // Set major code.
        //
        irpStack->MajorFunction = IRP_MJ_SCSI;
    
        //
        // Set SRB pointer.
        //
        irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)&srb;
    
        //
        // Setup a completion routine so we know when the request has completed.
        //

        IoSetCompletionRoutine(irp,
                               SpSignalCompletion,
                               &event,
                               TRUE,
                               TRUE,
                               TRUE);

        //
        // Flush the data buffer for output.  This will insure that the data is
        // written back to memory.  Since the data-in flag is the the port driver
        // will flush the data again for input which will ensure the data is not
        // in the cache.
        //
        KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
    
        //
        // Call port driver to handle this request.
        //
        IoCallDriver(logicalUnit->CommonExtension.DeviceObject, irp);
    
        //
        // Wait for request to complete.
        //
        KeWaitForSingleObject(&event,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
    
        status = irp->IoStatus.Status;

        //
        // Relay the return buffer's size to the caller on success.
        //
        if (NT_SUCCESS(status)) {
            WmiParameters->BufferSize = srb.DataTransferLength;
        }
    
        //
        // Copy back the correct number of bytes into the caller provided buffer.
        //
    
        RtlCopyMemory(WmiParameters->Buffer,
                      commonBuffer,
                      WmiParameters->BufferSize);

        //
        // Free the irp and MDL.
        //

        IoFreeMdl(mdl);
        IoFreeIrp(irp);

    } finally {

        HalFreeCommonBuffer(fdoExtension->DmaAdapterObject,
                            commonBufferSize,
                            physicalAddress,
                            commonBuffer,
                            FALSE);
    
        SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject,
                            removeTag);
    }

    //
    // Return the IRP's status.
    //
    return status;
}
Пример #10
0
NTSTATUS
ScsiPortSystemControlIrp(
    PDEVICE_OBJECT DeviceObject,
    PIRP           Irp
    )

/*++

Routine Description:

   Process an IRP_MJ_SYSTEM_CONTROL request packet.

Arguments:

   DeviceObject - Pointer to the functional or physical device object.

   Irp          - Pointer to the request packet.

Return Value:

   NTSTATUS result code.

--*/

{
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION       irpSp;
    NTSTATUS                 status          = STATUS_SUCCESS;
    WMI_PARAMETERS           wmiParameters;

    ULONG isRemoved;

    PAGED_CODE();

    isRemoved = SpAcquireRemoveLock(DeviceObject, Irp);

    if (isRemoved) {
        Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
        SpReleaseRemoveLock(DeviceObject, Irp);
        SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);
        return STATUS_DEVICE_DOES_NOT_EXIST;
    }

    //
    // Obtain a pointer to the current IRP stack location.
    //
    irpSp = IoGetCurrentIrpStackLocation(Irp);

    ASSERT(irpSp->MajorFunction == IRP_MJ_SYSTEM_CONTROL);

    //
    // Determine if this WMI request was destined to us.  If not, pass the IRP
    // down.
    //
    if ( (PDEVICE_OBJECT)irpSp->Parameters.WMI.ProviderId != DeviceObject) {

        //
        // Copy parameters from our stack location to the next stack location.
        //
        IoCopyCurrentIrpStackLocationToNext(Irp);

        //
        // Pass the IRP on to the next driver.
        //
        SpReleaseRemoveLock(DeviceObject, Irp);
        return IoCallDriver(commonExtension->LowerDeviceObject, Irp);
    }

    //
    // Copy the WMI parameters into our local WMISRB structure.
    //
    wmiParameters.ProviderId = irpSp->Parameters.WMI.ProviderId;
    wmiParameters.DataPath   = irpSp->Parameters.WMI.DataPath;
    wmiParameters.Buffer     = irpSp->Parameters.WMI.Buffer;
    wmiParameters.BufferSize = irpSp->Parameters.WMI.BufferSize;

    //
    // Determine what the WMI request wants of us.
    //
    switch (irpSp->MinorFunction) {
        case IRP_MN_QUERY_ALL_DATA:
            //
            // Query for all instances of a data block.
            //
        case IRP_MN_QUERY_SINGLE_INSTANCE:
            //
            // Query for a single instance of a data block.
            //
        case IRP_MN_CHANGE_SINGLE_INSTANCE:
            //
            // Change all data items in a data block for a single instance.
            //
        case IRP_MN_CHANGE_SINGLE_ITEM:
            //
            // Change a single data item in a data block for a single instance.
            //
        case IRP_MN_ENABLE_EVENTS:
            //
            // Enable events.
            //
        case IRP_MN_DISABLE_EVENTS:
            //
            // Disable events.
            //
        case IRP_MN_ENABLE_COLLECTION:
            //
            // Enable data collection for the given GUID.
            //
        case IRP_MN_DISABLE_COLLECTION:
            //
            // Disable data collection for the given GUID.
            //
            status = SpWmiIrpNormalRequest(DeviceObject,
                                           irpSp->MinorFunction,
                                           &wmiParameters);
            break;

        case IRP_MN_EXECUTE_METHOD:
            //
            // Execute method
            //
            status = SpWmiIrpNormalRequest(DeviceObject,
                                           irpSp->MinorFunction,
                                           &wmiParameters);
            break;

        case IRP_MN_REGINFO:
            //
            // Query for registration and registration update information.
            //
            status = SpWmiIrpRegisterRequest(DeviceObject, &wmiParameters);
            break;

        default:
            //
            // Unsupported WMI request.
            //
            status = STATUS_INVALID_DEVICE_REQUEST;
            ASSERT(FALSE);
            break;
    }

    //
    // Complete this WMI IRP request.
    //
    Irp->IoStatus.Status     = status;
    Irp->IoStatus.Information= NT_SUCCESS(status) ? wmiParameters.BufferSize : 0;
    SpReleaseRemoveLock(DeviceObject, Irp);
    SpCompleteRequest(DeviceObject, Irp, NULL, IO_NO_INCREMENT);

    return status;
}