Ejemplo n.º 1
0
KnxMSG_BufferPtr KnxMSG_AllocateBuffer(void)
#endif /* KSTACK_MEMORY_MAPPING */
{
    uint8               fp;
    KnxMSG_BufferPtr    ptr;

    DISABLE_ALL_INTERRUPTS();

    AllocCount++;

    if ((fp = KnxMSG_Queues[TASK_FREE_ID]) == MSG_NO_NEXT) {
        ENABLE_ALL_INTERRUPTS();
        return (KnxMSG_BufferPtr)NULL;       /* no Buffer available. */
    }

    ptr = &KnxMSG_Buffers[fp];

    if (ptr->next == MSG_NO_NEXT) {
        KnxMSG_Queues[TASK_FREE_ID] = MSG_NO_NEXT;
    } else {
        KnxMSG_Queues[TASK_FREE_ID]    = ptr->next;
        ptr->next                      = MSG_NO_NEXT;
    }

    ENABLE_ALL_INTERRUPTS();
    return &KnxMSG_Buffers[fp];
}
Ejemplo n.º 2
0
//------------------------------------------------------------------------
void RF22_clearRxBuf()
{
    DISABLE_ALL_INTERRUPTS();    // Disable Interrupts
    _bufLen = 0;
    _rxBufValid = false;
    ENABLE_ALL_INTERRUPTS();     // Enable Interrupts
}
Ejemplo n.º 3
0
//------------------------------------------------------------------------
void RF22_clearTxBuf()
{
    DISABLE_ALL_INTERRUPTS();
    _bufLen = 0;
    _txBufSentIndex = 0;
    _txPacketSent = false;
    ENABLE_ALL_INTERRUPTS();     // Enable Interrupts
}
Ejemplo n.º 4
0
/*----------------------------------------------------------------------------
*  Module:
*   Capcom23ISR
*
*   This function is triggered automatically when the the value of the T8
*   CAPCOM timer is equal to the value of the CAPCOM23 (CC23) register.
*
--------------------------------------------------------------------------- */
interrupt (CAPCOM_REGISTER_23) using (CAPCOM_RB) void Capcom23ISR (void)
{

    DISABLE_ALL_INTERRUPTS();

    ENABLE_ALL_INTERRUPTS();

}
Ejemplo n.º 5
0
//Configures interrupt pin supported by ADS7843 controller
static void touchIntPinInit()
{
	ADS7843_PORT_INT_CLOCK();
	ADS7843_INT_INPUT();
	ADS7843_INT_CONFIG_AS_FALLING();
	GPIOPortIntRegister(ADS7843_PORT_INT, TouchScreenIntHandler);
	ENABLE_ALL_INTERRUPTS();
    touchIntPinInterruptEnable(true);
}
Ejemplo n.º 6
0
static void RF22_IntPinInit()
{
	RFM_22_PORT_INT_CLOCK();
	RFM_22_INT_INPUT();
	GPIOPortIntRegister(RFM_22_PORT_INT, RF22_PinIntHandler);
	RFM_22_INT_CONFIG_AS_FALLING();
	RFM_22_INT_INTERRUPT_ENABLE();
	ENABLE_ALL_INTERRUPTS();
}
Ejemplo n.º 7
0
//------------------------------------------------------------------------
bool RF22_appendTxBuf(const uint8_t* data, uint8_t len)
{
    if (((uint16_t)_bufLen + len) > RF22_MAX_MESSAGE_LEN)
    {
        return false;
    }
    DISABLE_ALL_INTERRUPTS();    // Disable Interrupts
    memcpy(_buf + _bufLen, data, len);
    _bufLen += len;
    ENABLE_ALL_INTERRUPTS();     // Enable Interrupts
    return true;
}
Ejemplo n.º 8
0
void KnxMSG_ReleaseBuffer(KnxMSG_BufferPtr ptr)
#endif /* KSTACK_MEMORY_MAPPING */
{
    uint8   buf_num;
    uint8   old_fp;
    uint8   t_fp;

    DISABLE_ALL_INTERRUPTS();

    if ((buf_num = GetBufferNumber(ptr)) == MSG_INVALID_BUFFER) {
        /* TODO: call error-handler */
        ENABLE_ALL_INTERRUPTS();
        return;
    }

    ReleaseCount++;

    old_fp = KnxMSG_Queues[TASK_FREE_ID];
    t_fp   = old_fp;

    while (t_fp != MSG_NO_NEXT) {
        if (t_fp == buf_num) {
            ENABLE_ALL_INTERRUPTS();
            /* TODO: call error-handler */
            return;   /* not allocated. */
        }

        t_fp = KnxMSG_Buffers[t_fp].next;
    }

    KnxMSG_Queues[TASK_FREE_ID]    = buf_num;
    KnxMSG_Buffers[buf_num].next   = old_fp;
    ClearMessageBuffer(buf_num);

    ptr = (KnxMSG_BufferPtr)NULL;  /* invalidate Buffer. */
    ENABLE_ALL_INTERRUPTS();
}
Ejemplo n.º 9
0
//------------------------------------------------------------------------
bool RF22_recv(uint8_t* buf, uint8_t* len)
{
    if (!RF22_available())
    {
        return false;
    }
    DISABLE_ALL_INTERRUPTS();
    if (*len > _bufLen)
    {
        *len = _bufLen;
    }
    memcpy(buf, _buf, *len);
    RF22_clearRxBuf();
    ENABLE_ALL_INTERRUPTS();     // Enable Interrupts

    return true;
}
Ejemplo n.º 10
0
//Configures Timer0A as a 32-bit periodic timer
static void touchScreenTimerInit()
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER_UP);
    // Set the Timer0A load value to 1ms.
    TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet() / 1000); //1 [ms]

    //enable all interrupts
    ENABLE_ALL_INTERRUPTS();

    // Configure the Timer0A interrupt for timer timeout.
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);

    // Enable the Timer0A interrupt on the processor (NVIC).
    IntEnable(INT_TIMER0A);

    m_counter = 0;

    // Disable Timer0A.
    touchScreenTimerEnable(true);
}
Ejemplo n.º 11
0
VOID
SerialProdXonXoff(
    IN PSERIAL_DEVICE_EXTENSION Extension,
    IN BOOLEAN SendXon
    )

/*++

Routine Description:

    This routine will set up the SendXxxxChar variables if
    necessary and determine if we are going to be interrupting
    because of current transmission state.  It will cause an
    interrupt to occur if neccessary, to send the xon/xoff char.

    NOTE: This routine assumes that it is called at interrupt
          level.

Arguments:

    Extension - A pointer to the serial device extension.

    SendXon - If a character is to be send, this indicates whether
              it should be an Xon or an Xoff.

Return Value:

    None.

--*/

{

    //
    // We assume that if the prodding is called more than
    // once that the last prod has set things up appropriately.
    //
    // We could get called before the character is sent out
    // because the send of the character was blocked because
    // of hardware flow control (or break).
    //

    if (!Extension->SendXonChar && !Extension->SendXoffChar
        && Extension->HoldingEmpty) {

        DISABLE_ALL_INTERRUPTS(Extension->Controller);
        ENABLE_ALL_INTERRUPTS(Extension->Controller);

    }

    if (SendXon) {

        Extension->SendXonChar = TRUE;
        Extension->SendXoffChar = FALSE;

    } else {

        Extension->SendXonChar = FALSE;
        Extension->SendXoffChar = TRUE;

    }

}
Ejemplo n.º 12
0
//--------------------------------------------------------------------------
// Module:
//  BurninDigitalTests
//
///   This function turns on/off the output drives on the HIDAC so that B+ (through
///   a resistor) or ground is presented to the digital inputs. Whenever an output is made
///   high, the output transistor is shut off. The signal in the test box
///   is pulled up and therefore B+ is presented to the digital input. If the output
///   is made low, the output transistor is turned on and the digital input is presented
///   ground. This function sets the bit, verifies the input is high, and then resets
///   the bit and verifies the input is low. Whenever a "low" failure is detected,
///   LOW_SIDE_ERROR is added to the error code so that the user can discern the
///   difference between a HIGH and LOW failure.
///
//--------------------------------------------------------------------------
static void BurninDigitalTests (void)
{
    const DigitalTest_t digTest[] =
    {
        {DIGOUT_BIT00,	DIGIN_00, HIGH, ERR_DIGITAL_IO_10},
        {DIGOUT_BIT01,	DIGIN_01, HIGH, ERR_DIGITAL_IO_11},
        {DIGOUT_BIT02,	DIGIN_02, HIGH, ERR_DIGITAL_IO_12},
        {DIGOUT_BIT03,	DIGIN_03, HIGH, ERR_DIGITAL_IO_13},
        {DIGOUT_BIT04,	DIGIN_04, HIGH, ERR_DIGITAL_IO_14},
        {DIGOUT_BIT05,	DIGIN_05, HIGH, ERR_DIGITAL_IO_15},
        {DIGOUT_BIT06,	DIGIN_06, HIGH, ERR_DIGITAL_IO_16},
        {DIGOUT_BIT07,	DIGIN_07, HIGH, ERR_DIGITAL_IO_17},

        {DIGOUT_BIT08,	DIGIN_08, HIGH, ERR_DIGITAL_IO_20},
        /* DIGOUT_BIT09 is checked separately because it is used to drive
           the Burn-In box LED
        {DIGOUT_BIT09,	DIGIN_09, HIGH, ERR_DIGITAL_IO_21}, */
        {DIGOUT_BIT10,	DIGIN_10, HIGH, ERR_DIGITAL_IO_22},
        {DIGOUT_BIT11,	DIGIN_11, HIGH, ERR_DIGITAL_IO_23},
        {DIGOUT_BIT12,	DIGIN_12, HIGH, ERR_DIGITAL_IO_24},
        {DIGOUT_BIT13,	DIGIN_13, HIGH, ERR_DIGITAL_IO_25},
        {DIGOUT_BIT14,	DIGIN_14, HIGH, ERR_DIGITAL_IO_26},
        {DIGOUT_BIT15,	DIGIN_15, HIGH, ERR_DIGITAL_IO_27},

        {DIGOUT_BIT16,	DIGIN_16, HIGH, ERR_DIGITAL_IO_30},
        {DIGOUT_BIT17,	DIGIN_17, HIGH, ERR_DIGITAL_IO_31},
        {DIGOUT_BIT18,	DIGIN_18, HIGH, ERR_DIGITAL_IO_32},
        {DIGOUT_BIT19,	DIGIN_19, HIGH, ERR_DIGITAL_IO_33},
        {DIGOUT_BIT20,	DIGIN_20, HIGH, ERR_DIGITAL_IO_34},
        {DIGOUT_BIT21,	DIGIN_21, HIGH, ERR_DIGITAL_IO_35},
        {DIGOUT_BIT22,	DIGIN_22, HIGH, ERR_DIGITAL_IO_36},
        {DIGOUT_BIT23,	DIGIN_23, HIGH, ERR_DIGITAL_IO_37},

        {DIGOUT_BIT24,	DIGIN_24, HIGH, ERR_DIGITAL_IO_40},
        {DIGOUT_BIT25,	DIGIN_25, HIGH, ERR_DIGITAL_IO_41},
        {DIGOUT_BIT26,	DIGIN_26, HIGH, ERR_DIGITAL_IO_42},
        {DIGOUT_BIT27,	DIGIN_27, HIGH, ERR_DIGITAL_IO_43},
        {DIGOUT_BIT28,	DIGIN_28, HIGH, ERR_DIGITAL_IO_44},
        {DIGOUT_BIT29,	DIGIN_29, HIGH, ERR_DIGITAL_IO_45},
        {DIGOUT_BIT30,	DIGIN_30, HIGH, ERR_DIGITAL_IO_46},
        {DIGOUT_BIT31,	DIGIN_31, HIGH, ERR_DIGITAL_IO_47},

    };

    UINT_16 i;
    eDigInBitState din9;
    eDigInBitState drv9;

    for (i = 0; i < sizeof (digTest) / sizeof (DigitalTest_t); i++)
    {

        /* Set the Digital Outputs */
        DO_SetBitWithId (digTest[i].outBit);

        /* Give time for the output to settle */
        GiveSettleTime();

        /* Read the Input bit and verify */
        if (DI_ReadBit (digTest[i].inBit) != digTest[i].expectedFBDriveHigh)
        {

            /* An error code was detected, set the error code and return */
            burnin_error_code = digTest[i].errorId;
			consecutiveFailureCount++;
            DO_ResetBitWithId (digTest[i].outBit);
#ifndef CONTINUOUS
			return;
#endif
		}

        /* Turn the drive off */
        DO_ResetBitWithId (digTest[i].outBit);

        /* Give time for the output to settle */
        GiveSettleTime();

        /* Read the Input bit after resetting the output bit and verify
           that it is the opposite when setting the bit */
        if (DI_ReadBit (digTest[i].inBit) == digTest[i].expectedFBDriveHigh)
        {
            /* An error code was detected, set the error code and return */
            burnin_error_code = digTest[i].errorId + LOW_SIDE_ERROR;
			consecutiveFailureCount++;

            /* Set the Outputs to minimize current draw in the burn-in box resistor */
            DO_SetBitWithId (digTest[i].outBit);
#ifndef CONTINUOUS
			return;
#endif
        }

        /* Set the output high (FET is high impedance) to minimize the current
           draw in the burn-in box pull-up resistor */
        DO_SetBitWithId (digTest[i].outBit);

    }

    /* Check DRV9 and DIN9; the Burn-In box LED. Cycle twice to allow the
       LED to change states. */
    for (i = 0; i < 2; i++)
    {

        /* Read the output state and the input state DRV9 and DIN9
           Burn-In Box LED */
        DISABLE_ALL_INTERRUPTS();
        drv9 = DO_ReadBitState (DIGOUT_BIT09) ? HIGH : LOW;
        din9 = DI_ReadBit (DIGIN_09);
        ENABLE_ALL_INTERRUPTS();

        if (drv9 != din9)
        {
            if (drv9)
            {
                burnin_error_code = (UINT_8)(ERR_DIGITAL_IO_21);
				consecutiveFailureCount++;
            }
            else
            {
                burnin_error_code = (UINT_8)(ERR_DIGITAL_IO_21) + (UINT_8)(LOW_SIDE_ERROR);
				consecutiveFailureCount++;
            }
#ifndef CONTINUOUS
			return;
#endif
        }

        /* Give time for the LED to toggle */
        TM_Wait (1000);
    }

}
Ejemplo n.º 13
0
//--------------------------------------------------------------------------
// Module:
//  main
//
///   This function is the main program. It provides initialization of hardware
///   and software components and software. The main loop  portion handles
///   only the Debug task.
///
//--------------------------------------------------------------------------
void main (void)
{
    UINT_16 temp = 0;

	/* Disable all C167 interrupts */
    DISABLE_ALL_INTERRUPTS();

	/* Don't allow any interrupt processing to occur */
    SetMvbReady (FALSE);
    SetStartupSuccessful (FALSE);

    /* Release MVB IPACK hardware */
    ReleaseIpackHw();

    /* Configure Push-Pull digital IOs at P7 to Digital Outputs */
    DO_Init (0xFF);

	/* Initialize the HiDAC outputs */
    InitP8ForDigOuts();
    InitDigitalOutputs();
    InitAnalogOutputs();

	/* Toggle VDrive and CPU watchdogs */
    ToggleVDriveWatchdog();
    ToggleCPUWatchdog();

    /* Set the state of the HIDAC LEDs */
    HIDAC_TEST_LED_ON();
    HIDAC_FAIL_LED_OFF();

    /* Enable SSMR1, SSMR2, VDrive & +5V to Hex LED Display */
    DO_WriteBank (DIGOUT_BANK2, 0x00FF);

	/* Initialize the software to detect a 15 volt failure */
    Init15VoltFailDetect();
    /* This call initializes the 10 ms Timer ISR 
*/
	InitTimer0();
    InitTimer1 ();
	InitTimer7 ();

	ENABLE_ALL_INTERRUPTS();

	/* Allow the VDrive watchdog to toggle and wait some timer before 
	   trying to drive display */
    SetVdriveDisable (FALSE);
	TM_Wait (250);


    /* Display the stored CRC checksum for approximately 1 second at startup */
    DisplayCRConHexLED();

    /* Perform the RAM Test. */
    if (!VerifyRAM())
    {
        HIDAC_FAIL_LED_ON();
        UpdateHidacError (RAM_FAILURE);
    }

	if (!HidacErrorExists())
	{
		/* Perform the ROM Test. */
		if (!VerifyCRCAtStart())
		{
			HIDAC_FAIL_LED_ON();
			UpdateHidacError (ROM_FAILURE);
		}
	}

    /* Init the RS-232 */
    InitSerialCommunications();

    /* Init the analog inputs */
    InitAnalogInputs();

    /* Init the PWM input hardware */
    PwmInInit();

    /* Init the MVB IPACK interface */
    InitMVBIpack();

	/* DAS This call to InitPwmOutputs needs to be after InitMVBIpack. After Sweden made an
	  an upgrade to the IPACK CPLD to rev 2, for some reason, initializing PWM1 prior to initializing 
	  the IPACK causes the IPACK not to initialize properly. Didn't have time to investigate ????? */
	InitPwmOutputs();

	if (!HidacErrorExists())
	{
	    /* stop here if +/- 15VDC supply is low */
		if (Get15VoltBad())
		{
			HexLEDUpdate (0x15);
			HIDAC_FAIL_LED_ON();
			UpdateHidacError (BAD_15V);
		}
	}

#ifdef BURN_IN
	if (!HidacErrorExists())
	{
		BurnInCode();
	}
	else
	{
		while (1);
	}
    ////////////////////////////////////////////////////////////////
    // Code never gets past here if Burn-In code enabled
    // Infinite while (FOREVER) in BurnInCode() or if error detected
    ////////////////////////////////////////////////////////////////
#endif


    HIDAC_TEST_LED_OFF();

    SetStartupSuccessful (TRUE);

	// Setting the argument to FALSE indicates that the baseline CPU loading has
	// already been performed and that the CPU load check, that can be performed via
	// the serial port, will report the CPU loading as a percentage. Setting to TRUE
	// should only be done when capturing the CPU baseline loading and should be returned
	// to FALSE for normal operation
    DebugInit (FALSE);

    if (!HidacErrorExists())
    {
        HexLEDUpdate (0x00);
    }

    /* This is the background loop */
    while (1)
    {
		// Used to measure CPU loading
		DebugUpdateLoadCounter();
        
		/* Code that executes in the main while forever loop. All RealTime critical
			application code is interrupt driven */
        DebugService();

    }

}
Ejemplo n.º 14
0
UCHAR
SerialProcessLSR(
    IN PSERIAL_DEVICE_EXTENSION Extension
    )

/*++

Routine Description:

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

Arguments:

    Extension - The serial device extension.

Return Value:

    The value of the line status register.

--*/

{
    PREQUEST_CONTEXT reqContext = NULL;

    UCHAR LineStatus = READ_LINE_STATUS(Extension, Extension->Controller);


    Extension->HoldingEmpty = (LineStatus & SERIAL_LSR_THRE) ? TRUE : FALSE;

    //
    // If the line status register is just the fact that
    // the trasmit 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 (Extension->EscapeChar) {

            SerialPutChar(
                Extension,
                Extension->EscapeChar
                );

            SerialPutChar(
                Extension,
                (UCHAR)((LineStatus & SERIAL_LSR_DR)?
                    (SERIAL_LSRMST_LSR_DATA):(SERIAL_LSRMST_LSR_NODATA))
                );

            SerialPutChar(
                Extension,
                LineStatus
                );

            if (LineStatus & SERIAL_LSR_DR) {

                Extension->PerfStats.ReceivedCount++;
                Extension->WmiPerfData.ReceivedCount++;
                SerialPutChar(
                    Extension,
                    READ_RECEIVE_BUFFER(Extension, Extension->Controller)
                    );

            }

        }

        if (LineStatus & SERIAL_LSR_OE) {

            Extension->PerfStats.SerialOverrunErrorCount++;
            Extension->WmiPerfData.SerialOverrunErrorCount++;
            Extension->ErrorWord |= SERIAL_ERROR_OVERRUN;

            if (Extension->HandFlow.FlowReplace &
                SERIAL_ERROR_CHAR) {

                SerialPutChar(
                    Extension,
                    Extension->SpecialChars.ErrorChar
                    );

                if (LineStatus & SERIAL_LSR_DR) {

                    Extension->PerfStats.ReceivedCount++;
                    Extension->WmiPerfData.ReceivedCount++;
                    READ_RECEIVE_BUFFER(Extension, Extension->Controller);

                }

            } else {

                if (LineStatus & SERIAL_LSR_DR) {

                    Extension->PerfStats.ReceivedCount++;
                    Extension->WmiPerfData.ReceivedCount++;
                    SerialPutChar(
                        Extension,
                        READ_RECEIVE_BUFFER(Extension,
                            Extension->Controller
                            )
                        );

                }

            }

        }

        if (LineStatus & SERIAL_LSR_BI) {

            Extension->ErrorWord |= SERIAL_ERROR_BREAK;

            if (Extension->HandFlow.FlowReplace &
                SERIAL_BREAK_CHAR) {

                SerialPutChar(
                    Extension,
                    Extension->SpecialChars.BreakChar
                    );

            }

        } else {

            //
            // Framing errors only count if they
            // occur exclusive of a break being
            // received.
            //

            if (LineStatus & SERIAL_LSR_PE) {

                Extension->PerfStats.ParityErrorCount++;
                Extension->WmiPerfData.ParityErrorCount++;
                Extension->ErrorWord |= SERIAL_ERROR_PARITY;

                if (Extension->HandFlow.FlowReplace &
                    SERIAL_ERROR_CHAR) {

                    SerialPutChar(
                        Extension,
                        Extension->SpecialChars.ErrorChar
                        );

                    if (LineStatus & SERIAL_LSR_DR) {

                        Extension->PerfStats.ReceivedCount++;
                        Extension->WmiPerfData.ReceivedCount++;
                        READ_RECEIVE_BUFFER(Extension, Extension->Controller);

                    }

                }

            }

            if (LineStatus & SERIAL_LSR_FE) {

                Extension->PerfStats.FrameErrorCount++;
                Extension->WmiPerfData.FrameErrorCount++;
                Extension->ErrorWord |= SERIAL_ERROR_FRAMING;

                if (Extension->HandFlow.FlowReplace &
                    SERIAL_ERROR_CHAR) {

                    SerialPutChar(
                        Extension,
                        Extension->SpecialChars.ErrorChar
                        );
                    if (LineStatus & SERIAL_LSR_DR) {

                        Extension->PerfStats.ReceivedCount++;
                        Extension->WmiPerfData.ReceivedCount++;
                        READ_RECEIVE_BUFFER(Extension, Extension->Controller);

                    }

                }

            }

        }

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

        if (Extension->HandFlow.ControlHandShake &
            SERIAL_ERROR_ABORT) {

            SerialInsertQueueDpc(
                Extension->CommErrorDpc
                );

        }

        //
        // 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 (Extension->IsrWaitMask) {

            if ((Extension->IsrWaitMask & SERIAL_EV_ERR) &&
                (LineStatus & (SERIAL_LSR_OE |
                               SERIAL_LSR_PE |
                               SERIAL_LSR_FE))) {

                Extension->HistoryMask |= SERIAL_EV_ERR;

            }

            if ((Extension->IsrWaitMask & SERIAL_EV_BREAK) &&
                (LineStatus & SERIAL_LSR_BI)) {

                Extension->HistoryMask |= SERIAL_EV_BREAK;

            }

            if (Extension->IrpMaskLocation &&
                Extension->HistoryMask) {

                *Extension->IrpMaskLocation =
                 Extension->HistoryMask;
                Extension->IrpMaskLocation = NULL;
                Extension->HistoryMask = 0;
                reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest);
                reqContext->Information =  sizeof(ULONG);
                SerialInsertQueueDpc(
                    Extension->CommWaitDpc
                    );

            }

        }

        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 (Extension->WriteLength |
                Extension->TransmitImmediate) {

                DISABLE_ALL_INTERRUPTS(Extension,
                    Extension->Controller
                    );
                ENABLE_ALL_INTERRUPTS(Extension,
                    Extension->Controller
                    );
            }

        }

    }

    return LineStatus;
}
Ejemplo n.º 15
0
BOOLEAN
SerialPretendXon(
    IN PVOID Context
    )

/*++

Routine Description:

    This routine is used to process the Ioctl that request the
    driver to act as if an Xon was received.

    Note: If the driver does not have automatic Xoff/Xon enabled
    then the only way to restart transmission is for the
    application to request we "act" as if we saw the xon.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

    This routine always returns FALSE.

--*/

{

    PSERIAL_DEVICE_EXTENSION Extension = Context;

    if (Extension->TXHolding) {

        //
        // We actually have a good reason for testing if transmission
        // is holding instead of blindly clearing the bit.
        //
        // If transmission actually was holding and the result of
        // clearing the bit is that we should restart transmission
        // then we will poke the interrupt enable bit, which will
        // cause an actual interrupt and transmission will then
        // restart on its own.
        //
        // If transmission wasn't holding and we poked the bit
        // then we would interrupt before a character actually made
        // it out and we could end up over writing a character in
        // the transmission hardware.

        Extension->TXHolding &= ~SERIAL_TX_XOFF;

        if (!Extension->TXHolding &&
            (Extension->TransmitImmediate ||
             Extension->WriteLength) &&
             Extension->HoldingEmpty) {

            DISABLE_ALL_INTERRUPTS(Extension->Controller);
            ENABLE_ALL_INTERRUPTS(Extension->Controller);

        }

    }

    return FALSE;

}
Ejemplo n.º 16
0
ULONG
SerialHandleModemUpdate(
    IN PSERIAL_DEVICE_EXTENSION Extension,
    IN BOOLEAN DoingTX
    )

/*++

Routine Description:

    This routine will be to check on the modem status, and
    handle any appropriate event notification as well as
    any flow control appropriate to modem status lines.

    NOTE: This routine assumes that it is called at interrupt
          level.

Arguments:

    Extension - A pointer to the serial device extension.

    DoingTX - This boolean is used to indicate that this call
              came from the transmit processing code.  If this
              is true then there is no need to cause a new interrupt
              since the code will be trying to send the next
              character as soon as this call finishes.

Return Value:

    This returns the old value of the modem status register
    (extended into a ULONG).

--*/

{

    //
    // We keep this local so that after we are done
    // examining the modem status and we've updated
    // the transmission holding value, we know whether
    // we've changed from needing to hold up transmission
    // to transmission being able to proceed.
    //
    ULONG OldTXHolding = Extension->TXHolding;

    //
    // Holds the value in the mode status register.
    //
    UCHAR ModemStatus;

    ModemStatus =
        READ_MODEM_STATUS(Extension->Controller);

    //
    // If we are placeing the modem status into the data stream
    // on every change, we should do it now.
    //

    if (Extension->EscapeChar) {

        if (ModemStatus & (SERIAL_MSR_DCTS |
                           SERIAL_MSR_DDSR |
                           SERIAL_MSR_TERI |
                           SERIAL_MSR_DDCD)) {

            SerialPutChar(
                Extension,
                Extension->EscapeChar
                );
            SerialPutChar(
                Extension,
                SERIAL_LSRMST_MST
                );
            SerialPutChar(
                Extension,
                ModemStatus
                );

        }

    }


    //
    // Take care of input flow control based on sensitivity
    // to the DSR.  This is done so that the application won't
    // see spurious data generated by odd devices.
    //
    // Basically, if we are doing dsr sensitivity then the
    // driver should only accept data when the dsr bit is
    // set.
    //

    if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) {

        if (ModemStatus & SERIAL_MSR_DSR) {

            //
            // The line is high.  Simply make sure that
            // RXHolding does't have the DSR bit.
            //

            Extension->RXHolding &= ~SERIAL_RX_DSR;

        } else {

            Extension->RXHolding |= SERIAL_RX_DSR;

        }

    } else {

        //
        // We don't have sensitivity due to DSR.  Make sure we
        // arn't holding. (We might have been, but the app just
        // asked that we don't hold for this reason any more.)
        //

        Extension->RXHolding &= ~SERIAL_RX_DSR;

    }

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

    if (Extension->IsrWaitMask) {

        if ((Extension->IsrWaitMask & SERIAL_EV_CTS) &&
            (ModemStatus & SERIAL_MSR_DCTS)) {

            Extension->HistoryMask |= SERIAL_EV_CTS;

        }

        if ((Extension->IsrWaitMask & SERIAL_EV_DSR) &&
            (ModemStatus & SERIAL_MSR_DDSR)) {

            Extension->HistoryMask |= SERIAL_EV_DSR;

        }

        if ((Extension->IsrWaitMask & SERIAL_EV_RING) &&
            (ModemStatus & SERIAL_MSR_TERI)) {

            Extension->HistoryMask |= SERIAL_EV_RING;

        }

        if ((Extension->IsrWaitMask & SERIAL_EV_RLSD) &&
            (ModemStatus & SERIAL_MSR_DDCD)) {

            Extension->HistoryMask |= SERIAL_EV_RLSD;

        }

        if (Extension->IrpMaskLocation &&
            Extension->HistoryMask) {

            *Extension->IrpMaskLocation =
             Extension->HistoryMask;
            Extension->IrpMaskLocation = NULL;
            Extension->HistoryMask = 0;

            Extension->CurrentWaitIrp->
                IoStatus.Information = sizeof(ULONG);
            KeInsertQueueDpc(
                &Extension->CommWaitDpc,
                NULL,
                NULL
                );

        }

    }

    //
    // If the app has modem line flow control then
    // we check to see if we have to hold up transmission.
    //

    if (Extension->HandFlow.ControlHandShake &
        SERIAL_OUT_HANDSHAKEMASK) {

        if (Extension->HandFlow.ControlHandShake &
            SERIAL_CTS_HANDSHAKE) {

            if (ModemStatus & SERIAL_MSR_CTS) {

                Extension->TXHolding &= ~SERIAL_TX_CTS;

            } else {

                Extension->TXHolding |= SERIAL_TX_CTS;

            }

        } else {

            Extension->TXHolding &= ~SERIAL_TX_CTS;

        }

        if (Extension->HandFlow.ControlHandShake &
            SERIAL_DSR_HANDSHAKE) {

            if (ModemStatus & SERIAL_MSR_DSR) {

                Extension->TXHolding &= ~SERIAL_TX_DSR;

            } else {

                Extension->TXHolding |= SERIAL_TX_DSR;

            }

        } else {

            Extension->TXHolding &= ~SERIAL_TX_DSR;

        }

        if (Extension->HandFlow.ControlHandShake &
            SERIAL_DCD_HANDSHAKE) {

            if (ModemStatus & SERIAL_MSR_DCD) {

                Extension->TXHolding &= ~SERIAL_TX_DCD;

            } else {

                Extension->TXHolding |= SERIAL_TX_DCD;

            }

        } else {

            Extension->TXHolding &= ~SERIAL_TX_DCD;

        }

        //
        // If we hadn't been holding, and now we are then
        // queue off a dpc that will lower the RTS line
        // if we are doing transmit toggling.
        //

        if (!OldTXHolding && Extension->TXHolding  &&
            ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
              SERIAL_TRANSMIT_TOGGLE)) {

            KeInsertQueueDpc(
                &Extension->StartTimerLowerRTSDpc,
                NULL,
                NULL
                )?Extension->CountOfTryingToLowerRTS++:0;

        }

        //
        // We've done any adjusting that needed to be
        // done to the holding mask given updates
        // to the modem status.  If the Holding mask
        // is clear (and it wasn't clear to start)
        // and we have "write" work to do set things
        // up so that the transmission code gets invoked.
        //

        if (!DoingTX && OldTXHolding && !Extension->TXHolding) {

            if (!Extension->TXHolding &&
                (Extension->TransmitImmediate ||
                 Extension->WriteLength) &&
                 Extension->HoldingEmpty) {

                DISABLE_ALL_INTERRUPTS(Extension->Controller);
                ENABLE_ALL_INTERRUPTS(Extension->Controller);

            }

        }

    } else {

        //
        // We need to check if transmission is holding
        // up because of modem status lines.  What
        // could have occured is that for some strange
        // reason, the app has asked that we no longer
        // stop doing output flow control based on
        // the modem status lines.  If however, we
        // *had* been held up because of the status lines
        // then we need to clear up those reasons.
        //

        if (Extension->TXHolding & (SERIAL_TX_DCD |
                                    SERIAL_TX_DSR |
                                    SERIAL_TX_CTS)) {

            Extension->TXHolding &= ~(SERIAL_TX_DCD |
                                      SERIAL_TX_DSR |
                                      SERIAL_TX_CTS);


            if (!DoingTX && OldTXHolding && !Extension->TXHolding) {

                if (!Extension->TXHolding &&
                    (Extension->TransmitImmediate ||
                     Extension->WriteLength) &&
                     Extension->HoldingEmpty) {

                    DISABLE_ALL_INTERRUPTS(Extension->Controller);
                    ENABLE_ALL_INTERRUPTS(Extension->Controller);

                }

            }

        }

    }

    return ((ULONG)ModemStatus);
}
Ejemplo n.º 17
0
BOOLEAN
SerialGiveImmediateToIsr(
    IN WDFINTERRUPT  Interrupt,
    IN PVOID         Context
    )
/*++

Routine Description:

    Try to start off the write by slipping it in behind
    a transmit immediate char, or if that isn't available
    and the transmit holding register is empty, "tickle"
    the UART into interrupting with a transmit buffer
    empty.

    NOTE: This routine is called by WdfInterruptSynchronize.

    NOTE: This routine assumes that it is called with the
          cancel spin lock held.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

    This routine always returns FALSE.

--*/
{
    PSERIAL_DEVICE_EXTENSION Extension = Context;
    PREQUEST_CONTEXT         reqContext;

    UNREFERENCED_PARAMETER(Interrupt);

    reqContext = SerialGetRequestContext(Extension->CurrentImmediateRequest);

    Extension->TransmitImmediate = TRUE;
    Extension->ImmediateChar =  *((UCHAR *) (reqContext->SystemBuffer));

    //
    // The isr now has a reference to the request.
    //

    SERIAL_SET_REFERENCE(
        reqContext,
        SERIAL_REF_ISR
        );

    //
    // Check first to see if a write is going on.  If
    // there is then we'll just slip in during the write.
    //

    if (!Extension->WriteLength) {

        //
        // If there is no normal write transmitting then we
        // will "re-enable" the transmit holding register empty
        // interrupt.  The 8250 family of devices will always
        // signal a transmit holding register empty interrupt
        // *ANY* time this bit is set to one.  By doing things
        // this way we can simply use the normal interrupt code
        // to start off this write.
        //
        // We've been keeping track of whether the transmit holding
        // register is empty so it we only need to do this
        // if the register is empty.
        //

        if (Extension->HoldingEmpty) {
            DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller);
            ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller);

        }

    }

    return FALSE;

}
Ejemplo n.º 18
0
BOOLEAN
SerialTurnOffBreak(
    IN PVOID Context
    )

/*++

Routine Description:

    This routine will turn off break in the hardware and
    record the fact the break is off, in the extension variable
    that holds reasons that transmission is stopped.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

    This routine always returns FALSE.

--*/

{

    PSERIAL_DEVICE_EXTENSION Extension = Context;

    UCHAR OldLineControl;

    if (Extension->TXHolding & SERIAL_TX_BREAK) {

        //
        // We actually have a good reason for testing if transmission
        // is holding instead of blindly clearing the bit.
        //
        // If transmission actually was holding and the result of
        // clearing the bit is that we should restart transmission
        // then we will poke the interrupt enable bit, which will
        // cause an actual interrupt and transmission will then
        // restart on its own.
        //
        // If transmission wasn't holding and we poked the bit
        // then we would interrupt before a character actually made
        // it out and we could end up over writing a character in
        // the transmission hardware.

        OldLineControl = READ_LINE_CONTROL(Extension->Controller);

        OldLineControl &= ~SERIAL_LCR_BREAK;

        WRITE_LINE_CONTROL(
            Extension->Controller,
            OldLineControl
            );

        Extension->TXHolding &= ~SERIAL_TX_BREAK;

        if (!Extension->TXHolding &&
            (Extension->TransmitImmediate ||
             Extension->WriteLength) &&
             Extension->HoldingEmpty) {

            DISABLE_ALL_INTERRUPTS(Extension->Controller);
            ENABLE_ALL_INTERRUPTS(Extension->Controller);

        } else {

            //
            // The following routine will lower the rts if we
            // are doing transmit toggleing and there is no
            // reason to keep it up.
            //

            Extension->CountOfTryingToLowerRTS++;
            SerialPerhapsLowerRTS(Extension);

        }

    }

    return FALSE;

}
Ejemplo n.º 19
0
//------------------------------------------------------------------------
// C level interrupt handler for this instance
void RF22_handleInterrupt()
{
    uint8_t _lastInterruptFlags[2];

    // Read the interrupt flags which clears the interrupt
    spiBurstRead(RF22_REG_03_INTERRUPT_STATUS1, _lastInterruptFlags, 2);

    if (_lastInterruptFlags[0] & RF22_IFFERROR)
    {
    	RF22_resetFifos(); // Clears the interrupt
        if (_mode == RF22_MODE_TX)
        {
        	RF22_restartTransmit();
        }
        else if (_mode == RF22_MODE_RX)
        {
        	RF22_clearRxBuf();
            //stop and start Rx
        	RF22_setModeIdle();
        	RF22_setModeRx();
        }
        // stop handling the remaining interruppts as something went wrong here
        return;
    }
    
    // Caution, any delay here may cause a FF underflow or overflow
    if (_lastInterruptFlags[0] & RF22_ITXFFAEM)
    {
    	RF22_sendNextFragment();
    }
  
    if (_lastInterruptFlags[0] & RF22_IRXFFAFULL)
    {
    	RF22_readNextFragment();
    }   
    if (_lastInterruptFlags[0] & RF22_IEXT)
    {
    	RF22_handleExternalInterrupt();
    }
    if (_lastInterruptFlags[1] & RF22_IWUT)
    {

    	RF22_handleWakeupTimerInterrupt();
    }    
    if (_lastInterruptFlags[0] & RF22_IPKSENT)
    {
        _txGood++;
        _mode = RF22_MODE_IDLE;
    }
   
    if (_lastInterruptFlags[0] & RF22_IPKVALID)
    {
        uint8_t len = spiRead(RF22_REG_4B_RECEIVED_PACKET_LENGTH);

        // May have already read one or more fragments
        // Get any remaining unread octets, based on the expected length
        // First make sure we dont overflow the buffer in the case of a stupid length
        // or partial bad receives
        if (len >  RF22_MAX_MESSAGE_LEN
            || len < _bufLen)
        {
            _rxBad++;
            _mode = RF22_MODE_IDLE;
            RF22_clearRxBuf();
            return; // Hmmm receiver buffer overflow.
        }
        spiBurstRead(RF22_REG_7F_FIFO_ACCESS, _buf + _bufLen, len - _bufLen);
        DISABLE_ALL_INTERRUPTS();    // Disable Interrupts
        _rxGood++;
        _bufLen = len;
        _mode = RF22_MODE_IDLE;
        _rxBufValid = true;
        // reset the fifo for next packet??
        //resetRxFifo();
        ENABLE_ALL_INTERRUPTS();     // Enable Interrupts
    }
    
    if (_lastInterruptFlags[0] & RF22_ICRCERROR) {
        _rxBad++;
        RF22_clearRxBuf();
        RF22_resetRxFifo();
        _mode = RF22_MODE_IDLE;
        RF22_setModeRx(); // Keep trying
    }
    
    if (_lastInterruptFlags[1] & RF22_IPREAVAL) {      
        _lastRssi = spiRead(RF22_REG_26_RSSI);
        RF22_clearRxBuf();


    }
}
Ejemplo n.º 20
0
NTSTATUS
SerialEvtDeviceD0Entry(
    IN  WDFDEVICE Device,
    IN  WDF_POWER_DEVICE_STATE PreviousState
    )
/*++

Routine Description:

    EvtDeviceD0Entry event callback must perform any operations that are
    necessary before the specified device is used.  It will be called every
    time the hardware needs to be (re-)initialized.  This includes after
    IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE,
    IRP_MN_SET_POWER-D0.

    This function is not marked pageable because this function is in the
    device power up path. When a function is marked pagable and the code
    section is paged out, it will generate a page fault which could impact
    the fast resume behavior because the client driver will have to wait
    until the system drivers can service this page fault.

    This function runs at PASSIVE_LEVEL, even though it is not paged.  A
    driver can optionally make this function pageable if DO_POWER_PAGABLE
    is set.  Even if DO_POWER_PAGABLE isn't set, this function still runs
    at PASSIVE_LEVEL.  In this case, though, the function absolutely must
    not do anything that will cause a page fault.

Arguments:

    Device - Handle to a framework device object.

    PreviousState - Device power state which the device was in most recently.
        If the device is being newly started, this will be
        PowerDeviceUnspecified.

Return Value:

    NTSTATUS

--*/
{
    PSERIAL_DEVICE_EXTENSION deviceExtension;
    PSERIAL_DEVICE_STATE pDevState;
    SHORT divisor;
    SERIAL_IOCTL_SYNC S;

    SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER,
                "-->SerialEvtDeviceD0Entry - coming from %s\n", DbgDevicePowerString(PreviousState));

    deviceExtension = SerialGetDeviceExtension (Device);
    pDevState = &deviceExtension->DeviceState;

    //
    // Restore the state of the UART.  First, that involves disabling
    // interrupts both via OUT2 and IER.
    //

    WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, 0);
    DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);

    //
    // Set the baud rate
    //

    SerialGetDivisorFromBaud(deviceExtension->ClockRate, deviceExtension->CurrentBaud, &divisor);
    S.Extension = deviceExtension;
    S.Data = (PVOID) (ULONG_PTR) divisor;

#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "PFD warning that we are calling interrupt synchronize routine directly. Suppress it because interrupt is disabled above.")
    SerialSetBaud(deviceExtension->WdfInterrupt, &S);

    //
    // Reset / Re-enable the FIFO's
    //

    if (deviceExtension->FifoPresent) {
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0);
       READ_RECEIVE_BUFFER(deviceExtension, deviceExtension->Controller);
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller,
                          (UCHAR)(SERIAL_FCR_ENABLE | deviceExtension->RxFifoTrigger
                                  | SERIAL_FCR_RCVR_RESET
                                  | SERIAL_FCR_TXMT_RESET));
    } else {
       WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0);
    }

    //
    // Restore a couple more registers
    //

    WRITE_INTERRUPT_ENABLE(deviceExtension, deviceExtension->Controller, pDevState->IER);
    WRITE_LINE_CONTROL(deviceExtension, deviceExtension->Controller, pDevState->LCR);

    //
    // Clear out any stale interrupts
    //

    READ_INTERRUPT_ID_REG(deviceExtension, deviceExtension->Controller);
    READ_LINE_STATUS(deviceExtension, deviceExtension->Controller);
    READ_MODEM_STATUS(deviceExtension, deviceExtension->Controller);

    //
    // TODO:  move this code to EvtInterruptEnable.
    //

    if (deviceExtension->DeviceState.Reopen == TRUE) {
       SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Reopening device\n");

       SetDeviceIsOpened(deviceExtension, TRUE, FALSE);

       //
       // This enables interrupts on the device!
       //

       WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller,
                           (UCHAR)(pDevState->MCR | SERIAL_MCR_OUT2));

       //
       // Refire the state machine
       //

       DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);
       ENABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller);
    }

    SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Entry\n");

    return STATUS_SUCCESS;
}
Ejemplo n.º 21
0
Archivo: write.c Proyecto: ms-iot/bsp
/*++

Routine Description:

    Try to start off the write by slipping it in behind
    a transmit immediate char, or if that isn't available
    and the transmit holding register is empty, "tickle"
    the UART into interrupting with a transmit buffer
    empty.

    NOTE: This routine is called by WdfInterruptSynchronize.

    NOTE: This routine assumes that it is called with the
          cancel spin lock held.

Arguments:

    Context - Really a pointer to the device extension.

Return Value:

    This routine always returns FALSE.

--*/
_Use_decl_annotations_
BOOLEAN
SerialGiveWriteToIsr(
    WDFINTERRUPT Interrupt,
    PVOID Context
    )
{
    PSERIAL_DEVICE_EXTENSION extension = Context;

    // The current stack location.  This contains all of the
    // information we need to process this particular request.

    PREQUEST_CONTEXT reqContext;

    UNREFERENCED_PARAMETER(Interrupt);

    reqContext = SerialGetRequestContext(extension->CurrentWriteRequest);

    // We might have a xoff counter request masquerading as a
    // write.  The length of these requests will always be one
    // and we can get a pointer to the actual character from
    // the data supplied by the user.

    if (reqContext->MajorFunction == IRP_MJ_WRITE) {

        extension->WriteLength = reqContext->Length;
        extension->WriteCurrentChar = reqContext->SystemBuffer;

    } else {

        extension->WriteLength = 1;
        extension->WriteCurrentChar =
            ((PUCHAR)reqContext->SystemBuffer) +
            FIELD_OFFSET(SERIAL_XOFF_COUNTER, XoffChar);
    }

    // The isr now has a reference to the request.

    SERIAL_SET_REFERENCE(reqContext, SERIAL_REF_ISR);

    // Check first to see if an immediate char is transmitting.
    // If it is then we'll just slip in behind it when its done.

    if (!extension->TransmitImmediate) {

        // If there is no immediate char transmitting then we
        // will "re-enable" the transmit holding register empty
        // interrupt.  The 16550 family of devices will always
        // signal a transmit holding register empty interrupt
        // *ANY* time this bit is set to one.  By doing things
        // this way we can simply use the normal interrupt code
        // to start off this write.
        //
        // We've been keeping track of whether the transmit holding
        // register is empty so it we only need to do this
        // if the register is empty.

        if (extension->HoldingEmpty) {

            DISABLE_ALL_INTERRUPTS(extension, extension->Controller);
            ENABLE_ALL_INTERRUPTS(extension, extension->Controller);
        }
    }

    // The rts line may already be up from previous writes,
    // however, it won't take much additional time to turn
    // on the RTS line if we are doing transmit toggling.

    if ((extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
        SERIAL_TRANSMIT_TOGGLE) {

        SerialSetRTS(extension->WdfInterrupt, extension);
    }

    return FALSE;
}