/** @file\r
ConsoleOut Routines that speak VGA.\r
\r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
\r
BiosKeyboardPrivate->Queue.Front = 0;\r
BiosKeyboardPrivate->Queue.Rear = 0;\r
+ BiosKeyboardPrivate->QueueForNotify.Front = 0;\r
+ BiosKeyboardPrivate->QueueForNotify.Rear = 0;\r
BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;\r
BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;\r
BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;\r
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
goto Done;\r
}\r
- \r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ BiosKeyboardPrivate,\r
+ &BiosKeyboardPrivate->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 Done;\r
+ }\r
+\r
//\r
// Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
//\r
// Check bit 6 of Feature Byte 2.\r
// If it is set, then Int 16 Func 09 is supported\r
//\r
- if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {\r
+ if (*(UINT8 *) (((UINTN) Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {\r
//\r
// Get Keyboard Functionality\r
//\r
if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {\r
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); \r
}\r
+\r
+ if (BiosKeyboardPrivate->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
+ }\r
+\r
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
\r
if (BiosKeyboardPrivate->TimerEvent != NULL) {\r
gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);\r
gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);\r
+ gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
\r
FreePool (BiosKeyboardPrivate);\r
}\r
\r
//\r
- // Use TimerEvent callback funciton to check whether there's any key pressed\r
+ // Use TimerEvent callback function to check whether there's any key pressed\r
//\r
\r
//\r
@param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
\r
@retval EFI_SUCCESS The command byte is written successfully.\r
- @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.\r
+ @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.\r
\r
**/\r
EFI_STATUS\r
);\r
\r
//\r
- // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
- // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
+ // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
+ // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
// Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,\r
// Real reset will not do.\r
//\r
//\r
gBS->Stall (1000);\r
//\r
- // Use TimerEvent callback funciton to check whether there's any key pressed\r
+ // Use TimerEvent callback function to check whether there's any key pressed\r
//\r
BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));\r
\r
// will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when \r
// KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit \r
// in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode \r
- // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers \r
+ // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other drivers\r
// performance, like USB.\r
//\r
// 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In \r
//\r
// Clear the CTRL and ALT BDA flag\r
//\r
- KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1\r
- KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
+ ACCESS_PAGE0_CODE (\r
+ KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1\r
+ KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
+ );\r
\r
DEBUG_CODE (\r
{\r
//\r
// Clear left alt and left ctrl BDA flag\r
//\r
- KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);\r
- *((UINT8 *) (UINTN) 0x418) = KbFlag2;\r
- KbFlag1 &= ~0x0C; \r
- *((UINT8 *) (UINTN) 0x417) = KbFlag1; \r
-\r
+ ACCESS_PAGE0_CODE (\r
+ KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);\r
+ *((UINT8 *) (UINTN) 0x418) = KbFlag2;\r
+ KbFlag1 &= ~0x0C;\r
+ *((UINT8 *) (UINTN) 0x417) = KbFlag1;\r
+ );\r
\r
//\r
// Output EFI input key and shift/toggle state\r
}\r
\r
//\r
- // Invoke notification functions if exist\r
+ // Signal KeyNotify process event if this key pressed matches any key registered.\r
//\r
for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
CurrentNotify = CR (\r
NotifyEntry, \r
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
- CurrentNotify->KeyNotificationFn (&KeyData);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ //\r
+ // The key notification function needs to run at TPL_CALLBACK\r
+ // while current TPL is TPL_NOTIFY. It will be invoked in\r
+ // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.\r
+ //\r
+ Enqueue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);\r
+ gBS->SignalEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);\r
}\r
}\r
\r
return ; \r
}\r
\r
+/**\r
+ Process key notify.\r
+\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &BiosKeyboardPrivate->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ // \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = Dequeue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);\r
+ //\r
+ // Leave critical section\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+ CurrentNotify = CR (Link, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Free keyboard notify list.\r
\r
\r
@param This Protocol instance pointer.\r
@param KeyData A pointer to a buffer that is filled in with the keystroke \r
- information data for the key that was pressed.\r
+ information data for the key that was pressed. If KeyData.Key,\r
+ KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState\r
+ are 0, then any incomplete keystroke will trigger a notification of\r
+ the KeyNotificationFunction.\r
@param KeyNotificationFunction Points to the function to be called when the key \r
- sequence is typed specified by KeyData. \r
- @param NotifyHandle Points to the unique handle assigned to the registered notification. \r
+ sequence is typed specified by KeyData. This notification function\r
+ should be called at <=TPL_CALLBACK.\r
+ @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
\r
- \r
@retval EFI_SUCCESS The notification function was registered successfully.\r
@retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
@retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
- \r
-**/ \r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
BiosKeyboardRegisterKeyNotify (\r