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

📄 isr.cpp

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

    if (m_ReadBufferBase != m_InterruptReadBuffer) 
    {
        // Increment the following value so
        // that the interval timer (if one exists
        // for this read) can know that a character
        // has been read.
        m_ReadByIsr++;

        // We are in the user buffer.  Place the
        // character into the buffer.  See if the
        // read is complete.

        *m_CurrentCharSlot = CharToPut;

        if (m_CurrentCharSlot == m_LastCharSlot) 
        {
            // We've filled up the users buffer.
            // Switch back to the interrupt buffer
            // and send off a DPC to Complete the read.
            //
            // It is inherent that when we were using
            // a user buffer that the interrupt buffer
            // was empty.

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

            m_CurrentReadIrp.Information() = m_CurrentReadIrp.ReadLength() ;
            
            m_KdDpc_CompleteRead.InsertQueue();
        } 
        else 
        {
            // Not done with the users read.
            m_CurrentCharSlot++;
        }
    }
    else 
    {
        // We need to see if we reached our flow
        // control threshold.  If we have then
        // we turn on whatever flow control the
        // owner has specified.  If no flow
        // control was specified, well..., we keep
        // trying to receive characters and hope that
        // we have enough room.  Note that no matter
        // what flow control protocol we are using, it
        // will not prevent us from reading whatever
        // characters are available.
        if ((m_HandFlow.ControlHandShake & SERIAL_DTR_MASK) ==
            SERIAL_DTR_HANDSHAKE) 
        {
            // If we are already doing a
            // dtr hold then we don't have
            // to do anything else.
            if (!(m_RXHolding & SERIAL_RX_DTR)) 
            {
                if ((m_BufferSize - m_HandFlow.XoffLimit)
                    <= (m_CharsInInterruptBuffer+1)) 
                {
                    m_RXHolding |= SERIAL_RX_DTR;
                    ClrDTR();

                }
            }
        }

        if ((m_HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
            SERIAL_RTS_HANDSHAKE) 
        {
            // If we are already doing a
            // rts hold then we don't have
            // to do anything else.
            if (!(m_RXHolding & SERIAL_RX_RTS)) 
            {
                if ((m_BufferSize - m_HandFlow.XoffLimit)
                    <= (m_CharsInInterruptBuffer+1)) 
                {
                    m_RXHolding |= SERIAL_RX_RTS;
                    ClrRTS();
                }
            }
        }

        if (m_HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) 
        {
            // If we are already doing a
            // xoff hold then we don't have
            // to do anything else.
            if (!(m_RXHolding & SERIAL_RX_XOFF)) 
            {
                if ((m_BufferSize - m_HandFlow.XoffLimit)
                    <= (m_CharsInInterruptBuffer+1)) 
                {
                    m_RXHolding |= SERIAL_RX_XOFF;
                    // If necessary cause an
                    // off to be sent.
                    ProdXonXoff(FALSE);
                }
            }
        }

        if (m_CharsInInterruptBuffer < m_BufferSize) 
        {
            *m_CurrentCharSlot = CharToPut;
            m_CharsInInterruptBuffer++;

            // If we've become 80% full on this character
            // and this is an interesting event, note it.
            if (m_CharsInInterruptBuffer == m_BufferSizePt8) 
            {
                if (m_IsrWaitMask & SERIAL_EV_RX80FULL) 
                {
                    m_HistoryMask |= SERIAL_EV_RX80FULL;

                    if (m_IrpMaskLocation) 
                    {
                        *m_IrpMaskLocation = m_HistoryMask;
                        m_IrpMaskLocation = NULL;
                        m_HistoryMask = 0;

                        m_CurrentWaitIrp.Information() = sizeof(ULONG);
                        m_KdDpc_CommWait.InsertQueue();
                    }
                }
            }

            // Point to the next available space
            // for a received character.  Make sure
            // that we wrap around to the beginning
            // of the buffer if this last character
            // received was placed at the last slot
            // in the buffer.

            if (m_CurrentCharSlot == m_LastCharSlot)
                m_CurrentCharSlot = m_InterruptReadBuffer;
            else
                m_CurrentCharSlot++;
        } 
        else 
        {
            // We have a new character but no room for it.

            m_PerfStats.BufferOverrunErrorCount++;
            m_ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN;

            if (m_HandFlow.FlowReplace & SERIAL_ERROR_CHAR) 
            {
                // valid place for a character.  Be careful!,
                // that place might not be the previous location!
                if (m_CurrentCharSlot == m_InterruptReadBuffer) 
                {
                    *(m_InterruptReadBuffer+ (m_BufferSize-1)) =
                        m_SpecialChars.ErrorChar;
                }
                else 
                    *(m_CurrentCharSlot-1) = m_SpecialChars.ErrorChar;
            }

            // If the application has requested it, abort all reads
            // and writes on an error.

            if (m_HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) 
                m_KdDpc_CommError.InsertQueue();
        }
    }
}

UCHAR KdSerialDevice::ProcessLSR()

/*++

Routine Description:

    This routine, which only runs at device level, reads the
    ISR and totally processes everything that might have
    changed.

Return Value:

    The value of the line status register.

--*/

{
    UCHAR LineStatus = m_pController->ReadByte(LINE_STATUS_REGISTER);

    m_HoldingEmpty = !!(LineStatus & SERIAL_LSR_THRE);

    // If the line status register is just the fact that
    // the transmit registers are empty or a character is
    // received then we want to reread the interrupt
    // identification register so that we just pick up that.

    if (LineStatus & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT
                       | SERIAL_LSR_DR)) 
    {

        // We have some sort of data problem in the receive.
        // For any of these errors we may abort all current
        // reads and writes.
        //
        //
        // If we are inserting the value of the line status
        // into the data stream then we should put the escape
        // character in now.

        if (m_EscapeChar) 
        {
            PutChar(m_EscapeChar);

            PutChar(
                (UCHAR)((LineStatus & SERIAL_LSR_DR) ?
                    (SERIAL_LSRMST_LSR_DATA) : (SERIAL_LSRMST_LSR_NODATA))
                );

            PutChar(LineStatus);

            if (LineStatus & SERIAL_LSR_DR) 
            {
                m_PerfStats.ReceivedCount++;
                PutChar(m_pController->ReadByte(RECEIVE_BUFFER_REGISTER));
            }
        }

        if (LineStatus & SERIAL_LSR_OE) 
        {
            m_PerfStats.SerialOverrunErrorCount++;
            m_ErrorWord |= SERIAL_ERROR_OVERRUN;

            if (m_HandFlow.FlowReplace & SERIAL_ERROR_CHAR) 
            {
                PutChar(m_SpecialChars.ErrorChar);
                if (LineStatus & SERIAL_LSR_DR)
                {
                    m_PerfStats.ReceivedCount++;
                    m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);
                }
            } 
            else 
            {
                if (LineStatus & SERIAL_LSR_DR) 
                {
                    m_PerfStats.ReceivedCount++;
                    PutChar(m_pController->ReadByte(RECEIVE_BUFFER_REGISTER));
                }
            }
        }

        if (LineStatus & SERIAL_LSR_BI) 
        {
            m_ErrorWord |= SERIAL_ERROR_BREAK;
            if (m_HandFlow.FlowReplace & SERIAL_BREAK_CHAR)
                PutChar(m_SpecialChars.BreakChar);
        } 
        else 
        {
            // Framing errors only count if they
            // occur exclusive of a break being
            // received.
            if (LineStatus & SERIAL_LSR_PE) 
            {
                m_PerfStats.ParityErrorCount++;
                m_ErrorWord |= SERIAL_ERROR_PARITY;

                if (m_HandFlow.FlowReplace & SERIAL_ERROR_CHAR) 
                {
                    PutChar(m_SpecialChars.ErrorChar);
                    if (LineStatus & SERIAL_LSR_DR) 
                    {
                        m_PerfStats.ReceivedCount++;
                        m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);
                    }
                }
            }

            if (LineStatus & SERIAL_LSR_FE) 
            {
                m_PerfStats.FrameErrorCount++;
                m_ErrorWord |= SERIAL_ERROR_FRAMING;

                if (m_HandFlow.FlowReplace & SERIAL_ERROR_CHAR) 
                {
                    PutChar(m_SpecialChars.ErrorChar);
                    if (LineStatus & SERIAL_LSR_DR) 
                    {
                        m_PerfStats.ReceivedCount++;
                        m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);
                    }
                }
            }
        }

        // If the application has requested it,
        // abort all the reads and writes
        // on an error.

        if (m_HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) 
            m_KdDpc_CommError.InsertQueue();

        // Check to see if we have a wait
        // pending on the comm error events.  If we
        // do then we schedule a dpc to satisfy
        // that wait.

        if (m_IsrWaitMask) 
        {
            if ((m_IsrWaitMask & SERIAL_EV_ERR) &&
                (LineStatus & (SERIAL_LSR_OE |
                               SERIAL_LSR_PE |
                               SERIAL_LSR_FE))) 
            {
                m_HistoryMask |= SERIAL_EV_ERR;
            }

            if ((m_IsrWaitMask & SERIAL_EV_BREAK) &&
                (LineStatus & SERIAL_LSR_BI)) 
            {
                m_HistoryMask |= SERIAL_EV_BREAK;
            }

            if (m_IrpMaskLocation && m_HistoryMask) 
            {
                *m_IrpMaskLocation =  m_HistoryMask;
                m_IrpMaskLocation = NULL;
                m_HistoryMask = 0;

                m_CurrentWaitIrp.Information() = sizeof(ULONG);
                m_KdDpc_CommWait.InsertQueue();
            }
        }

        if (LineStatus & SERIAL_LSR_THRE) 
        {
            // There is a hardware bug in some versions
            // of the 16450 and 550.  If THRE interrupt
            // is pending, but a higher interrupt comes
            // in it will only return the higher and
            // *forget* about the THRE.
            //
            // A suitable workaround - whenever we
            // are *all* done reading line status
            // of the device we check to see if the
            // transmit holding register is empty.  If it is
            // AND we are currently transmitting data
            // enable the interrupts which should cause
            // an interrupt indication which we quiet
            // when we read the interrupt id register.

            if (m_WriteLength | m_TransmitImmediate) 
            {
                DISABLE_ALL_INTERRUPTS(m_pController);
                ENABLE_ALL_INTERRUPTS(m_pController);
            }
        }
    }
    return LineStatus;
}

⌨️ 快捷键说明

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