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]; }
//------------------------------------------------------------------------ void RF22_clearRxBuf() { DISABLE_ALL_INTERRUPTS(); // Disable Interrupts _bufLen = 0; _rxBufValid = false; ENABLE_ALL_INTERRUPTS(); // Enable Interrupts }
/*---------------------------------------------------------------------------- * 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(); }
//------------------------------------------------------------------------ void RF22_clearTxBuf() { DISABLE_ALL_INTERRUPTS(); _bufLen = 0; _txBufSentIndex = 0; _txPacketSent = false; ENABLE_ALL_INTERRUPTS(); // Enable Interrupts }
//------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------ 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; }
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(); }
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; } }
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; }
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; }
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; }
//-------------------------------------------------------------------------- // 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(); } }
void InitTempSensor(void){ DISABLE_ALL_INTERRUPTS(); SET_MAIN_CLOCK_SOURCE(0); *((BYTE __xdata*) 0xDF26) = 0x80; }
//-------------------------------------------------------------------------- // 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); } }
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); }
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; }
//------------------------------------------------------------------------ // 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(); } }
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; }
/*++ 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; }