Heyi Guo, The TerminalDxe driver is intended to be a UEFI Driver. The Timer Arch Protocol is a PI Protocol that is intended to be used by the PI DXE Core. In order to determine the timer rate in a UEFI way, create a periodic timer event with a period of 1, 100ns unit, and then measure the time between timer event notification functions.
Mike > -----Original Message----- > From: Heyi Guo [mailto:heyi....@linaro.org] > Sent: Saturday, April 23, 2016 1:54 AM > To: edk2-devel@lists.01.org > Cc: Heyi Guo <heyi....@linaro.org>; Tian, Feng <feng.t...@intel.com>; Zeng, > Star > <star.z...@intel.com>; Kinney, Michael D <michael.d.kin...@intel.com> > Subject: [edk2] [PATCH] MdeModulePkg/TerminalDxe: Set polling rate by serial > IO mode > > Calculate serial input polling rate according to parameters from > serial IO mode as below, to fix potential input truncation. > > Polling interval (100ns) = > FifoDepth * (StartBit + DataBits + StopBits + ParityBits) * 10,000,000 > / BaudRate > (StopBits is assumed to be 1 and ParityBits is ignored for simplicity. > > However, as the event is time sensitive, we need to align the interval > to timer interrupt period to make sure the event will be triggered at > the expected rate. E.g. if the interval is 2.7ms and timer interrupt > period is 1ms, the event will be triggered by time slice sequence as > below: > 3ms 3ms 2ms 3ms 3ms 2ms... > > In such case we will adjust the polling interval to be 2ms. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Heyi Guo <heyi....@linaro.org> > Cc: Feng Tian <feng.t...@intel.com> > Cc: Star Zeng <star.z...@intel.com> > Cc: Michael D Kinney <michael.d.kin...@intel.com> > --- > .../Universal/Console/TerminalDxe/Terminal.c | 5 +- > .../Universal/Console/TerminalDxe/Terminal.h | 28 ++++++- > .../Universal/Console/TerminalDxe/TerminalConIn.c | 92 > ++++++++++++++++++++++ > .../Universal/Console/TerminalDxe/TerminalDxe.inf | 1 + > 4 files changed, 123 insertions(+), 3 deletions(-) > > diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c > b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c > index 6fde3b2..2944707 100644 > --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c > +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c > @@ -71,6 +71,7 @@ TERMINAL_DEV mTerminalDevTemplate = { > }, > NULL, // TerminalConsoleModeData > 0, // SerialInTimeOut > + 0, // 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); > > diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h > b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h > index 269d2ae..a1ff595 100644 > --- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h > +++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h > @@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS > OR IMPLIED. > #include <Protocol/DevicePath.h> > #include <Protocol/SimpleTextIn.h> > #include <Protocol/SimpleTextInEx.h> > +#include <Protocol/Timer.h> > > #include <Library/DebugLib.h> > #include <Library/UefiDriverEntryPoint.h> > @@ -68,8 +69,6 @@ typedef struct { > UINTN Rows; > } TERMINAL_CONSOLE_MODE_DATA; > > -#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s > - > #define TERMINAL_DEV_SIGNATURE SIGNATURE_32 ('t', 'm', 'n', 'l') > > #define TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('t', 'm', 'e', > 'n') > @@ -91,6 +90,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 +1358,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 > diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c > b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c > index 3be877b..e7788a0 100644 > --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c > +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c > @@ -15,6 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS > OR IMPLIED. > > #include "Terminal.h" > > +EFI_TIMER_ARCH_PROTOCOL *gTimer; > > /** > Reads the next keystroke from the input device. The WaitForKey Event can > @@ -502,6 +503,94 @@ 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; > + UINT64 BaudRate; > + UINT64 Interval; > + UINT64 TimerPeriod; > + EFI_STATUS Status; > + > + // Make some assumption if the values are not suitable for calculating. > + BaudRate = Mode->BaudRate; > + if (BaudRate == 0) { > + BaudRate = 115200; > + } > + FifoDepth = Mode->ReceiveFifoDepth; > + if (FifoDepth == 0) { > + FifoDepth = 1; > + } > + > + // We assume stop bits to be 1 and ignore parity bit to make it simple > + // and fast enough to poll. > + Interval = DivU64x64Remainder ( > + FifoDepth * (1 + Mode->DataBits + 1) * 10000000, > + Mode->BaudRate, > + NULL > + ); > + > + // As this is a time sensitive event, we still need to align the > + // interval to timer interrupt period. > + if (gTimer == NULL) { > + Status = gBS->LocateProtocol ( > + &gEfiTimerArchProtocolGuid, > + EFI_NATIVE_INTERFACE, > + (VOID **) &gTimer > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + Status = gTimer->GetTimerPeriod (gTimer, &TimerPeriod); > + ASSERT_EFI_ERROR (Status); > + > + if (Interval <= TimerPeriod) { > + return TimerPeriod; > + } > + return MultU64x64 (DivU64x64Remainder (Interval, TimerPeriod, NULL), > TimerPeriod); > +} > + > + > +/** > + 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 +649,9 @@ TerminalConInTimerHandler ( > TerminalDevice->SerialInTimeOut = SerialInTimeOut; > } > } > + > + UpdatePollingRate (TerminalDevice); > + > // > // Check whether serial buffer is empty. > // Skip the key transfer loop only if the SerialIo protocol instance > diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf > b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf > index 0780296..dfd5035 100644 > --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf > +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf > @@ -84,6 +84,7 @@ > gEfiSimpleTextInProtocolGuid ## BY_START > gEfiSimpleTextInputExProtocolGuid ## BY_START > gEfiSimpleTextOutProtocolGuid ## BY_START > + gEfiTimerArchProtocolGuid ## CONSUMES > > [Pcd] > gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType ## > SOMETIMES_CONSUMES > -- > 2.7.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel