@@ -71,6 +71,7 @@ TERMINAL_DEV mTerminalDevTemplate = {
},
NULL, // TerminalConsoleModeData
0, // SerialInTimeOut
+ DEFAULT_KEYBOARD_TIMER_INTERVAL, // KeyboardTimerInterval
NULL, // RawFifo
NULL, // UnicodeFiFo
@@ -984,10 +985,12 @@ TerminalDriverBindingStart (
);
ASSERT_EFI_ERROR (Status);
+ TerminalDevice->KeyboardTimerInterval = GetKeyboardTimerInterval (Mode);
+
Status = gBS->SetTimer (
TerminalDevice->TimerEvent,
TimerPeriodic,
- KEYBOARD_TIMER_INTERVAL
+ TerminalDevice->KeyboardTimerInterval
);
ASSERT_EFI_ERROR (Status);
@@ -68,7 +68,7 @@ typedef struct {
UINTN Rows;
} TERMINAL_CONSOLE_MODE_DATA;
-#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s
+#define DEFAULT_KEYBOARD_TIMER_INTERVAL 200000 // 0.02s
#define TERMINAL_DEV_SIGNATURE SIGNATURE_32 ('t', 'm', 'n', 'l')
@@ -91,6 +91,7 @@ typedef struct {
EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode;
TERMINAL_CONSOLE_MODE_DATA *TerminalConsoleModeData;
UINTN SerialInTimeOut;
+ UINT64 KeyboardTimerInterval;
RAW_DATA_FIFO *RawFiFo;
UNICODE_FIFO *UnicodeFiFo;
EFI_KEY_FIFO *EfiKeyFiFo;
@@ -1358,4 +1359,28 @@ TerminalConInTimerHandler (
IN EFI_EVENT Event,
IN VOID *Context
);
+
+/**
+ Calculate input polling timer interval by serial IO mode.
+
+ @param Mode Pointer to serial IO mode.
+
+ @retval The required polling timer interval in 100ns.
+
+**/
+UINT64
+GetKeyboardTimerInterval (
+ IN EFI_SERIAL_IO_MODE *Mode
+ );
+
+/**
+ Update period of polling timer event.
+
+ @param TerminalDevice The terminal device to update.
+**/
+VOID
+UpdatePollingRate (
+ IN TERMINAL_DEV *TerminalDevice
+ );
+
#endif
@@ -502,6 +502,71 @@ TerminalConInWaitForKey (
}
/**
+ Calculate input polling timer interval by serial IO mode.
+
+ @param Mode Pointer to serial IO mode.
+
+ @retval The required polling timer interval in 100ns.
+
+**/
+UINT64
+GetKeyboardTimerInterval (
+ IN EFI_SERIAL_IO_MODE *Mode
+ )
+{
+ UINT32 FifoDepth;
+
+ if (Mode->BaudRate == 0) {
+ return DEFAULT_KEYBOARD_TIMER_INTERVAL;
+ }
+
+ FifoDepth = Mode->ReceiveFifoDepth;
+ // Fix incorrect FIFO depth
+ if (FifoDepth == 0) {
+ FifoDepth = 1;
+ }
+
+ // We ignore stop bits and parity bit, and reduce the interval by 1/3,
+ // to make polling rate fast enough to avoid serial input truncation.
+ return DivU64x64Remainder (
+ FifoDepth * Mode->DataBits * 10000000 * 2,
+ Mode->BaudRate * 3,
+ NULL
+ );
+}
+
+
+/**
+ Update period of polling timer event.
+
+ @param TerminalDevice The terminal device to update.
+**/
+VOID
+UpdatePollingRate (
+ IN TERMINAL_DEV *TerminalDevice
+ )
+{
+ UINT64 NewInterval;
+ EFI_STATUS Status;
+
+ NewInterval = GetKeyboardTimerInterval (TerminalDevice->SerialIo->Mode);
+
+ if (TerminalDevice->KeyboardTimerInterval == NewInterval) {
+ return;
+ }
+
+ Status = gBS->SetTimer (
+ TerminalDevice->TimerEvent,
+ TimerPeriodic,
+ NewInterval
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ TerminalDevice->KeyboardTimerInterval = NewInterval;
+}
+
+
+/**
Timer handler to poll the key from serial.
@param Event Indicates the event that invoke this function.
@@ -560,6 +625,9 @@ TerminalConInTimerHandler (
TerminalDevice->SerialInTimeOut = SerialInTimeOut;
}
}
+
+ UpdatePollingRate (TerminalDevice);
+
//
// Check whether serial buffer is empty.
// Skip the key transfer loop only if the SerialIo protocol instance
Calculate serial input polling rate according to parameters from serial IO mode as below, to fix potential input truncation with fixed polling interval 0.02s. Polling interval (100ns) = FifoDepth * (ParityBits + StopBits + DataBits) * 10,000,000 / BaudRate However, as UEFI events will probably delayed by other code of higher TPL, we use below equation to make polling rate fast enough: FifoDepth * DataBits * 10,000,000 * 2 / (BaudRate * 3) Signed-off-by: Heyi Guo <heyi.guo@linaro.org> Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> --- .../Universal/Console/TerminalDxe/Terminal.c | 5 +- .../Universal/Console/TerminalDxe/Terminal.h | 27 ++++++++- .../Universal/Console/TerminalDxe/TerminalConIn.c | 68 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) -- 2.7.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel