3 Routines that access 8042 keyboard controller
5 Copyright (c) 2006 - 2007 Intel Corporation. All rights reserved. <BR>
6 This software and associated documentation (if any) is furnished
7 under a license and may only be used or copied in accordance
8 with the terms of the license. Except as permitted by such
9 license, no part of this software or documentation may be
10 reproduced, stored in a retrieval system, or transmitted in any
11 form or by any means without the express written consent of
17 // Include common header file for this module.
19 #include "CommonHeader.h"
21 #include "Ps2Keyboard.h"
24 // Function declarations
29 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
34 KeyWriteDataRegister (
35 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
41 KeyWriteCommandRegister (
42 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
49 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
50 IN CHAR16
*ErrMsg
// should be a unicode string
56 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
64 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
72 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
79 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
85 KeyboardWaitForValue (
86 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
93 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
104 CHAR16 ShiftUnicodeChar
;
106 ConvertKeyboardScanCodeToEfiKey
[] = {
433 0x37, // Numeric Keypad *
439 0x38, //Left Alt/Extended Right Alt
559 0x4c, // Numeric Keypad 5
628 // The WaitForValue time out
630 STATIC UINTN mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
634 KeyReadDataRegister (
635 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
641 GC_TODO: Add function description
645 ConsoleIn - GC_TODO: add argument description
649 GC_TODO: add return values
653 EFI_ISA_IO_PROTOCOL
*IsaIo
;
657 // Use IsaIo protocol to perform IO operations
659 IsaIo
= ConsoleIn
->IsaIo
;
664 ConsoleIn
->DataRegisterAddress
,
674 KeyWriteDataRegister (
675 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
682 GC_TODO: Add function description
686 ConsoleIn - GC_TODO: add argument description
687 Data - GC_TODO: add argument description
691 GC_TODO: add return values
695 EFI_ISA_IO_PROTOCOL
*IsaIo
;
698 // Use IsaIo protocol to perform IO operations
700 IsaIo
= ConsoleIn
->IsaIo
;
705 ConsoleIn
->DataRegisterAddress
,
711 // outp(ConsoleIn->DataRegisterAddress, Data);
716 KeyReadStatusRegister (
717 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
723 GC_TODO: Add function description
727 ConsoleIn - GC_TODO: add argument description
731 GC_TODO: add return values
735 EFI_ISA_IO_PROTOCOL
*IsaIo
;
739 // Use IsaIo protocol to perform IO operations
741 IsaIo
= ConsoleIn
->IsaIo
;
746 ConsoleIn
->StatusRegisterAddress
,
757 KeyWriteCommandRegister (
758 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
765 GC_TODO: Add function description
769 ConsoleIn - GC_TODO: add argument description
770 Data - GC_TODO: add argument description
774 GC_TODO: add return values
778 EFI_ISA_IO_PROTOCOL
*IsaIo
;
781 // Use IsaIo protocol to perform IO operations
783 IsaIo
= ConsoleIn
->IsaIo
;
788 ConsoleIn
->CommandRegisterAddress
,
798 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
805 Display error message
812 // GC_TODO: ConsoleIn - add argument and description to function comment
813 // GC_TODO: ErrMsg - add argument and description to function comment
815 ConsoleIn
->KeyboardErr
= TRUE
;
818 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");
819 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);
825 KeyboardTimerHandler (
833 Timer event handler: read a series of scancodes from 8042
834 and put them into memory scancode buffer.
835 it read as much scancodes to either fill
836 the memory buffer or empty the keyboard buffer.
837 It is registered as running under TPL_NOTIFY
841 Event - The timer event
842 Context - A KEYBOARD_CONSOLE_IN_DEV pointer
850 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
855 // Enter critical section
857 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
859 if (((KEYBOARD_CONSOLE_IN_DEV
*) Context
)->KeyboardErr
) {
861 // Leave critical section and return
863 gBS
->RestoreTPL (OldTpl
);
867 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
868 // KB is not connected to system. If KB is not connected to system, driver will find there's something
869 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
870 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
871 // Just skip the 'resend' process simply.
877 // if there is no key present, just return
879 if ((KeyReadStatusRegister (Context
) & 0x21) != 0x1) {
881 // Leave critical section and return
883 gBS
->RestoreTPL (OldTpl
);
888 // Read one byte of the scan code and store it into the memory buffer
890 if (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
) {
892 Data
= KeyReadDataRegister (Context
);
894 // put the scancode into the memory scancode buffer
896 ConsoleIn
->ScancodeBufCount
++;
897 ConsoleIn
->ScancodeBufEndPos
++;
898 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
899 ConsoleIn
->ScancodeBufEndPos
= 0;
902 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Data
;
905 // Handle Alt+Ctrl+Del Key combination
908 case SCANCODE_CTRL_MAKE
:
909 ConsoleIn
->Ctrled
= TRUE
;
912 case SCANCODE_CTRL_BREAK
:
913 ConsoleIn
->Ctrled
= FALSE
;
916 case SCANCODE_ALT_MAKE
:
917 ConsoleIn
->Alted
= TRUE
;
920 case SCANCODE_ALT_BREAK
:
921 ConsoleIn
->Alted
= FALSE
;
925 // if Alt+Ctrl+Del, Reboot the System
927 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Data
== 0x53) {
928 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
932 // Leave critical section and return
934 gBS
->RestoreTPL (OldTpl
);
942 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
950 Read several bytes from the scancode buffer without removing them.
951 This function is called to see if there are enough bytes of scancode
952 representing a single key.
956 Count - Number of bytes to be read
957 Buf - Store the results
964 // GC_TODO: ConsoleIn - add argument and description to function comment
965 // GC_TODO: EFI_NOT_READY - add return value to function comment
966 // GC_TODO: EFI_SUCCESS - add return value to function comment
975 // check the valid range of parameter 'Count'
977 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
978 return EFI_NOT_READY
;
981 // retrieve the values
983 for (Index
= 0; Index
< Count
; Index
++) {
987 Pos
= ConsoleIn
->ScancodeBufStartPos
;
991 if (Pos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
996 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[Pos
];
1004 PopScancodeBufHead (
1005 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1011 Routine Description:
1013 Read & remove several bytes from the scancode buffer.
1014 This function is usually called after GetScancodeBufHead()
1018 Count - Number of bytes to be read
1019 Buf - Store the results
1026 // GC_TODO: ConsoleIn - add argument and description to function comment
1027 // GC_TODO: EFI_NOT_READY - add return value to function comment
1028 // GC_TODO: EFI_SUCCESS - add return value to function comment
1035 // Check the valid range of parameter 'Count'
1037 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
1038 return EFI_NOT_READY
;
1041 // Retrieve and remove the values
1043 for (Index
= 0; Index
< Count
; Index
++) {
1047 ConsoleIn
->ScancodeBufStartPos
++;
1048 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1049 ConsoleIn
->ScancodeBufStartPos
= 0;
1053 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufStartPos
];
1054 ConsoleIn
->ScancodeBufCount
--;
1057 ConsoleIn
->ScancodeBufStartPos
++;
1058 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1059 ConsoleIn
->ScancodeBufStartPos
= 0;
1067 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1072 Routine Description:
1074 GC_TODO: Add function description
1078 ConsoleIn - GC_TODO: add argument description
1079 Data - GC_TODO: add argument description
1083 EFI_TIMEOUT - GC_TODO: Add description for return value
1084 EFI_SUCCESS - GC_TODO: Add description for return value
1095 // wait till output buffer full then perform the read
1097 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1098 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1100 *Data
= KeyReadDataRegister (ConsoleIn
);
1117 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1122 Routine Description:
1124 GC_TODO: Add function description
1128 ConsoleIn - GC_TODO: add argument description
1129 Data - GC_TODO: add argument description
1133 EFI_TIMEOUT - GC_TODO: Add description for return value
1134 EFI_SUCCESS - GC_TODO: Add description for return value
1145 // wait for input buffer empty
1147 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1148 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1162 KeyWriteDataRegister (ConsoleIn
, Data
);
1170 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1175 Routine Description:
1177 GC_TODO: Add function description
1181 ConsoleIn - GC_TODO: add argument description
1182 Data - GC_TODO: add argument description
1186 EFI_TIMEOUT - GC_TODO: Add description for return value
1187 EFI_TIMEOUT - GC_TODO: Add description for return value
1188 EFI_SUCCESS - GC_TODO: Add description for return value
1199 // Wait For Input Buffer Empty
1201 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1202 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1214 // issue the command
1216 KeyWriteCommandRegister (ConsoleIn
, Data
);
1219 // Wait For Input Buffer Empty again
1222 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1223 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1240 KeyboardWaitForValue (
1241 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1246 Routine Description:
1248 wait for a specific value to be presented on
1249 8042 Data register by keyboard and then read it,
1250 used in keyboard commands ack
1254 ConsoleIn - The KEYBOARD_CONSOLE_IN_DEV instance pointer
1255 Value - The value to be waited for
1262 // GC_TODO: EFI_SUCCESS - add return value to function comment
1263 // GC_TODO: EFI_TIMEOUT - add return value to function comment
1275 // Make sure the initial value of 'Data' is different from 'Value'
1278 if (Data
== Value
) {
1282 // Read from 8042 (multiple times if needed)
1283 // until the expected value appears
1284 // use SumTimeOut to control the iteration
1290 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1291 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1292 Data
= KeyReadDataRegister (ConsoleIn
);
1299 SumTimeOut
+= TimeOut
;
1301 if (Data
== Value
) {
1306 if (SumTimeOut
>= mWaitForValueTimeOut
) {
1323 UpdateStatusLights (
1324 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1328 Routine Description:
1330 Show keyboard status lights according to
1331 indicators in ConsoleIn.
1338 // GC_TODO: ConsoleIn - add argument and description to function comment
1344 // Send keyboard command
1346 Status
= KeyboardWrite (ConsoleIn
, 0xed);
1347 if (EFI_ERROR (Status
)) {
1351 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1354 // Light configuration
1357 if (ConsoleIn
->CapsLock
) {
1361 if (ConsoleIn
->NumLock
) {
1365 if (ConsoleIn
->ScrollLock
) {
1369 Status
= KeyboardWrite (ConsoleIn
, Command
);
1371 if (EFI_ERROR (Status
)) {
1375 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1381 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1385 Routine Description:
1387 Get scancode from scancode buffer
1388 and translate into EFI-scancode and unicode defined by EFI spec
1389 The function is always called in TPL_NOTIFY
1393 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1397 EFI_NOT_READY - Input from console not ready yet.
1398 EFI_SUCCESS - Function executed successfully.
1406 UINT8 ScancodeArr
[4];
1411 UINT32 ScancodeArrPos
;
1413 // point to the current position in ScancodeArr
1421 // Read one byte of the scan code and store it into the memory buffer
1422 // This block of code is added to insert an action that is equivalent to
1423 // the timer event handling function, so as to increase the frequency of
1424 // detecting the availability of keys. Timer event has a max frequency of
1425 // 18Hz which is insufficient
1428 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
1429 // KB is not connected to system. If KB is not connected to system, driver will find there's something
1430 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
1431 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
1432 // Just skip the 'resend' process simply.
1436 if (((KeyReadStatusRegister (ConsoleIn
) & 0x21) == 0x1) && (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
)) {
1438 Readed
= KeyReadDataRegister (ConsoleIn
);
1440 // put the scancode into the memory scancode buffer
1442 ConsoleIn
->ScancodeBufCount
++;
1443 ConsoleIn
->ScancodeBufEndPos
++;
1444 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1445 ConsoleIn
->ScancodeBufEndPos
= 0;
1448 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Readed
;
1451 // Handle Alt+Ctrl+Del Key combination
1455 case SCANCODE_CTRL_MAKE
:
1456 ConsoleIn
->Ctrled
= TRUE
;
1459 case SCANCODE_CTRL_BREAK
:
1460 ConsoleIn
->Ctrled
= FALSE
;
1463 case SCANCODE_ALT_MAKE
:
1464 ConsoleIn
->Alted
= TRUE
;
1467 case SCANCODE_ALT_BREAK
:
1468 ConsoleIn
->Alted
= FALSE
;
1472 // if Alt+Ctrl+Del, Reboot the System
1474 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Readed
== 0x53) {
1475 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1479 // Check if there are enough bytes of scancode representing a single key
1480 // available in the buffer
1484 Status
= GetScancodeBufHead (ConsoleIn
, 1, ScancodeArr
);
1486 if (EFI_ERROR (Status
)) {
1487 return EFI_NOT_READY
;
1490 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED
) {
1492 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1494 if (EFI_ERROR (Status
)) {
1495 return EFI_NOT_READY
;
1499 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
1500 // if present, ignore them
1502 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED1
) {
1504 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1507 if (EFI_ERROR (Status
)) {
1508 return EFI_NOT_READY
;
1511 Status
= GetScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1514 if (EFI_ERROR (Status
)) {
1515 return EFI_NOT_READY
;
1518 PopScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1519 return EFI_NOT_READY
;
1522 // if we reach this position, scancodes for a key is in buffer now,pop them
1524 Status
= PopScancodeBufHead (ConsoleIn
, ScancodeArrPos
+ 1, ScancodeArr
);
1525 if (EFI_ERROR (Status
)) {
1526 return EFI_NOT_READY
;
1529 // store the last available byte, this byte of scancode will be checked
1531 ScanCode
= ScancodeArr
[ScancodeArrPos
];
1534 // Check for special keys and update the driver state.
1538 case SCANCODE_CTRL_MAKE
:
1539 ConsoleIn
->Ctrl
= TRUE
;
1542 case SCANCODE_CTRL_BREAK
:
1543 ConsoleIn
->Ctrl
= FALSE
;
1546 case SCANCODE_ALT_MAKE
:
1547 ConsoleIn
->Alt
= TRUE
;
1550 case SCANCODE_ALT_BREAK
:
1551 ConsoleIn
->Alt
= FALSE
;
1554 case SCANCODE_LEFT_SHIFT_MAKE
:
1555 case SCANCODE_RIGHT_SHIFT_MAKE
:
1557 ConsoleIn
->Shift
= TRUE
;
1561 case SCANCODE_LEFT_SHIFT_BREAK
:
1562 case SCANCODE_RIGHT_SHIFT_BREAK
:
1564 ConsoleIn
->Shift
= FALSE
;
1568 case SCANCODE_CAPS_LOCK_MAKE
:
1569 ConsoleIn
->CapsLock
= (BOOLEAN
)!ConsoleIn
->CapsLock
;
1570 UpdateStatusLights (ConsoleIn
);
1573 case SCANCODE_NUM_LOCK_MAKE
:
1574 ConsoleIn
->NumLock
= (BOOLEAN
)!ConsoleIn
->NumLock
;
1575 UpdateStatusLights (ConsoleIn
);
1578 case SCANCODE_SCROLL_LOCK_MAKE
:
1579 ConsoleIn
->ScrollLock
= (BOOLEAN
)!ConsoleIn
->ScrollLock
;
1580 UpdateStatusLights (ConsoleIn
);
1584 // If this is a BREAK Key or above the valid range, ignore it
1586 if (ScanCode
>= SCANCODE_MAX_MAKE
) {
1593 // If this is the SysRq, ignore it
1595 if (Extended
&& ScanCode
== 0x37) {
1596 return EFI_NOT_READY
;
1599 // Treat Numeric Key Pad "/" specially
1601 if (Extended
&& ScanCode
== 0x35) {
1602 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1603 ConsoleIn
->Key
.UnicodeChar
= '/';
1607 // Convert Keyboard ScanCode into an EFI Key
1609 for (Index
= 0; ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
!= TABLE_END
; Index
+= 1) {
1610 if (ScanCode
== ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
) {
1611 ConsoleIn
->Key
.ScanCode
= ConvertKeyboardScanCodeToEfiKey
[Index
].EfiScanCode
;
1612 if (ConsoleIn
->Shift
) {
1613 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1615 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1618 // alphabetic key is affected by CapsLock State
1620 if (ConsoleIn
->CapsLock
) {
1621 if (ConsoleIn
->Key
.UnicodeChar
>= 'a' && ConsoleIn
->Key
.UnicodeChar
<= 'z') {
1622 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1623 } else if (ConsoleIn
->Key
.UnicodeChar
>= 'A' && ConsoleIn
->Key
.UnicodeChar
<= 'Z') {
1624 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1633 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1635 if (ScanCode
>= 0x47 && ScanCode
<= 0x53) {
1637 if (ConsoleIn
->NumLock
&& !ConsoleIn
->Shift
&& !Extended
) {
1638 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1639 } else if (ScanCode
!= 0x4a && ScanCode
!= 0x4e) {
1640 ConsoleIn
->Key
.UnicodeChar
= 0x00;
1644 // If the key can not be converted then just return.
1646 if (ConsoleIn
->Key
.ScanCode
== SCAN_NULL
&& ConsoleIn
->Key
.UnicodeChar
== 0x00) {
1647 return EFI_NOT_READY
;
1655 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1656 IN BOOLEAN ExtendedVerification
1660 Routine Description:
1662 Perform 8042 controller and keyboard Initialization
1663 If ExtendedVerification is TRUE, do additional test for
1664 the keyboard interface
1668 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1669 ExtendedVerification - indicates a thorough initialization
1676 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1677 // GC_TODO: EFI_SUCCESS - add return value to function comment
1678 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1683 STATIC BOOLEAN EnableMouseInterface
;
1684 EFI_PS2_POLICY_PROTOCOL
*Ps2Policy
;
1686 Status
= EFI_SUCCESS
;
1687 EnableMouseInterface
= TRUE
;
1690 // Get Ps2 policy to set this
1692 Status
= gBS
->LocateProtocol (
1693 &gEfiPs2PolicyProtocolGuid
,
1695 (VOID
**) &Ps2Policy
1698 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1700 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
,
1701 ConsoleIn
->DevicePath
1705 // Perform a read to cleanup the Status Register's
1706 // output buffer full bits
1708 while (!EFI_ERROR (Status
)) {
1709 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1712 // We should disable mouse interface during the initialization process
1713 // since mouse device output could block keyboard device output in the
1714 // 60H port of 8042 controller.
1716 // So if we are not initializing 8042 controller for the
1717 // first time, we have to remember the previous mouse interface
1720 // Test the system flag in to determine whether this is the first
1721 // time initialization
1723 if ((KeyReadStatusRegister (ConsoleIn
) & 0x04)) {
1725 // 8042 controller is already setup (by myself or by mouse driver):
1726 // See whether mouse interface is already enabled
1727 // which determines whether we should enable it later
1730 // Read the command byte of 8042 controller
1732 Status
= KeyboardCommand (ConsoleIn
, 0x20);
1733 if (EFI_ERROR (Status
)) {
1734 KeyboardError (ConsoleIn
, L
"\n\r");
1738 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1739 if (EFI_ERROR (Status
)) {
1740 KeyboardError (ConsoleIn
, L
"\n\r");
1744 // Test the mouse enabling bit
1746 if (CommandByte
& 0x20) {
1747 EnableMouseInterface
= FALSE
;
1749 EnableMouseInterface
= TRUE
;
1754 // 8042 controller is not setup yet:
1755 // 8042 controller selftest;
1756 // Don't enable mouse interface later.
1759 // Disable keyboard and mouse interfaces
1761 Status
= KeyboardCommand (ConsoleIn
, 0xad);
1762 if (EFI_ERROR (Status
)) {
1763 KeyboardError (ConsoleIn
, L
"\n\r");
1767 Status
= KeyboardCommand (ConsoleIn
, 0xa7);
1768 if (EFI_ERROR (Status
)) {
1769 KeyboardError (ConsoleIn
, L
"\n\r");
1773 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1775 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_SELF_TEST
,
1776 ConsoleIn
->DevicePath
1779 // 8042 Controller Self Test
1781 Status
= KeyboardCommand (ConsoleIn
, 0xaa);
1782 if (EFI_ERROR (Status
)) {
1783 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1787 Status
= KeyboardWaitForValue (ConsoleIn
, 0x55);
1788 if (EFI_ERROR (Status
)) {
1789 KeyboardError (ConsoleIn
, L
"8042 controller self test failed!\n\r");
1793 // Don't enable mouse interface later
1795 EnableMouseInterface
= FALSE
;
1799 if (Ps2Policy
!= NULL
) {
1800 Ps2Policy
->Ps2InitHardware (ConsoleIn
->Handle
);
1803 // Write 8042 Command Byte, set System Flag
1804 // While at the same time:
1805 // 1. disable mouse interface,
1806 // 2. enable kbd interface,
1807 // 3. enable PC/XT kbd translation mode
1808 // 4. enable mouse and kbd interrupts
1810 // ( Command Byte bits:
1812 // 6: PC/XT translation mode
1813 // 5: Disable Auxiliary device interface
1814 // 4: Disable keyboard interface
1817 // 1: Enable Auxiliary device interrupt
1818 // 0: Enable Keyboard interrupt )
1820 Status
= KeyboardCommand (ConsoleIn
, 0x60);
1821 if (EFI_ERROR (Status
)) {
1822 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1826 Status
= KeyboardWrite (ConsoleIn
, 0x67);
1827 if (EFI_ERROR (Status
)) {
1828 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1833 // Clear Memory Scancode Buffer
1835 ConsoleIn
->ScancodeBufStartPos
= 0;
1836 ConsoleIn
->ScancodeBufEndPos
= KEYBOARD_BUFFER_MAX_COUNT
- 1;
1837 ConsoleIn
->ScancodeBufCount
= 0;
1838 ConsoleIn
->Ctrled
= FALSE
;
1839 ConsoleIn
->Alted
= FALSE
;
1842 // Reset the status indicators
1844 ConsoleIn
->Ctrl
= FALSE
;
1845 ConsoleIn
->Alt
= FALSE
;
1846 ConsoleIn
->Shift
= FALSE
;
1847 ConsoleIn
->CapsLock
= FALSE
;
1848 ConsoleIn
->NumLock
= FALSE
;
1849 ConsoleIn
->ScrollLock
= FALSE
;
1852 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1853 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1854 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
1855 // and normally during booting an OS, it's skipped.
1857 if (ExtendedVerification
&& CheckKeyboardConnect (ConsoleIn
)) {
1859 // Additional verifications for keyboard interface
1862 // Keyboard Interface Test
1864 Status
= KeyboardCommand (ConsoleIn
, 0xab);
1865 if (EFI_ERROR (Status
)) {
1866 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1870 Status
= KeyboardWaitForValue (ConsoleIn
, 0x00);
1871 if (EFI_ERROR (Status
)) {
1874 L
"Some specific value not aquired from 8042 controller!\n\r"
1879 // Keyboard reset with a BAT(Basic Assurance Test)
1881 Status
= KeyboardWrite (ConsoleIn
, 0xff);
1882 if (EFI_ERROR (Status
)) {
1883 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1887 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1888 if (EFI_ERROR (Status
)) {
1889 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1893 // wait for BAT completion code
1895 mWaitForValueTimeOut
= KEYBOARD_BAT_TIMEOUT
;
1897 Status
= KeyboardWaitForValue (ConsoleIn
, 0xaa);
1898 if (EFI_ERROR (Status
)) {
1899 KeyboardError (ConsoleIn
, L
"Keyboard self test failed!\n\r");
1903 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
1906 // Set Keyboard to use Scan Code Set 2
1908 Status
= KeyboardWrite (ConsoleIn
, 0xf0);
1909 if (EFI_ERROR (Status
)) {
1910 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1914 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1915 if (EFI_ERROR (Status
)) {
1916 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1920 Status
= KeyboardWrite (ConsoleIn
, 0x02);
1921 if (EFI_ERROR (Status
)) {
1922 KeyboardError (ConsoleIn
, L
"8042 controller data write error!!\n\r");
1926 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1927 if (EFI_ERROR (Status
)) {
1928 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1933 // Clear Keyboard Scancode Buffer
1935 Status
= KeyboardWrite (ConsoleIn
, 0xf4);
1936 if (EFI_ERROR (Status
)) {
1937 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1941 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1942 if (EFI_ERROR (Status
)) {
1943 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1947 if (Ps2Policy
!= NULL
) {
1948 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_CAPSLOCK
) == EFI_KEYBOARD_CAPSLOCK
) {
1949 ConsoleIn
->CapsLock
= TRUE
;
1952 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_NUMLOCK
) == EFI_KEYBOARD_NUMLOCK
) {
1953 ConsoleIn
->NumLock
= TRUE
;
1956 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_SCROLLLOCK
) == EFI_KEYBOARD_SCROLLLOCK
) {
1957 ConsoleIn
->ScrollLock
= TRUE
;
1961 // Update Keyboard Lights
1963 Status
= UpdateStatusLights (ConsoleIn
);
1964 if (EFI_ERROR (Status
)) {
1965 KeyboardError (ConsoleIn
, L
"Update keyboard status lights error!\n\r");
1970 // At last, we can now enable the mouse interface if appropriate
1974 if (EnableMouseInterface
) {
1976 // Enable mouse interface
1978 Status1
= KeyboardCommand (ConsoleIn
, 0xa8);
1979 if (EFI_ERROR (Status1
)) {
1980 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1981 return EFI_DEVICE_ERROR
;
1985 if (!EFI_ERROR (Status
)) {
1988 return EFI_DEVICE_ERROR
;
1995 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1999 Routine Description:
2001 Disable the keyboard interface of the 8042 controller
2005 ConsoleIn - the device instance
2012 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
2017 // Disable keyboard interface
2019 Status
= KeyboardCommand (ConsoleIn
, 0xad);
2020 if (EFI_ERROR (Status
)) {
2021 KeyboardError (ConsoleIn
, L
"\n\r");
2022 return EFI_DEVICE_ERROR
;
2029 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
2030 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
2031 should not be in system.
2033 @param[in] BiosKeyboardPrivate Keyboard Private Data Structure
2035 @retval TRUE Keyboard in System.
2036 @retval FALSE Keyboard not in System.
2040 CheckKeyboardConnect (
2041 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
2045 UINTN WaitForValueTimeOutBcakup
;
2047 Status
= EFI_SUCCESS
;
2049 // enable keyboard itself and wait for its ack
2050 // If can't receive ack, Keyboard should not be connected.
2052 Status
= KeyboardWrite (
2057 if (EFI_ERROR (Status
)) {
2063 WaitForValueTimeOutBcakup
= mWaitForValueTimeOut
;
2064 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
2065 Status
= KeyboardWaitForValue (
2067 KEYBOARD_CMDECHO_ACK
2069 mWaitForValueTimeOut
= WaitForValueTimeOutBcakup
;
2071 if (EFI_ERROR (Status
)) {