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

📄 initunlo.cpp

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

            m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);

            // There are fifos on this card.  Set the value of the
            // receive fifo to interrupt when 4 characters are present.

            m_pController->WriteByte(FIFO_CONTROL_REGISTER ,
                        (UCHAR)(SERIAL_FCR_ENABLE | m_RxFifoTrigger |
                        SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET));
        }

        // The !m_FifoPresent is included in the test so that
        // broken chips like the WinBond will still work after we test
        // for the fifo.

        if (!ForceFifo || !m_FifoPresent) 
        {
            m_FifoPresent = FALSE;
            m_pController->WriteByte(FIFO_CONTROL_REGISTER, 0);
        }

        if (m_FifoPresent)
        {
            if (LogFifo) 
            {
                KdSerialDriver::LogError(
                    15,
                    STATUS_SUCCESS,
                    SERIAL_FIFO_PRESENT,
                    this,
                    m_OriginalController,
                    InsertString
                    );
            }
            DebugDump(DBG_DIAG1, ("Fifo's detected at port address: %x\n",
                 m_pController->GetSystemAddress()) );
        }

        // In case we are dealing with a bitmasked multiportcard,
        // that has the mask register enabled, enable all
        // interrupts.

        if (m_pInterruptStatus) 
            m_pInterruptStatus->WriteByte(0, 0xff);
    }
    return returnValue;
}

BOOLEAN KdSerialDevice::Reset()
/*++
Routine Description:
    This places the hardware in a standard configuration.
    NOTE: This assumes that it is called at interrupt level.

Arguments:
    Context - not used.

Return Value:
    Always FALSE.
--*/
{
    UCHAR regContents;
    UCHAR oldModemControl;
    ULONG i;

    // Adjust the out2 bit.
    // This will also prevent any interrupts from occuring.

    oldModemControl = m_pController->ReadByte(MODEM_CONTROL_REGISTER);

    if (m_Jensen)
        m_pController->WriteByte(MODEM_CONTROL_REGISTER, (UCHAR)(oldModemControl | SERIAL_MCR_OUT2));
    else
        m_pController->WriteByte(MODEM_CONTROL_REGISTER, (UCHAR)(oldModemControl & ~SERIAL_MCR_OUT2));

    // Reset the fifo's if there are any.

    if (m_FifoPresent) 
    {
        // There is a fine new "super" IO chip out there that
        // will get stuck with a line status interrupt if you
        // attempt to clear the fifo and enable it at the same
        // time if data is present.  The best workaround seems
        // to be that you should turn off the fifo read a single
        // byte, and then re-enable the fifo.

        m_pController->WriteByte(FIFO_CONTROL_REGISTER, 0);

        m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);
        
        m_pController->WriteByte(FIFO_CONTROL_REGISTER,
                    (UCHAR)(SERIAL_FCR_ENABLE | m_RxFifoTrigger |
                    SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET));
    }

    // Make sure that the line control set up correct.
    //
    // 1) Make sure that the Divisor latch select is set
    //    up to select the transmit and receive register.
    //
    // 2) Make sure that we aren't in a break state.

    regContents = m_pController->ReadByte(LINE_CONTROL_REGISTER);
    regContents &= ~(SERIAL_LCR_DLAB | SERIAL_LCR_BREAK);
    m_pController->WriteByte(LINE_CONTROL_REGISTER, regContents);

    // Read the receive buffer until the line status is
    // clear.  (Actually give up after a 5 reads.)

    for (i = 0; i<5; i++) 
    {
        m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);
        if (!(m_pController->ReadByte(LINE_CONTROL_REGISTER) & 1))
            break;
    }

    // Read the modem status until the low 4 bits are
    // clear.  (Actually give up after a 5 reads.)

    for (i = 0;  i<1000;i++) 
    {
        if (!(m_pController->ReadByte(MODEM_STATUS_REGISTER) & 0x0f))
            break;
    }

    // Now we set the line control, modem control, and the
    // baud to what they should be.

    SetLineControl();

    SetupNewHandFlow(&m_HandFlow);

    HandleModemUpdate(FALSE);

    SHORT  appropriateDivisor;

    GetDivisorFromBaud(m_CurrentBaud, &appropriateDivisor);
    SetBaud((PVOID)appropriateDivisor);

    // Enable which interrupts we want to receive.
    //
    // NOTE NOTE: This does not actually let interrupts
    // occur.  We must still raise the OUT2 bit in the
    // modem control register.  We will do that on open.

    ENABLE_ALL_INTERRUPTS(m_pController);

    // Read the interrupt id register until the low bit is
    // set.  (Actually give up after a 5 reads.)

    for (i = 0; i<5; i++) 
    {
        if (m_pController->ReadByte(INTERRUPT_IDENT_REGISTER) & 0x01)
            break;
    }

    // Now we know that nothing could be transmitting at this point
    // so we set the HoldingEmpty indicator.

    m_HoldingEmpty = TRUE;

    return FALSE;
}

NTSTATUS KdSerialDevice::GetDivisorFromBaud(LONG DesiredBaud, PSHORT pAppropriateDivisor)
/*++
Routine Description:
    This routine will determine a divisor based on an unvalidated
    baud rate.

Arguments:
    DesiredBaud - The baud rate for whose divisor we seek.

    AppropriateDivisor - Given that the DesiredBaud is valid, the
    LONG pointed to by this parameter will be set to the appropriate
    value.  NOTE: The long is undefined if the DesiredBaud is not
    supported.

Return Value:
    This function will return STATUS_SUCCESS if the baud is supported.
--*/
{   
    SHORT AppropriateDivisor;

    NTSTATUS status = STATUS_SUCCESS;
    SHORT calculatedDivisor;
    ULONG denominator;
    ULONG remainder;

    // Allow up to a 1 percent error

    ULONG maxRemain18 = 18432;
    ULONG maxRemain30 = 30720;
    ULONG maxRemain42 = 42336;
    ULONG maxRemain80 = 80000;
    ULONG maxRemain;

    // Reject any non-positive bauds.

    denominator = DesiredBaud*(ULONG)16;

    if (DesiredBaud <= 0)
        AppropriateDivisor = -1;

    else if ((LONG)denominator < DesiredBaud) 
    {
        // If the desired baud was so huge that it cause the denominator
        // calculation to wrap, don't support it.
        AppropriateDivisor = -1;
    } 
    else 
    {
        switch (m_ClockRate)
        {
            case 1843200: 
                maxRemain = maxRemain18;
                break;
            case 3072000:
                maxRemain = maxRemain30;
                break;
            case 4233600:
                maxRemain = maxRemain42;
                break;
            default:
                maxRemain = maxRemain80;
        }

        calculatedDivisor = (SHORT)(m_ClockRate / denominator);
        remainder = m_ClockRate % denominator;

        // Round up.
        if (((remainder*2) > m_ClockRate) && (DesiredBaud != 110))
            calculatedDivisor++;

        // Only let the remainder calculations effect us if
        // the baud rate is > 9600.

        if (DesiredBaud >= 9600) 
        {
            // If the remainder is less than the maximum remainder (wrt
            // the m_ClockRate) or the remainder + the maximum remainder is
            // greater than or equal to the m_ClockRate then assume that the
            // baud is ok.
            if ((remainder >= maxRemain) && ((remainder+maxRemain) < m_ClockRate))
                calculatedDivisor = -1;
        }

        // Don't support a baud that causes the denominator to
        // be larger than the clock.

        if (denominator > m_ClockRate)
            calculatedDivisor = -1;

        // Ok, Now do some special casing so that things can actually continue
        // working on all platforms.
        switch (m_ClockRate)
        {
            case 1843200: 
                if (DesiredBaud == 56000)
                    calculatedDivisor = 2;
                break;
            case 3072000:
                if (DesiredBaud == 14400)
                    calculatedDivisor = 13;
                break;
            case 4233600:
                switch (DesiredBaud)
                {
                    case 9600:
                        calculatedDivisor = 28;
                        break;
                    case 14400:
                        calculatedDivisor = 18;
                        break;
                    case 19200:
                        calculatedDivisor = 14;
                        break;
                    case 38400:
                        calculatedDivisor = 7;
                        break;
                    case 56000:
                        calculatedDivisor = 5;
                        break;
                }
            case 8000000:
                if (DesiredBaud == 14400)
                    calculatedDivisor = 35;
                else if (DesiredBaud == 56000)
                    calculatedDivisor = 9;
                break;
        }
        AppropriateDivisor = calculatedDivisor;
    }

    if (AppropriateDivisor == -1)
        status = STATUS_INVALID_PARAMETER;

    if (pAppropriateDivisor)
        *pAppropriateDivisor = AppropriateDivisor;

    return status;
}

KdSerialDriver::~KdSerialDriver()
{
}

NTSTATUS SerialItemCallBack(QUERY_RESULT* Results, PVOID Context)
/*++
Routine Description:
    This routine is called to check if a particular item
    is present in the registry.

Arguments:
    Context - Pointer to a boolean.
    Results - results of the callback.  Not Used.

Return Value:
    STATUS_SUCCESS
--*/
{
    *((BOOLEAN *)Context) = TRUE;
    return STATUS_SUCCESS;
}

// This structure is only used to communicate between the
// code that queries what the firmware found and the code
// that is calling the quering of the firmware data.
class SERIAL_FIRMWARE_DATA 
{
public:
    SERIAL_FIRMWARE_DATA() 
        : ConfigList(CONFIG_LIST_OFFSET)
    {
        ControllersFound = 0;
        ForceFifoEnableDefault = 0;
        RxFIFODefault = 0;
        TxFIFODefault = 0;
        PermitShareDefault = 0;
        PermitSystemWideShare = 0;
        LogFifoDefault = 0;
    }
    ULONG ControllersFound;
    ULONG ForceFifoEnableDefault;
    ULONG RxFIFODefault;
    ULONG TxFIFODefault;
    ULONG PermitShareDefault;
    ULONG PermitSystemWideShare;
    ULONG LogFifoDefault;
    KdString Directory;
    KdString NtNameSuffix;
    KdString DirectorySymbolicName;
    KdConfigList ConfigList;
};
typedef SERIAL_FIRMWARE_DATA * PSERIAL_FIRMWARE_DATA;

NTSTATUS SerialConfigCallBack(QUERY_RESULT* Results, PVOID Context)
/*++
Routine Description:
    This routine is used to acquire all of the configuration
    information for each serial controller found by the firmware

Arguments:
    Context - Pointer to the list head o

⌨️ 快捷键说明

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