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

📄 openclos.cpp

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

    m_BufferSize = 0;
    ExFreePool(m_InterruptReadBuffer);
    m_InterruptReadBuffer = NULL;

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

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

    // Unlock the pages.  If this is the last reference to the section
    // then the driver code will be flushed out.
    return STATUS_SUCCESS;
}

BOOLEAN KdSerialDevice::CheckOpen(IN PVOID Context)
/*++
Routine Description:
    This routine will traverse the circular doubly linked list
    of devices that are using the same interrupt object.  It will look
    for other devices that are open.  If it doesn't find any
    it will indicate that it is ok to open this device.

    If it finds another device open we have two cases:

        1) The device we are trying to open is on a multiport card.

           If the already open device is part of a multiport device
           this code will indicate it is ok to open.  We do this on the
           theory that the multiport devices are daisy chained
           and the cards can correctly arbitrate the interrupt
           line.  Note this assumption could be wrong.  Somebody
           could put two non-daisychained multiports on the
           same interrupt.  However, only a total clod would do
           such a thing, and in my opinion deserves everything they
           get.

        2) The device we are trying to open is not on a multiport card.

            We indicate that it is not ok to open.

Arguments:
    Context - This is a structure that contains a pointer to an NTSTATUS that 
              will indicate whether the device was opened or not.

Return Value:
    This routine always returns FALSE.

--*/

{
    NTSTATUS *status = (NTSTATUS *) Context;
    PLIST_ENTRY firstEntry = &m_CommonInterruptObject;
    PLIST_ENTRY currentEntry = firstEntry;
    PKdSerialDevice pCurrentDevice;

    do {
        pCurrentDevice = CONTAINING_RECORD(currentEntry,
                                           KdSerialDevice,
                                           m_CommonInterruptObject);
        if (pCurrentDevice->m_DeviceIsOpened) 
            break;

        currentEntry = pCurrentDevice->m_CommonInterruptObject.Flink;
    } while (currentEntry != firstEntry);

    if (currentEntry == firstEntry) 
    {

        // We searched the whole list and found no other opens
        // mark the status as successful and call the regular
        // opening routine.

        *status = STATUS_SUCCESS;
        MarkOpen();
    }
    else 
    {
        if (!m_PortOnAMultiportCard)
            *status = STATUS_SHARED_IRQ_BUSY;
        else 
        {
            if (!pCurrentDevice->m_PortOnAMultiportCard) 
                *status = STATUS_SHARED_IRQ_BUSY;
            else 
            {
                *status = STATUS_SUCCESS;
                MarkOpen();
            }
        }
    }
    return FALSE;
}

BOOLEAN KdSerialDevice::MarkOpen()
/*++
Routine Description:
    This routine merely sets a boolean to true to mark the fact that
    somebody opened the device and its worthwhile to pay attention
    to interrupts.

Return Value:
    This routine always returns FALSE.
--*/
{
    Reset();

    // Prepare for the opening by re-enabling interrupts.
    //
    // We do this my modifying the OUT2 line in the modem control.
    // In PC's this bit is "anded" with the interrupt line.
    //
    // For the Jensen, we will ALWAYS leave the line high.  That's
    // the way the hardware engineers want it.

    m_pController->WriteByte(MODEM_CONTROL_REGISTER,
        m_pController->ReadByte(MODEM_CONTROL_REGISTER) | SERIAL_MCR_OUT2);

    m_DeviceIsOpened = TRUE;
    m_ErrorWord = 0;
    return FALSE;
}

BOOLEAN KdSerialDevice::MarkClose()
/*++
Routine Description:
    This routine merely sets a boolean to false to mark the fact that
    somebody closed the device and it's no longer worthwhile to pay attention
    to interrupts.

Return Value:
    This routine always returns FALSE.
--*/
{
    // Prepare for the closing by stopping interrupts.
    //
    // We do this by adjusting the OUT2 line in the modem control.
    // In PC's this bit is "anded" with the interrupt line.
    //
    // The line should stay high on the Jensen because that's the
    // way the hardware engineers did it.

    if (!m_Jensen)
    {
        m_pController->WriteByte(MODEM_CONTROL_REGISTER,
            (m_pController->ReadByte(MODEM_CONTROL_REGISTER) & ~SERIAL_MCR_OUT2));
    }

    if (m_FifoPresent) 
        m_pController->WriteByte(FIFO_CONTROL_REGISTER ,0);
    m_DeviceIsOpened = FALSE;
    return FALSE;
}

NTSTATUS KdSerialDevice::DispatchCleanup(KdIrp &Irp)
/*++
Routine Description:
    This function is used to kill all longstanding IO operations.

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

Return Value:
    The function value is the final status of the call
--*/
{
    KIRQL oldIrql;

    DebugDump(DBG_DIAG6, ("Dispatch entry for: %x\n",Irp) );
    // First kill all the reads and writes.

    KillAllReadsOrWrites(&m_WriteQueue, &m_CurrentWriteIrp);
    KillAllReadsOrWrites(&m_ReadQueue, &m_CurrentReadIrp);

    // Next get rid of purges.
    KillAllReadsOrWrites(&m_PurgeQueue, &m_CurrentPurgeIrp);

    // Get rid of any mask operations.
    KillAllReadsOrWrites(&m_MaskQueue, &m_CurrentMaskIrp);

    // Now get rid a pending wait mask irp.
    IoAcquireCancelSpinLock(&oldIrql);

    if (m_CurrentWaitIrp) 
    {
        PDRIVER_CANCEL cancelRoutine;

        cancelRoutine = m_CurrentWaitIrp->CancelRoutine;
        m_CurrentWaitIrp->Cancel = TRUE;

        if (cancelRoutine) 
        {
            m_CurrentWaitIrp->CancelIrql = oldIrql;
            m_CurrentWaitIrp->CancelRoutine = NULL;

            cancelRoutine(
                m_pDeviceObject,
                m_CurrentWaitIrp
                );
        }
    } 
    else 
        IoReleaseCancelSpinLock(oldIrql);

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

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

LARGE_INTEGER KdSerialDevice::GetCharTime()
/*++
Routine Description:
    This function will return the number of 100 nanosecond intervals
    there are in one character time (based on the present form
    of flow control.

Return Value:
    100 nanosecond intervals in a character time.
--*/
{
    ULONG dataSize;
    ULONG paritySize;
    ULONG stopSize;
    ULONG charTime;
    ULONG bitTime;
    LARGE_INTEGER tmp;

    switch (m_LineControl & SERIAL_DATA_MASK)
    {
        case SERIAL_5_DATA:
            dataSize = 5;
            break;
        case SERIAL_6_DATA:
            dataSize = 6;
            break;
        case SERIAL_7_DATA:
            dataSize = 7;
            break;
        case SERIAL_8_DATA:
            dataSize = 8;
            break;
    }

    paritySize = 1;
    if ((m_LineControl & SERIAL_PARITY_MASK)==SERIAL_NONE_PARITY)
        paritySize = 0;

    if (m_LineControl & SERIAL_2_STOP) 
    {
        // Even if it is 1.5, for sanities sake were going
        // to say 2.
        stopSize = 2;
    }
    else 
        stopSize = 1;

    // First we calculate the number of 100 nanosecond intervals
    // are in a single bit time (Approximately).

    bitTime = (10000000+(m_CurrentBaud-1))/m_CurrentBaud;
    charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);

    tmp.QuadPart = charTime;
    return tmp;
}

⌨️ 快捷键说明

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