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

📄 openclos.cpp

📁 这个是串口驱动程序开发包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*++

Abstract:

    This module contains the code that is very specific to
    opening, closing, and cleaning up in the serial driver.

--*/

#include "precomp.h"

// Just a bogus little routine to make sure that we
// can synch with the ISR.
BOOLEAN KdSerialDevice::NullSynch()
{
    return FALSE;
}

NTSTATUS KdSerialDevice::DispatchCreate(IN KdIrp &Irp)
/*++

Routine Description:

    We connect up to the interrupt for the create/open and initialize
    the structures needed to maintain an open for a device.

Arguments:

    Irp - Pointer to the IRP for the current request

Return Value:

    The function value is the final status of the call

--*/
{
    NTSTATUS localStatus;

    DebugDump(DBG_DIAG6, ("Dispatch entry for: %x\n",Irp) );
    DebugDump(DBG_DIAG3, ("In DispatchOpen\n") );

    // Before we do anything, let's make sure they aren't trying
    // to create a directory.  This is a silly, but what's a driver to do!?

    if (Irp.GetStackLocation(STACK_NEXT)->Parameters.Create.Options & FILE_DIRECTORY_FILE) 
    {
        Irp.Status() = STATUS_NOT_A_DIRECTORY;
        Irp.Information() = 0;

        DebugDump(DBG_DIAG6, ("Complete Irp: %x\n",Irp) );
        Irp.Complete();
        return STATUS_NOT_A_DIRECTORY;
    }

    // Create a buffer for the RX data when no reads are outstanding.

    m_InterruptReadBuffer = NULL;
    m_BufferSize = 0;

    switch (MmQuerySystemSize()) 
    {
        case MmLargeSystem:
            m_BufferSize = 4096;
            m_InterruptReadBuffer = (PUCHAR) ExAllocatePool(NonPagedPool, m_BufferSize);
            if (m_InterruptReadBuffer)
                break;

        case MmMediumSystem:
            m_BufferSize = 1024;
            m_InterruptReadBuffer = (PUCHAR)ExAllocatePool(NonPagedPool, m_BufferSize);
            if (m_InterruptReadBuffer) 
                break;

        case MmSmallSystem:
            m_BufferSize = 128;
            m_InterruptReadBuffer = (PUCHAR)ExAllocatePool(NonPagedPool, m_BufferSize);
    }

    if (!m_InterruptReadBuffer) 
    {
        m_BufferSize = 0;
        Irp.Status() = STATUS_INSUFFICIENT_RESOURCES;
        Irp.Information() = 0;

        DebugDump(DBG_DIAG6, ("Complete Irp: %x\n",Irp) );
        Irp.Complete();
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // Ok, it looks like we really are going to open.  Lock down the driver.

    // On a new open we "flush" the read queue by initializing the
    // count of characters.

    m_CharsInInterruptBuffer = 0;
    m_LastCharSlot = m_InterruptReadBuffer +
                              (m_BufferSize - 1);

    m_ReadBufferBase = m_InterruptReadBuffer;
    m_CurrentCharSlot = m_InterruptReadBuffer;
    m_FirstReadableChar = m_InterruptReadBuffer;

    m_TotalCharsQueued = 0;

    // We set up the default xon/xoff limits.

    m_HandFlow.XoffLimit = m_BufferSize >> 3;
    m_HandFlow.XonLimit = m_BufferSize >> 1;

    m_BufferSizePt8 = ((3*(m_BufferSize>>2))+
                                   (m_BufferSize>>4));

    m_IrpMaskLocation = NULL;
    m_HistoryMask = 0;
    m_IsrWaitMask = 0;

    m_SendXonChar = FALSE;
    m_SendXoffChar = FALSE;

    // Clear out the statistics.

    m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) ClearStats);

    // The escape char replacement must be reset upon every open.

    m_EscapeChar = 0;

    if (!m_PermitShare) 
    {
        if (!m_InterruptShareable) 
            m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK_PARM) CheckOpen, &Irp.Status());
        else 
        {
            m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) MarkOpen);
            Irp.Status() = STATUS_SUCCESS;
        }
    } 
    else 
    {
        // Synchronize with the ISR and let it know that the device
        // has been successfully opened.
        m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) MarkOpen);
        Irp.Status() = STATUS_SUCCESS;
    }

    localStatus = Irp.Status();
    Irp.Information() =0L;

    DebugDump(DBG_DIAG6, ("Complete Irp: %x\n",Irp) );
    Irp.Complete();

    return localStatus;
}

NTSTATUS KdSerialDevice::DispatchClose(KdIrp &Irp)
/*++
Routine Description:
    We simply disconnect the interrupt for now.

Arguments:
    Irp - Pointer to the IRP for the current request

Return Value:
    The function value is the final status of the call
--*/
{
    // This "timer value" is used to wait 10 character times
    // after the hardware is empty before we actually "run down"
    // all of the flow control/break junk.
    LARGE_INTEGER tenCharDelay;

    // Holds a character time.
    LARGE_INTEGER charTime;

    DebugDump(DBG_DIAG6, ("Dispatch entry for: %x\n",Irp) );
    DebugDump(DBG_DIAG3, ("In DispatchClose\n") );

    charTime.QuadPart = -GetCharTime().QuadPart;

    // Do this now so that if the isr gets called it won't do anything
    // to cause more chars to get sent.  We want to run down the hardware.

    m_DeviceIsOpened = FALSE;

    // Synchronize with the isr to turn off break if it
    // is already on.

    m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) TurnOffBreak);

    // Wait until all characters have been emptied out of the hardware.

    while ((m_pController->ReadByte(LINE_STATUS_REGISTER) &
            (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) !=
            (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) 
    {
        KeDelayExecutionThread(KernelMode, FALSE, &charTime);
    }

    // Synchronize with the ISR to let it know that interrupts are
    // no longer important.

    m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) MarkClose);

    // If the driver has automatically transmitted an Xoff in
    // the context of automatic receive flow control then we
    // should transmit an Xon.

    if (m_RXHolding & SERIAL_RX_XOFF) 
    {
        // Loop until the holding register is empty.
        while (!(m_pController->ReadByte(LINE_STATUS_REGISTER) & SERIAL_LSR_THRE)) 
            KeDelayExecutionThread(KernelMode, FALSE, &charTime);

        m_pController->WriteByte(TRANSMIT_HOLDING_REGISTER, m_SpecialChars.XonChar);

        // Wait until the character have been emptied out of the hardware.

        while ((m_pController->ReadByte(LINE_STATUS_REGISTER) &
                (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) !=
                (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) 
        {
            KeDelayExecutionThread(KernelMode, FALSE, &charTime);
        }
    }

    // The hardware is empty.  Delay 10 character times before
    // shut down all the flow control.

    tenCharDelay.QuadPart = charTime.QuadPart * 10;

    KeDelayExecutionThread(KernelMode, TRUE, &tenCharDelay);

    ClrDTR();

    // We have to be very careful how we clear the RTS line.
    // Transmit toggling might have been on at some point.
    //
    // We know that there is nothing left that could start
    // out the "polling"  execution path.  We need to
    // check the counter that indicates that the execution
    // path is active.  If it is then we loop delaying one
    // character time.  After each delay we check to see if
    // the counter has gone to zero.  When it has we know that
    // the execution path should be just about finished.  We
    // make sure that we still aren't in the routine that
    // synchronized execution with the ISR by synchronizing
    // ourselves with the ISR.

    if (m_CountOfTryingToLowerRTS) 
    {
        do {
            KeDelayExecutionThread(KernelMode, FALSE, &charTime);
        } while (m_CountOfTryingToLowerRTS);

        m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) NullSynch);

        // The execution path should no longer exist that
        // is trying to push down the RTS.  Well just
        // make sure it's down by falling through to
        // code that forces it down.
    }

    ClrRTS();

    // Clean out the holding reasons (since we are closed).

    m_RXHolding = 0;
    m_TXHolding = 0;

    // All is done.  The port has been disabled from interrupting
    // so there is no point in keeping the memory around.

⌨️ 快捷键说明

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