⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 怎样在win2000下构造驱动程序znsoft_Serial2000_demo.ZIP
💻 C
📖 第 1 页 / 共 4 页
字号:
                }

            } else {

                //
                // The irp might go under control of the isr.  It
                // won't hurt to initialize the reference count
                // right now.
                //

                SERIAL_INIT_REFERENCE(Extension->CurrentReadIrp);

                IoAcquireCancelSpinLock(&oldIrql);

                //
                // We need to see if this irp should be canceled.
                //

                if (Extension->CurrentReadIrp->Cancel) {

                    IoReleaseCancelSpinLock(oldIrql);
                    KeReleaseSpinLock(
                        &Extension->ControlLock,
                        controlIrql
                        );
                    Extension->CurrentReadIrp->IoStatus.Status =
                        STATUS_CANCELLED;
                    Extension->CurrentReadIrp->IoStatus.Information = 0;

                    if (!setFirstStatus) {

                        firstStatus = STATUS_CANCELLED;
                        setFirstStatus = TRUE;

                    }

                } else {

                    //
                    // If we are supposed to crunch the read down to
                    // one character, then update the read length
                    // in the irp and truncate the number needed for
                    // read down to one. Note that if we are doing
                    // this crunching, then the information must be
                    // zero (or we would have completed above) and
                    // the number needed for the read must still be
                    // equal to the read length.
                    //

                    if (crunchDownToOne) {

                        ASSERT(
                            (!Extension->CurrentReadIrp->IoStatus.Information)
                            &&
                            (Extension->NumberNeededForRead ==
                                IoGetCurrentIrpStackLocation(
                                    Extension->CurrentReadIrp
                                    )->Parameters.Read.Length)
                            );

                        Extension->NumberNeededForRead = 1;
                        IoGetCurrentIrpStackLocation(
                            Extension->CurrentReadIrp
                            )->Parameters.Read.Length = 1;

                    }

                    //
                    // We still need to get more characters for this read.
                    // synchronize with the isr so that we can update the
                    // number of characters and if necessary it will have the
                    // isr switch to copying into the users buffer.
                    //

                    KeSynchronizeExecution(
                        Extension->Interrupt,
                        SerialUpdateAndSwitchToUser,
                        &updateChar
                        );

                    if (!updateChar.Completed) {

                        //
                        // The irp still isn't complete.  The
                        // completion routines will end up reinvoking
                        // this routine.  So we simply leave.
                        //
                        // First thought we should start off the total
                        // timer for the read and increment the reference
                        // count that the total timer has on the current
                        // irp.  Note that this is safe, because even if
                        // the io has been satisfied by the isr it can't
                        // complete yet because we still own the cancel
                        // spinlock.
                        //

                        if (useTotalTimer) {

                            SERIAL_SET_REFERENCE(
                                Extension->CurrentReadIrp,
                                SERIAL_REF_TOTAL_TIMER
                                );

                            SerialSetTimer(
                                &Extension->ReadRequestTotalTimer,
                                totalTime,
                                &Extension->TotalReadTimeoutDpc,
                                Extension
                                );

                        }

                        if (useIntervalTimer) {

                            SERIAL_SET_REFERENCE(
                                Extension->CurrentReadIrp,
                                SERIAL_REF_INT_TIMER
                                );

                            KeQuerySystemTime(
                                &Extension->LastReadTime
                                );
                            SerialSetTimer(
                                &Extension->ReadRequestIntervalTimer,
                                *Extension->IntervalTimeToUse,
                                &Extension->IntervalReadTimeoutDpc,
                                Extension
                                );

                        }

                        IoMarkIrpPending(Extension->CurrentReadIrp);
                        IoReleaseCancelSpinLock(oldIrql);
                        KeReleaseSpinLock(
                            &Extension->ControlLock,
                            controlIrql
                            );
                        if (!setFirstStatus) {

                            firstStatus = STATUS_PENDING;

                        }
                        return firstStatus;

                    } else {

                        IoReleaseCancelSpinLock(oldIrql);
                        KeReleaseSpinLock(
                            &Extension->ControlLock,
                            controlIrql
                            );
                        Extension->CurrentReadIrp->IoStatus.Status =
                            STATUS_SUCCESS;

                        if (!setFirstStatus) {

                            firstStatus = STATUS_SUCCESS;
                            setFirstStatus = TRUE;

                        }

                    }

                }

            }

        }

        //
        // Well the operation is complete.
        //

        SerialGetNextIrp(
            &Extension->CurrentReadIrp,
            &Extension->ReadQueue,
            &newIrp,
            TRUE,
            Extension
            );

    } while (newIrp);

    return firstStatus;

}

VOID
SerialCompleteRead(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemContext1,
    IN PVOID SystemContext2
    )

/*++

Routine Description:

    This routine is merely used to complete any read that
    ended up being used by the Isr.  It assumes that the
    status and the information fields of the irp are already
    correctly filled in.

Arguments:

    Dpc - Not Used.

    DeferredContext - Really points to the device extension.

    SystemContext1 - Not Used.

    SystemContext2 - Not Used.

Return Value:

    None.

--*/

{

    PSERIAL_DEVICE_EXTENSION extension = DeferredContext;
    KIRQL oldIrql;

    UNREFERENCED_PARAMETER(SystemContext1);
    UNREFERENCED_PARAMETER(SystemContext2);


    SerialDump(SERTRACECALLS, ("SERIAL: SerialCompleteRead\n"));


    IoAcquireCancelSpinLock(&oldIrql);

    //
    // We set this to indicate to the interval timer
    // that the read has completed.
    //
    // Recall that the interval timer dpc can be lurking in some
    // DPC queue.
    //

    extension->CountOnLastRead = SERIAL_COMPLETE_READ_COMPLETE;

    SerialTryToCompleteCurrent(
        extension,
        NULL,
        oldIrql,
        STATUS_SUCCESS,
        &extension->CurrentReadIrp,
        &extension->ReadQueue,
        &extension->ReadRequestIntervalTimer,
        &extension->ReadRequestTotalTimer,
        SerialStartRead,
        SerialGetNextIrp,
        SERIAL_REF_ISR
        );

    SerialDpcEpilogue(extension, Dpc);
}

VOID
SerialCancelCurrentRead(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )

/*++

Routine Description:

    This routine is used to cancel the current read.

Arguments:

    DeviceObject - Pointer to the device object for this device

    Irp - Pointer to the IRP to be canceled.

Return Value:

    None.

--*/

{

    PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
    SERIAL_LOCKED_PAGED_CODE();

    //
    // We set this to indicate to the interval timer
    // that the read has encountered a cancel.
    //
    // Recall that the interval timer dpc can be lurking in some
    // DPC queue.
    //

    extension->CountOnLastRead = SERIAL_COMPLETE_READ_CANCEL;

    SerialTryToCompleteCurrent(
        extension,
        SerialGrabReadFromIsr,
        Irp->CancelIrql,
        STATUS_CANCELLED,
        &extension->CurrentReadIrp,
        &extension->ReadQueue,
        &extension->ReadRequestIntervalTimer,
        &extension->ReadRequestTotalTimer,
        SerialStartRead,
        SerialGetNextIrp,
        SERIAL_REF_CANCEL
        );

}

BOOLEAN
SerialGrabReadFromIsr(
    IN PVOID Context
    )

/*++

Routine Description:

    This routine is used to grab (if possible) the irp from the
    isr.  If it finds that the isr still owns the irp it grabs
    the ipr away (updating the number of characters copied into the
    users buffer).  If it grabs it away it also decrements the
    reference count on the irp since it no longer belongs to the
    isr (and the dpc that would complete it).

    NOTE: This routine assumes that if the current buffer that the
          ISR is copying characters into is the interrupt buffer then
          the dpc has already been queued.

    NOTE: This routine is being called from KeSynchronizeExecution.

    NOTE: This routine assumes that it is called with the cancel spin
          lock held.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

    Always false.

--*/

{

    PSERIAL_DEVICE_EXTENSION extension = Context;
    SERIAL_LOCKED_PAGED_CODE();

    if (extension->ReadBufferBase !=
        extension->InterruptReadBuffer) {

        //
        // We need to set the information to the number of characters
        // that the read wanted minus the number of characters that
        // didn't get read into the interrupt buffer.
        //

        extension->CurrentReadIrp->IoStatus.Information =
            IoGetCurrentIrpStackLocation(
                extension->CurrentReadIrp
                )->Parameters.Read.Length -
            ((extension->LastCharSlot - extension->CurrentCharSlot) + 1);

        //
        // Switch back to the interrupt buffer.
        //

        extension->ReadBufferBase = extension->InterruptReadBuffer;
        extension->CurrentCharSlot = extension->InterruptReadBuffer;
        extension->FirstReadableChar = extension->InterruptReadBuffer;
        extension->LastCharSlot = extension->InterruptReadBuffer +
                                      (extension->BufferSize - 1);
        extension->CharsInInterruptBuffer = 0;

        SERIAL_CLEAR_REFERENCE(
            extension->CurrentReadIrp,
            SERIAL_REF_ISR
            );

    }

    return FALSE;

}

VOID
SerialReadTimeout(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemContext1,
    IN PVOID SystemContext2
    )

/*++

Routine Description:

    This routine is used to complete a read because its total
    timer has expired.

Arguments:

    Dpc - Not Used.

    DeferredContext - Really points to the device extension.

    SystemContext1 - Not Used.

    SystemContext2 - Not Used.

Return Value:

    None.

--*/

{

    PSERIAL_DEVICE_EXTENSION extension = DeferredContext;
    KIRQL oldIrql;

    UNREFERENCED_PARAMETER(SystemContext1);
    UNREFERENCED_PARAMETER(SystemContext2);


    SerialDump(SERTRACECALLS, ("SERIAL: SerialReadTimeout\n"));

    IoAcquireCancelSpinLock(&oldIrql);

    //
    // We set this to indicate to the interval timer
    // that the read has completed due to total timeout.
    //
    // Recall that the interval timer dpc can be lurking in some
    // DPC queue.
    //

    extension->CountOnLastRead = SERIAL_COMPLETE_READ_TOTAL;

    SerialTryToCompleteCurrent(
        extension,
        SerialGrabReadFromIsr,
        oldIrql,
        STATUS_TIMEOUT,
        &extension->CurrentReadIrp,
        &extension->ReadQueue,
        &extension->ReadRequestIntervalTimer,
        &extension->ReadRequestTotalTimer,
        SerialStartRead,
        SerialGetNextIrp,
        SERIAL_REF_TOTAL_TIMER
        );

    SerialDpcEpilogue(extension, Dpc);

}

BOOLEAN
SerialUpdateReadByIsr(
    IN PVOID Context
    )

/*++

Routine Description:

    This routine is used to update the count of characters read
    by the isr since the last interval timer experation.

    NOTE: This routine is being called from KeSynchronizeExecution.

    NOTE: This routine assumes that it is called with the cancel spin
          lock held.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

⌨️ 快捷键说明

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