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

📄 initunlo.cpp

📁 这个是串口驱动程序开发包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        ConfigData->InterfaceType,
        ConfigData->BusNumber,
        ConfigData->OriginalIrql,
        ConfigData->OriginalVector,
        ConfigData->InterruptMode,
        (ConfigData->PermitSystemWideShare ? TRUE : FALSE)
        );


    m_Resources.Init(ConfigData->InterfaceType, ConfigData->BusNumber, this);

    m_Resources.AddIo(ConfigData->Controller,
                      ConfigData->SpanOfInterruptStatus,                             
                      CmResourceShareDeviceExclusive,
                      (USHORT)ConfigData->AddressSpace);

    m_Resources.AddInterrupt(ConfigData->OriginalIrql,
                             ConfigData->OriginalVector,
                             0,
                             (m_InterruptShareable ? CmResourceShareShared : CmResourceShareDriverExclusive),
                             (ConfigData->InterruptMode == Latched ? CM_RESOURCE_INTERRUPT_LATCHED : 
                                                                     CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE));
    if (m_pInterruptStatus)
    {
        m_Resources.AddIo(ConfigData->InterruptStatus,
                          ConfigData->SpanOfInterruptStatus,                             
                          CmResourceShareDriverExclusive,
                          (USHORT)ConfigData->AddressSpace);
    }

    // Report it's resources.  We do this now because we are just
    // about to touch the resources for the first time.
    if (!NT_SUCCESS(m_Resources.Report(L"LOADED SERIAL DRIVER RESOURCES")))
    {
        DebugDump(DBG_ERRORS, ("FAILED ReportResourcesDevice\n"
             "------- for device %x of port %ws\n",
             this, DeviceName()));
    }
    else if (m_Resources.GetIsConflictDetected()) 
    {
        DebugDump(DBG_ERRORS, ("Reporting resources for %ws with device %x\n"
             "------- detected a conflict\n",
             (PCWSTR)m_sNtNameForPort,this) );

        KdSerialDriver::LogError(
            9,
            STATUS_SUCCESS,
            SERIAL_RESOURCE_CONFLICT,
            this,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );

        // This status won't propagate far.

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto deviceCleanup;
    }

    // If the user said to permit sharing within the device, propagate this
    // through.
    m_PermitShare = ConfigData->PermitShare;

    // Before we test whether the port exists (which will enable the FIFO)
    // convert the rx trigger value to what should be used in the register.
    //
    // If a bogus value was given - crank them down to 1.

    switch (ConfigData->RxFIFO) 
    {
        case 1:
            m_RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER;
            break;
        case 4:
            m_RxFifoTrigger = SERIAL_4_BYTE_HIGH_WATER;
            break;
        case 8:
            m_RxFifoTrigger = SERIAL_8_BYTE_HIGH_WATER;
            break;
        case 14:
            m_RxFifoTrigger = SERIAL_14_BYTE_HIGH_WATER;
            break;
        default:
            m_RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER;
            break;
    }

    if ((ConfigData->TxFIFO > 16) || (ConfigData->TxFIFO < 1)) 
        m_TxFifoAmount = 1;
    else 
        m_TxFifoAmount = ConfigData->TxFIFO;

    if (!DoesPortExist(
             ConfigData->sSymbolicLinkName,
             ConfigData->ForceFifoEnable,
             ConfigData->LogFifo
             )) 
    {
        // We couldn't verify that there was actually a
        // port. No need to log an error as the port exist
        // code will log exactly why.

        DebugDump(DBG_ERRORS, ("Does Port exist test failed for %ws\n",
              (PCWSTR)ConfigData->sNtNameForPort) );

        status = STATUS_NO_SUCH_DEVICE;
        goto deviceCleanup;

    }

    // If the user requested that we disable the port, then
    // do it now.  Log the fact that the port has been disabled.

    if (ConfigData->DisablePort) 
    {
        DebugDump(DBG_ERRORS, ("disabled port %ws as requested in configuration\n",
              (PCWSTR)ConfigData->sNtNameForPort) );

        status = STATUS_NO_SUCH_DEVICE;
        KdSerialDriver::LogError(
            57,
            STATUS_SUCCESS,
            SERIAL_DISABLED_PORT,
            this,
            ConfigData->Controller,
            ConfigData->sSymbolicLinkName
            );
        goto deviceCleanup;
    }



    // Set up the default device control fields.
    // Note that if the values are changed after
    // the file is open, they do NOT revert back
    // to the old value at file close.

    m_SpecialChars.XonChar = SERIAL_DEF_XON;
    m_SpecialChars.XoffChar = SERIAL_DEF_XOFF;
    m_HandFlow.ControlHandShake = SERIAL_DTR_CONTROL;

    m_HandFlow.FlowReplace = SERIAL_RTS_CONTROL;

    // Default Line control protocol. 7E1
    //
    // Seven data bits.
    // Even parity.
    // 1 Stop bits.

    m_LineControl = SERIAL_7_DATA | SERIAL_EVEN_PARITY | SERIAL_NONE_PARITY;

    m_ValidDataMask = 0x7f;
    m_CurrentBaud = 1200;


    // 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));

    DebugDump(DBG_DIAG1, ("The default interrupt read buffer size is: %d\n"
         "------  The XoffLimit is                         : %d\n"
         "------  The XonLimit is                          : %d\n"
         "------  The pt 8 size is                         : %d\n",
         m_BufferSize,
         m_HandFlow.XoffLimit,
         m_HandFlow.XonLimit,
         m_BufferSizePt8) );

    // Go through all the "named" baud rates to find out which ones
    // can be supported with this port.

    m_SupportedBauds = SERIAL_BAUD_USER;

    if (NT_SUCCESS(GetDivisorFromBaud(75)))     m_SupportedBauds |= SERIAL_BAUD_075;
    if (NT_SUCCESS(GetDivisorFromBaud(110)))    m_SupportedBauds |= SERIAL_BAUD_110;
    if (NT_SUCCESS(GetDivisorFromBaud(135)))    m_SupportedBauds |= SERIAL_BAUD_134_5;
    if (NT_SUCCESS(GetDivisorFromBaud(150)))    m_SupportedBauds |= SERIAL_BAUD_150;
    if (NT_SUCCESS(GetDivisorFromBaud(300)))    m_SupportedBauds |= SERIAL_BAUD_300;
    if (NT_SUCCESS(GetDivisorFromBaud(600)))    m_SupportedBauds |= SERIAL_BAUD_600;
    if (NT_SUCCESS(GetDivisorFromBaud(1200)))   m_SupportedBauds |= SERIAL_BAUD_1200;
    if (NT_SUCCESS(GetDivisorFromBaud(1800)))   m_SupportedBauds |= SERIAL_BAUD_1800;
    if (NT_SUCCESS(GetDivisorFromBaud(2400)))   m_SupportedBauds |= SERIAL_BAUD_2400;
    if (NT_SUCCESS(GetDivisorFromBaud(4800)))   m_SupportedBauds |= SERIAL_BAUD_4800;
    if (NT_SUCCESS(GetDivisorFromBaud(7200)))   m_SupportedBauds |= SERIAL_BAUD_7200;
    if (NT_SUCCESS(GetDivisorFromBaud(9600)))   m_SupportedBauds |= SERIAL_BAUD_9600;
    if (NT_SUCCESS(GetDivisorFromBaud(14400)))  m_SupportedBauds |= SERIAL_BAUD_14400;
    if (NT_SUCCESS(GetDivisorFromBaud(19200)))  m_SupportedBauds |= SERIAL_BAUD_19200;
    if (NT_SUCCESS(GetDivisorFromBaud(38400)))  m_SupportedBauds |= SERIAL_BAUD_38400;
    if (NT_SUCCESS(GetDivisorFromBaud(56000)))  m_SupportedBauds |= SERIAL_BAUD_56K;
    if (NT_SUCCESS(GetDivisorFromBaud(57600)))  m_SupportedBauds |= SERIAL_BAUD_57600;
    if (NT_SUCCESS(GetDivisorFromBaud(115200))) m_SupportedBauds |= SERIAL_BAUD_115200;
    if (NT_SUCCESS(GetDivisorFromBaud(128000))) m_SupportedBauds |= SERIAL_BAUD_128K;

    // Mark this device as not being opened by anyone.  We keep a
    // variable around so that spurious interrupts are easily
    // dismissed by the ISR.

    m_DeviceIsOpened = FALSE;

    // This call will set up the naming necessary for
    // external applications to get to the driver.  It
    // will also set up the device map.

    m_sNtNameForPort = ConfigData->sNtNameForPort;
    m_sSymbolicLinkName = ConfigData->sSymbolicLinkName;

    // Store values into the device for interval timing.

    // If the interval timer is less than a second then come
    // in with a short "polling" loop.
    //
    // For large (> then 2 seconds) use a 1 second poller.

    m_ShortIntervalAmount.QuadPart = -1;
    m_LongIntervalAmount.QuadPart = -10000000;
    m_CutOverAmount.QuadPart = 200000000;

    // Common error path cleanup.  If the status is
    // bad, get rid of the device , device object
    // and any memory associated with it.

deviceCleanup: ;

    delete ConfigData;
    return status;
}

BOOLEAN KdSerialDevice::DoesPortExist(KdString InsertString, ULONG ForceFifo, ULONG LogFifo)
/*++
Routine Description:
    This routine examines several of what might be the serial device
    registers.  It ensures that the bits that should be zero are zero.

    In addition, this routine will determine if the device supports
    fifo's.  If it does it will enable the fifo's and turn on a boolean
    in the device that indicates the fifo's presence.

    NOTE: If there is indeed a serial port at the address specified
          it will absolutely have interrupts inhibited upon return
          from this routine.

    NOTE: Since this routine should be called fairly early in
          the device driver initialization, the only element
          that needs to be filled in is the base register address.

    NOTE: These tests all assume that this code is the only
          code that is looking at these ports or this memory.

          This is a not to unreasonable assumption even on
          multiprocessor systems.

Arguments:
    InsertString - String to place in an error log entry.
    ForceFifo - !0 forces the fifo to be left on if found.
    LogFifo - !0 forces a log message if fifo found.

Return Value:
    Will return true if the port really exists, otherwise it
    will return false.
--*/
{
    UCHAR regContents;
    BOOLEAN returnValue = TRUE;
    UCHAR oldIERContents;
    UCHAR oldLCRContents;
    USHORT value1;
    USHORT value2;
    KIRQL oldIrql;

    // Save of the line control.

    oldLCRContents = m_pController->ReadByte(LINE_CONTROL_REGISTER);

    // Make sure that we are *aren't* accessing the divsior latch.

    m_pController->WriteByte(LINE_CONTROL_REGISTER, (UCHAR)(oldLCRContents & ~SERIAL_LCR_DLAB));

    oldIERContents = m_pController->ReadByte(INTERRUPT_ENABLE_REGISTER);

    // Go up to power level for a very short time to prevent
    // any interrupts from this device from coming in.

    KeRaiseIrql(
        POWER_LEVEL,
        &oldIrql
        );

    m_pController->WriteByte(INTERRUPT_ENABLE_REGISTER, 0x0f);

    value1 = m_pController->ReadByte(INTERRUPT_ENABLE_REGISTER);
    value1 = value1 << 8;
    value1 |= m_pController->ReadByte(RECEIVE_BUFFER_REGISTER);

    READ_DIVISOR_LATCH(m_pController, &value2);

    m_pController->WriteByte(LINE_CONTROL_REGISTER, oldLCRContents);

    // Put the ier back to where it was before.  If we are on a
    // level sensitive port this should prevent the interrupts
    // from coming in.  If we are on a latched, we don't care
    // cause the interrupts generated will just get dropped.

    m_pController->WriteByte(INTERRUPT_ENABLE_REGISTER, oldIERContents);

    KeLowerIrql(oldIrql);

    if (value1 == value2) 
    {
        KdSerialDriver::LogError(
            62,
            STATUS_SUCCESS,
            SERIAL_DLAB_INVALID,
            this,
            m_OriginalController,
            InsertString
            );
        returnValue = FALSE;
        goto AllDone;
    }

AllDone: ;

    // If we think that there is a serial device then we determine
    // if a fifo is present.

    if (returnValue) 
    {
        // Well, we think it's a serial device.  Absolutely
        // positively, prevent interrupts from occuring.
        //
        // We disable all the interrupt enable bits, and
        // push down all the lines in the modem control
        // We only needed to push down OUT2 which in
        // PC's must also be enabled to get an interrupt.

        DISABLE_ALL_INTERRUPTS(m_pController);

        m_pController->WriteByte(MODEM_CONTROL_REGISTER, (m_Jensen ? (UCHAR)SERIAL_MCR_OUT2 : 0));

        // See if this is a 16550.  We do this by writing to
        // what would be the fifo control register with a bit
        // pattern that tells the device to enable fifo's.
        // We then read the iterrupt Id register to see if the
        // bit pattern is present that identifies the 16550.

        m_pController->WriteByte(FIFO_CONTROL_REGISTER, SERIAL_FCR_ENABLE);

        regContents = m_pController->ReadByte(INTERRUPT_IDENT_REGISTER);

        if (regContents & SERIAL_IIR_FIFOS_ENABLED) 
        {
            // Save off that the device supports fifos.

            m_FifoPresent = TRUE;

            // 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);

⌨️ 快捷键说明

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