]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2Keyboard.c
index c0763633d09ef3b7c2e425eb05928beb038b888f..3fbb37820d20b950a1c01d6c914ce4e58ef9c17f 100644 (file)
@@ -1,7 +1,10 @@
-/*++\r
+/** @file\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+  PS/2 Keyboard driver. Routines that interacts with callers,\r
+  conforming to EFI driver model\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
@@ -9,22 +12,23 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
-\r
-  Ps2Keyboard.c\r
-\r
-Abstract:\r
-\r
-  PS/2 Keyboard driver. Routines that interacts with callers,\r
-  conforming to EFI driver model\r
-\r
---*/\r
+**/\r
 \r
 #include "Ps2Keyboard.h"\r
 \r
 //\r
 // Function prototypes\r
 //\r
+/**\r
+  Test controller is a keyboard Controller.\r
+\r
+  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL\r
+  @param Controller           driver's controller\r
+  @param RemainingDevicePath  children device path\r
+\r
+  @retval EFI_UNSUPPORTED controller is not floppy disk\r
+  @retval EFI_SUCCESS     controller is floppy disk\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverSupported (\r
@@ -33,6 +37,15 @@ KbdControllerDriverSupported (
   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
   );\r
 \r
+/**\r
+  Create KEYBOARD_CONSOLE_IN_DEV instance on controller.\r
+\r
+  @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL\r
+  @param Controller   driver controller handle\r
+  @param RemainingDevicePath Children's device path\r
+\r
+  @retval whether success to create floppy control instance.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverStart (\r
@@ -41,6 +54,20 @@ KbdControllerDriverStart (
   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
   );\r
 \r
+/**\r
+  Stop this driver on ControllerHandle. Support stopping any child handles\r
+  created by this driver.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  ControllerHandle  Handle of device to stop driver on\r
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                            children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
+  @retval other             This driver was not removed from this device\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverStop (\r
@@ -50,9 +77,19 @@ KbdControllerDriverStop (
   IN  EFI_HANDLE                     *ChildHandleBuffer\r
   );\r
 \r
-//\r
-// Global variables\r
-//\r
+/**\r
+  Free the waiting key notify list.\r
+\r
+  @param ListHead  Pointer to list head\r
+\r
+  @retval EFI_INVALID_PARAMETER  ListHead is NULL\r
+  @retval EFI_SUCCESS            Sucess to free NotifyList\r
+**/\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  );\r
+\r
 //\r
 // DriverBinding Protocol Instance\r
 //\r
@@ -65,6 +102,16 @@ EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
   NULL\r
 };\r
 \r
+/**\r
+  Test controller is a keyboard Controller.\r
+\r
+  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL\r
+  @param Controller           driver's controller\r
+  @param RemainingDevicePath  children device path\r
+\r
+  @retval EFI_UNSUPPORTED controller is not floppy disk\r
+  @retval EFI_SUCCESS     controller is floppy disk\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverSupported (\r
@@ -72,20 +119,6 @@ KbdControllerDriverSupported (
   IN EFI_HANDLE                     Controller,\r
   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  ControllerDriver Protocol Method\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// GC_TODO:    This - add argument and description to function comment\r
-// GC_TODO:    Controller - add argument and description to function comment\r
-// GC_TODO:    RemainingDevicePath - add argument and description to function comment\r
 {\r
   EFI_STATUS                          Status;\r
   EFI_ISA_IO_PROTOCOL                 *IsaIo;\r
@@ -123,6 +156,15 @@ Returns:
   return Status;\r
 }\r
 \r
+/**\r
+  Create KEYBOARD_CONSOLE_IN_DEV instance on controller.\r
+\r
+  @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL\r
+  @param Controller   driver controller handle\r
+  @param RemainingDevicePath Children's device path\r
+\r
+  @retval whether success to create floppy control instance.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverStart (\r
@@ -130,19 +172,6 @@ KbdControllerDriverStart (
   IN EFI_HANDLE                     Controller,\r
   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// GC_TODO:    This - add argument and description to function comment\r
-// GC_TODO:    Controller - add argument and description to function comment\r
-// GC_TODO:    RemainingDevicePath - add argument and description to function comment\r
-// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
 {\r
   EFI_STATUS                                Status;\r
   EFI_STATUS                                Status1;\r
@@ -214,13 +243,39 @@ Returns:
   ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;\r
   ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;\r
   ConsoleIn->IsaIo                  = IsaIo;\r
-  ConsoleIn->ScancodeBufStartPos    = 0;\r
-  ConsoleIn->ScancodeBufEndPos      = KEYBOARD_BUFFER_MAX_COUNT - 1;\r
-  ConsoleIn->ScancodeBufCount       = 0;\r
-  ConsoleIn->Ctrled                 = FALSE;\r
-  ConsoleIn->Alted                  = FALSE;\r
   ConsoleIn->DevicePath             = ParentDevicePath;\r
 \r
+  ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;\r
+  ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;\r
+  ConsoleIn->ConInEx.SetState            = KeyboardSetState;\r
+  ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;\r
+  ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;\r
+\r
+  InitializeListHead (&ConsoleIn->NotifyList);\r
+\r
+  //\r
+  // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.\r
+  // When KBC decode (IO port 0x60/0x64 decode) is not enabled,\r
+  // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.\r
+  // So instead we read status register to detect after read if KBC decode is enabled.\r
+  //\r
+\r
+  //\r
+  // Return code is ignored on purpose.\r
+  //\r
+  if (!PcdGetBool (PcdFastPS2Detection)) {\r
+    KeyboardRead (ConsoleIn, &Data);\r
+    if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {\r
+      //\r
+      // If nobody decodes KBC I/O port, it will read back as 0xFF.\r
+      // Check the Time-Out and Parity bit to see if it has an active KBC in system\r
+      //\r
+      Status      = EFI_DEVICE_ERROR;\r
+      StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
+      goto ErrorExit;\r
+    }\r
+  }\r
+\r
   //\r
   // Setup the WaitForKey event\r
   //\r
@@ -228,7 +283,7 @@ Returns:
                   EVT_NOTIFY_WAIT,\r
                   TPL_NOTIFY,\r
                   KeyboardWaitForKey,\r
-                  &(ConsoleIn->ConIn),\r
+                  ConsoleIn,\r
                   &((ConsoleIn->ConIn).WaitForKey)\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -237,6 +292,21 @@ Returns:
     goto ErrorExit;\r
   }\r
   //\r
+  // Setup the WaitForKeyEx event\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_WAIT,\r
+                  TPL_NOTIFY,\r
+                  KeyboardWaitForKeyEx,\r
+                  ConsoleIn,\r
+                  &(ConsoleIn->ConInEx.WaitForKeyEx)\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status      = EFI_OUT_OF_RESOURCES;\r
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
+    goto ErrorExit;\r
+  }\r
+\r
   // Setup a periodic timer, used for reading keystrokes at a fixed interval\r
   //\r
   Status = gBS->CreateEvent (\r
@@ -263,6 +333,19 @@ Returns:
     goto ErrorExit;\r
   }\r
 \r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  KeyNotifyProcessHandler,\r
+                  ConsoleIn,\r
+                  &ConsoleIn->KeyNotifyProcessEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    Status      = EFI_OUT_OF_RESOURCES;\r
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
+    goto ErrorExit;\r
+  }\r
+\r
   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
     EFI_PROGRESS_CODE,\r
     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,\r
@@ -272,21 +355,36 @@ Returns:
   //\r
   // Reset the keyboard device\r
   //\r
-  Status = ConsoleIn->ConIn.Reset (&ConsoleIn->ConIn, TRUE);\r
+  Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));\r
   if (EFI_ERROR (Status)) {\r
     Status      = EFI_DEVICE_ERROR;\r
     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
     goto ErrorExit;\r
   }\r
 \r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,\r
+    ParentDevicePath\r
+    );\r
+\r
   ConsoleIn->ControllerNameTable = NULL;\r
-  AddUnicodeString (\r
+  AddUnicodeString2 (\r
     "eng",\r
     gPs2KeyboardComponentName.SupportedLanguages,\r
     &ConsoleIn->ControllerNameTable,\r
-    L"PS/2 Keyboard Device"\r
+    L"PS/2 Keyboard Device",\r
+    TRUE\r
+    );\r
+  AddUnicodeString2 (\r
+    "en",\r
+    gPs2KeyboardComponentName2.SupportedLanguages,\r
+    &ConsoleIn->ControllerNameTable,\r
+    L"PS/2 Keyboard Device",\r
+    FALSE\r
     );\r
 \r
+\r
   //\r
   // Install protocol interfaces for the keyboard device.\r
   //\r
@@ -294,6 +392,8 @@ Returns:
                   &Controller,\r
                   &gEfiSimpleTextInProtocolGuid,\r
                   &ConsoleIn->ConIn,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &ConsoleIn->ConInEx,\r
                   NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -322,7 +422,13 @@ ErrorExit:
   if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {\r
     gBS->CloseEvent (ConsoleIn->TimerEvent);\r
   }\r
-\r
+  if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {\r
+    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
+  }\r
+  if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {\r
+    gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+  }\r
+  KbdFreeNotifyList (&ConsoleIn->NotifyList);\r
   if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {\r
     FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);\r
   }\r
@@ -330,9 +436,11 @@ ErrorExit:
   // Since there will be no timer handler for keyboard input any more,\r
   // exhaust input data just in case there is still keyboard data left\r
   //\r
-  Status1 = EFI_SUCCESS;\r
-  while (!EFI_ERROR (Status1)) {\r
-    Status1 = KeyboardRead (ConsoleIn, &Data);;\r
+  if (ConsoleIn != NULL) {\r
+    Status1 = EFI_SUCCESS;\r
+    while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {\r
+      Status1 = KeyboardRead (ConsoleIn, &Data);;\r
+    }\r
   }\r
 \r
   if (ConsoleIn != NULL) {\r
@@ -356,6 +464,20 @@ ErrorExit:
   return Status;\r
 }\r
 \r
+/**\r
+  Stop this driver on ControllerHandle. Support stopping any child handles\r
+  created by this driver.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  ControllerHandle  Handle of device to stop driver on\r
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                            children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
+  @retval other             This driver was not removed from this device\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 KbdControllerDriverStop (\r
@@ -364,20 +486,6 @@ KbdControllerDriverStop (
   IN  UINTN                          NumberOfChildren,\r
   IN  EFI_HANDLE                     *ChildHandleBuffer\r
   )\r
-/*++\r
-\r
-  Routine Description:\r
-\r
-  Arguments:\r
-\r
-  Returns:\r
-\r
---*/\r
-// GC_TODO:    This - add argument and description to function comment\r
-// GC_TODO:    Controller - add argument and description to function comment\r
-// GC_TODO:    NumberOfChildren - add argument and description to function comment\r
-// GC_TODO:    ChildHandleBuffer - add argument and description to function comment\r
-// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
 {\r
   EFI_STATUS                     Status;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;\r
@@ -398,6 +506,17 @@ KbdControllerDriverStop (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);\r
 \r
@@ -410,14 +529,10 @@ KbdControllerDriverStop (
     ConsoleIn->DevicePath\r
     );\r
 \r
-  if (ConsoleIn->TimerEvent) {\r
+  if (ConsoleIn->TimerEvent != NULL) {\r
     gBS->CloseEvent (ConsoleIn->TimerEvent);\r
     ConsoleIn->TimerEvent = NULL;\r
   }\r
-  //\r
-  // Disable the keyboard interface\r
-  //\r
-  Status = DisableKeyboard (ConsoleIn);\r
 \r
   //\r
   // Since there will be no timer handler for keyboard input any more,\r
@@ -428,12 +543,15 @@ KbdControllerDriverStop (
     Status = KeyboardRead (ConsoleIn, &Data);;\r
   }\r
   //\r
-  // Uninstall the Simple TextIn Protocol\r
+  // Uninstall the SimpleTextIn and SimpleTextInEx protocols\r
   //\r
-  Status = gBS->UninstallProtocolInterface (\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
                   Controller,\r
                   &gEfiSimpleTextInProtocolGuid,\r
-                  &ConsoleIn->ConIn\r
+                  &ConsoleIn->ConIn,\r
+                  &gEfiSimpleTextInputExProtocolGuid,\r
+                  &ConsoleIn->ConInEx,\r
+                  NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -456,13 +574,90 @@ KbdControllerDriverStop (
   //\r
   // Free other resources\r
   //\r
-  if ((ConsoleIn->ConIn).WaitForKey) {\r
+  if ((ConsoleIn->ConIn).WaitForKey != NULL) {\r
     gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);\r
     (ConsoleIn->ConIn).WaitForKey = NULL;\r
   }\r
-\r
+  if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {\r
+    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
+    ConsoleIn->ConInEx.WaitForKeyEx = NULL;\r
+  }\r
+  if (ConsoleIn->KeyNotifyProcessEvent != NULL) {\r
+    gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+    ConsoleIn->KeyNotifyProcessEvent = NULL;\r
+  }\r
+  KbdFreeNotifyList (&ConsoleIn->NotifyList);\r
   FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);\r
   gBS->FreePool (ConsoleIn);\r
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Free the waiting key notify list.\r
+\r
+  @param ListHead  Pointer to list head\r
+\r
+  @retval EFI_INVALID_PARAMETER  ListHead is NULL\r
+  @retval EFI_SUCCESS            Sucess to free NotifyList\r
+**/\r
+EFI_STATUS\r
+KbdFreeNotifyList (\r
+  IN OUT LIST_ENTRY           *ListHead\r
+  )\r
+{\r
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+\r
+  if (ListHead == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  while (!IsListEmpty (ListHead)) {\r
+    NotifyNode = CR (\r
+                   ListHead->ForwardLink,\r
+                   KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+                   NotifyEntry,\r
+                   KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
+                   );\r
+    RemoveEntryList (ListHead->ForwardLink);\r
+    gBS->FreePool (NotifyNode);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  The module Entry Point for module Ps2Keyboard.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializePs2Keyboard(\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Install driver model protocol(s).\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gKeyboardControllerDriver,\r
+             ImageHandle,\r
+             &gPs2KeyboardComponentName,\r
+             &gPs2KeyboardComponentName2\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+  return Status;\r
+}\r
+\r