Heyi,

I agree the source code required to detect the current tick rate using only 
UEFI services
is more complex.

However, a UEFI driver (especially ones on an add-in devices such as a PCI 
adapter) should not
use a PCD for the system tick rate because the add-in card can be used in 
systems with different
system tick rates.

If you are concerned about complexity, we could consider adding a new lib 
function to the
UefiLib that returns the current system tick rate using UEFI services to detect 
it.  This way, 
A UEFI driver can be kept simple and we move the complexity into a single new 
lib function.

Best regards,

Mike

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Heyi 
> Guo
> Sent: Tuesday, April 26, 2016 8:14 AM
> To: Kinney, Michael D <michael.d.kin...@intel.com>; edk2-devel@lists.01.org
> Cc: Tian, Feng <feng.t...@intel.com>; Zeng, Star <star.z...@intel.com>
> Subject: Re: [edk2] [PATCH] MdeModulePkg/TerminalDxe: Set polling rate by 
> serial IO
> mode
> 
> Hi Michael,
> 
> It seems we are making the implementation more and more complicated. How
> about just creating a PCD for polling rate which can be set freely by
> platforms?
> 
> Regards.
> 
> Heyi
> 
> On 04/24/2016 12:11 AM, Kinney, Michael D wrote:
> > 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
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to