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

📄 utils.c

📁 NXP产品LPC23XX的开发板的源文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation

Module Name:

    utils.c

Abstract:

    This module contains code that perform queueing and completion
    manipulation on requests.  Also module generic functions such
    as error logging.

Author:

    Anthony V. Ercolano 26-Sep-1991
	Henry Tan			31-Jul-2000

Environment:

    Kernel mode

--*/

#include "wdm.h"
#include "stdarg.h"
#include "stdio.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "usbcom.h"


VOID
SerialRundownIrpRefs(
    IN PIRP *CurrentOpIrp,
    IN PKTIMER IntervalTimer,
    IN PKTIMER TotalTimer,
    IN PDEVICE_EXTENSION PDevExt
    );
/*
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGESER,SerialGetNextIrp)
#pragma alloc_text(PAGESER, SerialGetNextIrpLocked)
#pragma alloc_text(PAGESER,SerialTryToCompleteCurrent)
#pragma alloc_text(PAGESER,SerialStartOrQueue)
#pragma alloc_text(PAGESER,SerialCancelQueued)
#pragma alloc_text(PAGESER,SerialCompleteIfError)
#pragma alloc_text(PAGESER,SerialRundownIrpRefs)

#pragma alloc_text(PAGESRP0, SerialLogError)
#pragma alloc_text(PAGESRP0, SerialMarkHardwareBroken)
#endif
*/
static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};


VOID
SerialKillAllReadsOrWrites(
    IN PDEVICE_OBJECT DeviceObject,
    IN PLIST_ENTRY QueueToClean,
    IN PIRP *CurrentOpIrp
    )

/*++

Routine Description:

    This function is used to cancel all queued and the current irps
    for reads or for writes.

Arguments:

    DeviceObject - A pointer to the serial device object.

    QueueToClean - A pointer to the queue which we're going to clean out.

    CurrentOpIrp - Pointer to a pointer to the current irp.

Return Value:

    None.

--*/

{

    KIRQL cancelIrql;
    PDRIVER_CANCEL cancelRoutine;

    //
    // We acquire the cancel spin lock.  This will prevent the
    // irps from moving around.
    //

    IoAcquireCancelSpinLock(&cancelIrql);

    //
    // Clean the list from back to front.
    //

    while (!IsListEmpty(QueueToClean)) {

        PIRP currentLastIrp = CONTAINING_RECORD(
                                  QueueToClean->Blink,
                                  IRP,
                                  Tail.Overlay.ListEntry
                                  );

        RemoveEntryList(QueueToClean->Blink);

        cancelRoutine = currentLastIrp->CancelRoutine;
        currentLastIrp->CancelIrql = cancelIrql;
        currentLastIrp->CancelRoutine = NULL;
        currentLastIrp->Cancel = TRUE;

        cancelRoutine(
            DeviceObject,
            currentLastIrp
            );

        IoAcquireCancelSpinLock(&cancelIrql);

    }

    //
    // The queue is clean.  Now go after the current if
    // it's there.
    //

    if (*CurrentOpIrp) {


        cancelRoutine = (*CurrentOpIrp)->CancelRoutine;
        (*CurrentOpIrp)->Cancel = TRUE;

        //
        // If the current irp is not in a cancelable state
        // then it *will* try to enter one and the above
        // assignment will kill it.  If it already is in
        // a cancelable state then the following will kill it.
        //

        if (cancelRoutine) {

            (*CurrentOpIrp)->CancelRoutine = NULL;
            (*CurrentOpIrp)->CancelIrql = cancelIrql;

            //
            // This irp is already in a cancelable state.  We simply
            // mark it as canceled and call the cancel routine for
            // it.
            //

            cancelRoutine(
                DeviceObject,
                *CurrentOpIrp
                );

        } else {

            IoReleaseCancelSpinLock(cancelIrql);

        }

    } else {

        IoReleaseCancelSpinLock(cancelIrql);

    }

}


VOID
SerialGetNextIrp(
    IN PIRP *CurrentOpIrp,
    IN PLIST_ENTRY QueueToProcess,
    OUT PIRP *NextIrp,
    IN BOOLEAN CompleteCurrent,
    IN PDEVICE_EXTENSION extension
    )

/*++

Routine Description:

    This function is used to make the head of the particular
    queue the current irp.  It also completes the what
    was the old current irp if desired.

Arguments:

    CurrentOpIrp - Pointer to a pointer to the currently active
                   irp for the particular work list.  Note that
                   this item is not actually part of the list.

    QueueToProcess - The list to pull the new item off of.

    NextIrp - The next Irp to process.  Note that CurrentOpIrp
              will be set to this value under protection of the
              cancel spin lock.  However, if *NextIrp is NULL when
              this routine returns, it is not necessaryly true the
              what is pointed to by CurrentOpIrp will also be NULL.
              The reason for this is that if the queue is empty
              when we hold the cancel spin lock, a new irp may come
              in immediately after we release the lock.

    CompleteCurrent - If TRUE then this routine will complete the
                      irp pointed to by the pointer argument
                      CurrentOpIrp.

Return Value:

    None.

--*/

{

    KIRQL oldIrql;
//    //SERIAL_LOCKED_PAGED_CODE();


    IoAcquireCancelSpinLock(&oldIrql);
    SerialGetNextIrpLocked(CurrentOpIrp, QueueToProcess, NextIrp,
                           CompleteCurrent, extension, oldIrql);
}


VOID 
SerialGetNextIrpLocked(
    IN PIRP *CurrentOpIrp,
    IN PLIST_ENTRY QueueToProcess,
    OUT PIRP *NextIrp,
    IN BOOLEAN CompleteCurrent,
    IN PDEVICE_EXTENSION extension,
    IN KIRQL OldIrql
    )

/*++

Routine Description:

    This function is used to make the head of the particular
    queue the current irp.  It also completes the what
    was the old current irp if desired.  The difference between
    this and SerialGetNextIrp() is that for this we assume the caller
    holds the cancel spinlock and we should release it when we're done.

Arguments:

    CurrentOpIrp - Pointer to a pointer to the currently active
                   irp for the particular work list.  Note that
                   this item is not actually part of the list.

    QueueToProcess - The list to pull the new item off of.

    NextIrp - The next Irp to process.  Note that CurrentOpIrp
              will be set to this value under protection of the
              cancel spin lock.  However, if *NextIrp is NULL when
              this routine returns, it is not necessaryly true the
              what is pointed to by CurrentOpIrp will also be NULL.
              The reason for this is that if the queue is empty
              when we hold the cancel spin lock, a new irp may come
              in immediately after we release the lock.

    CompleteCurrent - If TRUE then this routine will complete the
                      irp pointed to by the pointer argument
                      CurrentOpIrp.

    OldIrql - IRQL which the cancel spinlock was acquired at and what we
              should restore it to.

Return Value:

    None.

--*/

{

    PIRP oldIrp;

//    //SERIAL_LOCKED_PAGED_CODE();


    oldIrp = *CurrentOpIrp;

#if DBG
    if (oldIrp) {

        if (CompleteCurrent) {

            ASSERT(!oldIrp->CancelRoutine);

        }

    }
#endif

    //
    // Check to see if there is a new irp to start up.
    //

    if (!IsListEmpty(QueueToProcess)) {

        PLIST_ENTRY headOfList;

        headOfList = RemoveHeadList(QueueToProcess);

        *CurrentOpIrp = CONTAINING_RECORD(
                            headOfList,
                            IRP,
                            Tail.Overlay.ListEntry
                            );

        IoSetCancelRoutine(
            *CurrentOpIrp,
            NULL
            );

    } else {

        *CurrentOpIrp = NULL;

    }


    *NextIrp = *CurrentOpIrp;
    IoReleaseCancelSpinLock(OldIrql);


    if (CompleteCurrent) {

        if (oldIrp) {

            SerialDump(
                SERIRPPATH,
                ("SERIAL: Complete Irp: %x\n",oldIrp)
                );

            SerialCompleteRequest(extension, oldIrp, IO_SERIAL_INCREMENT);

        }
    }

}


void 
SerialTryToCompleteCurrent(
    IN PDEVICE_EXTENSION Extension,
    IN PKSYNCHRONIZE_ROUTINE SynchRoutine OPTIONAL,
    IN KIRQL IrqlForRelease,
    IN NTSTATUS StatusToUse,
    IN PIRP *CurrentOpIrp,
    IN PLIST_ENTRY QueueToProcess OPTIONAL,
    IN PKTIMER IntervalTimer OPTIONAL,
    IN PKTIMER TotalTimer OPTIONAL,
    IN PSERIAL_START_ROUTINE Starter OPTIONAL,
    IN PSERIAL_GET_NEXT_ROUTINE GetNextIrp OPTIONAL,
    IN LONG RefType
    )

/*++

Routine Description:

    This routine attempts to kill all of the reasons there are
    references on the current read/write.  If everything can be killed
    it will complete this read/write and try to start another.

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

Arguments:

    Extension - Simply a pointer to the device extension.

    SynchRoutine - A routine that will synchronize with the isr
                   and attempt to remove the knowledge of the
                   current irp from the isr.  NOTE: This pointer
                   can be null.

    IrqlForRelease - This routine is called with the cancel spinlock held.
                     This is the irql that was current when the cancel
                     spinlock was acquired.

    StatusToUse - The irp's status field will be set to this value, if
                  this routine can complete the irp.


Return Value:

    None.

--*/

{

//   //SERIAL_LOCKED_PAGED_CODE();

    //
    // We can decrement the reference to "remove" the fact
    // that the caller no longer will be accessing this irp.
    //

    SERIAL_CLEAR_REFERENCE(
        *CurrentOpIrp,
        RefType
        );

    if (SynchRoutine) {
/*
        KeSynchronizeExecution(
            Extension->Interrupt,
            SynchRoutine,
            Extension
            );
*/
		SynchRoutine(Extension);
    }

    //
    // Try to run down all other references to this irp.
    //

    SerialRundownIrpRefs(
        CurrentOpIrp,
        IntervalTimer,
        TotalTimer,
        Extension
        );

    //
    // See if the ref count is zero after trying to kill everybody else.
    //

    if (!SERIAL_REFERENCE_COUNT(*CurrentOpIrp)) {

        PIRP newIrp;


        //
        // The ref count was zero so we should complete this
        // request.
        //
        // The following call will also cause the current irp to be
        // completed.
        //

        (*CurrentOpIrp)->IoStatus.Status = StatusToUse;

        if (StatusToUse == STATUS_CANCELLED) {

            (*CurrentOpIrp)->IoStatus.Information = 0;

        }

        if (GetNextIrp) {

            IoReleaseCancelSpinLock(IrqlForRelease);
            GetNextIrp(
                CurrentOpIrp,
                QueueToProcess,
                &newIrp,
                TRUE,
                Extension
                );

            if (newIrp) {

                Starter(Extension);

            }

        } else {

            PIRP oldIrp = *CurrentOpIrp;

            //
            // There was no get next routine.  We will simply complete
            // the irp.  We should make sure that we null out the
            // pointer to the pointer to this irp.
            //

            *CurrentOpIrp = NULL;

            IoReleaseCancelSpinLock(IrqlForRelease);
            SerialDump(
                SERIRPPATH,
                ("SERIAL: Complete Irp: %x\n",oldIrp)
                );
            SerialCompleteRequest(Extension, oldIrp, IO_SERIAL_INCREMENT);
        }

    } else {

        IoReleaseCancelSpinLock(IrqlForRelease);

    }

}


VOID
SerialRundownIrpRefs(IN PIRP *CurrentOpIrp, IN PKTIMER IntervalTimer OPTIONAL,
                     IN PKTIMER TotalTimer OPTIONAL,
                     IN PDEVICE_EXTENSION PDevExt)

/*++

Routine Description:

    This routine runs through the various items that *could*
    have a reference to the current read/write.  It try's to kill
    the reason.  If it does succeed in killing the reason it
    will decrement the reference count on the irp.

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

Arguments:

    CurrentOpIrp - Pointer to a pointer to current irp for the
                   particular operation.

    IntervalTimer - Pointer to the interval timer for the operation.
                    NOTE: This could be null.

    TotalTimer - Pointer to the total timer for the operation.
                 NOTE: This could be null.

    PDevExt - Pointer to device extension

Return Value:

    None.

--*/


{

   ////SERIAL_LOCKED_PAGED_CODE();

    //
    // This routine is called with the cancel spin lock held
    // so we know only one thread of execution can be in here
    // at one time.
    //

    //
    // First we see if there is still a cancel routine.  If
    // so then we can decrement the count by one.
    //

    if ((*CurrentOpIrp)->CancelRoutine) {

        SERIAL_CLEAR_REFERENCE(
            *CurrentOpIrp,
            SERIAL_REF_CANCEL
            );

        IoSetCancelRoutine(
            *CurrentOpIrp,
            NULL
            );

    }

    if (IntervalTimer) {

        //
        // Try to cancel the operations interval timer.  If the operation
        // returns true then the timer did have a reference to the
        // irp.  Since we've canceled this timer that reference is
        // no longer valid and we can decrement the reference count.
        //
        // If the cancel returns false then this means either of two things:
        //
        // a) The timer has already fired.
        //
        // b) There never was an interval timer.
        //
        // In the case of "b" there is no need to decrement the reference
        // count since the "timer" never had a reference to it.
        //
        // In the case of "a", then the timer itself will be coming
        // along and decrement it's reference.  Note that the caller
        // of this routine might actually be the this timer, but it
        // has already decremented the reference.
        //

        if (SerialCancelTimer(IntervalTimer, PDevExt)) {

            SERIAL_CLEAR_REFERENCE(
                *CurrentOpIrp,
                SERIAL_REF_INT_TIMER
                );

        }

    }

⌨️ 快捷键说明

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