Re: [edk2] [patch] ShellPkg: update ping6 to use timer service instead of timer arch protocol .

2016-11-08 Thread Fu, Siyuan
Reviewed-by: Fu Siyuan 


> -Original Message-
> From: Zhang, Lubo
> Sent: Tuesday, November 8, 2016 7:08 PM
> To: edk2-devel@lists.01.org
> Cc: Ni, Ruiyu ; Ye, Ting ; Fu,
> Siyuan 
> Subject: [patch] ShellPkg: update ping6 to use timer service instead of
> timer arch protocol .
> 
> This patch update the shell ping command to use timer service to calculate
> the
> RTT time, instead of using the timer arch protocol.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Zhang Lubo 
> Cc: Ni Ruiyu 
> Cc: Ye Ting 
> Cc: Fu Siyuan 
> ---
>  .../Library/UefiShellNetwork2CommandsLib/Ping6.c   | 241 ++--
> -
>  .../UefiShellNetwork2CommandsLib.inf   |   1 +
>  .../UefiShellNetwork2CommandsLib.uni   |   4 +-
>  3 files changed, 170 insertions(+), 76 deletions(-)
> 
> diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
> b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
> index 90a2604..a30c064 100644
> --- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
> +++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
> @@ -17,45 +17,44 @@
> 
>  #define PING6_DEFAULT_TIMEOUT  5000
>  #define PING6_MAX_SEND_NUMBER  1
>  #define PING6_MAX_BUFFER_SIZE  32768
>  #define PING6_ONE_SECOND   1000
> -
> -//
> -// A similar amount of time that passes in femtoseconds
> -// for each increment of TimerValue. It is for NT32 only.
> -//
> -#define NTTIMERPERIOD358049
> +#define STALL_1_MILLI_SECOND  1000
> 
>  #pragma pack(1)
> 
>  typedef struct _ICMP6_ECHO_REQUEST_REPLY {
>UINT8   Type;
>UINT8   Code;
>UINT16  Checksum;
>UINT16  Identifier;
>UINT16  SequenceNum;
> -  UINT64  TimeStamp;
> +  UINT32  TimeStamp;
>UINT8   Data[1];
>  } ICMP6_ECHO_REQUEST_REPLY;
> 
>  #pragma pack()
> 
>  typedef struct _PING6_ICMP6_TX_INFO {
>LIST_ENTRY  Link;
>UINT16  SequenceNum;
> -  UINT64  TimeStamp;
> +  UINT32  TimeStamp;
>EFI_IP6_COMPLETION_TOKEN*Token;
>  } PING6_ICMP6_TX_INFO;
> 
>  typedef struct _PING6_PRIVATE_DATA {
>EFI_HANDLE  ImageHandle;
>EFI_HANDLE  NicHandle;
>EFI_HANDLE  Ip6ChildHandle;
>EFI_IP6_PROTOCOL*Ip6;
>EFI_EVENT   Timer;
> 
> +  UINT32  TimerPeriod;
> +  UINT32  RttTimerTick;
> +  EFI_EVENT   RttTimer;
> +
>EFI_STATUS  Status;
>LIST_ENTRY  TxList;
>EFI_IP6_COMPLETION_TOKENRxToken;
>UINT16  RxCount;
>UINT16  TxCount;
> @@ -97,100 +96,193 @@ SHELL_PARAM_ITEMPing6ParamList[] = {
>  //
>  // Global Variables in Ping6 application.
>  //
>  CONST CHAR16*mIp6DstString;
>  CONST CHAR16*mIp6SrcString;
> -UINT64  mFrequency = 0;
> -UINT64  mIp6CurrentTick = 0;
>  EFI_CPU_ARCH_PROTOCOL   *Cpu = NULL;
> 
> +/**
> +  RTT timer tick routine.
> 
> +  @param[in]EventA EFI_EVENT type event.
> +  @param[in]Context  The pointer to Context.
> +
> +**/
> +VOID
> +EFIAPI
> +Ping6RttTimerTickRoutine (
> +  IN EFI_EVENTEvent,
> +  IN VOID *Context
> +  )
> +{
> +  UINT32 *RttTimerTick;
> +
> +  RttTimerTick = (UINT32*) Context;
> +  (*RttTimerTick)++;
> +}
> 
>  /**
> -  Reads and returns the current value of the Time.
> +  Get the timer period of the system.
> +
> +  This function tries to get the system timer period by creating
> +  an 1ms period timer.
> 
> -  @return The current tick value.
> +  @return System timer period in MS, or 0 if operation failed.
> 
>  **/
> -UINT64
> -Ping6ReadTime ()
> +UINT32
> +Ping6GetTimerPeriod(
> +  VOID
> +  )
>  {
> -  UINT64 TimerPeriod;
> -  EFI_STATUS Status;
> +  EFI_STATUS Status;
> +  UINT32 RttTimerTick;
> +  EFI_EVENT  TimerEvent;
> +  UINT32 StallCounter;
> +  EFI_TPLOldTpl;
> 
> -  ASSERT (Cpu != NULL);
> +  RttTimerTick = 0;
> +  StallCounter   = 0;
> 
> -  Status = Cpu->GetTimerValue (Cpu, 0, , );
> +  Status = gBS->CreateEvent (
> +  EVT_TIMER | EVT_NOTIFY_SIGNAL,
> +  TPL_NOTIFY,
> +  Ping6RttTimerTickRoutine,
> +  ,
> +  
> +  );
>if (EFI_ERROR (Status)) {
> -//
> -// The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
> -// TimerPeriod by ourselves.
> -//
> 

[edk2] [patch] ShellPkg: update ping6 to use timer service instead of timer arch protocol .

2016-11-08 Thread Zhang Lubo
This patch update the shell ping command to use timer service to calculate the
RTT time, instead of using the timer arch protocol.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Zhang Lubo 
Cc: Ni Ruiyu 
Cc: Ye Ting 
Cc: Fu Siyuan 
---
 .../Library/UefiShellNetwork2CommandsLib/Ping6.c   | 241 ++---
 .../UefiShellNetwork2CommandsLib.inf   |   1 +
 .../UefiShellNetwork2CommandsLib.uni   |   4 +-
 3 files changed, 170 insertions(+), 76 deletions(-)

diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c 
b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
index 90a2604..a30c064 100644
--- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
+++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
@@ -17,45 +17,44 @@
 
 #define PING6_DEFAULT_TIMEOUT  5000
 #define PING6_MAX_SEND_NUMBER  1
 #define PING6_MAX_BUFFER_SIZE  32768
 #define PING6_ONE_SECOND   1000
-
-//
-// A similar amount of time that passes in femtoseconds
-// for each increment of TimerValue. It is for NT32 only.
-//
-#define NTTIMERPERIOD358049
+#define STALL_1_MILLI_SECOND  1000
 
 #pragma pack(1)
 
 typedef struct _ICMP6_ECHO_REQUEST_REPLY {
   UINT8   Type;
   UINT8   Code;
   UINT16  Checksum;
   UINT16  Identifier;
   UINT16  SequenceNum;
-  UINT64  TimeStamp;
+  UINT32  TimeStamp;
   UINT8   Data[1];
 } ICMP6_ECHO_REQUEST_REPLY;
 
 #pragma pack()
 
 typedef struct _PING6_ICMP6_TX_INFO {
   LIST_ENTRY  Link;
   UINT16  SequenceNum;
-  UINT64  TimeStamp;
+  UINT32  TimeStamp;
   EFI_IP6_COMPLETION_TOKEN*Token;
 } PING6_ICMP6_TX_INFO;
 
 typedef struct _PING6_PRIVATE_DATA {
   EFI_HANDLE  ImageHandle;
   EFI_HANDLE  NicHandle;
   EFI_HANDLE  Ip6ChildHandle;
   EFI_IP6_PROTOCOL*Ip6;
   EFI_EVENT   Timer;
 
+  UINT32  TimerPeriod;
+  UINT32  RttTimerTick;   
+  EFI_EVENT   RttTimer;
+
   EFI_STATUS  Status;
   LIST_ENTRY  TxList;
   EFI_IP6_COMPLETION_TOKENRxToken;
   UINT16  RxCount;
   UINT16  TxCount;
@@ -97,100 +96,193 @@ SHELL_PARAM_ITEMPing6ParamList[] = {
 //
 // Global Variables in Ping6 application.
 //
 CONST CHAR16*mIp6DstString;
 CONST CHAR16*mIp6SrcString;
-UINT64  mFrequency = 0;
-UINT64  mIp6CurrentTick = 0;
 EFI_CPU_ARCH_PROTOCOL   *Cpu = NULL;
 
+/**
+  RTT timer tick routine.
 
+  @param[in]EventA EFI_EVENT type event.
+  @param[in]Context  The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6RttTimerTickRoutine (
+  IN EFI_EVENTEvent,
+  IN VOID *Context
+  )
+{
+  UINT32 *RttTimerTick;
+
+  RttTimerTick = (UINT32*) Context;
+  (*RttTimerTick)++;
+}
 
 /**
-  Reads and returns the current value of the Time.
+  Get the timer period of the system.
+
+  This function tries to get the system timer period by creating
+  an 1ms period timer.
 
-  @return The current tick value.
+  @return System timer period in MS, or 0 if operation failed.
 
 **/
-UINT64
-Ping6ReadTime ()
+UINT32
+Ping6GetTimerPeriod(
+  VOID
+  )
 {
-  UINT64 TimerPeriod;
-  EFI_STATUS Status;
+  EFI_STATUS Status;
+  UINT32 RttTimerTick;
+  EFI_EVENT  TimerEvent;
+  UINT32 StallCounter;
+  EFI_TPLOldTpl;
 
-  ASSERT (Cpu != NULL);
+  RttTimerTick = 0;
+  StallCounter   = 0;
 
-  Status = Cpu->GetTimerValue (Cpu, 0, , );
+  Status = gBS->CreateEvent (
+  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+  TPL_NOTIFY,
+  Ping6RttTimerTickRoutine,
+  ,
+  
+  );
   if (EFI_ERROR (Status)) {
-//
-// The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
-// TimerPeriod by ourselves.
-//
-mIp6CurrentTick += 100;
+return 0;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  Status = gBS->SetTimer (
+  TimerEvent,
+  TimerPeriodic,
+  TICKS_PER_MS
+  );
+  if (EFI_ERROR (Status)) {
+gBS->CloseEvent (TimerEvent);
+return 0;
+  }
+
+  while (RttTimerTick < 10) {
+gBS->Stall (STALL_1_MILLI_SECOND);
+++StallCounter;
   }
 
-  return mIp6CurrentTick;
+  gBS->RestoreTPL (OldTpl);
+
+  gBS->SetTimer (TimerEvent, TimerCancel, 0);
+  gBS->CloseEvent (TimerEvent);
+
+  return StallCounter / RttTimerTick;
 }
 
+
 /**
-  Get and calculate the