class2.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,425 行 · 第 1/5 页

C
2,425
字号

Arguments:

    DeviceObject - Supplies the device object which represents the logical
        unit.

    Irp - Supplies the Irp which has completed.

    Context - Supplies a pointer to the SRB.

Return Value:

    NT status

--*/

{
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PSCSI_REQUEST_BLOCK srb = Context;
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    NTSTATUS status;
    BOOLEAN retry;

    //
    // Check SRB status for success of completing request.
    //

    if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {

        DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb));

        //
        // Release the queue if it is frozen.
        //

        if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
            ScsiClassReleaseQueue(DeviceObject);
        }

        retry = ScsiClassInterpretSenseInfo(
            DeviceObject,
            srb,
            irpStack->MajorFunction,
            irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
            MAXIMUM_RETRIES - ((ULONG)irpStack->Parameters.Others.Argument4),
            &status);

        //
        // If the status is verified required and the this request
        // should bypass verify required then retry the request.
        //

        if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
            status == STATUS_VERIFY_REQUIRED) {

            status = STATUS_IO_DEVICE_ERROR;
            retry = TRUE;
        }

        if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG)irpStack->Parameters.Others.Argument4-1))) {

            //
            // Retry request.
            //

            DebugPrint((1, "Retry request %lx\n", Irp));
            RetryRequest(DeviceObject, Irp, srb, FALSE);
            return STATUS_MORE_PROCESSING_REQUIRED;
        }
    } else {

        //
        // Set status for successful request.
        //

        status = STATUS_SUCCESS;

    } // end if (SRB_STATUS(srb->SrbStatus) ...

    //
    // Return SRB to list.
    //

    ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
                                srb);

    //
    // Set status in completing IRP.
    //

    Irp->IoStatus.Status = status;
    if ((NT_SUCCESS(status)) && (Irp->Flags & IRP_PAGING_IO)) {
        ASSERT(Irp->IoStatus.Information);
    }

    //
    // Set the hard error if necessary.
    //

    if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) {

        //
        // Store DeviceObject for filesystem, and clear
        // in IoStatus.Information field.
        //

        IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
        Irp->IoStatus.Information = 0;
    }

    //
    // If pending has be returned for this irp then mark the current stack as
    // pending.
    //

    if (Irp->PendingReturned) {
      IoMarkIrpPending(Irp);
    }

    if (deviceExtension->ClassStartIo) {
        if (irpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) {
            IoStartNextPacket(DeviceObject, FALSE);
        }
    }

    return status;

} // end ScsiClassIoComplete()


NTSTATUS
STDCALL
ScsiClassIoCompleteAssociated(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )

/*++

Routine Description:

    This routine executes when the port driver has completed a request.
    It looks at the SRB status in the completing SRB and if not success
    it checks for valid request sense buffer information. If valid, the
    info is used to update status with more precise message of type of
    error. This routine deallocates the SRB.  This routine is used for
    requests which were build by split request.  After it has processed
    the request it decrements the Irp count in the master Irp.  If the
    count goes to zero then the master Irp is completed.

Arguments:

    DeviceObject - Supplies the device object which represents the logical
        unit.

    Irp - Supplies the Irp which has completed.

    Context - Supplies a pointer to the SRB.

Return Value:

    NT status

--*/

{
    PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(Irp);
    PSCSI_REQUEST_BLOCK srb = Context;
    PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
    PIRP                originalIrp = Irp->AssociatedIrp.MasterIrp;
    LONG                irpCount;
    NTSTATUS            status;
    BOOLEAN             retry;

    //
    // Check SRB status for success of completing request.
    //

    if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {

        DebugPrint((2,"ScsiClassIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb));

        //
        // Release the queue if it is frozen.
        //

        if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
            ScsiClassReleaseQueue(DeviceObject);
        }

        retry = ScsiClassInterpretSenseInfo(
            DeviceObject,
            srb,
            irpStack->MajorFunction,
            irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
            MAXIMUM_RETRIES - ((ULONG)irpStack->Parameters.Others.Argument4),
            &status);

        //
        // If the status is verified required and the this request
        // should bypass verify required then retry the request.
        //

        if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
            status == STATUS_VERIFY_REQUIRED) {

            status = STATUS_IO_DEVICE_ERROR;
            retry = TRUE;
        }

        if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG)irpStack->Parameters.Others.Argument4-1))) {

            //
            // Retry request. If the class driver has supplied a StartIo,
            // call it directly for retries.
            //

            DebugPrint((1, "Retry request %lx\n", Irp));

            /*
            if (!deviceExtension->ClassStartIo) {
                RetryRequest(DeviceObject, Irp, srb, TRUE);
            } else {
                deviceExtension->ClassStartIo(DeviceObject, Irp);
            }
            */

            RetryRequest(DeviceObject, Irp, srb, TRUE);

            return STATUS_MORE_PROCESSING_REQUIRED;
        }



    } else {

        //
        // Set status for successful request.
        //

        status = STATUS_SUCCESS;

    } // end if (SRB_STATUS(srb->SrbStatus) ...

    //
    // Return SRB to list.
    //

    ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
                                srb);

    //
    // Set status in completing IRP.
    //

    Irp->IoStatus.Status = status;

    DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial xfer IRP %lx\n", Irp));

    //
    // Get next stack location. This original request is unused
    // except to keep track of the completing partial IRPs so the
    // stack location is valid.
    //

    irpStack = IoGetNextIrpStackLocation(originalIrp);

    //
    // Update status only if error so that if any partial transfer
    // completes with error, then the original IRP will return with
    // error. If any of the asynchronous partial transfer IRPs fail,
    // with an error then the original IRP will return 0 bytes transfered.
    // This is an optimization for successful transfers.
    //

    if (!NT_SUCCESS(status)) {

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

        //
        // Set the hard error if necessary.
        //

        if (IoIsErrorUserInduced(status)) {

            //
            // Store DeviceObject for filesystem.
            //

            IoSetHardErrorOrVerifyDevice(originalIrp, DeviceObject);
        }
    }

    //
    // Decrement and get the count of remaining IRPs.
    //

    irpCount = InterlockedDecrement((PLONG)&irpStack->Parameters.Others.Argument1);

    DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial IRPs left %d\n",
                irpCount));

    //
    // Old bug could cause irp count to negative
    //

    ASSERT(irpCount >= 0);

    if (irpCount == 0) {

        //
        // All partial IRPs have completed.
        //

        DebugPrint((2,
                 "ScsiClassIoCompleteAssociated: All partial IRPs complete %lx\n",
                 originalIrp));

        IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);

        //
        // If the class driver has supplied a startio, start the
        // next request.
        //

        if (deviceExtension->ClassStartIo) {
            IoStartNextPacket(DeviceObject, FALSE);
        }
    }

    //
    // Deallocate IRP and indicate the I/O system should not attempt any more
    // processing.
    //

    IoFreeIrp(Irp);
    return STATUS_MORE_PROCESSING_REQUIRED;

} // end ScsiClassIoCompleteAssociated()


NTSTATUS
STDCALL
ScsiClassSendSrbSynchronous(
    PDEVICE_OBJECT DeviceObject,
    PSCSI_REQUEST_BLOCK Srb,
    PVOID BufferAddress,
    ULONG BufferLength,
    BOOLEAN WriteToDevice
    )

/*++

Routine Description:

    This routine is called by SCSI device controls to complete an
    SRB and send it to the port driver synchronously (ie wait for
    completion). The CDB is already completed along with the SRB CDB
    size and request timeout value.

Arguments:

    DeviceObject - Supplies the device object which represents the logical
        unit.

    Srb - Supplies a partially initialized SRB. The SRB cannot come from zone.

    BufferAddress - Supplies the address of the buffer.

    BufferLength - Supplies the length in bytes of the buffer.

    WriteToDevice - Indicates the data should be transfer to the device.

Return Value:

    Nt status indicating the final results of the operation.

--*/

{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    IO_STATUS_BLOCK ioStatus;
    ULONG controlType;
    PIRP irp;
    PIO_STACK_LOCATION irpStack;
    KEVENT event;
    PUCHAR senseInfoBuffer;
    ULONG retryCount = MAXIMUM_RETRIES;
    NTSTATUS status;
    BOOLEAN retry;

    PAGED_CODE();

    //
    // Write length to SRB.
    //

    Srb->Length = SCSI_REQUEST_BLOCK_SIZE;

    //
    // Set SCSI bus address.
    //

    Srb->PathId = deviceExtension->PathId;
    Srb->TargetId = deviceExtension->TargetId;
    Srb->Lun = deviceExtension->Lun;
    Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;

    //
    // 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] |= deviceExtension->Lun << 5;

    //
    // Enable auto request sense.
    //

    Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;

    //
    // Sense buffer is in aligned nonpaged pool.
    //

    senseInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

    if (senseInfoBuffer == NULL) {

        DebugPrint((1,
            "ScsiClassSendSrbSynchronous: Can't allocate request sense buffer\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    Srb->SenseInfoBuffer = senseInfoBuffer;
    Srb->DataBuffer = BufferAddress;

    //
    // Start retries here.
    //

retry:

    //
    // Set the event object to the unsignaled state.
    // It will be used to signal request completion.
    //

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Set controlType and Srb direction flags.
    //

    if (BufferAddress != NULL) {

        if (WriteToDevice) {

            controlType = IOCTL_SCSI_EXECUTE_OUT;
            Srb->SrbFlags = SRB_FLAGS_DATA_OUT;

        } else {

            controlType = IOCTL_SCSI_EXECUTE_IN;
            Srb->SrbFlags = SRB_FLAGS_DATA_IN;

        }

    } else {

        BufferLength = 0;
        controlType = IOCTL_SCSI_EXECUTE_NONE;
        Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
    }

    //
    // Build device I/O control request with data transfer.
    //

    irp = IoBuildDeviceIoControlRequest(controlType,
                                        deviceExtension->PortDeviceObject,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?