3 Routines that access 8042 keyboard controller
5 Copyright (c) 2006 - 2007, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 // Include common header file for this module.
19 #include "Ps2Keyboard.h"
22 // Function declarations
27 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
32 KeyWriteDataRegister (
33 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
39 KeyWriteCommandRegister (
40 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
47 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
48 IN CHAR16
*ErrMsg
// should be a unicode string
54 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
62 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
70 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
77 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
83 KeyboardWaitForValue (
84 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
92 CHAR16 ShiftUnicodeChar
;
94 ConvertKeyboardScanCodeToEfiKey
[] = {
421 0x37, // Numeric Keypad *
427 0x38, //Left Alt/Extended Right Alt
547 0x4c, // Numeric Keypad 5
634 // The WaitForValue time out
636 STATIC UINTN mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
640 KeyReadDataRegister (
641 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
647 GC_TODO: Add function description
651 ConsoleIn - GC_TODO: add argument description
655 GC_TODO: add return values
659 EFI_ISA_IO_PROTOCOL
*IsaIo
;
663 // Use IsaIo protocol to perform IO operations
665 IsaIo
= ConsoleIn
->IsaIo
;
670 ConsoleIn
->DataRegisterAddress
,
680 KeyWriteDataRegister (
681 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
688 GC_TODO: Add function description
692 ConsoleIn - GC_TODO: add argument description
693 Data - GC_TODO: add argument description
697 GC_TODO: add return values
701 EFI_ISA_IO_PROTOCOL
*IsaIo
;
704 // Use IsaIo protocol to perform IO operations
706 IsaIo
= ConsoleIn
->IsaIo
;
711 ConsoleIn
->DataRegisterAddress
,
717 // outp(ConsoleIn->DataRegisterAddress, Data);
722 KeyReadStatusRegister (
723 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
729 GC_TODO: Add function description
733 ConsoleIn - GC_TODO: add argument description
737 GC_TODO: add return values
741 EFI_ISA_IO_PROTOCOL
*IsaIo
;
745 // Use IsaIo protocol to perform IO operations
747 IsaIo
= ConsoleIn
->IsaIo
;
752 ConsoleIn
->StatusRegisterAddress
,
763 KeyWriteCommandRegister (
764 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
771 GC_TODO: Add function description
775 ConsoleIn - GC_TODO: add argument description
776 Data - GC_TODO: add argument description
780 GC_TODO: add return values
784 EFI_ISA_IO_PROTOCOL
*IsaIo
;
787 // Use IsaIo protocol to perform IO operations
789 IsaIo
= ConsoleIn
->IsaIo
;
794 ConsoleIn
->CommandRegisterAddress
,
804 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
811 Display error message
818 // GC_TODO: ConsoleIn - add argument and description to function comment
819 // GC_TODO: ErrMsg - add argument and description to function comment
821 ConsoleIn
->KeyboardErr
= TRUE
;
824 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");
825 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);
831 KeyboardTimerHandler (
839 Timer event handler: read a series of scancodes from 8042
840 and put them into memory scancode buffer.
841 it read as much scancodes to either fill
842 the memory buffer or empty the keyboard buffer.
843 It is registered as running under TPL_NOTIFY
847 Event - The timer event
848 Context - A KEYBOARD_CONSOLE_IN_DEV pointer
856 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
861 // Enter critical section
863 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
865 if (((KEYBOARD_CONSOLE_IN_DEV
*) Context
)->KeyboardErr
) {
867 // Leave critical section and return
869 gBS
->RestoreTPL (OldTpl
);
873 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
874 // KB is not connected to system. If KB is not connected to system, driver will find there's something
875 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
876 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
877 // Just skip the 'resend' process simply.
883 // if there is no key present, just return
885 if ((KeyReadStatusRegister (Context
) & 0x21) != 0x1) {
887 // Leave critical section and return
889 gBS
->RestoreTPL (OldTpl
);
894 // Read one byte of the scan code and store it into the memory buffer
896 if (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
) {
898 Data
= KeyReadDataRegister (Context
);
900 // put the scancode into the memory scancode buffer
902 ConsoleIn
->ScancodeBufCount
++;
903 ConsoleIn
->ScancodeBufEndPos
++;
904 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
905 ConsoleIn
->ScancodeBufEndPos
= 0;
908 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Data
;
911 // Handle Alt+Ctrl+Del Key combination
914 case SCANCODE_CTRL_MAKE
:
915 ConsoleIn
->Ctrled
= TRUE
;
918 case SCANCODE_CTRL_BREAK
:
919 ConsoleIn
->Ctrled
= FALSE
;
922 case SCANCODE_ALT_MAKE
:
923 ConsoleIn
->Alted
= TRUE
;
926 case SCANCODE_ALT_BREAK
:
927 ConsoleIn
->Alted
= FALSE
;
931 // if Alt+Ctrl+Del, Reboot the System
933 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Data
== 0x53) {
934 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
938 // Leave critical section and return
940 gBS
->RestoreTPL (OldTpl
);
948 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
956 Read several bytes from the scancode buffer without removing them.
957 This function is called to see if there are enough bytes of scancode
958 representing a single key.
962 Count - Number of bytes to be read
963 Buf - Store the results
970 // GC_TODO: ConsoleIn - add argument and description to function comment
971 // GC_TODO: EFI_NOT_READY - add return value to function comment
972 // GC_TODO: EFI_SUCCESS - add return value to function comment
981 // check the valid range of parameter 'Count'
983 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
984 return EFI_NOT_READY
;
987 // retrieve the values
989 for (Index
= 0; Index
< Count
; Index
++) {
993 Pos
= ConsoleIn
->ScancodeBufStartPos
;
997 if (Pos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1002 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[Pos
];
1010 PopScancodeBufHead (
1011 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1017 Routine Description:
1019 Read & remove several bytes from the scancode buffer.
1020 This function is usually called after GetScancodeBufHead()
1024 Count - Number of bytes to be read
1025 Buf - Store the results
1032 // GC_TODO: ConsoleIn - add argument and description to function comment
1033 // GC_TODO: EFI_NOT_READY - add return value to function comment
1034 // GC_TODO: EFI_SUCCESS - add return value to function comment
1041 // Check the valid range of parameter 'Count'
1043 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
1044 return EFI_NOT_READY
;
1047 // Retrieve and remove the values
1049 for (Index
= 0; Index
< Count
; Index
++) {
1053 ConsoleIn
->ScancodeBufStartPos
++;
1054 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1055 ConsoleIn
->ScancodeBufStartPos
= 0;
1059 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufStartPos
];
1060 ConsoleIn
->ScancodeBufCount
--;
1063 ConsoleIn
->ScancodeBufStartPos
++;
1064 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1065 ConsoleIn
->ScancodeBufStartPos
= 0;
1073 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1078 Routine Description:
1080 GC_TODO: Add function description
1084 ConsoleIn - GC_TODO: add argument description
1085 Data - GC_TODO: add argument description
1089 EFI_TIMEOUT - GC_TODO: Add description for return value
1090 EFI_SUCCESS - GC_TODO: Add description for return value
1101 // wait till output buffer full then perform the read
1103 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1104 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1106 *Data
= KeyReadDataRegister (ConsoleIn
);
1123 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1128 Routine Description:
1130 GC_TODO: Add function description
1134 ConsoleIn - GC_TODO: add argument description
1135 Data - GC_TODO: add argument description
1139 EFI_TIMEOUT - GC_TODO: Add description for return value
1140 EFI_SUCCESS - GC_TODO: Add description for return value
1151 // wait for input buffer empty
1153 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1154 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1168 KeyWriteDataRegister (ConsoleIn
, Data
);
1176 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1181 Routine Description:
1183 GC_TODO: Add function description
1187 ConsoleIn - GC_TODO: add argument description
1188 Data - GC_TODO: add argument description
1192 EFI_TIMEOUT - GC_TODO: Add description for return value
1193 EFI_TIMEOUT - GC_TODO: Add description for return value
1194 EFI_SUCCESS - GC_TODO: Add description for return value
1205 // Wait For Input Buffer Empty
1207 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1208 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1220 // issue the command
1222 KeyWriteCommandRegister (ConsoleIn
, Data
);
1225 // Wait For Input Buffer Empty again
1228 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1229 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1246 KeyboardWaitForValue (
1247 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1252 Routine Description:
1254 wait for a specific value to be presented on
1255 8042 Data register by keyboard and then read it,
1256 used in keyboard commands ack
1260 ConsoleIn - The KEYBOARD_CONSOLE_IN_DEV instance pointer
1261 Value - The value to be waited for
1268 // GC_TODO: EFI_SUCCESS - add return value to function comment
1269 // GC_TODO: EFI_TIMEOUT - add return value to function comment
1281 // Make sure the initial value of 'Data' is different from 'Value'
1284 if (Data
== Value
) {
1288 // Read from 8042 (multiple times if needed)
1289 // until the expected value appears
1290 // use SumTimeOut to control the iteration
1296 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1297 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1298 Data
= KeyReadDataRegister (ConsoleIn
);
1305 SumTimeOut
+= TimeOut
;
1307 if (Data
== Value
) {
1312 if (SumTimeOut
>= mWaitForValueTimeOut
) {
1328 UpdateStatusLights (
1329 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1333 Routine Description:
1335 Show keyboard status lights according to
1336 indicators in ConsoleIn.
1343 // GC_TODO: ConsoleIn - add argument and description to function comment
1349 // Send keyboard command
1351 Status
= KeyboardWrite (ConsoleIn
, 0xed);
1352 if (EFI_ERROR (Status
)) {
1356 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1359 // Light configuration
1362 if (ConsoleIn
->CapsLock
) {
1366 if (ConsoleIn
->NumLock
) {
1370 if (ConsoleIn
->ScrollLock
) {
1374 Status
= KeyboardWrite (ConsoleIn
, Command
);
1376 if (EFI_ERROR (Status
)) {
1380 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1386 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1390 Routine Description:
1392 Get scancode from scancode buffer
1393 and translate into EFI-scancode and unicode defined by EFI spec
1394 The function is always called in TPL_NOTIFY
1398 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1402 EFI_NOT_READY - Input from console not ready yet.
1403 EFI_SUCCESS - Function executed successfully.
1411 UINT8 ScancodeArr
[4];
1416 UINT32 ScancodeArrPos
;
1418 // point to the current position in ScancodeArr
1426 // Read one byte of the scan code and store it into the memory buffer
1427 // This block of code is added to insert an action that is equivalent to
1428 // the timer event handling function, so as to increase the frequency of
1429 // detecting the availability of keys. Timer event has a max frequency of
1430 // 18Hz which is insufficient
1433 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
1434 // KB is not connected to system. If KB is not connected to system, driver will find there's something
1435 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
1436 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
1437 // Just skip the 'resend' process simply.
1441 if (((KeyReadStatusRegister (ConsoleIn
) & 0x21) == 0x1) && (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
)) {
1443 Readed
= KeyReadDataRegister (ConsoleIn
);
1445 // put the scancode into the memory scancode buffer
1447 ConsoleIn
->ScancodeBufCount
++;
1448 ConsoleIn
->ScancodeBufEndPos
++;
1449 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1450 ConsoleIn
->ScancodeBufEndPos
= 0;
1453 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Readed
;
1456 // Handle Alt+Ctrl+Del Key combination
1460 case SCANCODE_CTRL_MAKE
:
1461 ConsoleIn
->Ctrled
= TRUE
;
1464 case SCANCODE_CTRL_BREAK
:
1465 ConsoleIn
->Ctrled
= FALSE
;
1468 case SCANCODE_ALT_MAKE
:
1469 ConsoleIn
->Alted
= TRUE
;
1472 case SCANCODE_ALT_BREAK
:
1473 ConsoleIn
->Alted
= FALSE
;
1477 // if Alt+Ctrl+Del, Reboot the System
1479 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Readed
== 0x53) {
1480 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1484 // Check if there are enough bytes of scancode representing a single key
1485 // available in the buffer
1489 Status
= GetScancodeBufHead (ConsoleIn
, 1, ScancodeArr
);
1491 if (EFI_ERROR (Status
)) {
1492 return EFI_NOT_READY
;
1495 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED
) {
1497 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1499 if (EFI_ERROR (Status
)) {
1500 return EFI_NOT_READY
;
1504 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
1505 // if present, ignore them
1507 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED1
) {
1509 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1512 if (EFI_ERROR (Status
)) {
1513 return EFI_NOT_READY
;
1516 Status
= GetScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1519 if (EFI_ERROR (Status
)) {
1520 return EFI_NOT_READY
;
1523 PopScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1524 return EFI_NOT_READY
;
1527 // if we reach this position, scancodes for a key is in buffer now,pop them
1529 Status
= PopScancodeBufHead (ConsoleIn
, ScancodeArrPos
+ 1, ScancodeArr
);
1530 if (EFI_ERROR (Status
)) {
1531 return EFI_NOT_READY
;
1534 // store the last available byte, this byte of scancode will be checked
1536 ScanCode
= ScancodeArr
[ScancodeArrPos
];
1539 // Check for special keys and update the driver state.
1543 case SCANCODE_CTRL_MAKE
:
1544 ConsoleIn
->Ctrl
= TRUE
;
1547 case SCANCODE_CTRL_BREAK
:
1548 ConsoleIn
->Ctrl
= FALSE
;
1551 case SCANCODE_ALT_MAKE
:
1552 ConsoleIn
->Alt
= TRUE
;
1555 case SCANCODE_ALT_BREAK
:
1556 ConsoleIn
->Alt
= FALSE
;
1559 case SCANCODE_LEFT_SHIFT_MAKE
:
1561 ConsoleIn
->Shift
= TRUE
;
1562 ConsoleIn
->LeftShift
= TRUE
;
1565 case SCANCODE_RIGHT_SHIFT_MAKE
:
1567 ConsoleIn
->Shift
= TRUE
;
1568 ConsoleIn
->RightShift
= TRUE
;
1572 case SCANCODE_LEFT_SHIFT_BREAK
:
1574 ConsoleIn
->Shift
= FALSE
;
1575 ConsoleIn
->LeftShift
= FALSE
;
1577 ConsoleIn
->SysReq
= FALSE
;
1580 case SCANCODE_RIGHT_SHIFT_BREAK
:
1582 ConsoleIn
->Shift
= FALSE
;
1583 ConsoleIn
->RightShift
= FALSE
;
1587 case SCANCODE_LEFT_LOGO_MAKE
:
1588 ConsoleIn
->LeftLogo
= TRUE
;
1590 case SCANCODE_LEFT_LOGO_BREAK
:
1591 ConsoleIn
->LeftLogo
= FALSE
;
1593 case SCANCODE_RIGHT_LOGO_MAKE
:
1594 ConsoleIn
->RightLogo
= TRUE
;
1596 case SCANCODE_RIGHT_LOGO_BREAK
:
1597 ConsoleIn
->RightLogo
= FALSE
;
1599 case SCANCODE_MENU_MAKE
:
1600 ConsoleIn
->Menu
= TRUE
;
1602 case SCANCODE_MENU_BREAK
:
1603 ConsoleIn
->Menu
= FALSE
;
1605 case SCANCODE_SYS_REQ_MAKE
:
1607 ConsoleIn
->SysReq
= TRUE
;
1609 case SCANCODE_CAPS_LOCK_MAKE
:
1610 ConsoleIn
->CapsLock
= (BOOLEAN
)!ConsoleIn
->CapsLock
;
1611 UpdateStatusLights (ConsoleIn
);
1614 case SCANCODE_NUM_LOCK_MAKE
:
1615 ConsoleIn
->NumLock
= (BOOLEAN
)!ConsoleIn
->NumLock
;
1616 UpdateStatusLights (ConsoleIn
);
1619 case SCANCODE_SCROLL_LOCK_MAKE
:
1620 ConsoleIn
->ScrollLock
= (BOOLEAN
)!ConsoleIn
->ScrollLock
;
1621 UpdateStatusLights (ConsoleIn
);
1625 // If this is a BREAK Key or above the valid range, ignore it
1627 if (ScanCode
>= SCANCODE_MAX_MAKE
) {
1634 // Treat Numeric Key Pad "/" specially
1636 if (Extended
&& ScanCode
== 0x35) {
1637 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1638 ConsoleIn
->Key
.UnicodeChar
= '/';
1642 // Convert Keyboard ScanCode into an EFI Key
1644 for (Index
= 0; ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
!= TABLE_END
; Index
+= 1) {
1645 if (ScanCode
== ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
) {
1646 ConsoleIn
->Key
.ScanCode
= ConvertKeyboardScanCodeToEfiKey
[Index
].EfiScanCode
;
1647 if (ConsoleIn
->Shift
) {
1648 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1650 // Need not return associated shift state if a class of printable characters that
1651 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1653 if (ConsoleIn
->Key
.UnicodeChar
>= 'A' && ConsoleIn
->Key
.UnicodeChar
<= 'Z') {
1654 ConsoleIn
->LeftShift
= FALSE
;
1655 ConsoleIn
->RightShift
= FALSE
;
1658 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1661 // alphabetic key is affected by CapsLock State
1663 if (ConsoleIn
->CapsLock
) {
1664 if (ConsoleIn
->Key
.UnicodeChar
>= 'a' && ConsoleIn
->Key
.UnicodeChar
<= 'z') {
1665 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1666 } else if (ConsoleIn
->Key
.UnicodeChar
>= 'A' && ConsoleIn
->Key
.UnicodeChar
<= 'Z') {
1667 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1671 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1673 if (ConsoleIn
->Ctrled
) {
1674 if (ConsoleIn
->Key
.UnicodeChar
>= 'a' && ConsoleIn
->Key
.UnicodeChar
<= 'z') {
1675 ConsoleIn
->Key
.UnicodeChar
= (UINT16
) (ConsoleIn
->Key
.UnicodeChar
- 'a' + 1);
1676 } else if (ConsoleIn
->Key
.UnicodeChar
>= 'A' && ConsoleIn
->Key
.UnicodeChar
<= 'Z') {
1677 ConsoleIn
->Key
.UnicodeChar
= (UINT16
) (ConsoleIn
->Key
.UnicodeChar
- 'A' + 1);
1686 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1688 if (ScanCode
>= 0x47 && ScanCode
<= 0x53) {
1690 if (ConsoleIn
->NumLock
&& !ConsoleIn
->Shift
&& !Extended
) {
1691 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1692 } else if (ScanCode
!= 0x4a && ScanCode
!= 0x4e) {
1693 ConsoleIn
->Key
.UnicodeChar
= 0x00;
1697 // If the key can not be converted then just return.
1699 if (ConsoleIn
->Key
.ScanCode
== SCAN_NULL
&& ConsoleIn
->Key
.UnicodeChar
== 0x00) {
1700 return EFI_NOT_READY
;
1704 // Save the Shift/Toggle state
1706 if (ConsoleIn
->Ctrl
) {
1707 ConsoleIn
->KeyState
.KeyShiftState
|= (Extended
== TRUE
) ? EFI_RIGHT_CONTROL_PRESSED
: EFI_LEFT_CONTROL_PRESSED
;
1709 if (ConsoleIn
->Alt
) {
1710 ConsoleIn
->KeyState
.KeyShiftState
|= (Extended
== TRUE
) ? EFI_RIGHT_ALT_PRESSED
: EFI_LEFT_ALT_PRESSED
;
1712 if (ConsoleIn
->LeftShift
) {
1713 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1715 if (ConsoleIn
->RightShift
) {
1716 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1718 if (ConsoleIn
->LeftLogo
) {
1719 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
1721 if (ConsoleIn
->RightLogo
) {
1722 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
1724 if (ConsoleIn
->Menu
) {
1725 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_MENU_KEY_PRESSED
;
1727 if (ConsoleIn
->SysReq
) {
1728 ConsoleIn
->KeyState
.KeyShiftState
|= EFI_SYS_REQ_PRESSED
;
1730 if (ConsoleIn
->CapsLock
) {
1731 ConsoleIn
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1733 if (ConsoleIn
->NumLock
) {
1734 ConsoleIn
->KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1736 if (ConsoleIn
->ScrollLock
) {
1737 ConsoleIn
->KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1745 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1746 IN BOOLEAN ExtendedVerification
1750 Routine Description:
1752 Perform 8042 controller and keyboard Initialization
1753 If ExtendedVerification is TRUE, do additional test for
1754 the keyboard interface
1758 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1759 ExtendedVerification - indicates a thorough initialization
1766 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1767 // GC_TODO: EFI_SUCCESS - add return value to function comment
1768 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1773 STATIC BOOLEAN EnableMouseInterface
;
1774 EFI_PS2_POLICY_PROTOCOL
*Ps2Policy
;
1776 Status
= EFI_SUCCESS
;
1777 EnableMouseInterface
= TRUE
;
1780 // Get Ps2 policy to set this
1782 Status
= gBS
->LocateProtocol (
1783 &gEfiPs2PolicyProtocolGuid
,
1785 (VOID
**) &Ps2Policy
1788 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1790 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
,
1791 ConsoleIn
->DevicePath
1795 // Perform a read to cleanup the Status Register's
1796 // output buffer full bits
1798 while (!EFI_ERROR (Status
)) {
1799 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1802 // We should disable mouse interface during the initialization process
1803 // since mouse device output could block keyboard device output in the
1804 // 60H port of 8042 controller.
1806 // So if we are not initializing 8042 controller for the
1807 // first time, we have to remember the previous mouse interface
1810 // Test the system flag in to determine whether this is the first
1811 // time initialization
1813 if ((KeyReadStatusRegister (ConsoleIn
) & 0x04)) {
1815 // 8042 controller is already setup (by myself or by mouse driver):
1816 // See whether mouse interface is already enabled
1817 // which determines whether we should enable it later
1820 // Read the command byte of 8042 controller
1822 Status
= KeyboardCommand (ConsoleIn
, 0x20);
1823 if (EFI_ERROR (Status
)) {
1824 KeyboardError (ConsoleIn
, L
"\n\r");
1828 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1829 if (EFI_ERROR (Status
)) {
1830 KeyboardError (ConsoleIn
, L
"\n\r");
1834 // Test the mouse enabling bit
1836 if (CommandByte
& 0x20) {
1837 EnableMouseInterface
= FALSE
;
1839 EnableMouseInterface
= TRUE
;
1844 // 8042 controller is not setup yet:
1845 // 8042 controller selftest;
1846 // Don't enable mouse interface later.
1849 // Disable keyboard and mouse interfaces
1851 Status
= KeyboardCommand (ConsoleIn
, 0xad);
1852 if (EFI_ERROR (Status
)) {
1853 KeyboardError (ConsoleIn
, L
"\n\r");
1857 Status
= KeyboardCommand (ConsoleIn
, 0xa7);
1858 if (EFI_ERROR (Status
)) {
1859 KeyboardError (ConsoleIn
, L
"\n\r");
1863 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1865 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_SELF_TEST
,
1866 ConsoleIn
->DevicePath
1869 // 8042 Controller Self Test
1871 Status
= KeyboardCommand (ConsoleIn
, 0xaa);
1872 if (EFI_ERROR (Status
)) {
1873 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1877 Status
= KeyboardWaitForValue (ConsoleIn
, 0x55);
1878 if (EFI_ERROR (Status
)) {
1879 KeyboardError (ConsoleIn
, L
"8042 controller self test failed!\n\r");
1883 // Don't enable mouse interface later
1885 EnableMouseInterface
= FALSE
;
1889 if (Ps2Policy
!= NULL
) {
1890 Ps2Policy
->Ps2InitHardware (ConsoleIn
->Handle
);
1893 // Write 8042 Command Byte, set System Flag
1894 // While at the same time:
1895 // 1. disable mouse interface,
1896 // 2. enable kbd interface,
1897 // 3. enable PC/XT kbd translation mode
1898 // 4. enable mouse and kbd interrupts
1900 // ( Command Byte bits:
1902 // 6: PC/XT translation mode
1903 // 5: Disable Auxiliary device interface
1904 // 4: Disable keyboard interface
1907 // 1: Enable Auxiliary device interrupt
1908 // 0: Enable Keyboard interrupt )
1910 Status
= KeyboardCommand (ConsoleIn
, 0x60);
1911 if (EFI_ERROR (Status
)) {
1912 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1916 Status
= KeyboardWrite (ConsoleIn
, 0x67);
1917 if (EFI_ERROR (Status
)) {
1918 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1923 // Clear Memory Scancode Buffer
1925 ConsoleIn
->ScancodeBufStartPos
= 0;
1926 ConsoleIn
->ScancodeBufEndPos
= KEYBOARD_BUFFER_MAX_COUNT
- 1;
1927 ConsoleIn
->ScancodeBufCount
= 0;
1928 ConsoleIn
->Ctrled
= FALSE
;
1929 ConsoleIn
->Alted
= FALSE
;
1932 // Reset the status indicators
1934 ConsoleIn
->Ctrl
= FALSE
;
1935 ConsoleIn
->Alt
= FALSE
;
1936 ConsoleIn
->Shift
= FALSE
;
1937 ConsoleIn
->CapsLock
= FALSE
;
1938 ConsoleIn
->NumLock
= FALSE
;
1939 ConsoleIn
->ScrollLock
= FALSE
;
1940 ConsoleIn
->LeftShift
= FALSE
;
1941 ConsoleIn
->RightShift
= FALSE
;
1942 ConsoleIn
->LeftLogo
= FALSE
;
1943 ConsoleIn
->RightLogo
= FALSE
;
1944 ConsoleIn
->Menu
= FALSE
;
1945 ConsoleIn
->SysReq
= FALSE
;
1948 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1949 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1950 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
1951 // and normally during booting an OS, it's skipped.
1953 if (ExtendedVerification
&& CheckKeyboardConnect (ConsoleIn
)) {
1955 // Additional verifications for keyboard interface
1958 // Keyboard Interface Test
1960 Status
= KeyboardCommand (ConsoleIn
, 0xab);
1961 if (EFI_ERROR (Status
)) {
1962 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1966 Status
= KeyboardWaitForValue (ConsoleIn
, 0x00);
1967 if (EFI_ERROR (Status
)) {
1970 L
"Some specific value not aquired from 8042 controller!\n\r"
1975 // Keyboard reset with a BAT(Basic Assurance Test)
1977 Status
= KeyboardWrite (ConsoleIn
, 0xff);
1978 if (EFI_ERROR (Status
)) {
1979 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1983 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1984 if (EFI_ERROR (Status
)) {
1985 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1989 // wait for BAT completion code
1991 mWaitForValueTimeOut
= KEYBOARD_BAT_TIMEOUT
;
1993 Status
= KeyboardWaitForValue (ConsoleIn
, 0xaa);
1994 if (EFI_ERROR (Status
)) {
1995 KeyboardError (ConsoleIn
, L
"Keyboard self test failed!\n\r");
1999 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
2002 // Set Keyboard to use Scan Code Set 2
2004 Status
= KeyboardWrite (ConsoleIn
, 0xf0);
2005 if (EFI_ERROR (Status
)) {
2006 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
2010 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
2011 if (EFI_ERROR (Status
)) {
2012 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
2016 Status
= KeyboardWrite (ConsoleIn
, 0x02);
2017 if (EFI_ERROR (Status
)) {
2018 KeyboardError (ConsoleIn
, L
"8042 controller data write error!!\n\r");
2022 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
2023 if (EFI_ERROR (Status
)) {
2024 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
2029 // Clear Keyboard Scancode Buffer
2031 Status
= KeyboardWrite (ConsoleIn
, 0xf4);
2032 if (EFI_ERROR (Status
)) {
2033 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
2037 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
2038 if (EFI_ERROR (Status
)) {
2039 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
2043 if (Ps2Policy
!= NULL
) {
2044 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_CAPSLOCK
) == EFI_KEYBOARD_CAPSLOCK
) {
2045 ConsoleIn
->CapsLock
= TRUE
;
2048 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_NUMLOCK
) == EFI_KEYBOARD_NUMLOCK
) {
2049 ConsoleIn
->NumLock
= TRUE
;
2052 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_SCROLLLOCK
) == EFI_KEYBOARD_SCROLLLOCK
) {
2053 ConsoleIn
->ScrollLock
= TRUE
;
2057 // Update Keyboard Lights
2059 Status
= UpdateStatusLights (ConsoleIn
);
2060 if (EFI_ERROR (Status
)) {
2061 KeyboardError (ConsoleIn
, L
"Update keyboard status lights error!\n\r");
2066 // At last, we can now enable the mouse interface if appropriate
2070 if (EnableMouseInterface
) {
2072 // Enable mouse interface
2074 Status1
= KeyboardCommand (ConsoleIn
, 0xa8);
2075 if (EFI_ERROR (Status1
)) {
2076 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
2077 return EFI_DEVICE_ERROR
;
2081 if (!EFI_ERROR (Status
)) {
2084 return EFI_DEVICE_ERROR
;
2091 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
2095 Routine Description:
2097 Disable the keyboard interface of the 8042 controller
2101 ConsoleIn - the device instance
2108 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
2113 // Disable keyboard interface
2115 Status
= KeyboardCommand (ConsoleIn
, 0xad);
2116 if (EFI_ERROR (Status
)) {
2117 KeyboardError (ConsoleIn
, L
"\n\r");
2118 return EFI_DEVICE_ERROR
;
2125 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
2126 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
2127 should not be in system.
2129 @param[in] BiosKeyboardPrivate Keyboard Private Data Structure
2131 @retval TRUE Keyboard in System.
2132 @retval FALSE Keyboard not in System.
2136 CheckKeyboardConnect (
2137 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
2141 UINTN WaitForValueTimeOutBcakup
;
2143 Status
= EFI_SUCCESS
;
2145 // enable keyboard itself and wait for its ack
2146 // If can't receive ack, Keyboard should not be connected.
2148 Status
= KeyboardWrite (
2153 if (EFI_ERROR (Status
)) {
2159 WaitForValueTimeOutBcakup
= mWaitForValueTimeOut
;
2160 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
2161 Status
= KeyboardWaitForValue (
2163 KEYBOARD_CMDECHO_ACK
2165 mWaitForValueTimeOut
= WaitForValueTimeOutBcakup
;
2167 if (EFI_ERROR (Status
)) {