diff options
Diffstat (limited to 'Core/EM/PS2CTL')
-rw-r--r-- | Core/EM/PS2CTL/Names.c | 269 | ||||
-rw-r--r-- | Core/EM/PS2CTL/PS2Ctl.cif | 19 | ||||
-rw-r--r-- | Core/EM/PS2CTL/PS2Ctl.sdl | 6 | ||||
-rw-r--r-- | Core/EM/PS2CTL/Ps2Ctl.chm | bin | 0 -> 138933 bytes | |||
-rw-r--r-- | Core/EM/PS2CTL/efismplpp.c | 256 | ||||
-rw-r--r-- | Core/EM/PS2CTL/hotkey.c | 420 | ||||
-rw-r--r-- | Core/EM/PS2CTL/kbc.c | 1495 | ||||
-rw-r--r-- | Core/EM/PS2CTL/kbc.h | 321 | ||||
-rw-r--r-- | Core/EM/PS2CTL/mouse.c | 1215 | ||||
-rw-r--r-- | Core/EM/PS2CTL/ps2ctl.h | 178 | ||||
-rw-r--r-- | Core/EM/PS2CTL/ps2kbd.c | 2888 | ||||
-rw-r--r-- | Core/EM/PS2CTL/ps2main.c | 655 | ||||
-rw-r--r-- | Core/EM/PS2CTL/ps2mouse.h | 178 |
13 files changed, 7900 insertions, 0 deletions
diff --git a/Core/EM/PS2CTL/Names.c b/Core/EM/PS2CTL/Names.c new file mode 100644 index 0000000..0acdad4 --- /dev/null +++ b/Core/EM/PS2CTL/Names.c @@ -0,0 +1,269 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/Names.c 7 8/28/09 10:03a Felixp $ +// +// $Revision: 7 $ +// +// $Date: 8/28/09 10:03a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/Names.c $ +// +// 7 8/28/09 10:03a Felixp +// Component Name protocol implementation is upadted to support both +// ComponentName and ComponentName2 protocols +// (based on value of the EFI_SPECIFICATION_VERSION SDL token). +// +// 6 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 5 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 4 4/10/07 10:04a Felixp +// LookupHID routine renamed to LookupPs2Hid to avoid linking issue when +// linking with FloppyCtrl module +// +// 3 3/13/06 2:38a Felixp +// +// 2 3/04/05 1:37p Mandal +// +// 1 2/01/05 1:11a Felixp +// +// 3 1/28/05 1:21p Felixp +// bug fix in component name +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 2 9/30/04 8:13a Olegi +// HotKeys added. +// +// 1 9/21/04 5:42p Olegi +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: Names.c +// +// Description: Component name producer for PS/2 Controller DXE driver +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include "efi.h" +#include "ps2ctl.h" +#include <Protocol\ComponentName.h> +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +#ifndef LANGUAGE_CODE_ENGLISH +#define LANGUAGE_CODE_ENGLISH "eng" +#endif +static BOOLEAN LanguageCodesEqual( + CONST CHAR8* LangCode1, CONST CHAR8* LangCode2 +){ + return LangCode1[0]==LangCode2[0] + && LangCode1[1]==LangCode2[1] + && LangCode1[2]==LangCode2[2]; +} +#endif +//---------------------------------------------------------------------- + +EFI_STATUS PS2GetDriverName( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName +); + +EFI_STATUS +PS2GetControllerName( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName +); + +extern EFI_DRIVER_BINDING_PROTOCOL gPS2CtlDriverBinding; +extern PS2DEV_TABLE supportedDevices[]; + +//---------------------------------------------------------------------- + +CHAR16 *gPS2DriverName = L"AMI PS/2 Driver"; + +//================================================================================== +// Driver component name instance for PS2Ctl Driver +//================================================================================== +EFI_COMPONENT_NAME_PROTOCOL gPS2CtlDriverName = { + PS2GetDriverName, + PS2GetControllerName, + LANGUAGE_CODE_ENGLISH +}; + +//---------------------------------------------------------------------- + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: PS2GetDriverName +// +// Description: Retrieves a Unicode string that is the user readable name of +// the EFI Driver. +// +// +// Parameters: +// EFI_COMPONENT_NAME_PROTOCOL +// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. +// CHAR8 +// Language - A pointer to a three character ISO 639-2 language identifier. +// This is the language of the driver name that that the caller +// is requesting, and it must match one of the languages specified +// in SupportedLanguages. The number of languages supported by a +// driver is up to the driver writer. +// CHAR16 +// DriverName - A pointer to the Unicode string to return. This Unicode string +// is the name of the driver specified by This in the language +// specified by Language. +// +// Output: +// EFI_SUCCES - The Unicode string for the Driver specified by This +// and the language specified by Language was returned +// in DriverName. +// EFI_INVALID_PARAMETER - Language is NULL. +// EFI_INVALID_PARAMETER - DriverName is NULL. +// EFI_UNSUPPORTED - The driver specified by This does not support the +// language specified by Language. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +PS2GetDriverName( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName +) +{ + if(!Language || !DriverName) return EFI_INVALID_PARAMETER; + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) + return EFI_UNSUPPORTED; + *DriverName = gPS2DriverName; + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: PS2GetControllerName +// +// Description: Retrieves a Unicode string that is the user readable name of +// the controller that is being managed by an EFI Driver. +// +// Parameters: +// EFI_COMPONENT_NAME_PROTOCOL +// This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. +// EFI_HANDLE +// ControllerHandle - The handle of a controller that the driver specified by +// This is managing. This handle specifies the controller +// whose name is to be returned. +// EFI_HANDLE +// ChildHandle - The handle of the child controller to retrieve the name +// of. This is an optional parameter that may be NULL. It +// will be NULL for device drivers. It will also be NULL +// for a bus drivers that wish to retrieve the name of the +// bus controller. It will not be NULL for a bus driver +// that wishes to retrieve the name of a child controller. +// CHAR8 +// *Language - A pointer to a three character ISO 639-2 language +// identifier. This is the language of the controller name +// that that the caller is requesting, and it must match one +// of the languages specified in SupportedLanguages. The +// number of languages supported by a driver is up to the +// driver writer. +// CHAR16 +// **ControllerName - A pointer to the Unicode string to return. This Unicode +// string is the name of the controller specified by +// ControllerHandle and ChildHandle in the language +// specified by Language from the point of view of the +// driver specified by This. +// +// Output: +// EFI_SUCCESS - The Unicode string for the user readable name in the +// language specified by Language for the driver +// specified by This was returned in DriverName. +// EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. +// EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid +// EFI_HANDLE. +// EFI_INVALID_PARAMETER - Language is NULL. +// EFI_INVALID_PARAMETER - ControllerName is NULL. +// EFI_UNSUPPORTED - The driver specified by This is not currently +// managing the controller specified by +// ControllerHandle and ChildHandle. +// EFI_UNSUPPORTED - The driver specified by This does not support the +// language specified by Language. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +PS2GetControllerName( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName +) +{ + ACPI_HID_DEVICE_PATH* acpiDP; + PS2DEV_TABLE *ps2dev = 0; + if(!Language || !ControllerName) return EFI_INVALID_PARAMETER; + if (!LanguageCodesEqual( Language, LANGUAGE_CODE_ENGLISH)) + return EFI_UNSUPPORTED; + + // + // Find the last device node in the device path and return "Supported" + // for mouse and/or keyboard depending on the SDL switches. + // + if(!EFI_ERROR(GetPS2_DP(&gPS2CtlDriverBinding, Controller, &acpiDP, EFI_OPEN_PROTOCOL_GET_PROTOCOL)) && + LookupPs2Hid(supportedDevices, acpiDP->HID, acpiDP->UID, &ps2dev)){ + *ControllerName = ps2dev->name; + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/PS2Ctl.cif b/Core/EM/PS2CTL/PS2Ctl.cif new file mode 100644 index 0000000..df7d5f7 --- /dev/null +++ b/Core/EM/PS2CTL/PS2Ctl.cif @@ -0,0 +1,19 @@ +<component> + name = "PS2CTL" + category = ModulePart + LocalRoot = "Core\EM\PS2CTL\" + RefName = "PS2CTL" +[files] +"PS2Ctl.sdl" +"ps2kbd.c" +"ps2main.c" +"ps2ctl.h" +"kbc.h" +"kbc.c" +"ps2mouse.h" +"mouse.c" +"efismplpp.c" +"Names.c" +"hotkey.c" +"Ps2Ctl.chm" +<endComponent> diff --git a/Core/EM/PS2CTL/PS2Ctl.sdl b/Core/EM/PS2CTL/PS2Ctl.sdl new file mode 100644 index 0000000..b70e3f8 --- /dev/null +++ b/Core/EM/PS2CTL/PS2Ctl.sdl @@ -0,0 +1,6 @@ + +PATH + Name = "PS2Ctl_DIR" + Help = "PS/2 Controller source directory" +End + diff --git a/Core/EM/PS2CTL/Ps2Ctl.chm b/Core/EM/PS2CTL/Ps2Ctl.chm Binary files differnew file mode 100644 index 0000000..159b643 --- /dev/null +++ b/Core/EM/PS2CTL/Ps2Ctl.chm diff --git a/Core/EM/PS2CTL/efismplpp.c b/Core/EM/PS2CTL/efismplpp.c new file mode 100644 index 0000000..36bd2d9 --- /dev/null +++ b/Core/EM/PS2CTL/efismplpp.c @@ -0,0 +1,256 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/efismplpp.c 7 11/03/11 5:56a Rajeshms $ +// +// $Revision: 7 $ +// +// $Date: 11/03/11 5:56a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/efismplpp.c $ +// +// 7 11/03/11 5:56a Rajeshms +// [TAG] EIP73263 +// [Category] Improvement +// [Description] PS2Ctl Driver Follow the UEFI Driver Model as per the +// UEFI Spec. +// [Files] ps2main.c, efismplpp.c +// +// 6 8/23/10 4:26a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.h +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 5 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 4 12/16/08 2:06a Iminglin +// The function value of StopMouse for compliance. +// +// 3 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 2 3/04/05 1:37p Mandal +// +// 1 2/01/05 1:11a Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 3 10/04/04 7:42p Olegi +// +// 2 9/21/04 2:29p Andriyn +// +// 1 9/14/04 2:56p Andriyn +// +// 4 9/14/04 2:46p Andriyn +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: efismplpp.c +// +// Description: PS/2 mouse implmentation of simple pointer protocol +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include "ps2ctl.h" +#include <AmiLib.h> +#include "ps2ctl.h" +#include "kbc.h" +#include "ps2mouse.h" + +//---------------------------------------------------------------------- + + +extern MOUSE gMouse; +extern EFI_GUID gDevicePathProtocolGuid; +EFI_GUID gSimplePointerGuid = EFI_SIMPLE_POINTER_PROTOCOL_GUID; + +//---------------------------------------------------------------------- + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: StartMouse +// +// Description: This routine is called from Driver Binding Start function. +// It starts the mouse support +// +// Parameters: +// EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this instance of driver +// binding protocol structure +// EFI_HANDLE Controller - Handle for this driver +// +// Output: EFI_STATUS - Status of the operation +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS StartMouse ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *pDummyDevPath; + MOUSE* pmouse = 0; + + if (EFI_ERROR(gSysTable->BootServices->OpenProtocol( + Controller, + &gDevicePathProtocolGuid, + &pDummyDevPath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER))) { + return EFI_INVALID_PARAMETER; + } + + DetectPS2KeyboardAndMouse(); + + if ( EFI_ERROR(InitMOUSE( &pmouse ))) { + gSysTable->BootServices->CloseProtocol( + Controller, + &gDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + return EFI_DEVICE_ERROR; + } + + gSysTable->BootServices->CreateEvent( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + OnWaitingOnMouse, + pmouse, + &pmouse->iSmplPtr.WaitForInput); + // + // Install protocol interfaces for the pointer device. + // + Status = gSysTable->BootServices->InstallProtocolInterface ( + &Controller, &gSimplePointerGuid, EFI_NATIVE_INTERFACE, + &pmouse->iSmplPtr); + + if (EFI_ERROR(Status)) { + gSysTable->BootServices->CloseProtocol( + Controller, + &gDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + gSysTable->BootServices->CloseEvent(pmouse->iSmplPtr.WaitForInput); + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: StopMouse +// +// Description: This routine is called from Driver Binding Start function. +// It stops the mouse support +// +// Parameters: +// EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this instance of driver +// binding protocol structure +// EFI_HANDLE Controller - Handle for this driver +// +// Output: EFI_STATUS - Status of the operation +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS StopMouse ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller ) +{ + EFI_STATUS Status; + + // + // Kill wait event + // + Status = gSysTable->BootServices->CloseEvent(gMouse.iSmplPtr.WaitForInput); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Uninstall protocol interfaces from the Mouse device. + // + Status = gSysTable->BootServices->UninstallMultipleProtocolInterfaces ( + Controller, + &gSimplePointerGuid, &gMouse.iSmplPtr, + NULL + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Close protocols that is open during Start + // + Status = gSysTable->BootServices->CloseProtocol( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + if (EFI_ERROR(Status)) { + return Status; + } + + pBS->FreePool(gMouse.iSmplPtr.Mode); + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/hotkey.c b/Core/EM/PS2CTL/hotkey.c new file mode 100644 index 0000000..21ef2b9 --- /dev/null +++ b/Core/EM/PS2CTL/hotkey.c @@ -0,0 +1,420 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/hotkey.c 9 4/27/11 4:38a Lavanyap $ +// +// $Revision: 9 $ +// +// $Date: 4/27/11 4:38a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/hotkey.c $ +// +// 9 4/27/11 4:38a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 8 12/01/10 6:13a Anandv +// [TAG] - EIP 45947 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - Build Error on disabling INIT_DEFAULT_HOTKEYS SDL Token. +// [RootCause] - KEY_ASSOCIATION structure variable not declared based on +// INIT_DEFAULT_HOTKEYS SDL Token. +// [Solution] - KEY_ASSOCIATION structure variable declared based on +// INIT_DEFAULT_HOTKEYS SDL Token +// [Files] - hotkey.c +// +// 7 8/23/10 4:31a Rameshr +// Bug Fix: EIP 40818 +// Symptoms: Pause/Break function key has no function in logo screen +// FilesModified: HotKey.c +// Details:Pause key doesn't have valid Ps2 SCAN code. ProcesshotKey +// function will get 0 as input for Pause key and it tries to execute the +// invalid function.So getting exception. +// +// 6 1/06/10 12:09a Rameshr +// Sometimes reset fail in BIOS Setup +// EIP:33327 +// Ctrl+alt+del+Shift key also should reset the system +// +// 5 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 4 4/21/08 5:48p Olegi +// Bugfix in RegisterHotKey routine for multiple hot keys. +// +// 3 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 2 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 1 2/01/05 1:11a Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 1 9/30/04 8:07a Olegi +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: hotkeys.c +// +// Description: PS/2 keyboard hotkeys support routines +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +#include "ps2ctl.h" +#include "kbc.h" +#include <Protocol\HotKeys.h> + +EFI_GUID gHotKeysGuid = EFI_HOT_KEYS_PROTOCOL_GUID; + +HOT_KEYS_PROTOCOL HotKeysProtocol; +KEY_ASSOCIATION *HotKeys_Table; + +extern UINT8 MaxHotKeys; +extern BOOLEAN InitDefaultHotKeys; + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CopyKey +// +// Description: HotKey helper function - Copies key codes from source to +// target buffers +// +// Parameters: +// KEY_ASSOCIATION *SrcKey - Pointer to source buffer +// KEY_ASSOCIATION *TrgKey - Pointer to target buffer +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CopyKey ( + IN KEY_ASSOCIATION *SrcKey, + IN KEY_ASSOCIATION *TrgKey + ) +{ + TrgKey->KeyCode = SrcKey->KeyCode; + TrgKey->KeyAttrib = SrcKey->KeyAttrib; + TrgKey->ReportKey = SrcKey->ReportKey; + TrgKey->KeyExtendedFunc = SrcKey->KeyExtendedFunc; + TrgKey->FunctionContext = SrcKey->FunctionContext; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: RegisterHotKey +// +// Description: This is HotKey protocol API implementation function. +// It registers the "extended" key function. +// +// Parameters: KEY_ASSOCIATION *HotKey - Key code to register +// BOOLEAN ReplaceExisting - a rule that tells whether or +// not we will replace the existing function; this +// parameter will not be considered in case the function +// for a given key is not assigned yet. +// +// Output : EFI_SUCCESS if function is successfully registered +// EFI_OUT_OF_RESOURCES if we already have reached +// MAX_HOTKEYS registered functions and we are not +// replacing the existing one +// EFI_ACCESS_DENIED if requested key has been already +// assigned, can be returned only when ReplaceExisting +// is FALSE +// +// Modified: HotKeys_Table +// +// Referrals: HotKeys_Table +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS RegisterHotKey ( + IN KEY_ASSOCIATION *HotKey, + IN BOOLEAN ReplaceExisting ) +{ + + KEY_ASSOCIATION *hk = HotKeys_Table; + UINT8 i; + UINT8 emptySpot = 0xFF; + // + // See if the key is already registered, at the same time find the empty + // spot in HotKeys_Table + // + for (i = 0; i < MaxHotKeys; i++, hk++) { + if (!hk->KeyCode) { // empty entry found + if (emptySpot == 0xff) { + emptySpot = i; + } + continue; + } + if ((hk->KeyCode == HotKey->KeyCode) && (hk->KeyAttrib == HotKey->KeyAttrib)) { + if (ReplaceExisting) { + CopyKey(HotKey, hk); + return EFI_SUCCESS; + } + else { + return EFI_ACCESS_DENIED; + } + } + } + // + // We are here if the key duplicate is not found + // + if (emptySpot == 0xFF) { + return EFI_OUT_OF_RESOURCES; // no empty space found either + } + + CopyKey(HotKey, &HotKeys_Table[emptySpot]); // fill in the new entry + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: UnregisterHotKeys +// +// Description: This is HotKey protocol API implementation function. +// It unregisters all "extended" key functions. +// +// Parameters: None +// +// Output: EFI_SUCCESS if functions are successfully unregistered +// EFI_ACCESS_DENIED if functions are not unregistered +// +// Modified: HotKeys_Table +// +// Referrals: HotKeys_Table +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS UnregisterHotKeys() +{ + UINT8 i; + KEY_ASSOCIATION ZeroedEntry = {0}; + + for (i = 0; i < MaxHotKeys; i++) { + CopyKey(&ZeroedEntry, &HotKeys_Table[i]); + } + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ResetSystem +// +// Description: This routine performs a warm boot of the system +// +// Parameters: VOID *Context - Pointer to context +// +// Output: EFI_SUCCESS +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ResetSystem ( + VOID *Context ) +{ + gSysTable->RuntimeServices->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: InitHotKeys +// +// Description: This routine is called from StartKeyboard function, +// it initializes the PS/2 keyboard hot keys and produces +// HotKeys protocol. +// +// Parameters: EFI_HANDLE Controller - Handle for this driver +// +// Output: EFI_STATUS - Status of the operation +// +// Modified: HotKeysProtocol +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS InitHotKeys ( + EFI_HANDLE Controller ) +{ + EFI_STATUS Status; + KEY_ASSOCIATION hk; + // + // Publish the hot key registration interface + // + HotKeysProtocol.RegisterHotKey = RegisterHotKey; + HotKeysProtocol.UnregisterHotKeys = UnregisterHotKeys; + Status = gSysTable->BootServices->InstallProtocolInterface ( + &Controller, + &gHotKeysGuid, + EFI_NATIVE_INTERFACE, + &HotKeysProtocol + ); + // + // Initialise the hotkeys table list + // + Status = pBS->AllocatePool( + EfiBootServicesData, + MaxHotKeys * sizeof(KEY_ASSOCIATION), + &HotKeys_Table ); + pBS->SetMem( HotKeys_Table, MaxHotKeys * sizeof(KEY_ASSOCIATION), 0); + + if ( InitDefaultHotKeys ) { + // + // Register Ctl+Alt+Del combination for Soft Reset + // + hk.KeyCode = 0x53; + + hk.ReportKey = TRUE; + hk.KeyExtendedFunc = ResetSystem; + hk.FunctionContext = NULL; + + hk.KeyAttrib = LEFT_CONTROL_PRESSED | LEFT_ALT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = LEFT_CONTROL_PRESSED | RIGHT_ALT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | LEFT_ALT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | RIGHT_ALT_PRESSED; + RegisterHotKey(&hk, TRUE); + + hk.KeyAttrib = LEFT_CONTROL_PRESSED | LEFT_ALT_PRESSED | LEFT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = LEFT_CONTROL_PRESSED | RIGHT_ALT_PRESSED | LEFT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | LEFT_ALT_PRESSED | LEFT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | RIGHT_ALT_PRESSED | LEFT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + + hk.KeyAttrib = LEFT_CONTROL_PRESSED | LEFT_ALT_PRESSED | RIGHT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = LEFT_CONTROL_PRESSED | RIGHT_ALT_PRESSED | RIGHT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | LEFT_ALT_PRESSED | RIGHT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + hk.KeyAttrib = RIGHT_CONTROL_PRESSED | RIGHT_ALT_PRESSED | RIGHT_SHIFT_PRESSED; + RegisterHotKey(&hk, TRUE); + + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessHotKey +// +// Description: This routine searches the HotKey table for the matching +// key and executes the corresponding "key extension" +// function. +// +// Parameters: UINT8 Code - key make code +// UINT16 KeyShiftState - Shift/Alt/Ctrl modifiers: +// RIGHT_SHIFT_PRESSED 0x00000001 +// LEFT_SHIFT_PRESSED 0x00000002 +// RIGHT_CONTROL_PRESSED 0x00000004 +// LEFT_CONTROL_PRESSED 0x00000008 +// RIGHT_ALT_PRESSED 0x00000010 +// LEFT_ALT_PRESSED 0x00000020 +// RIGHT_LOGO_PRESSED 0x00000040 +// LEFT_LOGO_PRESSED 0x00000080 +// +// Output: EFI_SUCCESS if 1)key is not found or 2)key is found, +// function executed and key has to be reported back +// to the caller; +// EFI_NOT_READY if key is found but is not to be reported +// back to the caller. +// Referrals: HotKeys_Table +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +ProcessHotKey ( + UINT8 Code, + UINT16 KeyShiftState +) +{ + KEY_ASSOCIATION *hk = HotKeys_Table; + UINT8 i; + + // + // Validate the Input Data + // + if(Code == 0 && KeyShiftState == 0) { + return EFI_NOT_READY; + } + + // + // Find the match in the table + // + for (i = 0; i < MaxHotKeys; i++) { + if ((hk->KeyCode == Code) && (hk->KeyAttrib == (UINT8)KeyShiftState)) { + // + // Match found - execute the function + // + hk->KeyExtendedFunc(hk->FunctionContext); + return (hk->ReportKey)? EFI_SUCCESS: EFI_NOT_READY; + } + hk++; + } + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/kbc.c b/Core/EM/PS2CTL/kbc.c new file mode 100644 index 0000000..1712196 --- /dev/null +++ b/Core/EM/PS2CTL/kbc.c @@ -0,0 +1,1495 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/kbc.c 41 11/07/12 12:24a Srikantakumarp $ +// +// $Revision: 41 $ +// +// $Date: 11/07/12 12:24a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/kbc.c $ +// +// 41 11/07/12 12:24a Srikantakumarp +// [TAG] EIP99411 +// [Category] Improvement +// [Description] Add port validation check in the PS2Ctrl module before +// starting the driver. +// [Files] kbc.c, kbc.h, mouse.c, ps2main.c, CORE_DXE.sdl, Tokens.c +// +// 40 10/18/12 8:58a Deepthins +// [TAG] EIP70313 +// [Category] Improvement +// [Description] Used CheckIssueLEDCmd in function LEDsOnOff instead of +// OutToKb(Kbd, 0xED) +// [Files] kbc.c, ps2kbd.c and kbc.h +// +// 39 6/05/12 9:30a Lavanyap +// [TAG] EIP91313 +// [Category] Bug Fix +// [Severity] Critical +// [Symptom] Ps2 keyboard does not work with Ps2Ctl label (INT)4.6.5.4 +// [RootCause] Could not process PS2 keyboard data since there were more +// frequent calls to DISABLE the Keyboard. +// [Solution] Disabled and enabled the keyboard only before processing +// the PS2 keyboard data. +// [Files] kbc.c +// +// 38 5/02/12 2:27a Deepthins +// [TAG] EIP63116 +// [Category] Improvement +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Ps2kbd.c, Mouse.c, kbc.h, kbc.c +// +// 37 4/30/12 2:21a Rajeshms +// [TAG] EIP86986 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Can not detect F8 key on PS2 Keyboard while booting to EFI +// aware OS. +// [RootCause] Make code of F8 key (0x42) is taken by int09h and EFI +// aware OS calls only one ReadKeyStroke() for any key catch, Now PS2 +// driver will take Break Code of F8 key(0xC2) and returns EFI_NOT_READY. +// [Solution] Multiple Read from PS2 keyboard is implemented and read +// exits if any valid key is detected. Also, the BDA keyboard buffer is +// checked for any missed key in EFI. +// [Files] ps2kbd.c, kbc.c, CORE_DXE.sdl +// +// 36 2/01/12 1:59a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 35 8/02/11 4:43a Rameshr +// [TAG] - EIP 58974 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - Yellow exclamation mark in Windows when PS2 KB/MS are not +// present. +// [RootCause]- ACPI name space variable reports that PS2 device present +// [Solution] - Updated the SIO device status based on the device present +// after BDS. +// [Files] - Kbc.c, Kbc.h , Ps2main.c +// +// 34 4/27/11 4:36a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 33 2/05/11 3:57p Artems +// Fixed bug with ellow exclamation mark in Windows, when PS2 keyboard is +// absent +// +// 32 1/24/11 3:39p Pats +// [TAG] - EIP 18488 +// [Category] - Enhancement +// [Severity] - Normal +// [Symptom] - PS2CTL: Need hooks for port swap, Keybaord mouse detect. +// [RootCause] - Support may be needed for kbc controller or SIO with +// different support from AMI KB-5. +// [Solution] - Removed token control of AutodetectKbdMousePortsPtr. +// [Files] - kbc.c +// +// 31 1/05/11 1:02a Rameshr +// [TAG] EIPEIP 35306 +// [Category] Improvement +// [Description] Report the Ps2 Controller and Device Error Codes. +// [Files] AmiStatuscodes.h, Kbc.c, Kbc.h,Ps2ctl.sdl, ps2kbd.c, +// ps2main.c ,Statuscode.h +// +// 30 12/10/10 5:28a Rameshr +// [TAG] - EIP 47011 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - DTM IO Tests fail due to presence of PS/2 devices that are +// not ready - no PS/2 devices attached during test. +// [RootCause]- PS2 device _STA method returns that, device is present . +// [Solution] - Updated the SIO device status based on the device +// presence. +// [Files] - Kbc.c , Kbc.h, Mouse.c +// +// 29 8/23/10 4:37a Rameshr +// Bug Fix: EIP 41862 +// Symptoms: If plug PS/2 KB only, Can`t use hot key enter iSCSI OPROM +// .The CheckIssueLEDCmd routine cause PS2 keyboard not work. +// FilesModified: Kbc.c +// Details: Send Data immediately after sending LED command "ED". +// +// 28 8/23/10 4:23a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.c +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 27 7/01/10 9:03a Rameshr +// Issue:If PS/2 KBD isn't present, KBC returns oxFE when send 0xED +// command, that makes system to hang for 5 to 10 Sec. +// Solution:If command output is 0xFE (Resent) , tried for 3 times and +// gets out. +// EIP 40515 +// +// 26 8/04/09 4:32p Rameshr +// Symptom: Boot to Shell and Press Ps2 keyboard Key, Reduces the EFI +// available memory. +// RootCause: Progress_code macro allocate the memory for the Data hub and +// when ever key pressed , Disable/enable keyboard gets called. That sends +// the progress code. +// Solution: Removed the Progress code from Disable/Enable keyboard +// functions. +// +// 25 7/01/09 5:29p Olegi +// Correction: previous file headers changes were done on the older file. +// Now changes are applied to the latest file. +// +// 24 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 23 4/20/09 1:53p Rameshr +// CCB byte programmed once Keyboard controller is avilable. +// EIP 19880-CCB byte not programmed +// +// 22 4/22/08 4:31p Felixp +// Additional progress codes added +// +// 21 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 20 10/23/07 4:05p Olegi +// Removed BDA related data storage. +// +// 19 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 18 3/19/07 2:22p Pats +// Removed test for keyboard active. Issues start keyboard command on +// logic of SDL tokens only. +// +// 17 3/13/07 5:35p Pats +// Fixed problem of Lakeport not seeing setup key. +// +// 16 3/13/07 3:01p Pats +// If keyboard detection is disabled, tests for keyboard active and issues +// keyboard enable command only if it is not active. This preserves the +// input key if there is one. +// +// 15 3/13/07 11:11a Pats +// Added line to enable keyboard if keyboard detection is disabled. +// Required for some platforms. +// +// 14 3/01/07 3:20p Pats +// Fixed problem of mouse not working if keyboard detection disabled. +// +// 13 2/28/07 6:05p Pats +// Made PS2 Keyboard detection removable with SDL token, to speed up boot, +// and to keep keep Setup key (F2 or Del) from being absorbed. +// +// 12 4/12/06 9:14a Srinin +// Write to Port 80h removed. +// +// 11 1/09/06 11:38a Felixp +// +// 9 12/22/05 10:23a Srinin +// KBD Enable/Disable call optimized. Cleaned up the code. +// +// 8 10/27/05 1:04p Srinin +// When command to KBD is given, check for Timeout error added. +// +// 7 10/11/05 4:14p Srinin +// KBD and Mouse init done together. Re-entry problem fixed. +// +// 6 8/31/05 6:21p Srinin +// Comments added to "AutodetectKbdMousePorts" +// +// 5 8/31/05 4:45p Srinin +// When KBD not connected, DetectPS2Keyboard +// will returns EFI_SUCCESS in order to support hot plug. +// +// 4 8/30/05 5:23p Srinin +// PortSwap logic changed. +// +// 3 5/03/05 8:51a Olegi +// Delay correction in OutToKb function. +// +// 2 2/25/05 10:34a Olegi +// Removed duplicated code. +// +// 1 2/01/05 1:10a Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 2 9/17/04 7:02p Olegi +// +// 1 8/27/04 3:18p Olegi +// Initial VSS checkin. +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: kbc.c +// +// Description: PS/2 Controller I/O support fuctions +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include "ps2ctl.h" +#include "kbc.h" +#include "genericSio.h" + + +//---------------------------------------------------------------------- + +extern BOOLEAN MouseResetRequired; +extern BOOLEAN DetectPs2KeyboardValue; +extern BOOLEAN InstallKeyboardMouseAlways; +extern UINT32 IbFreeTimeoutValue; +extern UINT32 IbFreeMaxTimeoutValue; +BOOLEAN MouseEnableState = FALSE; +BOOLEAN KBDEnableState = TRUE; +BOOLEAN Ps2KbdDetected = FALSE; +BOOLEAN Ps2KbdMouseDetected=FALSE; +extern BOOLEAN Ps2MouseDetected; +extern BOOLEAN KbdIrqSupport; +extern UINT8 gKeyboardIrqInstall; +extern EFI_LEGACY_8259_PROTOCOL *mLegacy8259; +BOOLEAN InsidePS2DataDispatcher = FALSE; +//---------------------------------------------------------------------- + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KBCDummyGetData +// +// Description: Reads keyboard data port to clear it +// +// Parameters: VOID *Context - Pointer to context +// +// Output: UINT8 - Keyboard data port data +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +KBCDummyGetData ( + VOID *Context ) +{ + UINT8 bData; + bData = IoRead8(KBC_DATA_PORT); + TRACEKBD((-1,"KD %X ", bData)); + return bData; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: MouseDummyGetData +// +// Description: Reads keyboard data port to clear it +// +// Parameters: VOID *Context - Pointer to context +// +// Output: UINT8 - Keyboard data port data +// +// Modified: MouseResetRequired +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 +MouseDummyGetData ( + VOID *Context ) +{ + UINT8 bData; + bData = IoRead8(KBC_DATA_PORT); + TRACEKBD((-1,"MD %X ", bData)); + MouseResetRequired = TRUE; // Since a orphan mouse data is + // received, mouse packet will be out + // of sync. + return bData; + +} + + +//---------------------------------------------------------------------- +// The following two fuction pointers are initialized with dummy +// routines; they will be updated with the real routine pointers +// in the corresponding device drivers' start functions. +//---------------------------------------------------------------------- + +STATEMACHINEPROC DrivePS2KbdMachine = KBCDummyGetData; +STATEMACHINEPROC DrivePS2MouseMachine = MouseDummyGetData; + +extern KEYBOARD gKbd; + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KBCBatTest +// +// Description: Runs Basic Assurance Test on KBC. +// +// Parameters: None +// +// Output: EFI_SUCCESS or EFI_DEVICE_ERROR +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS KBCBatTest() +{ + UINT16 wCounter = 0xFFFF; + PROGRESS_CODE(DXE_KEYBOARD_SELF_TEST); + // + // Empty KBC before BAT + // + for (; wCounter; wCounter--) { + IoRead8(KBC_DATA_PORT); + IoDelay(); + if (!(IoRead8(KBC_CMDSTS_PORT) & (KBC_OBF | KBC_IBF))) { + break; + } + } + if (!wCounter) { + return EFI_DEVICE_ERROR; + } + + // + // Perform BAT + // + if (Read8042(0xAA) != 0x55) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: AutodetectKbdMousePorts +// +// Description: Auto detection of KB/MS using AMI KB-5. This code will +// allow the connector swap of Keyboard and PS2 Mouse i.e. +// keyboard can be connected to PS2 Mouse connector and +// vice-versa. +// +// Parameters: None. AMI KB-5 present in the system, keyboard controller +// BAT is complete. +// +// Output: None +// +// +// Notes: This code should be used only if the motherboard has +// AMI KB-5 which is also available in IO chipsets having KBC +// e.g. SMC932, etc. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID AutodetectKbdMousePorts() +{ + UINT8 bData, Index; + + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + WriteKeyboardCommand(0x60); // Lock KBD + IoRead8(KBC_DATA_PORT); // Discard any data + + Write8042CommandByte(0x74); // KBD and Aux device disabled + +// Check for KBC version + IoRead8(KBC_DATA_PORT); // Discard any data + WriteKeyboardCommand(0xa1); // + if (!ObFullReadTimeout(&bData, 20, TRUE) && bData == 0x35) { + + WriteKeyboardCommand(0x60); + WriteKeyboardData(4); + + for (Index = 6; Index; Index--){ // Read max. 6 data + if (ObFullReadTimeout(&bData, 10, TRUE)) break; + } + + WriteKeyboardCommand(0xa7); // Disable Mouse + WriteKeyboardCommand(0xc8); // Select Primary + + WriteKeyboardData(rKeyboardID); // Read KBD ID + + ObFullReadTimeout(&bData, 1000, TRUE); // Read ACK + + if (bData == rKeyboardID) goto PortSwap; + + if (bData == KB_ACK_COM) { + ObFullReadTimeout(&bData, 100, TRUE); +// When Mouse is connected to KBD port, control goes to PortSwap here + if (!bData) goto PortSwap; + ObFullReadTimeout(&bData, 100, TRUE); + } + bData = IoRead8(KBC_CMDSTS_PORT); +// When KBD is connected to the KBD port, control returns here + if (!(bData & KBC_TIMEOUT_ERR)) return; + + WriteKeyboardCommand(0xD4); // Secondary Port + WriteKeyboardData(rKeyboardID); // Read KBD ID + ObFullReadTimeout(&bData, 1000, TRUE); + if (bData == rKeyboardID) return; + if (bData == KB_ACK_COM) { +// When Mouse alone is connected to Mouseport, control returns here + if (!ObFullRead()) return; + bData = ObFullRead(); + } + bData = IoRead8(KBC_CMDSTS_PORT); +// When KBD alone is connected to Mouse port, no time out error and control +// goes to portswap. + if (bData & KBC_TIMEOUT_ERR) return; + +PortSwap: + WriteKeyboardCommand(0xC9); + return; + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: AuxDeviceCommand +// +// Description: This routine issues AuxDevice command, and returns the +// from the AUX device +// the connector swap of Keyboard and PS2 Mouse i.e. keyboard +// can be connected to PS2 Mouse connector and vice-versa. +// +// Parameters: UINT8 bCmd - AUX device command +// +// Output: UINT8 Data from AUX device +// +// Notes: Only AUX commands that expect the response from AUX device +// can be executed using this function; otherwise the code will +// be stuck waiting for OBF +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 AuxDeviceCommand ( + UINT8 bCmd ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return (UINT8)Status; + } + IoWrite8(KBC_CMDSTS_PORT, 0xD4); + + return IssueCommand(bCmd); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: IssueCommand +// +// Description: Helper function to read the data after executing AUX +// device command. +// +// Parameters: UINT8 bCmd - AUX device command +// +// Output: UINT8 Data from AUX device +// +// Notes: Only AUX commands that expect the response from AUX device +// can be executed using this function; otherwise the code will +// be stuck waiting for OBF +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 IssueCommand ( + UINT8 bCmd ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return (UINT8)Status; + } + IoWrite8(KBC_DATA_PORT, bCmd); + IbFree(); + for (;;) + { + if (IoRead8(KBC_CMDSTS_PORT) & KBC_OBF) { + return IoRead8(KBC_DATA_PORT); + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: Read8042 +// +// Description: Sends the given command to KBC, reads and returns the +// acknowledgement byte returned from KBC. +// +// Parameters: UINT8 bCmd - Command to send to KBC +// +// Output: UINT8 Acknowledgment byte +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 Read8042 ( + UINT8 bCmd ) +{ + + UINT8 bData = 0xFE; + WriteKeyboardCommand(bCmd); + ObFullReadTimeout(&bData, 40, FALSE); + return bData; + +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ReadDevice +// +// Description: Sends the given command to KBD, reads and returns the +// acknowledgement byte returned from KBD. +// +// Parameters: UINT8 bCmd - Command to send to KBC +// UINT8 *Data - Pointer to data buffer +// UINT8 Response - Response expected +// +// Output: EFI_SUCCESS - Data == Response +// EFI_DEVICE_ERROR - Data != Response +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ReadDevice ( + UINT8 bCmd, + UINT8 *Data, + UINT8 Response ) +{ + + WriteKeyboardData(bCmd); + if (ObFullReadTimeout(Data, 40, FALSE)) return EFI_DEVICE_ERROR; + if (*Data == Response) return EFI_SUCCESS; + return EFI_DEVICE_ERROR; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: WriteKeyboardCommand +// +// Description: Writes command to KBC. +// +// Parameters: UINT8 bCmd - Command to send to KBC +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteKeyboardCommand ( + UINT8 bCmd ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + IoWrite8(KBC_CMDSTS_PORT, bCmd); + IbFree(); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: WriteKeyboardData +// +// Description: Writes data to KBC. +// +// Parameters: UINT8 bCmd - Data to send to KBC +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID WriteKeyboardData ( + UINT8 bCmd ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + IoWrite8(KBC_DATA_PORT, bCmd); + IbFree(); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: Write8042CommandByte +// +// Description: Writes CCB to KBC +// +// Parameters: UINT8 bCCB - Command byte to send to KBC +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID Write8042CommandByte ( + UINT8 bCCB ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + WriteKeyboardCommand(0x60); // CMD to send command byte + IoWrite8(KBC_DATA_PORT, bCCB); // Write command byte into KBC + IbFree(); // Wait until input buffer is free +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ObFullRead +// +// Description: Waits for Output Buffer Full and then reads the data port +// +// Parameters: None +// +// Output: UINT8 KBC Data port data +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 ObFullRead() +{ + for (;;) { + if (IoRead8(KBC_CMDSTS_PORT) & KBC_OBF) { + return IoRead8(KBC_DATA_PORT); + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: IbFree +// +// Description: Waits for Iutput Buffer to be empty +// +// Parameters: None +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID IbFree() +{ + for (;;) { + if (!(IoRead8(KBC_CMDSTS_PORT) & KBC_IBF)) { + break; + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: IbFreeTimeout +// +// Description: Waits a specified timeout for Iutput Buffer to be empty +// +// Parameters: UINT32 TimeoutValue +// +// Return value: EFI_STATUS (EFI_SUCCESS or EFI_TIMEOUT) +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS IbFreeTimeout( UINT32 TimeoutValue) +{ + UINTN i; + + for (i = 0; i < TimeoutValue; i++) { + if (!(IoRead8(KBC_CMDSTS_PORT) & KBC_IBF)) { + return EFI_SUCCESS; + } + gSysTable->BootServices->Stall(1000); // 1 ms + } + return EFI_TIMEOUT; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: IoDelay +// +// Description: Performs IO delay by executing IO read. +// +// Parameters: None +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID IoDelay() +{ + IoRead8(0x61); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ObFullReadTimeout +// +// Description: This routine checks for the data availbility in output +// buffer for a short period of time, if data is available +// within this time, it reads and returns the data from +// output buffer. +// +// Paremeters: UINT8* data - Pointer to the byte to be updated +// UINT32 msec - Milliseconds timeout +// BOOLEAN ONLYOBF - Only waits for OBF if true +// +// Output: BOOLEAN - Returns FALSE if data is successfully updated +// (no timeout), data is updated +// Returns TRUE if time-out +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +ObFullReadTimeout ( + UINT8* data, + UINT32 msec, + BOOLEAN ONLYOBF ) +{ + + UINT8 bData; + UINT32 loopcount = msec << 1; + + + for (; loopcount; loopcount--) { + + bData = IoRead8(KBC_CMDSTS_PORT); + + if (ONLYOBF && (bData & KBC_OBF)) { + *data = IoRead8(KBC_DATA_PORT); + return FALSE; + } + + if ((bData & (KBC_OBF|KBC_AUX_OBF)) == KBC_OBF) { + *data = IoRead8(KBC_DATA_PORT); + if (bData & 0x40) { + TRACEKBD((-1, "Status Reg K : %x, %x\n", bData, *data)); + return TRUE; + } + else return FALSE; // No timeout + } + + if ((bData & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF | KBC_AUX_OBF)){ + TRACEKBD((-1, "AUX OBF inside KBD")); + return TRUE; + } + + gSysTable->BootServices->Stall(500); // 0.5msec + + } + TRACEKBD((-1, "KBD data not available")); + return TRUE; // Timeout +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: OutToKb +// +// Description: Send the given command to KDB during runtime. +// +// Parameters: KEYBOARD* kbd - Pointer to keyboard buffer +// UINT8 bCmd - Command to send to keyboard +// +// Output: EFI_SUCCESS or EFI_DEVICE_ERROR +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +OutToKb ( + KEYBOARD* kbd, + UINT8 bCmd ) +{ + UINT8 bCounter1, bData; + UINT32 Counter; + EFI_STATUS Status; + + // + // If Keyboard irq is supported, device acknowlegement is prossed by IRQ + // Handler. The acknowledgement data is stored in Kbd->CommandResponded + // + if(KbdIrqSupport && gKeyboardIrqInstall){ + if(KBDEnableState) { + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return Status; + } + IoWrite8(KBC_DATA_PORT, bCmd); + IbFree(); + for (Counter = 1000; Counter > 0; Counter--) { + if (kbd->CommandResponded == KB_ACK_COM){ + kbd->CommandResponded =NULL; + return EFI_SUCCESS; + } + if (kbd->CommandResponded == KB_RSND_COM){ + kbd->CommandResponded =NULL; + break; + } + gSysTable->BootServices->Stall(1000); + } + return EFI_DEVICE_ERROR; + } + } + + + for (bCounter1 = 3; bCounter1 > 0; bCounter1--) { + IbFree(); + IoWrite8(KBC_DATA_PORT, bCmd); + IbFree(); + + for (Counter = 1000; Counter > 0; Counter--) { + if (IoRead8(KBC_CMDSTS_PORT) & KBC_OBF) { + bData = IoRead8(KBC_DATA_PORT); + if (bData == 0xFA) { + return EFI_SUCCESS; + } else if (bData == 0xFE) { + break; + } else { + if (IoRead8(KBC_CMDSTS_PORT) & KBC_TIMEOUT_ERR) break; + // + // Insert the key into the buffer + // + if (kbd) { + HandleKBDData(kbd, bData); + if (kbd->KeyIsReady) { + ProcessHotKey(kbd->KeyData.PS2ScanCode, kbd->KeyData.KeyState.KeyShiftState); + InsertKeyToBuffer(kbd, &kbd->KeyData); + kbd->KeyIsReady = FALSE; + } + } + } + } + gSysTable->BootServices->Stall(1000); // 1msec + } + } + + return EFI_DEVICE_ERROR; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DisableKeyboard +// +// Description: Disables KBD interface and reads the data from KBC +// data port. +// +// Modified: KBDEnableState +// +// Referral(s): KBDEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID DisableKeyboard() +{ + EFI_STATUS Status; + + if (!KBDEnableState) return; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + IoWrite8(KBC_CMDSTS_PORT, 0xAD); + IbFree(); + KBDEnableState = FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: EnableKeyboard +// +// Description: Enables KBD interface. +// +// Paremeters: None +// +// Output: Status +// +// Modified: KBDEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS EnableKeyboard() +{ + EFI_STATUS Status=EFI_SUCCESS; + + if (KBDEnableState) { + return EFI_SUCCESS; + } + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return Status; + } + IoWrite8(KBC_CMDSTS_PORT, 0xAE); + Status = IbFreeTimeout(IbFreeTimeoutValue); + KBDEnableState = TRUE; + if (EFI_ERROR(Status)) { + KBDEnableState = FALSE; + } + + return Status; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DisableAuxDevice +// +// Description: Disables Aux interface. +// +// Paremeters: None +// +// Output: None +// +// Modified: MouseEnableState +// +// Referrals: MouseEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID DisableAuxDevice() +{ + EFI_STATUS Status; + if (!MouseEnableState) return; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + IoWrite8(KBC_CMDSTS_PORT, 0xA7); + IbFree(); + MouseEnableState = FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: EnableAuxDevice +// +// Description: Enables Aux interface. +// +// Paremeters: None +// +// Output: None +// +// Modified: MouseEnableState +// +// Referrals: MouseEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID EnableAuxDevice() +{ + EFI_STATUS Status; + if (MouseEnableState) return; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return; + } + IoWrite8(KBC_CMDSTS_PORT, 0xA8); + IbFree(); + MouseEnableState = TRUE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DetectPS2KeyboardAndMouse +// +// Description: Detects the presence of Keyboard and Mouse in KBC port. +// +// Parameters: None. Keyboard interface is disabled. +// +// Output: Ps2KbdDetected and Ps2MouseDetected variable set accorinding +// the device presence +// +// Modified: Ps2KbdDetected, Ps2MouseDetected +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS DetectPS2KeyboardAndMouse() +{ + UINT16 wCount; + UINT8 bData; + BOOLEAN bAck = FALSE; + + if(Ps2KbdMouseDetected) { + // + // Ps2Keyboard and Mouse Detected already + // + return EFI_SUCCESS; + } + + Ps2KbdMouseDetected=TRUE; + + DetectPs2Mouse(); + + + if ( DetectPs2KeyboardValue ) { + + PROGRESS_CODE(DXE_KEYBOARD_DETECT); + Write8042CommandByte (0x6d); + KBCGetData(); // Dummy read + + for (wCount = 0; wCount < 3; wCount++) { + // Disable Scanning + if (!ReadDevice(KBD_DISABLE_SCANNING, &bData, KB_ACK_COM)) break; + if (IoRead8(KBC_CMDSTS_PORT) & 0x40) { // Time out error + gSysTable->BootServices->Stall(6000); // 6 msec + // After power-up some junk data comes from KBD. If not eaten + // other command will fail. + KBCGetData(); + } + } + + DisableKeyboard(); + KBCGetData(); + + // + // 3 times retry on keyboard reset + // + for (wCount = 0; wCount < 3; wCount++) { + if (!ReadDevice(KBD_RESET, &bData, KB_ACK_COM)) { // ACK received + TRACEKBD((-1,"KBD Reset Response %X ", bData)); + bAck = TRUE; + break; + } else { + KBCGetData(); // Dummy read + } + } + + if (bAck) { //If not not Keyboard + if (ObFullRead() == 0xAA) { // Reset successful + Ps2KbdDetected=TRUE; + } else if (Read8042(0xAB)) { // On Success returns 0 + // + // 0x01 if Clock line stuck low, 0x02 if clock line stuck high, + // 0x03 if data line stuck low, and 0x04 if data line stuck high + // + Ps2KbdDetected=FALSE; + } + } + + // + // Check for lock key + // + if (!(IoRead8(KBC_CMDSTS_PORT) & 0x10)) { + // + // Keyboard is locked, we can report it here + // + Ps2KbdDetected=FALSE; + } + } else { + Ps2KbdDetected = TRUE; + KBDEnableState = TRUE; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: UpdateSioVariableForKeyboardMouse +// +// Description: Update the SIO variable in the ACPI name space depend on the +// Ps2keyboard and Mouse Present state. +// +// Parameters: None +// +// Output: None +// +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID UpdateSioVariableForKeyboardMouse( + EFI_EVENT Event, + VOID *Context +) +{ + static EFI_GUID SioDevStatusVarGuid = SIO_DEV_STATUS_VAR_GUID; + UINTN SioDevStatusVarSize = sizeof(SIO_DEV_STATUS); + SIO_DEV_STATUS SioDevStatus; + UINT32 SioDevStatusVarAttributes = 0; + EFI_STATUS Status; + + // + // Get the SIO variable. + // + Status = pRS->GetVariable( SIO_DEV_STATUS_VAR_NAME, + &SioDevStatusVarGuid, + &SioDevStatusVarAttributes, + &SioDevStatusVarSize, + &SioDevStatus.DEV_STATUS); + + // + // If variable not found return without updating it. + // + if(EFI_ERROR(Status)) { + SioDevStatus.DEV_STATUS = 0; + SioDevStatusVarAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS; + SioDevStatus.Res3 = 1; // To indicate that PS2 state vas updated + } + + // + // Set the flag based on the Ps2 keyboard presence state + // + if(Ps2KbdDetected) { + SioDevStatus.Key60_64 = 1; + } else { + SioDevStatus.Key60_64 = 0; + } + + + // + // Set the Mouse flag based on the Mouse Presence state. + // + if(Ps2MouseDetected) { + SioDevStatus.Ps2Mouse = 1; + } else { + SioDevStatus.Ps2Mouse = 0; + } + + // + // Set the SIO variable. + // + Status = pRS->SetVariable( SIO_DEV_STATUS_VAR_NAME, + &SioDevStatusVarGuid, + SioDevStatusVarAttributes, + SioDevStatusVarSize, + &SioDevStatus); + return; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DetectPS2Keyboard +// +// Description: Detects the presence of Keyboard in KBC port. +// +// Parameters: None +// +// Output: EFI_SUCCESS if mouse is detected +// EFI_NOT_FOUND if mouse is not detected +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS DetectPS2Keyboard( ) +{ + if ( InstallKeyboardMouseAlways ) { + return EFI_SUCCESS; + } else { + return Ps2KbdDetected ? EFI_SUCCESS : EFI_NOT_FOUND; + } +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: PS2DataDispatcher +// +// Description: This fuction checks whether data is available in the PS2 +// controller output buffer. If so, it gives control to the +// corresponding state machine executor. +// +// Parameters: VOID *Context - Pointer to the context for this function +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID PS2DataDispatcher ( + VOID *Context ) +{ + UINT8 data; + KEYBOARD *kbd = &gKbd; + UINT8 bIndicators; + + bIndicators = kbd->KeyData.KeyState.KeyToggleState & 7; // SCRL/NUM/CPSL + if(KbdIrqSupport){ + + // + // if keyboard irq supported check status of SCRL/NUM/CPSL keys + // and send the command to Keyboard to update the LED status + // + UINT8 bIndicators = kbd->KeyData.KeyState.KeyToggleState & 7; + if (bIndicators != kbd->Indicators && kbd->LEDCommandState == 0){ + LEDsOnOff(kbd); + } + return; + } + + if (InsidePS2DataDispatcher) return; + InsidePS2DataDispatcher = TRUE; + + for(data = IoRead8(KBC_CMDSTS_PORT); data & KBC_OBF; data = IoRead8(KBC_CMDSTS_PORT)) { + if (data & KBC_AUX_OBF) { + DrivePS2MouseMachine(Context); + } + else { + // + // Removed the DisableKeyboard() as to read multiple data from port60h, + // If any valid key is received we break out of the loop. + // + DrivePS2KbdMachine(Context); + if (CheckKeyinBuffer(kbd) ) { + break; + } + } + } + + // + // Check LED state before issuing ED command + // + if (bIndicators != kbd->Indicators && kbd->LEDCommandState == 0) { + // + // Disable the keyboard before issuing ED command + // + DisableKeyboard(); + CheckIssueLEDCmd(kbd); + } + + // + //Process the led command and data + // + ProcessLEDCommandData(kbd); + EnableKeyboard(); + InsidePS2DataDispatcher = FALSE; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CheckIssueLEDCmd +// +// Description: This function check if KBD LED command ED needs to be +// issued. +// If 'yes', sends ED command. No data is read. +// +// Parameters: KEYBOARD *kbd - Pointer to keyboard buffer +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID CheckIssueLEDCmd ( + KEYBOARD *Kbd ) +{ + + UINT8 bIndicators = Kbd->KeyData.KeyState.KeyToggleState & 7; // SCRL/NUM/CPSL + + if (bIndicators != Kbd->Indicators && Kbd->LEDCommandState == 0) { + // + // Don't issue LED command when data is pending + // + if (IoRead8(KBC_CMDSTS_PORT) & KBC_OBF) return; + Kbd->LEDCommandState = ED_COMMAND_ISSUED; + WriteKeyboardData(0xED); + } + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessKBDResponse +// +// Description: If 0xFA is received as data, check for any pending ACK +// and take necessary action. +// +// Parameters: KEYBOARD* kbd - Pointer to keyboard buffer +// UINT8 bData - Data received from keyboard +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID ProcessKBDResponse ( + KEYBOARD *Kbd, + UINT8 Data ) +{ + + UINT8 bIndicators = Kbd->KeyData.KeyState.KeyToggleState & 7; // SCRL/NUM/CPSL + + switch (Data) { + case 0xFA: + if (Kbd->LEDCommandState == ED_COMMAND_ISSUED) { + Kbd->LEDCommandState = ED_DATA_ISSUED; + Kbd->Indicators = bIndicators; + WriteKeyboardData(bIndicators); + break; + } + + if (Kbd->LEDCommandState == ED_DATA_ISSUED) { + Kbd->LEDCommandState = 0; + break; + } + + + case 0xFE: + if (Kbd->LEDCommandState == ED_COMMAND_ISSUED || Kbd->LEDCommandState == ED_DATA_ISSUED) { +// Error occured. Clear out the current indicator bits. +// Modifiers will have the correct bits that needs to be set. +// Next Call to CheckIssueLEDCmd will detect the mismatch +// and start the LED sequence. + WriteKeyboardData(0xF4); + Kbd->LEDCommandState = 0; + bIndicators = Kbd->KeyData.KeyState.KeyToggleState & 7; + Kbd->KeyData.KeyState.KeyToggleState &= + ~(SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE); + Kbd->Indicators &= 0xf0; + break; + } + + case 0xFF: + Kbd->LEDCommandState = 0; + break; + default: break; + } + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KBCGetData +// +// Description: Reads and returns byte of data from KBC data port. Also +// used as dummy KBC data process routine. +// +// Parameters: VOID *Context - Pointer to the context of this function +// +// Output: UINT8 Data read from KBC Data port. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 KBCGetData () +{ + UINT8 Data; + Data = IoRead8(KBC_DATA_PORT); + + return Data; +} + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/kbc.h b/Core/EM/PS2CTL/kbc.h new file mode 100644 index 0000000..44ec5ea --- /dev/null +++ b/Core/EM/PS2CTL/kbc.h @@ -0,0 +1,321 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/kbc.h 25 11/07/12 12:25a Srikantakumarp $ +// +// $Revision: 25 $ +// +// $Date: 11/07/12 12:25a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/kbc.h $ +// +// 25 11/07/12 12:25a Srikantakumarp +// [TAG] EIP99411 +// [Category] Improvement +// [Description] Add port validation check in the PS2Ctrl module before +// starting the driver. +// [Files] kbc.c, kbc.h, mouse.c, ps2main.c, CORE_DXE.sdl, Tokens.c +// +// 23 10/18/12 9:00a Deepthins +// [TAG] EIP70313 +// [Category] Improvement +// [Description] Used CheckIssueLEDCmd in function LEDsOnOff instead of +// OutToKb(Kbd, 0xED) +// [Files] kbc.c, ps2kbd.c and kbc.h +// +// 22 5/02/12 2:28a Deepthins +// [TAG] EIP63116 +// [Category] Improvement +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Ps2kbd.c, Mouse.c, kbc.h, kbc.c +// +// 21 4/24/12 2:18a Deepthins +// [TAG] EIP85747 +// [Category] Improvement +// [Description] USB-ReadKeyStrokeEx is returning EFI_SUCCESS with +// KEY_STATE_EXPOSED for Caps, Num and Scroll Lock Key's. +// KEY_STATE_EXPOSED only for the ShiftState Key's and not for togglestate +// key's. +// +// [Files] Efiusbkb.c, ps2kbd.c and kbc.h +// +// 20 2/01/12 1:59a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 19 9/22/11 6:32a Rameshr +// [TAG] EIP63054 +// [Category] New Feature +// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key +// press +// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c, +// Efiusbkb.c, efiusbkb.h +// +// 18 8/02/11 4:43a Rameshr +// [TAG] - EIP 58974 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - Yellow exclamation mark in Windows when PS2 KB/MS are not +// present. +// [RootCause]- ACPI name space variable reports that PS2 device present +// [Solution] - Updated the SIO device status based on the device present +// after BDS. +// [Files] - Kbc.c, Kbc.h , Ps2main.c +// +// 17 1/05/11 1:00a Rameshr +// [TAG] EIPEIP 35306 +// [Category] Improvement +// [Description] Report the Ps2 Controller and Device Error Codes. +// [Files] AmiStatuscodes.h, Kbc.c, Kbc.h,Ps2ctl.sdl, ps2kbd.c, +// ps2main.c ,Statuscode.h +// +// 16 12/10/10 5:30a Rameshr +// [TAG] - EIP 47011 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - DTM IO Tests fail due to presence of PS/2 devices that are +// not ready - no PS/2 devices attached during test. +// [RootCause]- PS2 device _STA method returns that, device is present . +// [Solution] - Updated the SIO device status based on the device +// presence. +// [Files] - Kbc.c , Kbc.h, Mouse.c +// +// 15 8/23/10 4:23a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.c +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 14 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 13 4/21/08 5:49p Olegi +// Removed keyboard modifiers bits definition, they should be taken from +// SimpleTextInEx.h +// +// 12 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 11 9/07/07 4:34p Olegi +// EFI_KEY code implementation. +// +// 10 8/31/07 2:17p Olegi +// Added SimpleTextInEx definitions. +// +// 9 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 8 3/13/06 2:38a Felixp +// +// 7 1/09/06 11:38a Felixp +// +// 5 12/22/05 10:22a Srinin +// ProcessKBDData added. +// +// 4 10/11/05 4:11p Srinin +// New function declarations added. +// +// 3 8/30/05 1:15p Srinin +// KEYBOARD struct modified. +// +// 2 3/04/05 1:38p Mandal +// +// 1 2/01/05 1:10a Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 3 9/30/04 8:13a Olegi +// HotKeys added. +// +// 2 9/17/04 7:02p Olegi +// +// 1 8/27/04 3:17p Olegi +// Initial VSS checkin. +// +// 4 8/18/04 6:37p Olegi +// Header and footer added. +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: kbc.h +// +// Description: Keyboard Controller functions header +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +#ifndef __PS2_KBC_SUPPORT_H__ +#define __PS2_KBC_SUPPORT_H__ + +#include <Protocol\Cpu.h> +#include <Protocol\Legacy8259.h> +// +// KBC command/status/data IO ports +// +#define KBC_CMDSTS_PORT 0x64 +#define KBC_DATA_PORT 0x60 + +// +// KBC status bits definition +// +#define KBC_OBF 0x01 +#define KBC_IBF 0x02 +#define KBC_SYSFLAG 0x04 +#define KBC_CMD_DATA 0x08 +#define KBC_INHIBIT_SW 0x10 +#define KBC_AUX_OBF 0x20 +#define KBC_TIMEOUT_ERR 0x40 +#define KBC_PARITY_ERR 0x80 + +// +// COMMANDS from KEYBOARD to SYSTEM +// +#define KB_ACK_COM 0xFA // ACKNOWLEDGE command +#define KB_RSND_COM 0xFE // RESEND command +#define KB_OVRN_COM 0xFF // OVERRUN command +#define KB_DIAG_FAIL_COM 0xFD // DIAGNOSTIC FAILURE command + +#define KBD_ENABLE_SCANNING 0xF4 +#define KBD_DISABLE_SCANNING 0xF5 +#define KBD_RESET 0xFF + +#define rKeyboardID 0xF2 +#define rMouseID 0xF2 + +// +// Keyboard scanner states +// +#define KBST_READY 0 +#define KBST_E0 1 +#define KBST_E1 2 + +#define BUFFER_SIZE 16 +#define SYSTEM_KEYBOARD_IRQ 0x01 +#define SYSTEM_MOUSE_IRQ 0x0C +#define SLAVE_IRQ 0X02 +// LED inter command state +#define ED_COMMAND_ISSUED 0x01 +#define ED_DATA_ISSUED 0x02 + +typedef struct { + EFI_SIMPLE_TEXT_INPUT_PROTOCOL iSimpleIn; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL iSimpleInEx; + AMI_EFIKEYCODE_PROTOCOL iKeycodeInEx; + AMI_EFI_KEY_DATA KeyData; + BOOLEAN KeyIsReady; + UINT8 ScannerState; + AMI_EFI_KEY_DATA* pBufHead; + AMI_EFI_KEY_DATA* pBufTail; + AMI_EFI_KEY_DATA* pBufStart; + AMI_EFI_KEY_DATA* pBufEnd; + UINT8 Count; +// UINT16 Modifiers; + UINT8 Indicators; + UINT8 LEDCommandState; + UINT8 CommandResponded; +} KEYBOARD; + +typedef struct { + UINT8 KbdBuffer[BUFFER_SIZE]; + UINT8 KbdIndex; +} KEYBOARD_IRQ_STORE; + +EFI_STATUS KBCBatTest(); +UINT8 Read8042(UINT8 bCmd); +UINT8 ObFullRead(); +void WriteKeyboardCommand(UINT8 bCmd); +void WriteKeyboardData(UINT8 bCmd); +void Write8042CommandByte(UINT8 bCCB); +void IbFree(); +EFI_STATUS IbFreeTimeout(UINT32 TimeoutValue); +void IoDelay(); +void AutodetectKbdMousePorts(); +EFI_STATUS ReadDevice(UINT8 bCmd, UINT8 *Data, UINT8 Response); +BOOLEAN ObFullReadTimeout(UINT8* data, UINT32 msec, BOOLEAN ONLYOBF); +UINT8 IssueCommand(UINT8 bCmd); +UINT8 AuxDeviceCommand(UINT8 bCmd); +EFI_STATUS OutToKb(KEYBOARD* kbd, UINT8 bCmd); +EFI_STATUS InsertKeyToBuffer (KEYBOARD* kbd, AMI_EFI_KEY_DATA *key); +EFI_STATUS GetKeyFromBuffer (KEYBOARD* kbd, VOID* key, UINT8 size); +BOOLEAN CheckKeyinBuffer (KEYBOARD* kbd); +void ReadAndProcessKey(void *Context); +void DisableKeyboard(); +EFI_STATUS EnableKeyboard(); +void DisableAuxDevice(); +void EnableAuxDevice(); +void LEDsOnOff(KEYBOARD* kbd); +void CheckIssueLEDCmd (KEYBOARD *kbd); +void ProcessKBDResponse (KEYBOARD *kbd, UINT8 bData); +EFI_STATUS DetectPS2Keyboard(); +EFI_STATUS DetectPS2KeyboardAndMouse(); +void HandleKBDData(void *Context, UINT8 data); +void ProcessKBDData (KEYBOARD *kbd, UINT8 data); +BOOLEAN ObFullReadMTimeout(UINT8* data, UINT32 msec); +EFI_STATUS ReadDeviceM(UINT8 bCmd, UINT8 *Data, UINT8 Response); +EFI_STATUS InitHotKeys(EFI_HANDLE Controller); +EFI_STATUS ProcessHotKey(UINT8 code, UINT16 modifiers); +EFI_STATUS DetectPs2Mouse(); +EFI_STATUS GetMouseData(); +VOID UpdateSioVariableForKeyboardMouse( + EFI_EVENT Event, + VOID *Context +); +EFI_STATUS +CheckPartialKey ( + KEYBOARD *Kbd, + EFI_KEY_DATA *Key +); +VOID InitKeyboardIrq(VOID); +void ProcessLEDCommandData(KEYBOARD* kbd); +EFI_STATUS ProcessMultiLanguage( + IN OUT AMI_EFI_KEY_DATA *KeyData + ); +#endif // __PS2_KBC_SUPPORT_H__ + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/mouse.c b/Core/EM/PS2CTL/mouse.c new file mode 100644 index 0000000..7fdbbfc --- /dev/null +++ b/Core/EM/PS2CTL/mouse.c @@ -0,0 +1,1215 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/mouse.c 24 11/07/12 12:26a Srikantakumarp $ +// +// $Revision: 24 $ +// +// $Date: 11/07/12 12:26a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/mouse.c $ +// +// 24 11/07/12 12:26a Srikantakumarp +// [TAG] EIP99411 +// [Category] Improvement +// [Description] Add port validation check in the PS2Ctrl module before +// starting the driver. +// [Files] kbc.c, kbc.h, mouse.c, ps2main.c, CORE_DXE.sdl, Tokens.c +// +// 23 10/18/12 9:49a Deepthins +// [TAG] EIP95111 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] PS2 mouse is not working in setup. +// [RootCause] In stream mode data reporting is disabled by default. The +// mouse will not actually issue any movement data packets until it +// receives the "Enable Data Reporting" (0xF4) command. So even when the +// DETECT_PS2_KEYBOARD and DETECT_PS2_MOUSE token is disabled we need to +// send command 0xf4 to Enable Data Reporting. +// [Solution] In MouseReset function, Set sampleRate ,Resolution and +// Enable streaming. +// [Files] mouse.c and ps2kbd.c +// +// 22 5/02/12 2:28a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Ps2kbd.c, Mouse.c, kbc.h, kbc.c +// +// 21 2/01/12 2:00a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 20 9/19/11 9:38a Lavanyap +// [TAG] EIP66198 +// [Category] Improvement +// [Description] Added Mouse Wheel support in PS2 and USB drivers. +// [Files] usbdef.h, usbms.c, efiusbms.c, ps2mouse.h, mouse.c +// +// 19 7/29/11 1:07a Lavanyap +// [TAG] EIP63310 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] MouseGetState() does not differentiate between driver busy +// and no state change between GetState calls. +// [RootCause] MouseGetState() return status codes does not follow UEFI +// specification. +// [Solution] MouseGetState() return status codes has been updated as +// per UEFI specification. +// [Files] mouse.c +// +// 18 4/27/11 4:37a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 17 12/10/10 5:31a Rameshr +// [TAG] - EIP 47011 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - DTM IO Tests fail due to presence of PS/2 devices that are +// not ready - no PS/2 devices attached during test. +// [RootCause]- PS2 device _STA method returns that, device is present . +// [Solution] - Updated the SIO device status based on the device +// presence. +// [Files] - Kbc.c , Kbc.h, Mouse.c +// +// 16 8/23/10 4:25a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.h +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 15 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 14 10/08/08 4:55p Olegi +// Change in GetMouseData that will reset the mouse in case the recieved +// packet is wrong. The failure was observed in TSE. +// +// 13 4/22/08 4:31p Felixp +// Additional progress codes added +// +// 12 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 11 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 10 3/01/07 3:43p Pats +// Modified for faster boot if keyboard detection disabled. +// +// 9 5/05/06 5:23p Ambikas +// +// 8 1/09/06 11:38a Felixp +// +// 6 12/22/05 10:25a Srinin +// Cleaned up the code. KBD disable inside GetMousedata removed. +// +// 5 10/11/05 4:15p Srinin +// Mouse is initialized for Streaming mode but kept disabled. Re-entry +// problem fixed. +// +// 4 7/18/05 3:37p Felixp +// +// 3 3/04/05 1:36p Mandal +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: Mouse.c +// +// Description: This is the PS/2 mouse EFI driver source file. +// +//<AMI_FHDR_END> +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: mouse.c +// +// Description: PS/2 mouse I/O support fuctions +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include <Efi.h> +#include <AmiLib.h> +#include "ps2ctl.h" +#include "kbc.h" +#include "ps2mouse.h" + +STATEMACHINEPROC DrivePS2MouseMachine; +BOOLEAN Ps2MouseDetected = FALSE; +UINT8 MouseData[5] = {0,}; +BOOLEAN InsideGetMouseData = FALSE; +BOOLEAN MouseResetRequired = FALSE; +UINT8 ByteCount = NON_WHEEL_REPORT_FORMAT; +extern BOOLEAN InsideKbdReadKey; +extern BOOLEAN InsideOnWaitingOnKey; +extern KEYBOARD gKbd; +typedef struct _STATE; +MOUSE gMouse = {0,}; +EFI_CPU_ARCH_PROTOCOL *gCpuArch; +EFI_LEGACY_8259_PROTOCOL *mLegacy8259; +UINT8 gMouseIrqInstall = FALSE; +extern UINT8 gKeyboardIrqInstall; +extern BOOLEAN KBDEnableState; +UINT8 gCurrentMouseIndex = NULL; +UINT8 gGetMouseStateStart=FALSE; +VOID GetMouseDataFromIrq(VOID); +UINT8 gMouseCommandActive=FALSE; +BOOLEAN InsideMouseReset; +extern BOOLEAN MsIrqSupport; +extern BOOLEAN MouseEnableState; +extern BOOLEAN DetectPs2MouseValue; +extern BOOLEAN InstallKeyboardMouseAlways; +extern BOOLEAN KbdIrqSupport; +extern BOOLEAN InsideKbdReset; +extern UINT32 IbFreeMaxTimeoutValue; + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ObFullRead +// +// Description: Waits for Output Buffer Full and then reads the data port +// +// Parameters: None +// +// Output: UINT8 KBC Data port data +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +UINT8 ObFullReadM() +{ + for (;;) { + if ((IoRead8(KBC_CMDSTS_PORT) & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF|KBC_AUX_OBF)) { + return IoRead8(KBC_DATA_PORT); + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ObFullReadMTimeout +// +// Description: This routine checks for the data availbility in output +// buffer for a short period of time, if data is available +// within this time, it reads and returns the data from +// output buffer. +// +// Paremeters: UINT8* data - Pointer to the byte to be updated +// UINT32 msec - Milliseconds timeout +// +// Output: BOOLEAN - Returns FALSE if data is successfully updated +// (no timeout), data is updated +// Returns TRUE if time-out +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN ObFullReadMTimeout ( + UINT8* data, + UINT32 msec ) +{ + + UINT8 bData; + UINT32 loopcount = msec << 1; + + for (; loopcount; loopcount--) { + + bData = IoRead8(KBC_CMDSTS_PORT); + + if ((bData & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF|KBC_AUX_OBF)) { + + *data = IoRead8(KBC_DATA_PORT); + if (bData & 0x40) { + *data = IoRead8(KBC_DATA_PORT); + TRACEKBD((-1, "Status Reg M : %x, %x\n", bData, *data)); + return TRUE; + } + else return FALSE; // No timeout + + } + + if ((bData & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF)){ + TRACEKBD((-1, "KB OBF inside Mouse")); + return TRUE; + } + + gSysTable->BootServices->Stall(500); // 0.5 msec + + } + + return TRUE; // Timeout +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ReadDeviceM +// +// Description: Sends the given command to KBD, reads and returns the +// acknowledgement byte returned from KBD. +// +// Parameters: UINT8 bCmd - Command to send to KBC +// UINT8 *Data - Pointer to data buffer +// UINT8 Response - Response expected +// +// Output: EFI_SUCCESS - Data == Response +// EFI_DEVICE_ERROR - Data != Response +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS ReadDeviceM ( + UINT8 bCmd, + UINT8 *Data, + UINT8 Response ) +{ + EFI_STATUS Status; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return Status; + } + IoWrite8(KBC_CMDSTS_PORT, 0xD4); + IbFree(); + WriteKeyboardData(bCmd); + + if (ObFullReadMTimeout(Data, 1000)) { + return EFI_DEVICE_ERROR; + } + if (*Data == Response) { + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; +} + + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: MouseInterruptHandler +// +// Description: An interrupt handler for PS2 mouse +// +// +// Input: InterruptType Interrupt type +// SystemContext System context +// +// Output: EFI_SUCCESS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID MouseInterruptHandler( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext +) +{ + EFI_TPL OldTpl=NULL; + KEYBOARD *Kbd = &gKbd; + + // + // Disable interrupt to prevent interrupt chaining + // + gCpuArch->DisableInterrupt(gCpuArch); + + // + // Post Code verifies the Mouse IRQ generation by sending command 0xD4(Write mouse device) + // and data. For the data if the control comes to Mouse IRQ handler, and IRQ method is enabled + // and active. Otherwise it will disable the Mouse IRQ + + if (gMouseCommandActive){ + gMouseIrqInstall = TRUE; + // + // Throw out the Dummy data that we sent to test the Mouse IRQ generation + // + IoRead8(KBC_DATA_PORT); + + } else { + + // + // Handle the Mouse Data + // + GetMouseDataFromIrq(); + } + + EnableAuxDevice(); + + // + // Send End Of Interrupt command twice as PIC is connected + // in cascade mode, once for master and once for corresponding + // slave + // + mLegacy8259->EndOfInterrupt(mLegacy8259, SYSTEM_MOUSE_IRQ); + mLegacy8259->EndOfInterrupt(mLegacy8259, SLAVE_IRQ); + gCpuArch->EnableInterrupt(gCpuArch); +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: InitMOUSE +// +// Description: Initializes mouse driver +// +// Parameters: MOUSE** ppMouse - Pointer to mouse structure +// +// Output: EFI_SUCCESS - Mouse initialized +// EFI_DEVICE_ERROR - Mouse not detected +// EFI_OUT_OF_RESOURCES - Not enough memory for buffers +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + + +EFI_STATUS InitMOUSE ( + MOUSE** ppMouse ) +{ + MOUSE* pmouse; + EFI_STATUS Status; + UINT32 MouseVector = NULL; + UINT32 loopcount = 1000; + + pmouse = *ppMouse = &gMouse; + + MemSet( &pmouse->state, sizeof(pmouse->state), 0 ); + pmouse->saved_flags=0; + + if (EFI_ERROR(DetectPS2mouse(pmouse))) { + // + // Ps2 Mouse not Present. + // + return EFI_DEVICE_ERROR; + } + + // + // Ps2 Mouse Present. Install Simple Pointer protocol. + // + (pmouse->iSmplPtr).Mode = MallocZ(sizeof (EFI_SIMPLE_POINTER_MODE)); + + if(!((pmouse->iSmplPtr).Mode)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Check for mouse IRQ support. + // + if(MsIrqSupport){ + if (!gMouseIrqInstall){ + if(mLegacy8259 == NULL){ + Status = pBS->LocateProtocol(&gEfiLegacy8259ProtocolGuid, NULL, &mLegacy8259); + if (EFI_ERROR(Status)) { + return Status; + } + } + + // + // Find the CPU Arch Protocol + // + if(gCpuArch == NULL){ + Status = pBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, &gCpuArch); + if (EFI_ERROR(Status)) { + return Status; + } + } + // + // Get Mouse vector + // + Status = mLegacy8259->GetVector(mLegacy8259, SYSTEM_MOUSE_IRQ, (UINT8 *) & MouseVector); + if (EFI_ERROR(Status)) { + return Status; + } + // + // Register interrupt handler for mouse + // + Status = gCpuArch->RegisterInterruptHandler(gCpuArch, MouseVector, MouseInterruptHandler); + if (EFI_ERROR(Status)) { + return Status; + } + // + // To set the interrupt mode operation in legacy mode + // + + mLegacy8259->SetMode(mLegacy8259,Efi8259LegacyMode,NULL,NULL); + // + // Enable Mouse interrupt + // + Status = mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_MOUSE_IRQ, FALSE); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = mLegacy8259->EnableIrq(mLegacy8259, 0x02, FALSE); + if (EFI_ERROR(Status)) { + return Status; + } + // + // To set the interrupt mode operation in protected mode + // + mLegacy8259->SetMode(mLegacy8259,Efi8259ProtectedMode,NULL,NULL); + + // + // Enable PS2 mouse interrupt + // + Status = mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_MOUSE_IRQ, FALSE); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Enable Master PIC interrupt IRQ2 + // + Status = mLegacy8259->EnableIrq(mLegacy8259, 0x02, FALSE); + if (EFI_ERROR(Status)) { + return Status; + } + // + // Enable INT2 bit in command register. + // + Write8042CommandByte(0x67); + + // Is Mouse IRQ active? + gMouseCommandActive = TRUE; + Status = IbFreeTimeout(IbFreeMaxTimeoutValue); + if (EFI_ERROR(Status)) { + return Status; + } + IoWrite8(KBC_CMDSTS_PORT, 0xD4); + IbFree(); + // + // Write mouse data + // + WriteKeyboardData(0xf4); + + for (; loopcount; loopcount--) { + if (gMouseIrqInstall) break; + gSysTable->BootServices->Stall(500); // 0.5 msec + } + gMouseCommandActive = FALSE; + + // + // If Mouse irq is not installed then disable interrupt + // + if (!gMouseIrqInstall){ + // + // a dummy read after writing to mouse + // + IoRead8(0x60); + Write8042CommandByte(0x65); + mLegacy8259->DisableIrq(mLegacy8259, SYSTEM_MOUSE_IRQ); + + } + } + } + + (pmouse->iSmplPtr).Mode->ResolutionX = 4; + (pmouse->iSmplPtr).Mode->ResolutionY = 4; + (pmouse->iSmplPtr).Mode->ResolutionZ = 4; + (pmouse->iSmplPtr).Mode->RightButton = TRUE; + (pmouse->iSmplPtr).Mode->LeftButton = TRUE; + + // + // Initialize pointer interface functions + // + (pmouse->iSmplPtr).Reset = (EFI_SIMPLE_POINTER_RESET)MouseReset; + (pmouse->iSmplPtr).GetState= (EFI_SIMPLE_POINTER_GET_STATE)MouseGetState; + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DetectPs2Mouse +// +// Description: +// Implements Reset operation of SimplePointer protocol. +// As part of initialization process, the firmware/device will make a quick +// but reasonable attempt to verify that the device is functioning. If the +// ExtendedVerification flag is TRUE the firmware may take an extended amount +// of time to verify the device is operating on reset. Otherwise the reset +// operation is to occur as quickly as possible. +// +// Parameters: None +// +// Output: +// Returns EFI_SUCCESS if the device was reset, othewise returns +// EFI_DEVICE_ERROR - device is not functioning correctly and could +// not be reset. +// +// Modified: MouseEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS DetectPs2Mouse() +{ + + UINT8 bData = 0, b1, b2, loop; + EFI_STATUS Status; + + if ( DetectPs2MouseValue ) { + + + PROGRESS_CODE(DXE_MOUSE_RESET); + + for (loop = 3; loop; loop--) { + + if ((IoRead8(KBC_CMDSTS_PORT) & KBC_OBF)) { + TRACEKBD((-1,"KBD")); + // + // Consume Data and discard it + // + KBCGetData(); + } + + TRACEKBD((-1,"Reseting mouse...\n")); + + Status = ReadDeviceM(0xFF, &bData, 0xFA); + TRACEKBD((-1,"%x, %x ", bData, Status)); + // + // ACK received + // + if (Status == EFI_SUCCESS) { + + if (ObFullReadMTimeout(&b1, 1000)) { + continue; + } + if (ObFullReadMTimeout(&b2, 1000)) { + continue; + } + + TRACEKBD((-1,"Data %x; %x\n",b1,b2)); + + if ( b1 == 0xAA && b2 == 0x00) { + TRACEKBD((-1,"Reset Mouse Ok\n")); + + // + // Enable wheel report format + // + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0xC8, &bData, 0xFA))) { + continue; // 200 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x64, &bData, 0xFA))) { + continue; // 100 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x50, &bData, 0xFA))) { + continue; // 80 samples/sec + } + + ReadDeviceM(0xF2, &bData, 0xFA); // Read Mouse ID + ObFullReadMTimeout(&bData, 1000); + + // If scroll wheel is supported Mouse Response = 3 + // else Mouse Response = 0 + if (bData == 3) { + ByteCount = WHEEL_REPORT_FORMAT; + } + + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x64, &bData, 0xFA))) { + continue; // 20 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xE8, &bData, 0xFA))) { + continue; // Set resolution + } + if (EFI_ERROR(ReadDeviceM(0x2, &bData, 0xFA))) { + continue; // 4 Count/mm + } + + // + // Enable streaming + // + ReadDeviceM(0xF4, &bData, 0xFA); + + MouseEnableState = TRUE; + DisableAuxDevice(); + Ps2MouseDetected = TRUE; + + return EFI_SUCCESS; + + } + } + } + + // + // Ps2 Mouse Not Present. Return with Error. + // + return EFI_DEVICE_ERROR; + } else { + // + // By default Ps2 mouse is enabled and Present + // + MouseEnableState = TRUE; + Ps2MouseDetected = TRUE; + return EFI_SUCCESS; + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: MouseReset +// +// Description: +// Implements Reset operation of SimplePointer protocol. +// As part of initialization process, the firmware/device will make a quick +// but reasonable attempt to verify that the device is functioning. If the +// ExtendedVerification flag is TRUE the firmware may take an extended amount +// of time to verify the device is operating on reset. Otherwise the reset +// operation is to occur as quickly as possible. +// +// Parameters: +// MOUSE *self - pointer to the mouse structure +// BOOLEAN extended - Indicates that the driver may perform a more exhaustive +// verification operation of the device during reset. +// +// Output: +// Returns EFI_SUCCESS if the device was reset, othewise returns +// EFI_DEVICE_ERROR - device is not functioning correctly and could +// not be reset. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS MouseReset( + MOUSE *self, + BOOLEAN extended) +{ + UINT8 bData = 0; + UINT8 b1; + UINT8 b2; + UINT8 loop; + EFI_STATUS Status; + + + // + // If ExtendedVerification Flag is true then reset the mouse, set + // sampleRate and Resolution and Enable streaming. + // + if(extended) { + + InsideMouseReset = TRUE; + Write8042CommandByte(0x74); + + // + // Check for keyboard IRQ support + // + if(KbdIrqSupport ) { + // + // Now Disable the interrupt + // + mLegacy8259->DisableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ); + } + + // + // Check for mouse IRQ support + // + if(MsIrqSupport) { + // + // Now Disable the interrupt + // + mLegacy8259->DisableIrq(mLegacy8259, SLAVE_IRQ); + mLegacy8259->DisableIrq(mLegacy8259, SYSTEM_MOUSE_IRQ); + } + + for (loop = 3; loop; loop--) { + + if ((IoRead8(KBC_CMDSTS_PORT) & KBC_OBF)) { + TRACEKBD((-1,"KBD")); + // + // Consume Data and discard it + // + KBCGetData(); + } + + TRACEKBD((-1,"Reseting mouse...\n")); + + Status = ReadDeviceM(0xFF, &bData, 0xFA); + TRACEKBD((-1,"%x, %x ", bData, Status)); + // + // ACK received + // + if (Status == EFI_SUCCESS) { + + ByteCount = NON_WHEEL_REPORT_FORMAT; + + if (ObFullReadMTimeout(&b1, 1000)) { + continue; + } + if (ObFullReadMTimeout(&b2, 1000)) { + continue; + } + + TRACEKBD((-1,"Data %x; %x\n",b1,b2)); + + if ( b1 == 0xAA && b2 == 0x00) { + TRACEKBD((-1,"Reset Mouse Ok\n")); + + // + // Enable wheel report format + // + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0xC8, &bData, 0xFA))) { + continue; // 200 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x64, &bData, 0xFA))) { + continue; // 100 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x50, &bData, 0xFA))) { + continue; // 80 samples/sec + } + + ReadDeviceM(0xF2, &bData, 0xFA); // Read Mouse ID + ObFullReadMTimeout(&bData, 1000); + + // If scroll wheel is supported Mouse Response = 3 + // else Mouse Response = 0 + if (bData == 3) { + ByteCount = WHEEL_REPORT_FORMAT; + } + + if (EFI_ERROR(ReadDeviceM(0xF3, &bData, 0xFA))) { + continue; // Set Sample Rate + } + if (EFI_ERROR(ReadDeviceM(0x64, &bData, 0xFA))) { + continue; // 20 samples/sec + } + if (EFI_ERROR(ReadDeviceM(0xE8, &bData, 0xFA))) { + continue; // Set resolution + } + if (EFI_ERROR(ReadDeviceM(0x2, &bData, 0xFA))) { + continue; // 4 Count/mm + } + + + // + // Enable streaming + // + ReadDeviceM(0xF4, &bData, 0xFA); + break; + } + } + } + + // + // Check for keyboard IRQ support + // + if(KbdIrqSupport ) { + // + // Now Disable the interrupt + // + mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ, FALSE); + } + if(MsIrqSupport) { + mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_MOUSE_IRQ, FALSE); + mLegacy8259->EnableIrq(mLegacy8259, SLAVE_IRQ, FALSE); + } + + Write8042CommandByte(0x47); + InsideMouseReset = FALSE; + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: MouseGetState +// +// Description: Retrieves the current state of a pointer device. +// +// Parameters: +// MOUSE *self - Pointer to the mouse structure +// EFI_SIMPLE_POINTER_STATE *state - Pointer to state machine buffer +// +// Output: EFI_SUCCESS - Mouse data ready +// EFI_NOT_READY - Mouse data not ready +// +// Modified: MouseData +// +// Referrals: MouseData +// +// Notes: +// The function retrieves the current state of a pointer device. This includes +// information on the buttons associated with the pointer device and the +// distance that each of the axes associated with the pointer device has been +// moved. If the state of the pointer device has not changed since the last +// call to MouseGetState(), then EFI_NOT_READY is returned. If the state of +// the pointer device has changed since the last call to MouseGetState(), then +// the state information is placed in State, and EFI_SUCCESS is returned. If a +// device error occurs while attempting to retrieve the state information, +// then EFI_DEVICE_ERROR is returned. +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + + +EFI_STATUS MouseGetState( + MOUSE *self, + EFI_SIMPLE_POINTER_STATE *state) +{ + + StdMouseDataPacket* packet = (StdMouseDataPacket*)MouseData; + EFI_STATUS Status; + + // Check if Mouse Data ready + if (!MouseData[ByteCount]) { + Status = GetMouseData(); + if (EFI_ERROR(Status)) { + return Status; + } + } + + if (MouseData[ByteCount]) { + + MouseData[ByteCount] = 0; + + if( packet->flags & (MOUSE_X_OVF|MOUSE_Y_OVF) ){ + return EFI_DEVICE_ERROR; + } else { + state->RelativeMovementX = (packet->flags & MOUSE_X_NEG)? (signed char)packet->x:packet->x; + state->RelativeMovementY = -(int)((packet->flags & MOUSE_Y_NEG)? (signed char)packet->y:packet->y); + state->LeftButton = (packet->flags & BUTTON_LEFT)?TRUE:FALSE; + state->RightButton = (packet->flags & BUTTON_RIGHT)?TRUE:FALSE; + + if (ByteCount == WHEEL_REPORT_FORMAT) { + state->RelativeMovementZ = ((signed char)packet->z); + } else { + state->RelativeMovementZ = 0; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_READY; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: DetectPS2mouse +// +// Description: Detects the presence of mouse in KBC port. +// +// Parameters: MOUSE* self - Pointer to the mouse structure +// +// Output: EFI_SUCCESS if mouse is detected +// EFI_NOT_FOUND if mouse is not detected +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS DetectPS2mouse ( + MOUSE* self ) +{ + if ( InstallKeyboardMouseAlways ) { + return EFI_SUCCESS; + } else { + return Ps2MouseDetected ? EFI_SUCCESS : EFI_NOT_FOUND; + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: OnWaitingOnMouse +// +// Description: Callback for the WaitForInput event; +// checks whether the mouse state has changed and if so - +// signals the event. +// +// Parameters: EFI_EVENT event - Event to signal +// MOUSE *self - Pointer to the mouse structure +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID OnWaitingOnMouse ( + EFI_EVENT event, + MOUSE *self ) +{ + // Check if Mouse Data ready + if (!MouseData[ByteCount]) { + GetMouseData(); + } + + if (MouseData[ByteCount]) gSysTable->BootServices->SignalEvent(event); + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: GetMouseDataFromIrq +// +// Description: Enables Mouse and returns data if available +// +// Parameters: None +// +// Output: EFI_SUCCESS - Mouse data returned +// EFI_NO_RESPONSE - No response from mouse +// +// Modified: MouseData, InsideGetMouseData +// +// Referrals: MouseData, InsideGetMouseData, MouseResetRequired, +// InsideKbdReadKey, InsideOnWaitingOnKey, gKbd +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID GetMouseDataFromIrq(VOID) +{ + UINT8 Port64flag = IoRead8(KBC_CMDSTS_PORT); + + + + if ((Port64flag & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF|KBC_AUX_OBF)) { + MouseData[gCurrentMouseIndex] = KBCGetData(); + if (gCurrentMouseIndex ==(ByteCount-1)){ + DisableAuxDevice(); + gCurrentMouseIndex = 0; + MouseData[ByteCount] = 1; + return; + } + gCurrentMouseIndex++; + } + + return; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: GetMouseData +// +// Description: Enables Mouse and returns data if available +// +// Parameters: None +// +// Output: EFI_SUCCESS - Mouse data returned +// EFI_NO_RESPONSE - No response from mouse +// +// Modified: MouseData, InsideGetMouseData +// +// Referrals: MouseData, InsideGetMouseData, MouseResetRequired, +// InsideKbdReadKey, InsideOnWaitingOnKey, gKbd +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS GetMouseData() +{ + + UINT8 Index; + BOOLEAN MouseDataRead; + KEYBOARD *kbd = &gKbd; + UINT8 KbdData[20], KbdDataIndex=0, Data8; + UINTN Delay, DelayPeriod = 100; + BOOLEAN MouseDataValid = FALSE; + + // + // If mouse irq is supported and installed then return with success + // + if(MsIrqSupport){ + if (gMouseIrqInstall){ + return EFI_SUCCESS; + } + } + + // Return if we are in the middle of KBD get key + if (InsideGetMouseData || InsideKbdReadKey || InsideOnWaitingOnKey || InsideKbdReset || InsideMouseReset) { + return EFI_DEVICE_ERROR; + } + + if (MouseData[ByteCount] == 1) return EFI_SUCCESS; + + // Try to complete the LED sequence + for (Index = 0; (Index < 40) && kbd->LEDCommandState; Index++ ) { + // + // if keyboard irq is supported but not installed yet then call + // Ps2DataDispatcher to check whether data is available on port or not + // + if(KbdIrqSupport) + if (!gKeyboardIrqInstall) + PS2DataDispatcher(NULL); + pBS->Stall(500); + } + + // LED sequence is still on, restart it + if (kbd->LEDCommandState) { + if(KbdIrqSupport) + if (!gKeyboardIrqInstall){ + TRACEKBD((-1,"BLS%x ", kbd->LEDCommandState)); + ProcessKBDResponse(kbd, 0xfe); + } + } + + InsideGetMouseData = TRUE; + + if ((IoRead8(KBC_CMDSTS_PORT) & (KBC_OBF|KBC_AUX_OBF)) == KBC_OBF) { + KbdData[KbdDataIndex] = KBCGetData(); + KbdDataIndex++; + } + + EnableAuxDevice(); + if (MouseResetRequired) { + DisableKeyboard(); + if ((IoRead8(KBC_CMDSTS_PORT) & (KBC_OBF|KBC_AUX_OBF)) == KBC_OBF) { + KbdData[KbdDataIndex] = KBCGetData(); + KbdDataIndex++; + } + ReadDeviceM(0xF4, &Index, 0xFA); + MouseResetRequired = FALSE; + } + + MouseData[ByteCount] = 0; + + DelayPeriod = 200; // Delay for the first byte + for (Index = 0; Index < ByteCount; Index++) { + + MouseDataRead = FALSE; + + for (Delay = 0; Delay < DelayPeriod; Delay++) { + + Data8 = IoRead8(KBC_CMDSTS_PORT); + + if ((Data8 & (KBC_OBF|KBC_AUX_OBF)) == KBC_OBF) { + KbdData[KbdDataIndex] = KBCGetData(); + KbdDataIndex++; + } + + if ((Data8 & (KBC_OBF|KBC_AUX_OBF)) == (KBC_OBF|KBC_AUX_OBF)) { + MouseData[Index] = KBCGetData(); + MouseDataValid = TRUE; + MouseDataRead = TRUE; + if (Index == (ByteCount-1)) DisableAuxDevice(); + break; + } + + pBS->Stall(100); + + } + + DelayPeriod = 100; // Delay for the Second & Third byte + + if (Index == (ByteCount-1) && MouseDataRead) { + MouseData[ByteCount] = 1; + } else if (Index == (ByteCount-1) && MouseDataValid) { + MouseResetRequired=TRUE; + } + + if (MouseDataRead) continue; + else break; + + } + + // Reset mouse counters if the mouse sequence is not correct + if (MouseData[ByteCount] == 1 && !(MouseData[0] & 8)) { + + for (; Index; Index--) { + TRACEKBD((-1,"%X ", MouseData[Index])); + } + TRACEKBD((-1,"\n")); + + DisableKeyboard(); + if ((IoRead8(KBC_CMDSTS_PORT) & (KBC_OBF|KBC_AUX_OBF)) == KBC_OBF) { + KbdData[KbdDataIndex] = KBCGetData(); + KbdDataIndex++; + } + ReadDeviceM(0xF4, &Index, 0xFA); + } + + EnableKeyboard(); + DisableAuxDevice(); + + for (Index =0 ; KbdDataIndex; KbdDataIndex--, Index++) { + ProcessKBDData(kbd, KbdData[Index]); + } + + InsideGetMouseData = FALSE; + + return EFI_SUCCESS; + +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/ps2ctl.h b/Core/EM/PS2CTL/ps2ctl.h new file mode 100644 index 0000000..a117f56 --- /dev/null +++ b/Core/EM/PS2CTL/ps2ctl.h @@ -0,0 +1,178 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2ctl.h 15 4/27/11 4:35a Lavanyap $ +// +// $Revision: 15 $ +// +// $Date: 4/27/11 4:35a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2ctl.h $ +// +// 15 4/27/11 4:35a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 14 1/24/11 3:41p Pats +// [TAG] - EIP 18488 +// [Category] - Enhancement +// [Severity] - Normal +// [Symptom] - PS2CTL: Need hooks for port swap, Keybaord mouse detect. +// [RootCause] - Support may be needed for kbc controller or SIO with +// different support from AMI KB-5. +// [Solution] - Added definition of AutodetectKbdMousePortsPtr. +// [Files] - ps2ctl.h +// NOTE: Implementation of this change requires changes to CORE_DXE.sdl +// and BdsBoard.c. +// +// 13 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 12 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 11 9/07/07 4:34p Olegi +// EFI_KEY code implementation. +// +// 10 8/31/07 2:17p Olegi +// Added SimpleTextInEx definitions. +// +// 9 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 8 4/10/07 10:04a Felixp +// LookupHID routine renamed to LookupPs2Hid to avoid linking issue when +// linking with FloppyCtrl module +// +// 7 3/13/06 2:38a Felixp +// +// 6 1/09/06 11:38a Felixp +// +// 4 12/22/05 10:22a Srinin +// +// 3 10/11/05 4:11p Srinin +// +// 2 3/04/05 1:38p Mandal +// +// 1 2/01/05 1:10a Felixp +// +// 2 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 1 10/28/04 10:19a Olegi +// +// 7 9/30/04 8:13a Olegi +// HotKeys added. +// +// 6 9/21/04 5:51p Olegi +// +// 5 8/27/04 3:17p Olegi +// Header and footer added. +// +// 4 8/18/04 6:37p Olegi +// Header and footer added. +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: ps2ctl.h +// +// Description: PS/2 Controller DXE driver header +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#ifndef __PS2_MAIN_H__ +#define __PS2_MAIN_H__ + +#include <Efi.h> +#include <AmiDxeLib.h> +#include <Protocol\DevicePath.h> +#include <Protocol\DriverBinding.h> +#include <Protocol\SimpleTextIn.h> +#include <Protocol\SimpleTextInEx.h> +#include <Protocol\AmiKeycode.h> +#include <Protocol\SimplePointer.h> +#include <token.h> +#define TRACEKBD + + +#define PS2_DRIVER_VER 0x10 +#define DEVICETYPE_MOUSE 1 +#define DEVICETYPE_KEYBOARD 2 +extern EFI_SYSTEM_TABLE *gSysTable; + + +EFI_STATUS StartMouse(EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller); +EFI_STATUS StartKeyboard(EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller); +EFI_STATUS StopMouse(EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller); +EFI_STATUS StopKeyboard(EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller); + +typedef EFI_STATUS (*STARTSTOPPROC)(EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller); + +typedef struct PS2DEV_TABLE_tag { + UINT32 hid; + UINT32 uid; + UINT8 DeviceType; + STARTSTOPPROC start; + STARTSTOPPROC stop; + CHAR16* name; +} PS2DEV_TABLE; + +typedef void (*STATEMACHINEPROC)(void*); +void PS2DataDispatcher(void*); +UINT8 KBCGetData(); + +BOOLEAN LookupPs2Hid(PS2DEV_TABLE*, UINT32, UINT32, PS2DEV_TABLE**); +EFI_STATUS GetPS2_DP(EFI_DRIVER_BINDING_PROTOCOL*, EFI_HANDLE, ACPI_HID_DEVICE_PATH**, UINT32); + +typedef VOID (*AUTODETECT_KBD_MOUSE_PORTS)(); +typedef EFI_STATUS (*DETECT_KBC_DEVICE)(); +extern AUTODETECT_KBD_MOUSE_PORTS AutodetectKbdMousePortsPtr; +extern DETECT_KBC_DEVICE DetectKeyboardPtr; +extern DETECT_KBC_DEVICE DetectMousePtr; + +#endif // __PS2_MAIN_H__ + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/ps2kbd.c b/Core/EM/PS2CTL/ps2kbd.c new file mode 100644 index 0000000..c74ba48 --- /dev/null +++ b/Core/EM/PS2CTL/ps2kbd.c @@ -0,0 +1,2888 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2kbd.c 63 11/01/12 6:42a Deepthins $ +// +// $Revision: 63 $ +// +// $Date: 11/01/12 6:42a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2kbd.c $ +// +// 63 11/01/12 6:42a Deepthins +// [TAG] EIP101100 +// [Category] Improvement +// [Description] Multi Language is supported in Ps2ctl driver +// [Files] CORE_DXE.sdl, kbc.h, ps2kbd.c and Tokens.c +// +// 62 10/18/12 9:51a Deepthins +// [TAG] EIP95111 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] PS2 mouse is not working in setup. +// [RootCause] In stream mode data reporting is disabled by default. The +// mouse will not actually issue any movement data packets until it +// receives the "Enable Data Reporting" (0xF4) command. So even when the +// DETECT_PS2_KEYBOARD and DETECT_PS2_MOUSE token is disabled we need to +// send command 0xf4 to Enable Data Reporting. +// +// [Solution] In MouseReset function, Set sampleRate ,Resolution and +// Enable streaming. +// [Files] mouse.c and ps2kbd.c +// +// 61 10/18/12 9:03a Deepthins +// [TAG] EIP70313 +// [Category] Improvement +// [Description] Used CheckIssueLEDCmd in function LEDsOnOff instead of +// OutToKb(Kbd, 0xED) +// [Files] kbc.c, ps2kbd.c and kbc.h +// +// 60 7/13/12 7:21a Rajeshms +// [TAG] EIP57005 +// [Category] Improvement +// [Description] Need to clear Struck Keys in StartKeyboard() & +// KbdReset() for some kinds of Notebook KBC. Implemented this feature +// based on CLEAR_PENDING_KEYS_IN_PS2 token. +// [Files] Ps2Kbd.c, CORE_DXE.sdl +// +// 59 7/09/12 3:13a Rajeshms +// [TAG] EIP94186 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] side effect after adding the solution of can not catch F8 +// key event on Keyboard - PS2 KB generic implement (EIP6986) +// [RootCause] BDA is Checked even when CSM is not launched. So even +// though keys are not pressed Junk Keys are reproted +// [Solution] Checked whether CSm is launched based of Presence of +// Legacy BIOS Protocol. +// [Files] Ps2Kbd.c +// +// 58 5/31/12 7:56a Srilathasc +// [TAG] EIP89947 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Ps2Keyboard doesn't work after reconnect -r command from +// Shell +// [RootCause] The keyboard driver's stop function does not uninstall +// AMIEFIKEYCODE Protocol. +// [Solution] AMIEFIKEYCODE Protocol uninstalled in stop function. +// [Files] ps2kbd.c +// +// 57 5/24/12 6:49a Nimishsv +// [TAG] EIP90180 +// [Category] Bug Fix +// [Severity] Normal +// [Symptom] Ps2driver doesn't return the proper ShiftState if the valid +// Unicode char's are pressed. +// [RootCause] Shift State was not cleared for printable characters +// [Solution] Shift state is cleared for printable characters +// [Files] ps2kbd.c +// +// 56 5/02/12 2:29a Deepthins +// [TAG] EIP63116 +// [Category] Improvement +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Ps2kbd.c, Mouse.c, kbc.h, kbc.c +// +// 55 4/30/12 2:22a Rajeshms +// [TAG] EIP86986 +// [Category] Bug Fix +// [Severity] Important +// [Symptom] Can not detect F8 key on PS2 Keyboard while booting to EFI +// aware OS. +// [RootCause] Make code of F8 key (0x42) is taken by int09h and EFI +// aware OS calls only one ReadKeyStroke() for any key catch, Now PS2 +// driver will take Break Code of F8 key(0xC2) and returns EFI_NOT_READY. +// [Solution] Multiple Read from PS2 keyboard is implemented and read +// exits if any valid key is detected. Also, the BDA keyboard buffer is +// checked for any missed key in EFI. +// [Files] ps2kbd.c, kbc.c, CORE_DXE.sdl +// +// 54 4/24/12 2:19a Deepthins +// [TAG] EIP85747 +// [Category] Improvement +// [Description] USB-ReadKeyStrokeEx is returning EFI_SUCCESS with +// KEY_STATE_EXPOSED for Caps, Num and Scroll Lock Key's. +// KEY_STATE_EXPOSED only for the ShiftState Key's and not for togglestate +// key's. +// [Files] Efiusbkb.c, ps2kbd.c and kbc.h +// +// 53 4/23/12 8:52a Jittenkumarp +// [TAG] EIP84902 +// [Category] Bug Fix +// [Symptom] Enter key is not working in PS2 key board +// [RootCause] Filling wrong EFI KEY value in +// ScancodeToEfi_table.Therefor Enter key is interpreted wrongly as +// EfiKeyC12. +// [Solution] Replaced EfiKeyC12 value with EfiKeyEnter value to +// Interpreted Enter key properly. +// +// [Files] ps2kbd.c +// +// 52 4/10/12 2:35a Rameshr +// [TAG] EIP87058 +// [Category] Bug Fix +// [Severity] Minor +// [Symptom] Not able to recognise Pause Key Click using ReadKeyStroke +// [RootCause] Pause Key detection should be done always and only the +// pause key action should be controlled by PAUSEKEY_SUPPORT SDL token +// [Solution] SDL token checking removed for the Pause Key detection +// [Files] Ps2kbd.c +// +// 51 2/01/12 2:01a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 50 9/22/11 7:39a Rameshr +// [TAG] EIP63054 +// [Category] New Feature +// [Description] 0000790: Add warning to ReadKeyStrokeEx for partial key +// press +// [Files] KeyboardCommonDefinitions.h, In.c, Kbc.h, Ps2Kbd.c, +// Efiusbkb.c, efiusbkb.h +// +// 49 6/21/11 12:24p Davidd +// [TAG] EIP55334 +// [Category] New Feature +// [Description] Add optional code to clear keyboard buffer at +// ReadyToBoot in PS2KB driver +// [Files] core_dxe.sdl +// ps2kbd.c +// +// 48 4/27/11 4:34a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 47 1/05/11 12:58a Rameshr +// [TAG] EIPEIP 35306 +// [Category] Improvement +// [Description] Report the Ps2 Controller and Device Error Codes. +// [Files] AmiStatuscodes.h, Kbc.c, Kbc.h,Ps2ctl.sdl, ps2kbd.c, +// ps2main.c ,Statuscode.h +// +// 46 8/23/10 4:21a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.c +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 45 8/19/10 8:08a Fredericko +// [TAG] EIP40711 +// [Category] BUG FIX +// [Severity] Normal +// [Symptom] Keyboard sometimes does not work in DOS if KBD is being +// pressed hapazardly during post. +// [RootCause] After reprogramming of Interrupt Controller base; if +// keyboard is being pressed hapardzadly, KBD IRQ could be missed and KBD +// might not work in DOS. +// [Solution] Follow proper procedures to Reset KBD controller after +// reprogramming the base of the Interrrupt controller +// [Files] Thunk.c in CSM +// +// 44 7/20/10 4:31a Rameshr +// Corrected the FreePool call in UnRegisterKeyNotify function +// +// 43 5/14/10 11:07a Olegi +// Added FreePool call in UnRegisterKeyNotify function. +// +// 42 5/10/10 1:50a Rameshr +// Issue:Shift Key issues in RegsiterkeyNotify function +// Solution: ShiftKeyState and KeyToggleState verified for +// RegisterKeyNotify callback function. +// EIP 38211 +// +// 41 5/10/10 1:41a Rameshr +// PrintKey/SysRq key, Menu Key, Left Logo and Right Logo Key support +// added in Ps2 Keyboard driver +// EIP 38212 +// +// 40 3/15/10 2:40p Krishnakumarg +// Pressing DEL key continously intermittently or sticking does not enter +// setup. EIP: 34615 +// +// 39 1/29/10 2:11p Krishnakumarg +// When user press "Ctrl+Break" key, the Scr Lk LED will turn on - #EIP +// 34317 +// +// 38 8/13/09 3:02p Rameshr +// When item "num-lock status" set off, Num-lock will keep open until in +// DOS. +// EIP:21757 +// +// 37 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 36 6/26/09 4:03p Rameshr +// Symptom: Shift Key Status get set when DELL key pressed more +// frequently. +// Reason: DELL key scan code E0 taken by Reset Function and Int9. This +// has been handled by modifiying Reset function and using BDA. +// EIP:22611 +// +// 35 3/30/09 10:28a Pats +// Issue: EIP 19547 - Pause key support needed in Aptio +// Solution: Function HandleKBDData modified to pass EFI_KEY vaule of +// pause key on rather than rejecting it. +// +// 34 1/23/09 9:54a Rameshr +// Symptom:SCT failure in ReadKeystrokeEx function. +// Solution: Validated the Input parameters Keydata for the +// ReadKeystrokeEx Function. +// Eip: 19039 +// +// 33 11/17/08 10:04a Rameshraju +// Problem:SCT failure on RegisterKeyNotify, SetState and +// UnregisterKeyNotify. +// Fix : Validated the input parameters for RegisterKeyNotify, SetState +// and UnregisterKeyNotify. +// EIP:17578 +// +// 32 10/08/08 4:56p Olegi +// Implemented the Register/Unregister key notofocation function in +// SimpletextinEx protocol. +// +// 31 8/15/08 10:57a Olegi +// Correction in KbdReset function. +// +// 30 8/13/08 9:54a Olegi +// Change in KbdReset function, EIP#8330. +// +// 29 6/05/08 4:26p Olegi +// Added support for extended keys (EIP#13630) +// +// 28 6/05/08 3:19p Olegi +// Bugfix in processing the '5' key on a keypad when NumLock is off: +// nothing should be reported. +// +// 27 5/09/08 10:11a Olegi +// ProcessByte function modified +// +// 26 4/22/08 4:31p Felixp +// Additional progress codes added +// +// 25 4/21/08 5:49p Olegi +// +// 24 4/09/08 10:19a Olegi +// Changed the key attributes (modifiers and shift state) reporting. +// +// 23 10/25/07 4:48p Olegi +// +// 22 10/24/07 6:00p Olegi +// +// 21 10/23/07 4:04p Olegi +// Lock keys maintenance modifications. +// +// 20 9/18/07 11:51a Olegi +// +// 19 9/18/07 11:47a Olegi +// +// 18 9/17/07 3:56p Olegi +// +// 17 9/10/07 1:14p Olegi +// +// 16 9/07/07 4:34p Olegi +// EFI_KEY code implementation. +// +// 15 8/31/07 2:44p Olegi +// Added SimpleTextInEx definitions. +// +// 14 6/22/07 2:14p Pats +// Fixed problem of right Ctrl and Alt keys "sticking" and causing reset +// when Ctrl-Alt-Del pressed sequentially rather than all at once. +// +// 13 4/19/07 1:00p Felixp +// File reformatted to comply with AMI coding standards +// +// 11 4/17/07 10:34a Pats +// Modified to comply with coding standard. No code changes. +// +// 10 5/05/06 5:23p Ambikas +// +// 9 3/13/06 2:38a Felixp +// +// 8 1/09/06 11:38a Felixp +// +// 6 12/22/05 10:21a Srinin +// Optimized KBD Enable/Disable call +// +// 5 10/27/05 1:04p Srinin +// In KbdReset, KBD driver buffer is cleared. +// +// 4 10/11/05 4:09p Srinin +// KBD reset function implemented and other minor changes done. +// +// 3 8/30/05 1:08p Srinin +// KeyBoard buffer and handling of keys which send 4 scan codes modified. +// +// 2 3/04/05 3:55p Olegi +// Shift states corrected for non-letter keys. +// +// 1 2/01/05 1:10a Felixp +// +// 3 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 2 12/16/04 2:28p Olegi +// Fix: Caps-Lock made irrelevant to the upper row of keys. +// +// 1 10/28/04 10:19a Olegi +// +// 10 9/30/04 8:13a Olegi +// HotKeys added. +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: ps2kbd.c +// +// Description: PS/2 keyboard support routines +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include "ps2ctl.h" +#include "kbc.h" + + +#define E0_STATUS_IN_BDA BIT1 +#define E1_STATUS_IN_BDA BIT0 +#define LEGACY_8259_CONTROL_REGISTER_MASTER 0x20 + +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT +#include <Protocol/LegacyBios.h> +UINT16 BdaSeg = 0x400; +UINT16 *BdaKbdHead = (UINT16 *)0x41A; +UINT16 *BdaKbdTail = (UINT16 *)0x41C; +EFI_LEGACY_BIOS_PROTOCOL *gLegacy=NULL; +BOOLEAN gLegacyBiosProtocolFound = FALSE; +#endif +#endif + +/* +Table 2. PS/2 Scan Codes Supported in Windows 2000/Windows XP and Windows Me + +HID usage/ key name Set 1Make Set 1Break Set 2Make Set 2Break + Scan Next Track E0 19 E0 99 E0 4D E0 F0 4D + Scan Previous Track E0 10 E0 90 E0 15 E0 F0 15 + Stop E0 24 E0 A4 E0 3B E0 F0 3B + Play/ Pause E0 22 E0 A2 E0 34 E0 F0 34 + Mute E0 20 E0 A0 E0 23 E0 F0 23 + Volume Increment E0 30 E0 B0 E0 32 E0 F0 32 + Volume Decrement E0 2E E0 AE E0 21 E0 F0 21 + AL Email Reader E0 6C E0 EC E0 48 E0 F0 48 + AC Search E0 65 E0 E5 E0 10 E0 F0 10 + AC Home E0 32 E0 B2 E0 3A E0 F0 3A + AC Back E0 6A E0 EA E0 38 E0 F0 38 + AC Forward E0 69 E0 E9 E0 30 E0 F0 30 + AC Stop E0 68 E0 E8 E0 28 E0 F0 28 + AC Refresh E0 67 E0 E7 E0 20 E0 F0 20 + AC Bookmarks E0 66 E0 E6 E0 18 E0 F0 18 + AL Calculator* E0 21 E0 A1 E0 2B E0 F0 2B + AL Local Browser* E0 6B E0 EB E0 40 E0 F0 40 + AL Consumer Control Configuration* + E0 6D E0 ED E0 50 E0 F0 50 +*/ +static UINT8 E0EnhancedKeys[] = {0x20,0x30,0x2E}; // only mute, volume-up, down +BOOLEAN IsEnhancedKey( UINT8 data) +{ + UINTN i; + + data &= 0x7F; // reset MSB + for ( i = 0; i < sizeof(E0EnhancedKeys); i++) { + if ( data == E0EnhancedKeys[i]) { + return TRUE; + } + } + return FALSE; +} + +//---------------------------------------------------------------------- + +extern BOOLEAN InsideGetMouseData; +extern BOOLEAN KBDEnableState; +extern UINT8 LedsAtStartup; +extern BOOLEAN InsideMouseReset; +BOOLEAN InsideKbdReadKey = FALSE; +BOOLEAN InsideOnWaitingOnKey = FALSE; +BOOLEAN InsideKbdReset = FALSE; +extern BOOLEAN InsidePS2DataDispatcher; +static EFI_GUID gAmiMultiLangSupportGuid = AMI_MULTI_LANG_SUPPORT_PROTOCOL_GUID; +AMI_MULTI_LANG_SUPPORT_PROTOCOL *gPs2MultiLangSupportProtocol=NULL; + +EFI_STATUS KbdReset( + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + BOOLEAN ExtendedVerification); + +EFI_STATUS KbdReadKey( + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + EFI_INPUT_KEY *key); + +EFI_STATUS KbdResetEx( + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + BOOLEAN ExtendedVerification ); + +EFI_STATUS KbdReadKeyEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +); + +EFI_STATUS KbdReadEfiKeyEx ( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData +); + +EFI_STATUS SetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +EFI_STATUS RegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +); + +EFI_STATUS UnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + +void OnWaitingOnKey(EFI_EVENT Event, void *Context); + +#if CLEAR_PENDING_KEYS_IN_PS2 +VOID Ps2KbdReset ( VOID ); +VOID ClearOBF ( VOID ); +#endif + + +typedef struct _KEY_WAITING_RECORD{ + DLINK Link; + EFI_KEY_DATA Context; + EFI_KEY_NOTIFY_FUNCTION Callback; +} KEY_WAITING_RECORD; + +DLIST mPs2KeyboardData; +KEY_WAITING_RECORD *mPs2KeyboardRecord; +EFI_EVENT Ps2KeyEvent; +#define KEY_POLLING_INTERVAL 500000 +VOID StartPollingKey(EFI_EVENT Event, VOID *Context); + + +extern STATEMACHINEPROC DrivePS2KbdMachine; +void ReadAndProcessKey(void*); +void ProcessByte(KEYBOARD *Kbd, UINT8 data, BOOLEAN fourth_byte); +void ResetStateMachine(KEYBOARD *Kbd); +void LEDsOnOff(KEYBOARD* Kbd); + +static UINT8 E0SeqA[4] = {0x2A, 0xAA, 0x46, 0xB6}; +static UINT8 E0SeqB[11] = {0xD3, 0xD0, 0xCF, 0xC7, 0xD2, 0xCB, 0xD1, 0xC9, 0xCD, 0xC8, 0xB5}; +static UINT8 E1Seq[5] = {0x1D, 0x45, 0xE1, 0x9D, 0xC5}; + +static UINT8 code_table[59] = { // Lower case keys +0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 8, +9, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 13, +0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'','`', +0,'\\','z','x','c','v','b','n','m',',','.','/',0, +'*', 0, ' ', 0}; +static UINT8 Code_Table[59] = { // Upper case keys +0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 8, +9, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 13, +0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', +0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, +'*', 0, ' ',0}; + +static UINT8 ScancodeToEfi_table[59] = { // EFI keys (UEFI Spec 2.1, Ch.28.4, Pg.1325) +0, EfiKeyEsc, EfiKeyE1, EfiKeyE2, EfiKeyE3,EfiKeyE4, EfiKeyE5, EfiKeyE6, +EfiKeyE7, EfiKeyE8, EfiKeyE9, EfiKeyE10, EfiKeyE11, EfiKeyE12, EfiKeyBackSpace, +EfiKeyTab, EfiKeyD1, EfiKeyD2, EfiKeyD3, EfiKeyD4, EfiKeyD5, EfiKeyD6, EfiKeyD7, +EfiKeyD8, EfiKeyD9, EfiKeyD10, EfiKeyD11, EfiKeyD12, EfiKeyEnter, +EfiKeyCapsLock, EfiKeyC1, EfiKeyC2, EfiKeyC3, EfiKeyC4, EfiKeyC5, EfiKeyC6, EfiKeyC7, +EfiKeyC8, EfiKeyC9, EfiKeyC10, EfiKeyC11, EfiKeyE0, +EfiKeyLShift, EfiKeyD13, EfiKeyB1, EfiKeyB2, EfiKeyB3, EfiKeyB4, EfiKeyB5, EfiKeyB6, +EfiKeyB7, EfiKeyB8, EfiKeyB9, EfiKeyB10, EfiKeyRshift, +0, 0, EfiKeySpaceBar, 0}; + +typedef struct { + UINT8 makecode; + UINT8 efi_scancode; + UINT8 efi_key; +}EFI_EXTKEY; + +static EFI_EXTKEY ScanCode_Table[] = { + 0x3B, EFI_SCAN_F1, EfiKeyF1, + 0x3C, EFI_SCAN_F2, EfiKeyF2, + 0x3D, EFI_SCAN_F3, EfiKeyF3, + 0x3E, EFI_SCAN_F4, EfiKeyF4, + 0x3F, EFI_SCAN_F5, EfiKeyF5, + 0x40, EFI_SCAN_F6, EfiKeyF6, + 0x41, EFI_SCAN_F7, EfiKeyF7, + 0x42, EFI_SCAN_F8, EfiKeyF8, + 0x43, EFI_SCAN_F9, EfiKeyF9, + 0x44, EFI_SCAN_F10, EfiKeyF10, + 0x57, EFI_SCAN_F11, EfiKeyF11, + 0x58, EFI_SCAN_F12, EfiKeyF12, + 0x47, EFI_SCAN_HOME, EfiKeyHome, + 0x48, EFI_SCAN_UP, EfiKeyUpArrow, + 0x49, EFI_SCAN_PGUP, EfiKeyPgUp, + 0x4B, EFI_SCAN_LEFT, EfiKeyLeftArrow, + 0x4D, EFI_SCAN_RIGHT, EfiKeyRightArrow, + 0x4F, EFI_SCAN_END, EfiKeyEnd, + 0x50, EFI_SCAN_DN, EfiKeyDownArrow, + 0x51, EFI_SCAN_PGDN, EfiKeyPgDn, + 0x52, EFI_SCAN_INS, EfiKeyIns, + 0x53, EFI_SCAN_DEL, EfiKeyDel, + 0xFF, 0xFF, 0xFF // End of table +}; + +static UINT8 KeyPad_Table[] = { + '7','8','9','-','4','5','6','+','1','2','3','0','.' +}; + +static UINT8 KeyPadEfiCode_Table[] = { + EfiKeySeven, EfiKeyEight, EfiKeyNine, EfiKeyMinus, + EfiKeyFour, EfiKeyFive, EfiKeySix, EfiKeyPlus, + EfiKeyOne, EfiKeyTwo, EfiKeyThree, + EfiKeyZero, EfiKeyPeriod +}; + +KEYBOARD gKbd; +KEYBOARD_IRQ_STORE gKeyboardIrqBuffer; +EFI_CPU_ARCH_PROTOCOL *gCpuArch; +EFI_LEGACY_8259_PROTOCOL *mLegacy8259; +BOOLEAN gKeyboardIrqInstall=FALSE; +BOOLEAN gKeyboardDriverStart=FALSE; + +extern BOOLEAN Ps2MouseDetected; +extern BOOLEAN KbdIrqSupport; +extern BOOLEAN KbRdBeforeInstall; +extern BOOLEAN InsideGetMouseData; +extern BOOLEAN KBDEnableState; + +#if CLEAR_PS2KB_BUFFER_AT_READYTOBOOT +EFI_EVENT gClearKbBufferEvent; + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: ClearKbBuffer +// +// Description: +// This function clear PS2 KB buffer +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> + +EFI_STATUS +ClearKbBuffer( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + KEYBOARD *Kbd = &gKbd; + UINT8 *BdaKbHead = (UINT8*)((UINTN) 0x41a); + UINT8 *BdaKbTail = (UINT8*)((UINTN) 0x41c); + UINT8 *BdaKbBuffer = (UINT8*)((UINTN) 0x41e); + + Kbd->pBufHead = Kbd->pBufStart; + Kbd->pBufTail = Kbd->pBufStart; + + pBS->SetMem(Kbd->pBufStart, BUFFER_SIZE * sizeof (AMI_EFI_KEY_DATA), 0); + + // Empty KB Buffer in BDA + pBS->SetMem(BdaKbBuffer, 32, 0); + *BdaKbTail = *BdaKbHead; + + pBS->CloseEvent(Event); + + return EFI_SUCCESS; +} +#endif + + +// <AMI_PHDR_START> +//---------------------------------------------------------------------------- +// +// Name: UpdateVariabletoCheckBda +// +// Description: +// This function updates variable Legacy BIOS Protocol found,to check BDA +// for pending keys in EFI. +// +// Input: +// IN EFI_EVENT Event - signalled event +// IN VOID *Context - pointer to event context +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//-------------------------------------------------------------------------- +// <AMI_PHDR_END> +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT +VOID UpdateVariabletoCheckBda( + IN EFI_EVENT Event, + IN VOID *Context +) +{ + EFI_STATUS Status; + // + // Update Variable to check BDA if Legacy Bios Protocol Found. + // + Status = pBS->LocateProtocol(&gEfiLegacyBiosProtocolGuid, NULL, &gLegacy); + if (!EFI_ERROR(Status)) { + gLegacyBiosProtocolFound = TRUE; + } +} +#endif +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: StartKeyboard +// +// Description: This routine is called from Driver Binding Start function, +// it starts the keyboard +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - A pointer to the +// EFI_DRIVER_BINDING_PROTOCOL instance +// EFI_HANDLE Controller - Handle for this controller +// +// Output: EFI_STATUS - status of the operation +// +// Referrals: gEfiSimpleTextInProtocolGuid +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS StartKeyboard( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller) +{ + + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *pDummyDevPath; + KEYBOARD* Kbd = &gKbd; + KEYBOARD_IRQ_STORE* KbIrqBuffer = &gKeyboardIrqBuffer; + UINT8 Index=0; +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + EFI_EVENT Event; + VOID *pRegistration; +#endif +#endif + + if (EFI_ERROR(gSysTable->BootServices->OpenProtocol( + Controller, + &gEfiDevicePathProtocolGuid, + &pDummyDevPath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER))) { + return EFI_INVALID_PARAMETER; + } + +#if CLEAR_PENDING_KEYS_IN_PS2 + // + // Reset the keyboard and Clear Pending Keys as some + // NoteBook Kbc needs reset and Clearing the OBF. + // + Ps2KbdReset(); + ClearOBF (); +#endif + + DetectPS2KeyboardAndMouse(); + + if (EFI_ERROR(DetectPS2Keyboard())) { + gSysTable->BootServices->CloseProtocol( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + return EFI_DEVICE_ERROR; + } + + // + // Initialize keyboard interface functions + // + (Kbd->iSimpleIn).Reset = KbdReset; + (Kbd->iSimpleIn).ReadKeyStroke = KbdReadKey; + + (Kbd->iSimpleInEx).Reset = KbdResetEx; + (Kbd->iSimpleInEx).ReadKeyStrokeEx = KbdReadKeyEx; + (Kbd->iSimpleInEx).SetState = SetState; + (Kbd->iSimpleInEx).RegisterKeyNotify = RegisterKeyNotify; + (Kbd->iSimpleInEx).UnregisterKeyNotify = UnRegisterKeyNotify; + + (Kbd->iKeycodeInEx).Reset = KbdResetEx; + (Kbd->iKeycodeInEx).ReadEfikey = KbdReadEfiKeyEx; + (Kbd->iKeycodeInEx).SetState = SetState; + (Kbd->iKeycodeInEx).RegisterKeyNotify = RegisterKeyNotify; + (Kbd->iKeycodeInEx).UnregisterKeyNotify = UnRegisterKeyNotify; + + gSysTable->BootServices->CreateEvent( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + OnWaitingOnKey, + Kbd, + &Kbd->iSimpleIn.WaitForKey); + + gSysTable->BootServices->CreateEvent( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + OnWaitingOnKey, + Kbd, + &Kbd->iSimpleInEx.WaitForKeyEx); + + gSysTable->BootServices->CreateEvent( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + OnWaitingOnKey, + Kbd, + &Kbd->iKeycodeInEx.WaitForKeyEx); + + // + // Install protocol interfaces for the keyboard device. + // + Status = gSysTable->BootServices->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextInProtocolGuid, &Kbd->iSimpleIn, + &gEfiSimpleTextInExProtocolGuid, &Kbd->iSimpleInEx, + &gAmiEfiKeycodeProtocolGuid, &Kbd->iKeycodeInEx, + NULL + ); + + if (EFI_ERROR(Status)) { + gSysTable->BootServices->CloseProtocol( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + gSysTable->BootServices->CloseEvent(Kbd->iSimpleIn.WaitForKey); + gSysTable->BootServices->CloseEvent(Kbd->iSimpleInEx.WaitForKeyEx); + gSysTable->BootServices->CloseEvent(Kbd->iKeycodeInEx.WaitForKeyEx); + } + + if (!(EFI_ERROR(Status))) { + // + // Initialize keyboard device + // + Kbd->KeyIsReady = FALSE; + Kbd->ScannerState = KBST_READY; + Kbd->KeyData.KeyState.KeyToggleState = LedsAtStartup; + Kbd->KeyData.KeyState.KeyToggleState |= TOGGLE_STATE_VALID; + Kbd->KeyData.KeyState.KeyShiftState = SHIFT_STATE_VALID; + + Kbd->pBufStart = MallocZ(BUFFER_SIZE * sizeof (AMI_EFI_KEY_DATA)); + if(!Kbd->pBufStart) return EFI_OUT_OF_RESOURCES; + Kbd->pBufHead = Kbd->pBufStart; + Kbd->pBufTail = Kbd->pBufStart; + Kbd->pBufEnd = Kbd->pBufStart + BUFFER_SIZE; + + DrivePS2KbdMachine = ReadAndProcessKey; + + // + // Set LED's + // + LEDsOnOff(Kbd); + + InitHotKeys(Controller); // Produce HotKeys protocol + +// for (Count = 3; Count; Count--) { +// if(IssueCommand(0xF4) == 0xFA) break; // Clear the KBD buffer +// } + + Kbd->LEDCommandState = 0; + +#if CLEAR_PS2KB_BUFFER_AT_READYTOBOOT + gSysTable->BootServices->CreateEvent( + EFI_EVENT_SIGNAL_READY_TO_BOOT, + TPL_NOTIFY, + ClearKbBuffer, + NULL, + &gClearKbBufferEvent); +#endif + +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + RegisterProtocolCallback( + &gEfiLegacyBiosProtocolGuid, UpdateVariabletoCheckBda, + NULL, &Event,&pRegistration + ); + + // + // Check whether Legacy BIOS Protocol Installed. + // + UpdateVariabletoCheckBda(NULL,NULL); + +#endif +#endif + } + + DListInit(&mPs2KeyboardData); + + Status = pBS->CreateEvent( + EVT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + TPL_NOTIFY, + StartPollingKey, + Kbd, + &Ps2KeyEvent + ); + + // + // if before keyboard driver starts data is available in buffer + // it will be collected in local buffer in KeyboardInterrupt?Handler + // only if KBD_READ_BEFORE_INSTALL = 1, the avalable data in local + // buffer is processed. + // + if(KbRdBeforeInstall){ + for (Index=0;Index < KbIrqBuffer->KbdIndex; Index++){ + ProcessKBDData(Kbd, KbIrqBuffer->KbdBuffer[Index]); + } + } + gKeyboardDriverStart = TRUE; + // + // Re enable keyboard irq as it was previously disabled. + // if KBD_READ_BEFORE_INSTALL = 0 then initialize keyboard irq here + // + if(KbdIrqSupport){ + if(KbRdBeforeInstall){ + gKeyboardIrqInstall = TRUE; + // + // Now enable the interrupt + // + mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ, FALSE); + } + else { + InitKeyboardIrq(); + } + } + // + // Enable the Keyboard and Keyboard Interrupt. We must initilize this + // one for the Keyboard to work on Legacy mode. And also Legacy mode AMIUSB driver + // expects Keyboard and Interrupt should be enabled once Port 60/64 is present. + // + Write8042CommandByte(0x65); + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: StopKeyboard +// +// Description: This routine is called from Driver Binding Stop function. +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - A pointer to the +// EFI_DRIVER_BINDING_PROTOCOL instance +// EFI_HANDLE Controller - Handle for this controller +// +// Output: EFI_STATUS - status of the operation +// +// Referrals: gEfiSimpleTextInProtocolGuid +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS StopKeyboard( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller) +{ + KEYBOARD* Kbd = &gKbd; + EFI_STATUS Status; + + // + // Uninstall protocol interfaces from the keyboard device. + // + Status = gSysTable->BootServices->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, &Kbd->iSimpleIn, + &gEfiSimpleTextInExProtocolGuid, &Kbd->iSimpleInEx, + &gAmiEfiKeycodeProtocolGuid, &Kbd->iKeycodeInEx, + NULL + ); + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Close protocols that is open during Start + // + Status = gSysTable->BootServices->CloseProtocol( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller); + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Kill wait event + // + gSysTable->BootServices->CloseEvent(Kbd->iSimpleIn.WaitForKey); + gSysTable->BootServices->CloseEvent(Kbd->iSimpleInEx.WaitForKeyEx); + gSysTable->BootServices->CloseEvent(Kbd->iKeycodeInEx.WaitForKeyEx); + gSysTable->BootServices->CloseEvent(Ps2KeyEvent); + + pBS->FreePool(Kbd->pBufStart); + + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KbdReset +// +// Description: Resets the input device hardware. This routine is a part +// of SimpleTextIn protocol implementation. +// +// Parameters: EFI_SIMPLE_TEXT_INPUT_PROTOCOL +// *This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL +// instance. +// BOOLEAN +// ExtendedVerification - Indicates that the driver may +// perform a more exhaustive verification operation of the +// device during reset. +// +// Output: EFI_SUCCESS The device was reset. +// EFI_DEVICE_ERROR The device is not functioning correctly +// and could not be reset. +// +// Modified: KBDEnableState +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS KbdReset( + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + BOOLEAN ExtendedVerification ) +{ + UINT8 bCount, bData, bBCount; + KEYBOARD* Kbd = &gKbd; + EFI_STATUS Status; + + // + // Check for keyboard IRQ support + // + if(KbdIrqSupport && gKeyboardIrqInstall) { + // + // Now Disable the interrupt + // + mLegacy8259->DisableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ); + } + InsideKbdReset = TRUE; + Kbd->KeyIsReady = FALSE; + Kbd->ScannerState = KBST_READY; + + Kbd->pBufHead = Kbd->pBufStart; + Kbd->pBufTail = Kbd->pBufStart; + + pBS->SetMem(Kbd->pBufStart, BUFFER_SIZE * sizeof (AMI_EFI_KEY_DATA), 0); + + DisableKeyboard(); + PROGRESS_CODE(DXE_KEYBOARD_RESET); + + for (bBCount = 0; bBCount < 4; bBCount++) { + for (bCount = 0; bCount < 3; bCount++) { + Status = ReadDevice(KBD_DISABLE_SCANNING, &bData, KB_ACK_COM); + if (!EFI_ERROR(Status)) { + break; + } + } + if (EFI_ERROR(Status)) { + continue; + } + for (bCount = 0; bCount < 3; bCount++) { + Status = ReadDevice(KBD_ENABLE_SCANNING, &bData, KB_ACK_COM); + if (!EFI_ERROR(Status)) { + break; + } + } + if (!EFI_ERROR(Status)) { + break; + } + } + // + // Report the Buffer FULL error code if there is failure. + // + if (EFI_ERROR(Status)) { + ERROR_CODE (DXE_KEYBOARD_BUFFER_FULL_ERROR, EFI_ERROR_MAJOR); + } + + KBDEnableState = FALSE; + Status = EnableKeyboard(); + + if (EFI_ERROR(Status)) { + // + // Report the KBC Controller error code. + // + ERROR_CODE (DXE_KEYBOARD_CONTROLLER_ERROR, EFI_ERROR_MAJOR); + } + +#if CLEAR_PENDING_KEYS_IN_PS2 + // + // Clear OBF as some Notebook KBC has some keys even after + // disabling and enabling scanning. + // + ClearOBF (); +#endif + + if(!gKeyboardIrqInstall){ + LEDsOnOff(Kbd); + } + + Kbd->LEDCommandState = 0; + InsideKbdReset = FALSE; + + if(KbdIrqSupport && gKeyboardIrqInstall) { + + + // + // Now enable the interrupt + // + mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ, FALSE); + } + + return EFI_SUCCESS; + +} + + +EFI_STATUS KbdResetEx( + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + BOOLEAN ExtendedVerification ) +{ + return KbdReset(0, ExtendedVerification); +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KbdReadKey +// +// Description: Reads the next keystroke from the input device. This +// routine is a part of SimpleTextIn protocol +// implementation. +// +// Paremeters: EFI_SIMPLE_TEXT_INPUT_PROTOCOL +// This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL +// instance. +// EFI_INPUT_KEY +// InputKey - A pointer to a buffer that is to be filled in +// with the keystroke information for the key that was +// pressed. +// +// Output: EFI_SUCCESS - The keystroke information was returned. +// EFI_NOT_READY - There was no keystroke data available. +// EFI_DEVICE_ERROR - The keystroke information was not +// returned due to hardware errors. +// +// Modified: InsideKbdReadKey +// +// Referral(s): InsideGetMouseData, InsideGetMouseData, +// InsideOnWaitingOnKey +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS KbdReadKey( + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + EFI_INPUT_KEY *InputKey ) +{ + KEYBOARD* Kbd = &gKbd; + + if (InsideGetMouseData || InsideKbdReadKey || InsideOnWaitingOnKey || InsideKbdReset || InsideMouseReset) { + return GetKeyFromBuffer (Kbd, (VOID*)InputKey, sizeof(EFI_INPUT_KEY)); + } + + InsideKbdReadKey = TRUE; + + PS2DataDispatcher(This); + + InsideKbdReadKey = FALSE; + +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + if( gLegacyBiosProtocolFound ) { + if (!CheckKeyinBuffer(Kbd)) { + if( *BdaKbdHead != *BdaKbdTail ) { + ProcessKBDData (Kbd, *((UINT8 *)(*BdaKbdHead + BdaSeg + 1))); + *BdaKbdHead += 2; + if(*BdaKbdHead == 0x3E) { + *BdaKbdHead = 0x1E; + } + } + } + } +#endif +#endif + + return GetKeyFromBuffer (Kbd, (VOID*)InputKey, sizeof(EFI_INPUT_KEY)); + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: KbdReadKeyEx +// +// Description: Reads the next keystroke from the input device. This +// routine is a part of SimpleTextInEx protocol +// implementation. +// +// Paremeters: EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL +// *This - A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL +// instance. +// +// Output: EFI_INPUT_KEY +// *key - A pointer to a buffer that is filled in with the +// keystroke state data for the key that was pressed. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +KbdReadKeyEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status; + KEYBOARD *Kbd = &gKbd; + + if(KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + if (!InsideGetMouseData && !InsideKbdReadKey && !InsideOnWaitingOnKey && !InsideKbdReset && !InsideMouseReset) { + InsideKbdReadKey = TRUE; + PS2DataDispatcher(This); + InsideKbdReadKey = FALSE; + } + +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + if( gLegacyBiosProtocolFound ) { + if (!CheckKeyinBuffer(Kbd)) { + if( *BdaKbdHead != *BdaKbdTail ) { + ProcessKBDData (Kbd, *((UINT8 *)(*BdaKbdHead + BdaSeg + 1))); + *BdaKbdHead += 2; + if(*BdaKbdHead == 0x3E) { + *BdaKbdHead = 0x1E; + } + } + } + } +#endif +#endif + + Status = GetKeyFromBuffer (Kbd, (VOID*)KeyData, sizeof(EFI_KEY_DATA)); + if (EFI_ERROR(Status)) { + + pBS->SetMem(KeyData, sizeof (EFI_KEY_DATA), 0); + // + // Check the partial Key. If found return Success with NULL data + // in EFI_INPUT_KEY. + // + Status=CheckPartialKey(Kbd, (EFI_KEY_DATA*)KeyData); + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS KbdReadEfiKeyEx ( + IN AMI_EFIKEYCODE_PROTOCOL *This, + OUT AMI_EFI_KEY_DATA *KeyData +) +{ + EFI_STATUS Status; + KEYBOARD *Kbd = &gKbd; + + if (!InsideGetMouseData && !InsideKbdReadKey && !InsideOnWaitingOnKey && !InsideKbdReset && !InsideMouseReset) { + InsideKbdReadKey = TRUE; + PS2DataDispatcher(This); + InsideKbdReadKey = FALSE; + } + + +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + if( gLegacyBiosProtocolFound ) { + // + // If there is no key, check whether any key is present BDA Keyboard buffer as + // we may miss any key in legacy mode. + // + if (!CheckKeyinBuffer(Kbd)) { + if( *BdaKbdHead != *BdaKbdTail ) { + // + // Get the scan code from BDA keyboard buffer and process it. + // + ProcessKBDData (Kbd, *((UINT8 *)(*BdaKbdHead + BdaSeg + 1))); + *BdaKbdHead += 2; + // + // Check whether we have reached end of circular buffer, if reached initialize + // header to beginning of the buffer. + // + if(*BdaKbdHead == 0x3E) { + *BdaKbdHead = 0x1E; + } + } + } + } +#endif +#endif + + Status = GetKeyFromBuffer (Kbd, (VOID*)KeyData, sizeof(AMI_EFI_KEY_DATA)); + if (EFI_ERROR(Status)) { + pBS->SetMem(KeyData, sizeof (AMI_EFI_KEY_DATA), 0); + // + // Check the partial Key. If found return Success with NULL data + // in EFI_INPUT_KEY. + // + Status=CheckPartialKey(Kbd, (EFI_KEY_DATA*)KeyData); + return Status; + } + + return Status; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: SetState +// +// Description: Set certain state for the input device. +// +// Paremeters: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// KeyToggleState - Pointer to the EFI_KEY_TOGGLE_STATE to +// set the state for the input device. +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +SetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +) +{ + BOOLEAN ChgSL = FALSE; + BOOLEAN ChgCL = FALSE; + BOOLEAN ChgNL = FALSE; + + KEYBOARD* Kbd = &gKbd; + + if(KeyToggleState == NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (!(*KeyToggleState & TOGGLE_STATE_VALID) || + ((*KeyToggleState & (~(TOGGLE_STATE_VALID | KEY_STATE_EXPOSED | + SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE)))) ) { + return EFI_UNSUPPORTED; + } + + + ChgSL = ((*KeyToggleState & SCROLL_LOCK_ACTIVE)!=0) ^ ((Kbd->KeyData.KeyState.KeyToggleState & SCROLL_LOCK_ACTIVE)!=0); + ChgNL = ((*KeyToggleState & NUM_LOCK_ACTIVE)!=0) ^ ((Kbd->KeyData.KeyState.KeyToggleState & NUM_LOCK_ACTIVE)!=0); + ChgCL = ((*KeyToggleState & CAPS_LOCK_ACTIVE)!=0) ^ ((Kbd->KeyData.KeyState.KeyToggleState & CAPS_LOCK_ACTIVE)!=0); + + if (ChgSL || ChgCL || ChgNL) { + Kbd->KeyData.KeyState.KeyToggleState &= ~(SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE); + + if (*KeyToggleState & SCROLL_LOCK_ACTIVE) Kbd->KeyData.KeyState.KeyToggleState |= SCROLL_LOCK_ACTIVE; + if (*KeyToggleState & NUM_LOCK_ACTIVE) Kbd->KeyData.KeyState.KeyToggleState |= NUM_LOCK_ACTIVE; + if (*KeyToggleState & CAPS_LOCK_ACTIVE) Kbd->KeyData.KeyState.KeyToggleState |= CAPS_LOCK_ACTIVE; + + LEDsOnOff(Kbd); + } + + return EFI_SUCCESS; +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: StartPollingKey +// +// Description: Get the keys from the keyboard controller +// +// Paremeters: IN EFI_EVENT Event event that has been signaled +// IN VOID *Context +// +// Output: None +// +// +//<AMI_PHDR_END> +//********************************************************************** +VOID StartPollingKey(EFI_EVENT Event, VOID *Context) +{ + if (!InsideGetMouseData && !InsideKbdReadKey && !InsideOnWaitingOnKey && !InsideKbdReset && !InsideMouseReset) { + InsideKbdReadKey = TRUE; + PS2DataDispatcher(Context); + InsideKbdReadKey = FALSE; + } + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CheckKeyNotify +// +// Description: Call the notification function based on the key pressed +// +// Input: Key - Key pressed +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +CheckKeyNotify(AMI_EFI_KEY_DATA *Key) +{ + + KEY_WAITING_RECORD *Ps2KeyIn = OUTTER(mPs2KeyboardData.pHead, Link, KEY_WAITING_RECORD); + BOOLEAN KeyScanCodeMatch=FALSE; + BOOLEAN KeyUniCodeMatch=FALSE; + BOOLEAN ShiftKeyMatch=FALSE; + BOOLEAN CtrlKeyMatch=FALSE; + BOOLEAN AltKeyMatch=FALSE; + BOOLEAN LogoKeyMatch=FALSE; + BOOLEAN MenuKeyMatch=FALSE; + BOOLEAN SysRqKeyMatch=FALSE; + BOOLEAN KeyShiftCodeMatch=FALSE; + BOOLEAN KeyToggleKeyMatch=FALSE; + + // if the list is empty return the status that was passed in + if (Ps2KeyIn == NULL) + return EFI_SUCCESS; + + // check for a handle that was already identified + while ( Ps2KeyIn != NULL) + { + KeyScanCodeMatch=FALSE; + KeyUniCodeMatch=FALSE; + ShiftKeyMatch=FALSE; + CtrlKeyMatch=FALSE; + AltKeyMatch=FALSE; + LogoKeyMatch=FALSE; + MenuKeyMatch=FALSE; + SysRqKeyMatch=FALSE; + KeyShiftCodeMatch=FALSE; + KeyToggleKeyMatch=FALSE; + + // + // Check the Scan Code if the Scan code is not 0 + // + if (Ps2KeyIn->Context.Key.ScanCode != 0) { + if( Ps2KeyIn->Context.Key.ScanCode == Key->Key.ScanCode) { + KeyScanCodeMatch=TRUE; + } + } else { + KeyScanCodeMatch=TRUE; + } + + // + // Check the Uncide Code Matching + // + + if(Ps2KeyIn->Context.Key.UnicodeChar == Key->Key.UnicodeChar) { + KeyUniCodeMatch=TRUE; + } + + if(Ps2KeyIn->Context.KeyState.KeyShiftState & SHIFT_STATE_VALID){ + + // + // Check the ShiftKey Matching. Left Shift Key is matched with + // Left or Right Shift Key. Same for Right Shift Key + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED)) { + if(Key->KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED)) { + ShiftKeyMatch=TRUE; + } + } else { + ShiftKeyMatch=TRUE; + } + + // + // Check the Ctrl Matching. Left Ctrl Key is matched with + // Left or Right Ctrl Key. Same for Right Ctrl Key + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & (RIGHT_CONTROL_PRESSED | LEFT_CONTROL_PRESSED)) { + if(Key->KeyState.KeyShiftState & (RIGHT_CONTROL_PRESSED | LEFT_CONTROL_PRESSED)) { + CtrlKeyMatch=TRUE; + } + } else { + CtrlKeyMatch=TRUE; + } + + // + // Check the Alt Matching. Left Alt Key is matched with + // Left or Right Alt Key. Same for Right Alt Key + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) { + if(Key->KeyState.KeyShiftState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) { + AltKeyMatch=TRUE; + } + } else { + AltKeyMatch=TRUE; + } + + // + // Check the Logo Matching. Left Logo Key is matched with + // Left or Right Logo Key. Same for Right Logo Key + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & (RIGHT_LOGO_PRESSED | LEFT_LOGO_PRESSED)) { + if(Key->KeyState.KeyShiftState & (RIGHT_LOGO_PRESSED | LEFT_LOGO_PRESSED)) { + LogoKeyMatch=TRUE; + } + } else { + LogoKeyMatch=TRUE; + } + + // + // Check the Menu Key Matching + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & MENU_KEY_PRESSED) { + if(Key->KeyState.KeyShiftState & MENU_KEY_PRESSED) { + MenuKeyMatch=TRUE; + } + } else { + MenuKeyMatch=TRUE; + } + + // + // Check the SysRq Key Matching + // + if (Ps2KeyIn->Context.KeyState.KeyShiftState & SYS_REQ_PRESSED) { + if(Key->KeyState.KeyShiftState & SYS_REQ_PRESSED) { + SysRqKeyMatch=TRUE; + } + } else { + SysRqKeyMatch=TRUE; + } + + KeyShiftCodeMatch=ShiftKeyMatch & CtrlKeyMatch & AltKeyMatch + & LogoKeyMatch & MenuKeyMatch & SysRqKeyMatch; + }else { + KeyShiftCodeMatch=TRUE; + } + // + // Check the Key Toggle State + // + if(Ps2KeyIn->Context.KeyState.KeyToggleState & TOGGLE_STATE_VALID){ + if(Ps2KeyIn->Context.KeyState.KeyToggleState == Key->KeyState.KeyToggleState) { + KeyToggleKeyMatch=TRUE; + } + } else { + KeyToggleKeyMatch=TRUE; + } + + // + // If everything matched, call the callback function. + // + if(KeyScanCodeMatch & KeyUniCodeMatch & KeyShiftCodeMatch & KeyToggleKeyMatch) { + //Call the notification function + // + Ps2KeyIn->Callback(&Ps2KeyIn->Context); + } + // go to the next element in the list + Ps2KeyIn = OUTTER(Ps2KeyIn->Link.pNext, Link, KEY_WAITING_RECORD); + } + + // if it is a new handle return the status pass in + return EFI_SUCCESS; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: RegisterKeyNotify +// +// Description: Register the callback function for the specific Key +// +// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// KeyData - Key value +// KeyNotificationFunction- Pointer to the Notification Function +// NotificationHandle - Handle to be unregisterd +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +RegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +) +{ + EFI_STATUS Status; + + + if(KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + // + // Create database record and add to database + // + Status = pBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (KEY_WAITING_RECORD), + &mPs2KeyboardRecord + ); + + if(EFI_ERROR(Status)) { + return Status; + } + + // + // Gather information about the registration request + // + + mPs2KeyboardRecord->Context = *KeyData; + mPs2KeyboardRecord->Callback = KeyNotificationFunction; + + DListAdd (&mPs2KeyboardData, &(mPs2KeyboardRecord->Link)); + + // + // Child's handle will be the address linked list link in the record + // + *NotifyHandle = (EFI_HANDLE) (&mPs2KeyboardRecord->Link); + + if(mPs2KeyboardData.Size == 1) { + pBS->SetTimer(Ps2KeyEvent, + TimerPeriodic, + KEY_POLLING_INTERVAL); + } + + return EFI_SUCCESS; +} +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: UnRegisterKeyNotify +// +// Description: Unregister the callback function +// +// Input: This - A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL_EX +// instance. +// NotificationHandle - Handle to be unregisterd +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS +UnRegisterKeyNotify( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +) +{ + + DLINK *ListPtr; + KEY_WAITING_RECORD *Ps2KeyIn; + + if(NotificationHandle == NULL ) { + return EFI_INVALID_PARAMETER; + } + + ListPtr = mPs2KeyboardData.pHead; + while ( ListPtr != NULL) + { + Ps2KeyIn = OUTTER(ListPtr, Link, KEY_WAITING_RECORD); + if ( (&Ps2KeyIn->Link) == NotificationHandle) + { + DListDelete(&mPs2KeyboardData, ListPtr); + pBS->FreePool(Ps2KeyIn); + break; + } + + ListPtr = ListPtr->pNext; + } + + if(ListPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if(mPs2KeyboardData.Size == 0) { + pBS->SetTimer(Ps2KeyEvent, + TimerCancel, + 0); + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: OnWaitingOnKey +// +// Description: Callback for the EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey +// event; +// checks whether the new key is available and if so - +// signals the event. +// +// Input: EFI_EVENT Event - Event to signal +// void Context - Event specific context (pointer to Kbd +// device) +// +// Output: None +// +// Modified: InsideOnWaitingOnKey +// +// Referrals: InsideGetMouseData, InsideKbdReadKey, +// InsideOnWaitingOnKey +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +OnWaitingOnKey ( + EFI_EVENT Event, + VOID *Context ) +{ + + if (InsideGetMouseData || InsideKbdReadKey || InsideOnWaitingOnKey || InsideKbdReset || InsideMouseReset) { + if (CheckKeyinBuffer((KEYBOARD*)Context)) gSysTable->BootServices->SignalEvent(Event); + return; + } + + InsideOnWaitingOnKey = TRUE; + + PS2DataDispatcher(Context); // Process new keys if available + + InsideOnWaitingOnKey = FALSE; + + if (CheckKeyinBuffer((KEYBOARD*)Context)) + { + gSysTable->BootServices->SignalEvent(Event); + } +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ReadAndProcessKey +// +// Description: PS2 keyboard keys processor, called from main PS2 +// dispatcher. +// It gets the key from KBC output buffer and calls +// HandleKBDData. +// +// Paremeters: void *Context - keyboard device pointer +// +// Output: None +// +// Notes: PS2 output buffer has data, incoming key is processed, +// Context->KeyIsReady is updated. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ReadAndProcessKey ( + VOID *Context ) +{ + + KEYBOARD *Kbd = &gKbd; + UINT8 data; + + data = KBCGetData(); + ProcessKBDData (Kbd, data); + return; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessKBDData +// +// Description: If key is ready, processes any hotkey, and inserts key +// in buffer +// +// Parameters: +// KEYBOARD *Kbd - Pointer to key buffer +// UINT8 data - Key data +// +// Output: None +// +// Notes: Incoming key is processed, Context->KeyIsReady is updated +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessKBDData ( + KEYBOARD *Kbd, + UINT8 data +) +{ + EFI_KEY_DATA DummyKey; + + HandleKBDData(Kbd, data); + if (Kbd->KeyIsReady) { + + ProcessHotKey(Kbd->KeyData.PS2ScanCode, + (UINT16)Kbd->KeyData.KeyState.KeyShiftState); + InsertKeyToBuffer(Kbd, &Kbd->KeyData); + Kbd->KeyIsReady = FALSE; + } else { + if (Kbd->KeyData.Key.ScanCode == 0 && Kbd->KeyData.Key.UnicodeChar == 0 && Kbd->ScannerState == KBST_READY ) { + // + // If the Key ShiftState has valid key, report as Partial Key + // + if ((Kbd->KeyData.KeyState.KeyShiftState & ~SHIFT_STATE_VALID) != 0) { + + pBS->CopyMem(&DummyKey, &Kbd->KeyData, sizeof(EFI_KEY_DATA)); + DummyKey.KeyState.KeyToggleState |= KEY_STATE_EXPOSED; + CheckKeyNotify((AMI_EFI_KEY_DATA*)&DummyKey); + } + } + } + return; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: HandleKBDData +// +// Description: Processes the input data. If a callback function is +// associated with the key, then it is executed. +// +// Paremeters: +// KEYBOARD *Kbd - Pointer to key buffer +// UINT8 data - Key data +// +// Output: None +// +// +// Notes: This routine can be called re-entrantly from LEDsOnOff(OutToKb) +// e.g. when Numlock and Del is pressed continously. +// Incoming key is processed, Context->KeyIsReady is updated. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +HandleKBDData ( + KEYBOARD *Kbd, + UINT8 data ) +{ + // + // PS2 keyboard could send one, two, four or six bytes in a row. + // Kbd->ScannerState is ST_READY if it is the first byte + // + if (Kbd->ScannerState == KBST_READY) + { + switch (data) { + case 0xE0: + Kbd->ScannerState = KBST_E0; + break; + case 0xE1: + Kbd->ScannerState = KBST_E1; + break; + default: + ProcessByte(Kbd, data, FALSE); + } + return; + } + else // Multi-byte sequence is being processed + { + if (Kbd->ScannerState == KBST_E1) // Processing E1 state + { + if (data != E1Seq[Kbd->Count]) { // Wrong byte in a sequence + ResetStateMachine(Kbd); + return; + } + // + // E1 sequence data is correct, proceed + // + if (Kbd->Count == 2) { // The ONLY 2-key sequence starting with E1 is Pause + Kbd->KeyData.EfiKey = EfiKeyPause; + Kbd->KeyIsReady = TRUE; + ResetStateMachine(Kbd); + return; + } + if (Kbd->Count == 4) { // E1 sequence has finished + ProcessByte(Kbd, data, FALSE); + ResetStateMachine(Kbd); + return; + } + // + // E1 sequence is not complete, update the counter and return + // + Kbd->Count++; + return; + } + else // Kbd->ScannerState == ST_E0 - processing E0 state + { + + // + // For E0 state the Count values will be: + // 0 for 1st and 2nd byte + // 2 for 3rd byte (if available) + // 1 for 4th byte (if available) + // No validity checking will be done for 2nd,3rd and 4th bytes + // + + if (Kbd->ScannerState == KBST_E0) { + if ( IsEnhancedKey( data)) { + ResetStateMachine(Kbd); + return; + } + // Processing E0 state, if data is 2A or AA or MSB bit is + // set (break key) ignore it. + if (data == 0x2A || data == 0xAA || data & 0x80 && \ + // except in special case of alt, ctrl, Print key, Left Logo, Right Logo and Menu Key + data != 0xb8 && data != 0x9d && data != 0xB7 && \ + data != 0xDB && data != 0xDC && data != 0xDD) { + ResetStateMachine(Kbd); + return; + } + else { + ProcessByte(Kbd, data, TRUE); + ResetStateMachine(Kbd); + return; + } + } + ProcessByte(Kbd, data, FALSE); + ResetStateMachine(Kbd); + return; + + } + } +} + + + +void ResetStateMachine(KEYBOARD *Kbd) +{ + Kbd->ScannerState = KBST_READY; + Kbd->Count = 0; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: IsLetter +// +// Description: Returns TRUE if the given make code belongs to the +// alphabetical symbol, otherwise returns FALSE. +// +// Paremeters: UINT8 data - The character to test +// +// Output: BOOLEAN - True if character is letter +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +IsLetter ( + UINT8 data ) +{ + if ((data >= 0x10 && data <= 0x19) || // Q...P + (data >= 0x1E && data <= 0x26) || // A...L + (data >= 0x2C && data <= 0x32)) { // Z...M + return TRUE; + } + return FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessByte +// +// Description: Checks for valid key, updates key modifiers, keyboard +// queue head and tail as well as Kbd->KeyIsReady field. +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// UINT8 data - byte to process +// BOOLEAN long_sequence - the indication of whether it is a +// 4 byte sequence or not; used to differentiate Shift keys +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessByte ( + KEYBOARD *Kbd, + UINT8 Data, + BOOLEAN long_sequence ) +{ + BOOLEAN bUpperCase, bShifted; + EFI_EXTKEY *extkey; + static BOOLEAN Make_Capslock = FALSE, Make_SCRLOCK = FALSE, Make_NUMLOCK = FALSE; + UINT8 *KeyboardTypeBda = (UINT8*)((UINTN) 0x496); + + + Kbd->KeyData.Key.ScanCode = 0; + Kbd->KeyData.Key.UnicodeChar = 0; + Kbd->KeyData.PS2ScanCode = Data; + + // + // Process ESC key + // + if (Data == 1) { + Kbd->KeyData.Key.ScanCode = EFI_SCAN_ESC; + Kbd->KeyData.EfiKey = EfiKeyEsc; + Kbd->KeyIsReady = TRUE; + return; + } + + // + // Get the E0, E1 Status from BDA (40:96). If those bit get set means Int9 processed the E0 + // E1 data and before processing other Scan code it came out of Legacy mode. + // Now EFI driver sees other scan code that's part of the E0 and E1 scan. So we don't want to Process + // those data. + // +#if CHECK_BDA_KEYBOARD_BUFFER +#if CSM_SUPPORT + if( gLegacyBiosProtocolFound ) { + if(*KeyboardTypeBda & (E0_STATUS_IN_BDA + E1_STATUS_IN_BDA)) { + *KeyboardTypeBda &=~(E0_STATUS_IN_BDA + E1_STATUS_IN_BDA); + return; + } + } +#endif +#endif + + // + // Process key modifiers: xyzLock (update LEDs) and Ctrl/Alt/Shift + // + switch (Data) { + case 0x38: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= RIGHT_ALT_PRESSED; + } else { + Kbd->KeyData.KeyState.KeyShiftState |= LEFT_ALT_PRESSED; + } + return; //break; + case 0xB8: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~RIGHT_ALT_PRESSED; + } else { + Kbd->KeyData.KeyState.KeyShiftState &= ~LEFT_ALT_PRESSED; + } + return; //break; + + case 0x1D: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= RIGHT_CONTROL_PRESSED; + } else { + Kbd->KeyData.KeyState.KeyShiftState |= LEFT_CONTROL_PRESSED; + } + return; //break; + case 0x9D: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~RIGHT_CONTROL_PRESSED; + } else { + Kbd->KeyData.KeyState.KeyShiftState &= ~LEFT_CONTROL_PRESSED; + } + return; //break; + + case 0x2A: { + Kbd->KeyData.KeyState.KeyShiftState |= LEFT_SHIFT_PRESSED; return; //break; + } + case 0xAA: // could be a part of a long break code + if (!long_sequence) { + Kbd->KeyData.KeyState.KeyShiftState &= ~LEFT_SHIFT_PRESSED; + } + return; //break; + + case 0x36: Kbd->KeyData.KeyState.KeyShiftState |= RIGHT_SHIFT_PRESSED; return; //break; + case 0xB6: Kbd->KeyData.KeyState.KeyShiftState &= ~RIGHT_SHIFT_PRESSED; return; //break; + + case 0x3A: + if (!Make_Capslock) { + Kbd->KeyData.KeyState.KeyToggleState ^= CAPS_LOCK_ACTIVE; + Make_Capslock = TRUE; + } + Kbd->KeyData.EfiKey = EfiKeyCapsLock; + Kbd->KeyIsReady = TRUE; + break; + + case 0xBA: Make_Capslock = FALSE; break; + + case 0x46: + if (Kbd->ScannerState != KBST_E0){ + if (!Make_SCRLOCK) { + Kbd->KeyData.KeyState.KeyToggleState ^= SCROLL_LOCK_ACTIVE; + Make_SCRLOCK = TRUE; + } + Kbd->KeyData.EfiKey = EfiKeySLck; + Kbd->KeyIsReady = TRUE; + } + break; + + case 0xC6: + if (Kbd->ScannerState != KBST_E0){ + Make_SCRLOCK = FALSE; + } + break; + case 0x45: + if (!Make_NUMLOCK) { + Kbd->KeyData.KeyState.KeyToggleState ^= NUM_LOCK_ACTIVE; + Make_NUMLOCK = TRUE; + } + Kbd->KeyData.EfiKey = EfiKeyNLck; + Kbd->KeyIsReady = TRUE; + break; + + case 0xC5: Make_NUMLOCK = FALSE; break; + // + // Handle the PrintScreen/SysRq make Code + // + case 0x37: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= SYS_REQ_PRESSED; + return; + } + break; + + // + // Handle the PrintScreen/SysRq breakcode + // + case 0xB7: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~ SYS_REQ_PRESSED; + return; + } + break; + + // + // Handle the Left Logo make Code + // + case 0x5B: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= LEFT_LOGO_PRESSED; + return; + } + break; + + // + // Handle the Left Logo breakcode + // + case 0xDB: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~ LEFT_LOGO_PRESSED; + return; + } + break; + + // + // Handle the Right Logo make Code + // + case 0x5C: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= RIGHT_LOGO_PRESSED; + return; + } + break; + + // + // Handle the Right Logo breakcode + // + case 0xDC: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~ RIGHT_LOGO_PRESSED; + return; + } + break; + + // + // Handle the Menu Key make Code + // + case 0x5D: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState |= MENU_KEY_PRESSED; + return; + } + break; + + // + // Handle the Meny Key breakcode + // + case 0xDD: + if (Kbd->ScannerState == KBST_E0) { + Kbd->KeyData.KeyState.KeyShiftState &= ~ MENU_KEY_PRESSED; + return; + } + break; + + case 0xFA: ProcessKBDResponse(Kbd, Data); break; + case 0xFE: ProcessKBDResponse(Kbd, Data); break; + case 0xFF: ProcessKBDResponse(Kbd, Data); break; + } + + // + // Process main block of keys + // + if (Data < 0x3A && !(Kbd->ScannerState == KBST_E0 && Data == 0x37)) {// Exceptional case is Printscreen/sys req + + bShifted = Kbd->KeyData.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED); + + if (Kbd->ScannerState == KBST_E0) bShifted = 0; // Check for '/' in Keypad. Otherwise '?' will be sent + + + if (IsLetter(Data)) { // for not-a-letter Caps-Lock must not work + bUpperCase = (Kbd->KeyData.KeyState.KeyToggleState & CAPS_LOCK_ACTIVE)? !bShifted: bShifted; + } + else { + bUpperCase = bShifted; + } + if (bUpperCase) { + Kbd->KeyData.Key.UnicodeChar = Code_Table[Data]; // UPPER CASE TABLE + } + else { + Kbd->KeyData.Key.UnicodeChar = code_table[Data]; // lower case table + } + Kbd->KeyData.EfiKey = ScancodeToEfi_table[Data]; + if (Kbd->KeyData.Key.UnicodeChar != 0) { + Kbd->KeyIsReady = TRUE; + } + return; + } + +// UK Keyboard "|\" (EfiKeyB0) +// data = 0x56(ScanCode Set1), EfiKeyB0, "|\" + if ( Data == 0x56) { + bShifted = Kbd->KeyData.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED); + if ( Kbd->ScannerState == KBST_E0) bShifted = 0; // Check for '/' in Keypad. Otherwise '?' will be sent + bUpperCase = bShifted; // for not-a-letter Caps-Lock must not work + if (bUpperCase) { + Kbd->KeyData.Key.UnicodeChar = '|'; // UPPER CASE TABLE + } + else { + Kbd->KeyData.Key.UnicodeChar = '\\'; // lower case + } + Kbd->KeyData.EfiKey = EfiKeyB0; + Kbd->KeyIsReady = TRUE; + return; + } + + // + // Process keypad keys. Exceptional cases: -, + on keypad + // Keypad numbers when NUMLOCK only is ON OR Shift only is pressed. + if (Kbd->ScannerState != KBST_E0) { + if ((Data > 0x46) && (Data < 0x54) && !long_sequence) { + if (((Kbd->KeyData.KeyState.KeyToggleState & NUM_LOCK_ACTIVE) // Only NUMLOCK in ON + && ((Kbd->KeyData.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED)) == 0)) + || (((Kbd->KeyData.KeyState.KeyToggleState & NUM_LOCK_ACTIVE) == 0) // Only shift key is pressed + && (Kbd->KeyData.KeyState.KeyShiftState & (RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED))) + || Data == 0x4a || Data ==0x4e) // check for -, + keys in keypad + { + Kbd->KeyData.Key.UnicodeChar = KeyPad_Table[Data-0x47]; + Kbd->KeyData.EfiKey = KeyPadEfiCode_Table[Data-0x47]; + Kbd->KeyIsReady = TRUE; + return; + } + } + } + // + // Process F-keys + // + for (extkey = ScanCode_Table; extkey->makecode != 0xFF; extkey++) { + if (Data == extkey->makecode) { + Kbd->KeyData.Key.ScanCode = extkey->efi_scancode; + Kbd->KeyData.EfiKey = extkey->efi_key; + Kbd->KeyIsReady = TRUE; + return; + } + } +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: LEDsOnOff +// +// Description: Turns keyboard LEDs on and off. +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +void LEDsOnOff ( + KEYBOARD* Kbd ) +{ + + UINT8 bIndicators = Kbd->KeyData.KeyState.KeyToggleState & 7; // SCRL/NUM/CPSL + + if (InsidePS2DataDispatcher) return; + InsidePS2DataDispatcher = TRUE; + + // + // Check for keyboard IRQ support + // + if(KbdIrqSupport){ + if(gKeyboardIrqInstall && KBDEnableState){ + if (bIndicators != Kbd->Indicators){ + // + // Turn on/off the lights + // + Kbd->CommandResponded = NULL; + // + // Issue Keyboard LED Command 0xED + // + CheckIssueLEDCmd(Kbd); + if(Kbd->LEDCommandState == ED_COMMAND_ISSUED) { + // + // LED command "ED" has been issues. Process the Data here itself. + // + UINT32 Counter; + for (Counter = 1000; Counter > 0; Counter--) { + // + // The Interrupt handler will handle the response + // and set the Kbd->LEDCommandState to zero in both + // case with or without error. Exit once the response is + // handled. + // + if(Kbd->LEDCommandState == 0) { + break; + } + gSysTable->BootServices->Stall(1000); + + } + } + } + Kbd->LEDCommandState = NULL; + InsidePS2DataDispatcher = FALSE; + return; + } + } + + + if (bIndicators != Kbd->Indicators) { + // + // Issue Keyboard LED Command 0xED + // + CheckIssueLEDCmd(Kbd); + + // + //Process the led command and data + // + ProcessLEDCommandData(Kbd); + } + + InsidePS2DataDispatcher = FALSE; + return; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: GetKeyFromBuffer +// +// Description: Gets the next key from the circular buffer +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// EFI_INPUT_KEY *key - Pointer to input key data +// +// Output: EFI_SUCCESS - key.ScanCode and key.UnicodeChar updated +// EFI_NOT_READY - no key in buffer +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +GetKeyFromBuffer ( + KEYBOARD *Kbd, + VOID *Key, + UINT8 KeySize +) +{ + AMI_EFI_KEY_DATA TempKey; + + if (Kbd->pBufHead == Kbd->pBufTail) return EFI_NOT_READY; + + pBS->CopyMem(&TempKey, Kbd->pBufHead, sizeof(AMI_EFI_KEY_DATA)); + + + TempKey.EfiKeyIsValid = 1; + TempKey.PS2ScanCodeIsValid = 1; + + ProcessMultiLanguage(&TempKey); + + if (TempKey.Key.UnicodeChar != 0) { + TempKey.KeyState.KeyShiftState &= ~(RIGHT_SHIFT_PRESSED | LEFT_SHIFT_PRESSED); + } + + pBS->CopyMem(Key, &TempKey, KeySize); + + Kbd->pBufHead++; + if (Kbd->pBufHead >= Kbd->pBufEnd) Kbd->pBufHead = Kbd->pBufStart; // Point to the beginning + + return EFI_SUCCESS; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: InsertKeyToBuffer +// +// Description: Insert the key into the circular buffer +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// AMI_EFI_INPUT_KEY key - input key data +// +// Output: EFI_SUCCESS - Key placed in buffer +// EFI_WARN_BUFFER_TOO_SMALL - Buffer to small +// +// Notes: If buffer is full, the EFI_WARN_BUFFER_TOO_SMALL. +// Tail points to the new Data. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +InsertKeyToBuffer ( + KEYBOARD *Kbd, + AMI_EFI_KEY_DATA *Key +) +{ + AMI_EFI_KEY_DATA *Temp = Kbd->pBufTail; + + CheckKeyNotify(Key); + if (Kbd->pBufTail != Kbd->pBufHead) { // Check if space available + Temp++; + if (Temp >= Kbd->pBufEnd) Temp = Kbd->pBufStart; + if (Kbd->pBufHead == Temp) return EFI_WARN_BUFFER_TOO_SMALL; // No more space + } + + *Kbd->pBufTail = *Key; + Kbd->pBufTail++; + + if (Kbd->pBufTail >= Kbd->pBufEnd) Kbd->pBufTail = Kbd->pBufStart; + + return EFI_SUCCESS; + +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CheckKeyinBuffer +// +// Description: Checks if any key is present in the buffer +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// +// Output: BOOLEAN - TRUE if a key is in the buffer, FALSE otherwise. +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN +CheckKeyinBuffer ( + KEYBOARD* Kbd +) +{ + if (Kbd->pBufHead == Kbd->pBufTail) return FALSE; + return TRUE; + +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: CheckPartialKey +// +// Description: Gets the next key from the circular buffer +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// EFI_INPUT_KEY *key - Pointer to input key data +// +// Output: EFI_SUCCESS - Partial Key Found +// EFI_NOT_READY - no key in buffer +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS +CheckPartialKey ( + KEYBOARD *Kbd, + EFI_KEY_DATA *Key +) +{ + + if (Kbd->KeyData.Key.ScanCode == 0 && Kbd->KeyData.Key.UnicodeChar == 0) { + // + // If the Key ShiftState has valid key, report as Partial Key + // + if ((Kbd->KeyData.KeyState.KeyShiftState & ~SHIFT_STATE_VALID) != 0) { + + pBS->CopyMem(Key, &Kbd->KeyData, sizeof(EFI_KEY_DATA)); + Key->KeyState.KeyToggleState |= KEY_STATE_EXPOSED; + CheckKeyNotify((AMI_EFI_KEY_DATA*)Key); + return EFI_SUCCESS; + } + } + + return EFI_NOT_READY; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------------- +// Procedure: KeyboardInterruptHandler +// +// Description: An interrupt handler for keyboard IRQ. +// +// +// Input: InterruptType Interrupt type +// SystemContext System context +// +// Output: EFI_SUCCESS +// +//---------------------------------------------------------------------------- +//<AMI_PHDR_END> +VOID KeyboardInterruptHandler( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext +) +{ + KEYBOARD_IRQ_STORE* KbIrqBuffer = &gKeyboardIrqBuffer; + KEYBOARD *Kbd = &gKbd; + UINT8 bIndicators = Kbd->KeyData.KeyState.KeyToggleState & 7; // SCRL/NUM/CPSL + UINT8 Data = IoRead8(KBC_DATA_PORT); + + gCpuArch->DisableInterrupt(gCpuArch); + + // + // Stored received acknowledgement + // + switch (Data) { + case 0xFA: + Kbd->CommandResponded = KB_ACK_COM; + if (Kbd->LEDCommandState == ED_COMMAND_ISSUED) { + Kbd->LEDCommandState = ED_DATA_ISSUED; + Kbd->Indicators = bIndicators; + WriteKeyboardData(bIndicators); + break; + } + + if (Kbd->LEDCommandState == ED_DATA_ISSUED) { + Kbd->LEDCommandState = 0; + break; + } + + break; + case 0xFE: + Kbd->CommandResponded = KB_RSND_COM; + if (Kbd->LEDCommandState == ED_COMMAND_ISSUED || Kbd->LEDCommandState == ED_DATA_ISSUED) { +// Error occured. Clear out the current indicator bits. +// Modifiers will have the correct bits that needs to be set. +// Next Call to CheckIssueLEDCmd will detect the mismatch +// and start the LED sequence. + WriteKeyboardData(0xF4); + Kbd->LEDCommandState = 0; + Kbd->KeyData.KeyState.KeyToggleState &= + ~(SCROLL_LOCK_ACTIVE | NUM_LOCK_ACTIVE | CAPS_LOCK_ACTIVE); + Kbd->Indicators &= 0xf0; + } + break; + case 0xFF: + Kbd->CommandResponded = KB_RSND_COM; + Kbd->LEDCommandState = 0; + break; + default: + // + // If key has been pressed before keyboard start then data will be saved in local buffer + // else data will be processed + // + if(!gKeyboardDriverStart){ + if (KbIrqBuffer->KbdIndex < BUFFER_SIZE){ + KbIrqBuffer->KbdBuffer[KbIrqBuffer->KbdIndex]=Data; + KbIrqBuffer->KbdIndex++; + } + } + else { + ProcessKBDData (Kbd, Data); + } + break; + } + + // + // End of interrupt command sent + // + mLegacy8259->EndOfInterrupt(mLegacy8259, SYSTEM_KEYBOARD_IRQ); + gCpuArch->EnableInterrupt(gCpuArch); +} + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: InitKeyboardIrq +// +// Description: To initialize keyboard interrupt, register keyboard +// handler, and enable the keyboard interrupt +// +// Input: +// +// Paremeters: +// +// Output: None +// +// +//<AMI_PHDR_END> +//********************************************************************** +VOID InitKeyboardIrq(VOID) +{ + + EFI_STATUS Status; + KEYBOARD_IRQ_STORE* KbIrqBuffer = &gKeyboardIrqBuffer; + EFI_GUID gEfiLegacy8259ProtocolGuid = EFI_LEGACY_8259_PROTOCOL_GUID; + EFI_GUID gEfiCpuArchProtocolGuid = EFI_CPU_ARCH_PROTOCOL_GUID; + UINT32 KeyboardVector = NULL; + + if (!gKeyboardIrqInstall){ + Status = pBS->LocateProtocol(&gEfiLegacy8259ProtocolGuid, NULL, &mLegacy8259); + if (EFI_ERROR(Status)) { + return; + } + + // Find the CPU Arch Protocol + Status = pBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, &gCpuArch); + if (EFI_ERROR(Status)) { + return; + } + + // + // Get keyboard Interrupt vector + // + Status = mLegacy8259->GetVector(mLegacy8259, SYSTEM_KEYBOARD_IRQ, (UINT8 *) & KeyboardVector); + if (EFI_ERROR(Status)) { + return; + } + + // + // Register interrupt handler for keyboard + // + Status = gCpuArch->RegisterInterruptHandler(gCpuArch, KeyboardVector, KeyboardInterruptHandler); + if (EFI_ERROR(Status)) { + return; + } + + KbIrqBuffer->KbdIndex=0; + gKeyboardIrqInstall = TRUE; + + // + // Now enable the interrupt + // + mLegacy8259->EnableIrq(mLegacy8259, SYSTEM_KEYBOARD_IRQ, FALSE); + } + return; +} + +#if CLEAR_PENDING_KEYS_IN_PS2 +// <AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: ClearOBF +// +// Description: +// Clears any pending keys in Ps2 Output Buffer. +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: This OBF clear is done since some PS2 KBC has pending keys even +// after resetting the Keyboard. +//--------------------------------------------------------------------------- +// <AMI_PHDR_END> +VOID +ClearOBF( +VOID +) +{ + UINT8 bData; + UINT8 Counter=200; + + pBS->Stall(10*1000); + + while( IoRead8(KBC_CMDSTS_PORT) & KBC_OBF ) + { + bData = IoRead8(KBC_DATA_PORT); + // + // wait 10 ms for KBC OBF output. + // + pBS->Stall(10*1000); + Counter--; + // + // If still keys are present after 2 sec. exit from the loop. + // + if(Counter==NULL) { + break; + } + } + return; +} + +// <AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Name: Ps2KbdReset +// +// Description: +// Reset the Ps2 Keyboard by sending disabling and Enabling scanning. +// +// Input: +// VOID +// +// Output: +// VOID +// +// Modified: +// +// Referrals: +// +// Notes: +// +//--------------------------------------------------------------------------- +// <AMI_PHDR_END> +VOID +Ps2KbdReset( +VOID +) +{ + EFI_STATUS Status; + UINT8 bCount, bData, bBCount; + + // + // Disable and enable keyboard to reset. + // + DisableKeyboard(); + + for (bBCount = 0; bBCount < 4; bBCount++) { + for (bCount = 0; bCount < 3; bCount++) { + Status = ReadDevice(KBD_DISABLE_SCANNING, &bData, KB_ACK_COM); + if (!EFI_ERROR(Status)) { + break; + } + } + + if (EFI_ERROR(Status)) { + continue; + } + + for (bCount = 0; bCount < 3; bCount++) { + Status = ReadDevice(KBD_ENABLE_SCANNING, &bData, KB_ACK_COM); + if (!EFI_ERROR(Status)) { + break; + } + } + + if (!EFI_ERROR(Status)) { + break; + } + } + + EnableKeyboard(); + return; +} + +#endif + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessLEDCommandData +// +// Description: Process the LED command and data. +// +// Input: KEYBOARD *Kbd - A pointer to the KEYBOARD device. +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID +ProcessLEDCommandData( + KEYBOARD* Kbd ) +{ + + UINT32 Counter; + UINT8 data; + + if(Kbd->LEDCommandState == ED_COMMAND_ISSUED) { + // + // LED command "ED" has been issued. Disable the keyboard and + // Process the Data here itself. + // + + DisableKeyboard(); + + for (Counter = 1000; Counter > 0; Counter--) { + for(data = IoRead8(KBC_CMDSTS_PORT); data & KBC_OBF; data = IoRead8(KBC_CMDSTS_PORT)) { + if (!(data & KBC_AUX_OBF)) { + // + // Handle the Command or Data Status + // + DrivePS2KbdMachine(NULL); + } + } + + // + // If the command and data is processed with or without error, exit here. + // + if(Kbd->LEDCommandState == 0) { + return; + } + gSysTable->BootServices->Stall(1000); + } + EnableKeyboard(); + } + return; +} + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: ProcessMultiLanguage +// +// Description: It maps the current key to a Unicode character from +// the keyboard layout +// +// Paremeters: KeyData - Pointer to the AMI_EFI_KEY_DATA . +// +// Output: None +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> +EFI_STATUS ProcessMultiLanguage( + IN OUT AMI_EFI_KEY_DATA *KeyData) +{ + EFI_STATUS Status; + + if(gPs2MultiLangSupportProtocol == NULL) { + Status= pBS->LocateProtocol ( + &gAmiMultiLangSupportGuid, + NULL, + &gPs2MultiLangSupportProtocol + ); + if(EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + } + Status = gPs2MultiLangSupportProtocol->KeyboardLayoutMap(gPs2MultiLangSupportProtocol,KeyData); + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/ps2main.c b/Core/EM/PS2CTL/ps2main.c new file mode 100644 index 0000000..d760970 --- /dev/null +++ b/Core/EM/PS2CTL/ps2main.c @@ -0,0 +1,655 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2main.c 22 11/07/12 12:23a Srikantakumarp $ +// +// $Revision: 22 $ +// +// $Date: 11/07/12 12:23a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2main.c $ +// +// 22 11/07/12 12:23a Srikantakumarp +// [TAG] EIP99411 +// [Category] Improvement +// [Description] Add port validation check in the PS2Ctrl module before +// starting the driver. +// [Files] kbc.c, kbc.h, mouse.c, ps2main.c, CORE_DXE.sdl, Tokens.c +// +// 21 2/01/12 2:02a Deepthins +// [TAG] EIP63116 +// [Category] New Feature +// [Description] PS/2 Keyboard/Mouse IRQ mode generic support +// [Files] Token.c, Ps2main.c, Ps2kbd.c, Mouse.c, kbc.h, kbc.c, +// CORE_DXE.sdl +// +// 20 12/15/11 5:42p Artems +// Fixed bug in Supported function +// +// 19 11/03/11 5:58a Rajeshms +// [TAG] EIP73263 +// [Category] Improvement +// [Description] PS2Ctl Driver Follow the UEFI Driver Model as per the +// UEFI Spec. +// [Files] ps2main.c, efismplpp.c +// +// 18 8/02/11 4:43a Rameshr +// [TAG] - EIP 58974 +// [Category]- BUG FIX +// [Severity]- Minor +// [Symptom] - Yellow exclamation mark in Windows when PS2 KB/MS are not +// present. +// [RootCause]- ACPI name space variable reports that PS2 device present +// [Solution] - Updated the SIO device status based on the device present +// after BDS. +// [Files] - Kbc.c, Kbc.h , Ps2main.c +// +// 17 4/27/11 4:35a Lavanyap +// [TAG] - EIP49407 +// [Category] - IMPROVEMENT +// [Description] - Move the Ps2 driver SDL tokens from Core Source to Core +// Bin,So that we don't need to add Core source for changing the Ps2 +// driver SDL tokens. +// [Files] - Ps2Ctl.sdl, ps2kbd.c, ps2main.c, ps2ctl.h, kbc.c, mouse.c, +// hotkey.c, CORE_DXE.sdl, Tokens.c +// +// 16 1/24/11 3:45p Pats +// [TAG] - EIP 18488 +// [Category] - Enhancement +// [Severity] - Normal +// [Symptom] - PS2CTL: Need hooks for port swap, Keybaord mouse detect. +// [RootCause] - Support may be needed for kbc controller or SIO with +// different support from AMI KB-5. +// [Solution] - Changes to make AutodetectKbdMousePortsPtr elink +// controlled instead of token controlled. +// [Files] - ps2main.c +// NOTE: Implementation of this change requires changes to CORE_DXE.sdl +// and BdsBoard.c. +// +// 15 1/05/11 12:43a Rameshr +// [TAG] EIPEIP 35306 +// [Category] Improvement +// [Description] Report the Ps2 Controller and Device Error Codes. +// [Files] AmiStatuscodes.h, Kbc.c, Kbc.h,Ps2ctl.sdl, ps2kbd.c, +// ps2main.c ,Statuscode.h +// +// 14 8/28/09 10:03a Felixp +// Component Name protocol implementation is upadted to support both +// ComponentName and ComponentName2 protocols +// (based on value of the EFI_SPECIFICATION_VERSION SDL token). +// +// 13 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 12 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 11 4/10/07 10:04a Felixp +// LookupHID routine renamed to LookupPs2Hid to avoid linking issue when +// linking with FloppyCtrl module +// +// 10 3/19/07 2:28p Pats +// Removed test for KBC acrive. +// +// 9 3/13/07 5:36p Pats +// Fixed problem in last BAT fix. +// +// 8 3/13/07 2:59p Pats +// Tests for KBC active and skips KBC BAT test if it is. This preserves +// the input key if there is one. +// +// 7 2/28/07 6:05p Pats +// Made KBC BAT test removable with SDL token, to speed up boot, and to +// keep keep Setup key (F2 or Del) from being absorbed. +// +// 6 3/13/06 2:38a Felixp +// +// 5 10/11/05 4:11p Srinin +// KBD and Mouse Start function is called in TPL_NOTIFY state. +// +// 4 6/03/05 5:35p Felixp +// +// 2 2/25/05 10:27a Olegi +// +// 1 2/01/05 1:10a Felixp +// +// 4 1/31/05 3:12p Felixp +// Driver Binding Installed on a new handle. +// +// 3 1/18/05 3:22p Felixp +// PrintDebugMessage renamed to Trace +// +// 2 1/07/05 4:57p Felixp +// Small bug fix in ComponentName Protocol (GetPS2_DP modified) +// +// 1 10/28/04 10:19a Olegi +// +// 9 9/30/04 8:13a Olegi +// HotKeys added. +// +// 8 9/24/04 4:36p Olegi +// +// 7 9/21/04 5:53p Olegi +// +// 6 8/27/04 3:17p Olegi +// Header and footer added. +// +// 5 8/18/04 6:44p Olegi +// Logitech mouse PNPID added. +// +// 4 8/18/04 6:37p Olegi +// Header and footer added. +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: ps2main.c +// +// Description: PS/2 Controller DXE driver +// This driver supports PS/2 keyboard and/or PS/2 mouse depending on the +// switches in SDL tokens. +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + +//---------------------------------------------------------------------- + +#include "efi.h" +#include "ps2ctl.h" +#include "kbc.h" +#include <Protocol\ComponentName.h> + +//---------------------------------------------------------------------- + +#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \ + {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93} + +EFI_GUID gBdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID; + +static EFI_GUID gDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; +#ifndef EFI_COMPONENT_NAME2_PROTOCOL_GUID //old Core +static EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; +#else +static EFI_GUID gComponentNameProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; +#endif +EFI_GUID gDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; +UINT8 gDriverStartCounter; + +VOID *gAllDriverConnectedNotifyRegistration; +EFI_EVENT gAllDriverConnectedEvent; + +extern BOOLEAN Ps2MouseSupport; +extern BOOLEAN Ps2KbdSupport; +extern BOOLEAN KbcBasicAssuranceTest; +extern EFI_COMPONENT_NAME_PROTOCOL gPS2CtlDriverName; +extern EFI_LEGACY_8259_PROTOCOL *mLegacy8259; +extern BOOLEAN KbRdBeforeInstall; +extern BOOLEAN KbdIrqSupport; +EFI_SYSTEM_TABLE *gSysTable = NULL; +extern UINT8 gKeyboardIrqInstall; +extern UINT32 IbFreeTimeoutValue; + + + +//================================================================================== +// Function Prototypes for Driver Binding Protocol Interface +//================================================================================== +EFI_STATUS PS2CtlSupported( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); + +EFI_STATUS PS2CtlStart( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath); + +EFI_STATUS PS2CtlStop( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + UINTN NumberOfChildren, + EFI_HANDLE *ChildHandleBuffer); + +//================================================================================== +// Driver binding protocol instance for PS2Ctl Driver +//================================================================================== +EFI_DRIVER_BINDING_PROTOCOL gPS2CtlDriverBinding = { + PS2CtlSupported, + PS2CtlStart, + PS2CtlStop, + PS2_DRIVER_VER, // Driver version + NULL, // Image Handle + NULL // DriverBindingHandle +}; + +//================================================================================== +// Supported PS2 devices table +//================================================================================== +CHAR16 *gPS2ControllerName = L"PS/2 Controller"; + +PS2DEV_TABLE supportedDevices[] = { + {EISA_PNP_ID(0xF03), 0, DEVICETYPE_MOUSE, StartMouse, StopMouse, L"Microsoft PS/2 Mouse"}, + {EISA_PNP_ID(0xF12), 0, DEVICETYPE_MOUSE, StartMouse, StopMouse, L"Logitech PS/2 Mouse"}, + {EISA_PNP_ID(0xF13), 0, DEVICETYPE_MOUSE, StartMouse, StopMouse, L"Generic PS/2 Mouse"}, + {EISA_PNP_ID(0x303), 1, DEVICETYPE_MOUSE, StartMouse, StopMouse, L"IBM Keyboard, PS/2 Mouse Support"}, + {EISA_PNP_ID(0x303), 0, DEVICETYPE_KEYBOARD, StartKeyboard, StopKeyboard, L"Generic PS/2 Keyboard"}, + {0} // End of table +}; + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: PS2CtlEntryPoint +// +// Description: PS/2 Controller Driver Entry Point +// This function is a part of DriverBinfing protocol +// +// Parameters: EFI_HANDLE ImageHandle - Image handle for this driver +// image +// EFI_SYSTEM_TABLE *SystemTable - pointer to the EFI +// system table +// +// Output: EFI_STATUS - Status of the operation +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS PS2CtlEntryPoint( + EFI_HANDLE ImageHandle, + EFI_SYSTEM_TABLE *SystemTable ) +{ + EFI_STATUS Status; + + InitAmiLib(ImageHandle,SystemTable); + + gSysTable = SystemTable; + gPS2CtlDriverBinding.DriverBindingHandle = NULL; + gPS2CtlDriverBinding.ImageHandle = ImageHandle; + + Status = gSysTable->BootServices->InstallMultipleProtocolInterfaces( + &gPS2CtlDriverBinding.DriverBindingHandle, + &gDriverBindingProtocolGuid, &gPS2CtlDriverBinding, + &gComponentNameProtocolGuid, &gPS2CtlDriverName, + NULL); + + gDriverStartCounter = 0; + + // + // Update the SIO variable in the ACPI name space depend on the + // Ps2keyboard and Mouse Present state. + // + Status = RegisterProtocolCallback( + &gBdsAllDriversConnectedProtocolGuid, + UpdateSioVariableForKeyboardMouse, + NULL, + &gAllDriverConnectedEvent, + &gAllDriverConnectedNotifyRegistration + ); + ASSERT_EFI_ERROR(Status); + + // + // Initialized Keyboard irq if keys are to be read before starting driver + // IRQ handler will save the data in temp buffer and once the Keyboard + // Driver started , the temp buffer data is pushed into Keyboard driver. + // So that the key's are pressed in post also taken by Ps2 driver + // + if(KbRdBeforeInstall){ + if(IoRead8(KBC_CMDSTS_PORT) != 0xFF) { + // + // Enable the Keyboard and Keyboard Interrupt + // + Write8042CommandByte(0x65); + InitKeyboardIrq(); + } + } + + return EFI_SUCCESS; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: PS2CtlSupported +// +// Description: PS/2 Controller Driver Supported function +// This function is a part of DriverBinfing protocol +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this +// instance of the driver binding protocol +// EFI_HANDLE Controller - Handle for this controller +// EFI_DEVICE_PATH_PROTOCOL - *RemainingDevicePath - +// Pointer to last node in device path +// +// Output: EFI_SUCCESS - Ps2 Controller supported +// EFI_UNSUPPORTED -- Ps2 Controller not supported +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS PS2CtlSupported( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) +{ + ACPI_HID_DEVICE_PATH* acpiDP; + + // + // Checking if KBC is available at all + // + if (IoRead8 (KBC_CMDSTS_PORT) == 0xFF){ + return EFI_DEVICE_ERROR; + } + // + // Find the last device node in the device path and return "Supported" + // for mouse and/or keyboard depending on the SDL switches. + // + if( !EFI_ERROR(GetPS2_DP(This, Controller, &acpiDP, EFI_OPEN_PROTOCOL_BY_DRIVER)) && + LookupPs2Hid(supportedDevices, acpiDP->HID, acpiDP->UID, 0)){ + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: PS2CtlStart +// +// Description: PS/2 Controller Driver Start function +// This function is a part of DriverBinfing protocol +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this +// instance of the driver binding protocol +// EFI_HANDLE Controller - Handle for this controller +// EFI_DEVICE_PATH_PROTOCOL - *RemainingDevicePath - +// Pointer to last node in device path +// +// Output: EFI_STATUS - Status of the operation +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS PS2CtlStart( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) +{ + ACPI_HID_DEVICE_PATH *acpiDP; + PS2DEV_TABLE *ps2dev = 0; + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // The following code performs the basic KBC initialization + // It has to be executed only once, we use global variable + // gDriverStartCounter to control this. Also, this code is + // executed on a higher TPL to prevent re-entrance. + // + OldTpl = gSysTable->BootServices->RaiseTPL(TPL_NOTIFY); + if (OldTpl > TPL_NOTIFY) return EFI_DEVICE_ERROR; + + while (!gDriverStartCounter) { + // + // Disable the Keyboard IRQ if it's enabled before + // Finish all the Keyboard Initilization and Re-enable the IRQ again + // + if(KbRdBeforeInstall){ + mLegacy8259->DisableIrq( mLegacy8259, SYSTEM_KEYBOARD_IRQ ); + gKeyboardIrqInstall=FALSE; + } + // Initialize KBC hardware + // + if ( KbcBasicAssuranceTest ) { + Status = KBCBatTest(); // Perform KBC Basic Assurance Test + if (EFI_ERROR(Status)) { + // + // Report the Error code if the BAT test failed + // + ERROR_CODE (DXE_KEYBOARD_STUCK_KEY_ERROR, EFI_ERROR_MAJOR); + break; + } + + // + // Check for stuck keys + // + Status = IbFreeTimeout(IbFreeTimeoutValue); + if (EFI_ERROR(Status)) { + // + // Report the Error Code. + // + ERROR_CODE (DXE_KEYBOARD_STUCK_KEY_ERROR, EFI_ERROR_MAJOR); + break; + } + } + // Swap ports if needed + if (AutodetectKbdMousePortsPtr!=NULL) AutodetectKbdMousePortsPtr(); + + gDriverStartCounter++; + } + + + if(!EFI_ERROR(GetPS2_DP(This, Controller, &acpiDP, EFI_OPEN_PROTOCOL_BY_DRIVER)) && + LookupPs2Hid(supportedDevices, acpiDP->HID, acpiDP->UID, &ps2dev) ){ + Status = ps2dev->start(This, Controller); + + // + // End of critical section - restore TPL + // + gSysTable->BootServices->RestoreTPL(OldTpl); + + if(EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + } + + // + // End of critical section - restore TPL + // + gSysTable->BootServices->RestoreTPL(OldTpl); + + // + // If control is here then something totally wrong happend: + // if device is not supported then Start shouldn't be called. + // + return EFI_DEVICE_ERROR; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: PS2CtlStop +// +// Description: PS/2 Controller Driver Stop function +// This function is a part of DriverBinfing protocol +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this +// instance of the driver binding protocol +// EFI_HANDLE Controller - Handle for this controller +// UINTN NumberOfChildren - Number of children of this +// controller +// EFI_HANDLE *ChildHandleBuffer - Pointer to a buffer +// for child handles +// +// Output: EFI_STATUS - Status of the operation +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS PS2CtlStop( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + UINTN NumberOfChildren, + EFI_HANDLE *ChildHandleBuffer) +{ + ACPI_HID_DEVICE_PATH *acpiDP; + PS2DEV_TABLE *ps2dev = 0; + EFI_STATUS Status; + + if(!EFI_ERROR(GetPS2_DP(This, Controller, &acpiDP, EFI_OPEN_PROTOCOL_GET_PROTOCOL)) && + LookupPs2Hid(supportedDevices, acpiDP->HID, acpiDP->UID, &ps2dev) ){ + Status = ps2dev->stop(This, Controller); + if(EFI_ERROR(Status)) { + return EFI_DEVICE_ERROR; + } + return EFI_SUCCESS; + } + + // + // If control is here then device path was not found in the lookup table + // + return EFI_DEVICE_ERROR; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: LookupPs2Hid +// +// Description: This fuction searches the PS2 device in table that +// matches given HID and UID +// +// Paremeters: +// PS2DEV_TABLE * devTable - Lookup table pointer +// UINT32 hid - HID to look for +// UINT32 uid - UID to look for +// PS2DEV_TABLE** dev - address of the matched table entry +// +// Output: +// BOOLEAN - TRUE if match is found, FALSE otherwise +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +BOOLEAN LookupPs2Hid( + PS2DEV_TABLE * devTable, + UINT32 hid, + UINT32 uid, + PS2DEV_TABLE** dev) +{ + for( ;devTable->hid;++devTable){ + if( devTable->hid == hid && devTable->uid==uid){ + if ( (devTable->DeviceType == DEVICETYPE_MOUSE && Ps2MouseSupport) || + (devTable->DeviceType == DEVICETYPE_KEYBOARD && Ps2KbdSupport) ) { + if(dev) *dev = devTable; + return TRUE; + } + } + } + return FALSE; +} + + +//<AMI_PHDR_START> +//---------------------------------------------------------------------- +// +// Procedure: GetPS2_DP +// +// Description: This fuction returns the last node in the device +// path for the given controller. +// +// Paremeters: EFI_DRIVER_BINDING_PROTOCOL *This - Pointer to this +// instance of the driver binding protocol +// EFI_HANDLE Controller - Handle for this controller +// ACPI_HID_DEVICE_PATH** ps2dp - Pointer to ACPI HID +// device path +// UINT32 Attributes - Attributes passed to driver binding +// protocol +// +// Output: +// EFI_SUCCESS or EFI_UNSUPPORTED +// +//---------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS GetPS2_DP( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + ACPI_HID_DEVICE_PATH** ps2dp, + UINT32 Attributes) +{ + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *acpiDP; + EFI_DEVICE_PATH_PROTOCOL * ps2DevPath, *pDP; + + // + // Get device path from Controller handle. + // + Status = gSysTable->BootServices->OpenProtocol ( + Controller, + &gDevicePathProtocolGuid, + (VOID**)&pDP, + This->DriverBindingHandle, + Controller, + Attributes + ); + + if (EFI_ERROR(Status)) { + if( Status != (EFI_ALREADY_STARTED || EFI_ACCESS_DENIED) ) { + return EFI_UNSUPPORTED; + } else { + return Status; + } + } + + // + // Process ps2DevPath - get the node which is before the EndNode + // + ps2DevPath=DPGetLastNode(pDP); + + // + // ps2DevPath is now the last node + // + acpiDP = *ps2dp = (ACPI_HID_DEVICE_PATH*)ps2DevPath; + + Status = (acpiDP->Header.Type == ACPI_DEVICE_PATH && + acpiDP->Header.SubType == ACPI_DP)? EFI_SUCCESS : EFI_UNSUPPORTED; + + if (Attributes!=EFI_OPEN_PROTOCOL_GET_PROTOCOL) + gSysTable->BootServices->CloseProtocol ( + Controller, + &gDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** diff --git a/Core/EM/PS2CTL/ps2mouse.h b/Core/EM/PS2CTL/ps2mouse.h new file mode 100644 index 0000000..24fbcce --- /dev/null +++ b/Core/EM/PS2CTL/ps2mouse.h @@ -0,0 +1,178 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2mouse.h 6 9/19/11 9:37a Lavanyap $ +// +// $Revision: 6 $ +// +// $Date: 9/19/11 9:37a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/PS2CTL/ps2mouse.h $ +// +// 6 9/19/11 9:37a Lavanyap +// [TAG] EIP66198 +// [Category] Improvement +// [Description] Added Mouse Wheel support in PS2 and USB drivers. +// [Files] usbdef.h, usbms.c, efiusbms.c, ps2mouse.h, mouse.c +// +// 5 8/23/10 4:25a Rameshr +// Bug Fix : EIP 40838 +// Symptoms: KBC.C build failed in DetectPS2Keyboard() if +// DETECT_PS2_KEYBOARD=0 & PS2MOUSE_SUPPORT=0 +// Files Modified: Efismplpp.c, Kbc.c, Kbc.h, Mouse.c PS2ctl.cif, +// Ps2ctl.sdl, Ps2Kbd.c, Ps2Mouse.h +// Details: +// 1) Added Detect_PS2_Mouse sdl token and modified the code. +// 2) INSTALL_KEYBOARD_MOUSE_ALWAYS sdl token added. +// 1 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer Always, +// 0 - Install the Keyboard- SimpleTextIn, Mouse - AbsPointer only if +// the device is present at the time of detection. +// This is for Ps2Keyboard Hot plug support in EFI +// 3) Code clean up in mouse.c EfiSmplpp.c ,ps2mouse.h +// 4) Unused file automaton.h removed. +// +// 4 7/01/09 12:32p Olegi +// Source is corrected according to the coding standard: function headers, +// copyright messages are updated. +// +// 3 4/16/07 6:28p Pats +// Modified to conform with coding standards. No code changes. +// +// 2 3/04/05 1:39p Mandal +// +//********************************************************************** + +//<AMI_FHDR_START> +//---------------------------------------------------------------------- +// +// Name: ps2mouse.h +// +// Description: Ps2 mouse support header +// +//---------------------------------------------------------------------- +//<AMI_FHDR_END> + + +#include <Protocol\SimplePointer.h> + +typedef struct { + EFI_SIMPLE_POINTER_PROTOCOL iSmplPtr; + EFI_SIMPLE_POINTER_MODE mode; + EFI_SIMPLE_POINTER_STATE state; + UINT8 saved_flags; +} MOUSE; + + +EFI_STATUS MouseReset( + MOUSE *This, + BOOLEAN ExtendedVerification +); + +EFI_STATUS MouseGetState( + MOUSE *This, + EFI_SIMPLE_POINTER_STATE *State +); + +EFI_STATUS DetectPS2mouse( + MOUSE* +); + +VOID OnWaitingOnMouse( + EFI_EVENT Event, + MOUSE *Context +); + +EFI_STATUS InitMOUSE( + MOUSE** +); + +#define KBC_CMD_ENABLE_AUX 0x0A8 +#define KBC_CMD_DISABLE_AUX 0x0A7 +#define KBC_CMD_ENABLE_KBD 0x0AE +#define KBC_CMD_DISABLE_KBD 0x0AD +#define KBC_CMD_CHK_AUX 0x0A9 +#define KBC_CMD_WRT_AUX 0x0D4 + + +//---------------------------------------------------------------------------- +// MOUSE COMMANDS from SYSTEM SET SAMPLING RATE & SET RESOLUTION +// Needs one more byte to be sent. +//---------------------------------------------------------------------------- + +#define RESET 0x0FF // Reset. +#define DISABLE 0x0F5 // Disable. +#define ENABLE 0x0F4 // Enable. +#define SET_SAMPLING_RATE 0x0F3 // Set sampling rate. +#define READ_DEVICE_TYPE 0x0F2 // Read device type. +#define STATUS_REQUEST 0x0E9 // Status request. +#define SET_RESOLUTION 0x0E8 // Set resolution. +#define SET_SCALING_2X1 0x0E7 // Set scaling 2:1. +#define RESET_SCALING 0x0E6 // Set scaling 1:1. +#define REMOTE_MODE 0x0F0 // Set Remote Mode - mouse transfers + // packets by request +#define READ_DATA 0x0eb // Forces thetransef of a mouse data packet +#define SET_STANDART 0x0f6 // Iitialize PS/2 and set standart state +//--------------------------------------- +// MOUSE RESPONSE ON COMMAND COMPLETION +//--------------------------------------- + +#define ACK 0x0fa // ACKnowledge +#define RSND 0x0fe // RESEND +#define ERROR 0x0fc // two invalid inputs received + +//--------------------------------------- +// CCB Flags +//--------------------------------------- + +#define CCB_PCCOMPAT 0x40 // PC Compatibility mode +#define CCB_PS2MS_DISABLE 0x20 // Disable PS/2 mouse interface +#define CCB_KBD_DISABLE 0x10 // Disable in succession by mouse +#define CCB_SYSTEM 0x04 // +#define CCB_MS_INTRPT 0x02 // +#define CCB_KBD_INTRPT 0x01 // + + +typedef struct { + UINT8 flags; + UINT8 x,y,z; +} StdMouseDataPacket; + +#define BUTTON_MID 0x04 +#define BUTTON_RIGHT 0x02 +#define BUTTON_LEFT 0x01 +#define MOUSE_X_NEG 0x10 +#define MOUSE_Y_NEG 0x20 +#define MOUSE_X_OVF 0x40 +#define MOUSE_Y_OVF 0x80 + +#define NON_WHEEL_REPORT_FORMAT 3 +#define WHEEL_REPORT_FORMAT 4 + + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2009, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |