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
,
91 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
102 CHAR16 ShiftUnicodeChar
;
104 ConvertKeyboardScanCodeToEfiKey
[] = {
431 0x37, // Numeric Keypad *
437 0x38, //Left Alt/Extended Right Alt
557 0x4c, // Numeric Keypad 5
626 // The WaitForValue time out
628 STATIC UINTN mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
632 KeyReadDataRegister (
633 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
639 GC_TODO: Add function description
643 ConsoleIn - GC_TODO: add argument description
647 GC_TODO: add return values
651 EFI_ISA_IO_PROTOCOL
*IsaIo
;
655 // Use IsaIo protocol to perform IO operations
657 IsaIo
= ConsoleIn
->IsaIo
;
662 ConsoleIn
->DataRegisterAddress
,
672 KeyWriteDataRegister (
673 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
680 GC_TODO: Add function description
684 ConsoleIn - GC_TODO: add argument description
685 Data - GC_TODO: add argument description
689 GC_TODO: add return values
693 EFI_ISA_IO_PROTOCOL
*IsaIo
;
696 // Use IsaIo protocol to perform IO operations
698 IsaIo
= ConsoleIn
->IsaIo
;
703 ConsoleIn
->DataRegisterAddress
,
709 // outp(ConsoleIn->DataRegisterAddress, Data);
714 KeyReadStatusRegister (
715 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
721 GC_TODO: Add function description
725 ConsoleIn - GC_TODO: add argument description
729 GC_TODO: add return values
733 EFI_ISA_IO_PROTOCOL
*IsaIo
;
737 // Use IsaIo protocol to perform IO operations
739 IsaIo
= ConsoleIn
->IsaIo
;
744 ConsoleIn
->StatusRegisterAddress
,
755 KeyWriteCommandRegister (
756 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
763 GC_TODO: Add function description
767 ConsoleIn - GC_TODO: add argument description
768 Data - GC_TODO: add argument description
772 GC_TODO: add return values
776 EFI_ISA_IO_PROTOCOL
*IsaIo
;
779 // Use IsaIo protocol to perform IO operations
781 IsaIo
= ConsoleIn
->IsaIo
;
786 ConsoleIn
->CommandRegisterAddress
,
796 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
803 Display error message
810 // GC_TODO: ConsoleIn - add argument and description to function comment
811 // GC_TODO: ErrMsg - add argument and description to function comment
813 ConsoleIn
->KeyboardErr
= TRUE
;
816 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");
817 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);
823 KeyboardTimerHandler (
831 Timer event handler: read a series of scancodes from 8042
832 and put them into memory scancode buffer.
833 it read as much scancodes to either fill
834 the memory buffer or empty the keyboard buffer.
835 It is registered as running under TPL_NOTIFY
839 Event - The timer event
840 Context - A KEYBOARD_CONSOLE_IN_DEV pointer
848 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
853 // Enter critical section
855 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
857 if (((KEYBOARD_CONSOLE_IN_DEV
*) Context
)->KeyboardErr
) {
859 // Leave critical section and return
861 gBS
->RestoreTPL (OldTpl
);
865 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
866 // KB is not connected to system. If KB is not connected to system, driver will find there's something
867 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
868 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
869 // Just skip the 'resend' process simply.
875 // if there is no key present, just return
877 if ((KeyReadStatusRegister (Context
) & 0x21) != 0x1) {
879 // Leave critical section and return
881 gBS
->RestoreTPL (OldTpl
);
886 // Read one byte of the scan code and store it into the memory buffer
888 if (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
) {
890 Data
= KeyReadDataRegister (Context
);
892 // put the scancode into the memory scancode buffer
894 ConsoleIn
->ScancodeBufCount
++;
895 ConsoleIn
->ScancodeBufEndPos
++;
896 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
897 ConsoleIn
->ScancodeBufEndPos
= 0;
900 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Data
;
903 // Handle Alt+Ctrl+Del Key combination
906 case SCANCODE_CTRL_MAKE
:
907 ConsoleIn
->Ctrled
= TRUE
;
910 case SCANCODE_CTRL_BREAK
:
911 ConsoleIn
->Ctrled
= FALSE
;
914 case SCANCODE_ALT_MAKE
:
915 ConsoleIn
->Alted
= TRUE
;
918 case SCANCODE_ALT_BREAK
:
919 ConsoleIn
->Alted
= FALSE
;
923 // if Alt+Ctrl+Del, Reboot the System
925 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Data
== 0x53) {
926 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
930 // Leave critical section and return
932 gBS
->RestoreTPL (OldTpl
);
940 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
948 Read several bytes from the scancode buffer without removing them.
949 This function is called to see if there are enough bytes of scancode
950 representing a single key.
954 Count - Number of bytes to be read
955 Buf - Store the results
962 // GC_TODO: ConsoleIn - add argument and description to function comment
963 // GC_TODO: EFI_NOT_READY - add return value to function comment
964 // GC_TODO: EFI_SUCCESS - add return value to function comment
973 // check the valid range of parameter 'Count'
975 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
976 return EFI_NOT_READY
;
979 // retrieve the values
981 for (Index
= 0; Index
< Count
; Index
++) {
985 Pos
= ConsoleIn
->ScancodeBufStartPos
;
989 if (Pos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
994 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[Pos
];
1002 PopScancodeBufHead (
1003 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1009 Routine Description:
1011 Read & remove several bytes from the scancode buffer.
1012 This function is usually called after GetScancodeBufHead()
1016 Count - Number of bytes to be read
1017 Buf - Store the results
1024 // GC_TODO: ConsoleIn - add argument and description to function comment
1025 // GC_TODO: EFI_NOT_READY - add return value to function comment
1026 // GC_TODO: EFI_SUCCESS - add return value to function comment
1033 // Check the valid range of parameter 'Count'
1035 if (Count
<= 0 || ConsoleIn
->ScancodeBufCount
< Count
) {
1036 return EFI_NOT_READY
;
1039 // Retrieve and remove the values
1041 for (Index
= 0; Index
< Count
; Index
++) {
1045 ConsoleIn
->ScancodeBufStartPos
++;
1046 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1047 ConsoleIn
->ScancodeBufStartPos
= 0;
1051 Buf
[Index
] = ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufStartPos
];
1052 ConsoleIn
->ScancodeBufCount
--;
1055 ConsoleIn
->ScancodeBufStartPos
++;
1056 if (ConsoleIn
->ScancodeBufStartPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1057 ConsoleIn
->ScancodeBufStartPos
= 0;
1065 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1070 Routine Description:
1072 GC_TODO: Add function description
1076 ConsoleIn - GC_TODO: add argument description
1077 Data - GC_TODO: add argument description
1081 EFI_TIMEOUT - GC_TODO: Add description for return value
1082 EFI_SUCCESS - GC_TODO: Add description for return value
1093 // wait till output buffer full then perform the read
1095 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1096 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1098 *Data
= KeyReadDataRegister (ConsoleIn
);
1115 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1120 Routine Description:
1122 GC_TODO: Add function description
1126 ConsoleIn - GC_TODO: add argument description
1127 Data - GC_TODO: add argument description
1131 EFI_TIMEOUT - GC_TODO: Add description for return value
1132 EFI_SUCCESS - GC_TODO: Add description for return value
1143 // wait for input buffer empty
1145 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1146 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1160 KeyWriteDataRegister (ConsoleIn
, Data
);
1168 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1173 Routine Description:
1175 GC_TODO: Add function description
1179 ConsoleIn - GC_TODO: add argument description
1180 Data - GC_TODO: add argument description
1184 EFI_TIMEOUT - GC_TODO: Add description for return value
1185 EFI_TIMEOUT - GC_TODO: Add description for return value
1186 EFI_SUCCESS - GC_TODO: Add description for return value
1197 // Wait For Input Buffer Empty
1199 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1200 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1212 // issue the command
1214 KeyWriteCommandRegister (ConsoleIn
, Data
);
1217 // Wait For Input Buffer Empty again
1220 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1221 if (!(KeyReadStatusRegister (ConsoleIn
) & 0x02)) {
1238 KeyboardWaitForValue (
1239 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1244 Routine Description:
1246 wait for a specific value to be presented on
1247 8042 Data register by keyboard and then read it,
1248 used in keyboard commands ack
1252 ConsoleIn - The KEYBOARD_CONSOLE_IN_DEV instance pointer
1253 Value - The value to be waited for
1260 // GC_TODO: EFI_SUCCESS - add return value to function comment
1261 // GC_TODO: EFI_TIMEOUT - add return value to function comment
1273 // Make sure the initial value of 'Data' is different from 'Value'
1276 if (Data
== Value
) {
1280 // Read from 8042 (multiple times if needed)
1281 // until the expected value appears
1282 // use SumTimeOut to control the iteration
1288 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
1289 if (KeyReadStatusRegister (ConsoleIn
) & 0x01) {
1290 Data
= KeyReadDataRegister (ConsoleIn
);
1297 SumTimeOut
+= TimeOut
;
1299 if (Data
== Value
) {
1304 if (SumTimeOut
>= mWaitForValueTimeOut
) {
1321 UpdateStatusLights (
1322 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1326 Routine Description:
1328 Show keyboard status lights according to
1329 indicators in ConsoleIn.
1336 // GC_TODO: ConsoleIn - add argument and description to function comment
1342 // Send keyboard command
1344 Status
= KeyboardWrite (ConsoleIn
, 0xed);
1345 if (EFI_ERROR (Status
)) {
1349 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1352 // Light configuration
1355 if (ConsoleIn
->CapsLock
) {
1359 if (ConsoleIn
->NumLock
) {
1363 if (ConsoleIn
->ScrollLock
) {
1367 Status
= KeyboardWrite (ConsoleIn
, Command
);
1369 if (EFI_ERROR (Status
)) {
1373 KeyboardWaitForValue (ConsoleIn
, 0xfa);
1379 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1383 Routine Description:
1385 Get scancode from scancode buffer
1386 and translate into EFI-scancode and unicode defined by EFI spec
1387 The function is always called in TPL_NOTIFY
1391 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1395 EFI_NOT_READY - Input from console not ready yet.
1396 EFI_SUCCESS - Function executed successfully.
1404 UINT8 ScancodeArr
[4];
1409 UINT32 ScancodeArrPos
;
1411 // point to the current position in ScancodeArr
1419 // Read one byte of the scan code and store it into the memory buffer
1420 // This block of code is added to insert an action that is equivalent to
1421 // the timer event handling function, so as to increase the frequency of
1422 // detecting the availability of keys. Timer event has a max frequency of
1423 // 18Hz which is insufficient
1426 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
1427 // KB is not connected to system. If KB is not connected to system, driver will find there's something
1428 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
1429 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
1430 // Just skip the 'resend' process simply.
1434 if (((KeyReadStatusRegister (ConsoleIn
) & 0x21) == 0x1) && (ConsoleIn
->ScancodeBufCount
< KEYBOARD_BUFFER_MAX_COUNT
)) {
1436 Readed
= KeyReadDataRegister (ConsoleIn
);
1438 // put the scancode into the memory scancode buffer
1440 ConsoleIn
->ScancodeBufCount
++;
1441 ConsoleIn
->ScancodeBufEndPos
++;
1442 if (ConsoleIn
->ScancodeBufEndPos
>= KEYBOARD_BUFFER_MAX_COUNT
) {
1443 ConsoleIn
->ScancodeBufEndPos
= 0;
1446 ConsoleIn
->ScancodeBuf
[ConsoleIn
->ScancodeBufEndPos
] = Readed
;
1449 // Handle Alt+Ctrl+Del Key combination
1453 case SCANCODE_CTRL_MAKE
:
1454 ConsoleIn
->Ctrled
= TRUE
;
1457 case SCANCODE_CTRL_BREAK
:
1458 ConsoleIn
->Ctrled
= FALSE
;
1461 case SCANCODE_ALT_MAKE
:
1462 ConsoleIn
->Alted
= TRUE
;
1465 case SCANCODE_ALT_BREAK
:
1466 ConsoleIn
->Alted
= FALSE
;
1470 // if Alt+Ctrl+Del, Reboot the System
1472 if (ConsoleIn
->Ctrled
&& ConsoleIn
->Alted
&& Readed
== 0x53) {
1473 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1477 // Check if there are enough bytes of scancode representing a single key
1478 // available in the buffer
1482 Status
= GetScancodeBufHead (ConsoleIn
, 1, ScancodeArr
);
1484 if (EFI_ERROR (Status
)) {
1485 return EFI_NOT_READY
;
1488 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED
) {
1490 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1492 if (EFI_ERROR (Status
)) {
1493 return EFI_NOT_READY
;
1497 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
1498 // if present, ignore them
1500 if (ScancodeArr
[ScancodeArrPos
] == SCANCODE_EXTENDED1
) {
1502 Status
= GetScancodeBufHead (ConsoleIn
, 2, ScancodeArr
);
1505 if (EFI_ERROR (Status
)) {
1506 return EFI_NOT_READY
;
1509 Status
= GetScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1512 if (EFI_ERROR (Status
)) {
1513 return EFI_NOT_READY
;
1516 PopScancodeBufHead (ConsoleIn
, 3, ScancodeArr
);
1517 return EFI_NOT_READY
;
1520 // if we reach this position, scancodes for a key is in buffer now,pop them
1522 Status
= PopScancodeBufHead (ConsoleIn
, ScancodeArrPos
+ 1, ScancodeArr
);
1523 if (EFI_ERROR (Status
)) {
1524 return EFI_NOT_READY
;
1527 // store the last available byte, this byte of scancode will be checked
1529 ScanCode
= ScancodeArr
[ScancodeArrPos
];
1532 // Check for special keys and update the driver state.
1536 case SCANCODE_CTRL_MAKE
:
1537 ConsoleIn
->Ctrl
= TRUE
;
1540 case SCANCODE_CTRL_BREAK
:
1541 ConsoleIn
->Ctrl
= FALSE
;
1544 case SCANCODE_ALT_MAKE
:
1545 ConsoleIn
->Alt
= TRUE
;
1548 case SCANCODE_ALT_BREAK
:
1549 ConsoleIn
->Alt
= FALSE
;
1552 case SCANCODE_LEFT_SHIFT_MAKE
:
1553 case SCANCODE_RIGHT_SHIFT_MAKE
:
1555 ConsoleIn
->Shift
= TRUE
;
1559 case SCANCODE_LEFT_SHIFT_BREAK
:
1560 case SCANCODE_RIGHT_SHIFT_BREAK
:
1562 ConsoleIn
->Shift
= FALSE
;
1566 case SCANCODE_CAPS_LOCK_MAKE
:
1567 ConsoleIn
->CapsLock
= (BOOLEAN
)!ConsoleIn
->CapsLock
;
1568 UpdateStatusLights (ConsoleIn
);
1571 case SCANCODE_NUM_LOCK_MAKE
:
1572 ConsoleIn
->NumLock
= (BOOLEAN
)!ConsoleIn
->NumLock
;
1573 UpdateStatusLights (ConsoleIn
);
1576 case SCANCODE_SCROLL_LOCK_MAKE
:
1577 ConsoleIn
->ScrollLock
= (BOOLEAN
)!ConsoleIn
->ScrollLock
;
1578 UpdateStatusLights (ConsoleIn
);
1582 // If this is a BREAK Key or above the valid range, ignore it
1584 if (ScanCode
>= SCANCODE_MAX_MAKE
) {
1591 // If this is the SysRq, ignore it
1593 if (Extended
&& ScanCode
== 0x37) {
1594 return EFI_NOT_READY
;
1597 // Treat Numeric Key Pad "/" specially
1599 if (Extended
&& ScanCode
== 0x35) {
1600 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1601 ConsoleIn
->Key
.UnicodeChar
= '/';
1605 // Convert Keyboard ScanCode into an EFI Key
1607 for (Index
= 0; ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
!= TABLE_END
; Index
+= 1) {
1608 if (ScanCode
== ConvertKeyboardScanCodeToEfiKey
[Index
].ScanCode
) {
1609 ConsoleIn
->Key
.ScanCode
= ConvertKeyboardScanCodeToEfiKey
[Index
].EfiScanCode
;
1610 if (ConsoleIn
->Shift
) {
1611 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1613 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1616 // alphabetic key is affected by CapsLock State
1618 if (ConsoleIn
->CapsLock
) {
1619 if (ConsoleIn
->Key
.UnicodeChar
>= 'a' && ConsoleIn
->Key
.UnicodeChar
<= 'z') {
1620 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].ShiftUnicodeChar
;
1621 } else if (ConsoleIn
->Key
.UnicodeChar
>= 'A' && ConsoleIn
->Key
.UnicodeChar
<= 'Z') {
1622 ConsoleIn
->Key
.UnicodeChar
= ConvertKeyboardScanCodeToEfiKey
[Index
].UnicodeChar
;
1631 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1633 if (ScanCode
>= 0x47 && ScanCode
<= 0x53) {
1635 if (ConsoleIn
->NumLock
&& !ConsoleIn
->Shift
&& !Extended
) {
1636 ConsoleIn
->Key
.ScanCode
= SCAN_NULL
;
1637 } else if (ScanCode
!= 0x4a && ScanCode
!= 0x4e) {
1638 ConsoleIn
->Key
.UnicodeChar
= 0x00;
1642 // If the key can not be converted then just return.
1644 if (ConsoleIn
->Key
.ScanCode
== SCAN_NULL
&& ConsoleIn
->Key
.UnicodeChar
== 0x00) {
1645 return EFI_NOT_READY
;
1653 IN OUT KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
,
1654 IN BOOLEAN ExtendedVerification
1658 Routine Description:
1660 Perform 8042 controller and keyboard Initialization
1661 If ExtendedVerification is TRUE, do additional test for
1662 the keyboard interface
1666 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1667 ExtendedVerification - indicates a thorough initialization
1674 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1675 // GC_TODO: EFI_SUCCESS - add return value to function comment
1676 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
1681 STATIC BOOLEAN EnableMouseInterface
;
1682 EFI_PS2_POLICY_PROTOCOL
*Ps2Policy
;
1684 Status
= EFI_SUCCESS
;
1685 EnableMouseInterface
= TRUE
;
1688 // Get Ps2 policy to set this
1690 Status
= gBS
->LocateProtocol (
1691 &gEfiPs2PolicyProtocolGuid
,
1693 (VOID
**) &Ps2Policy
1696 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1698 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
,
1699 ConsoleIn
->DevicePath
1703 // Perform a read to cleanup the Status Register's
1704 // output buffer full bits
1706 while (!EFI_ERROR (Status
)) {
1707 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1710 // We should disable mouse interface during the initialization process
1711 // since mouse device output could block keyboard device output in the
1712 // 60H port of 8042 controller.
1714 // So if we are not initializing 8042 controller for the
1715 // first time, we have to remember the previous mouse interface
1718 // Test the system flag in to determine whether this is the first
1719 // time initialization
1721 if ((KeyReadStatusRegister (ConsoleIn
) & 0x04)) {
1723 // 8042 controller is already setup (by myself or by mouse driver):
1724 // See whether mouse interface is already enabled
1725 // which determines whether we should enable it later
1728 // Read the command byte of 8042 controller
1730 Status
= KeyboardCommand (ConsoleIn
, 0x20);
1731 if (EFI_ERROR (Status
)) {
1732 KeyboardError (ConsoleIn
, L
"\n\r");
1736 Status
= KeyboardRead (ConsoleIn
, &CommandByte
);
1737 if (EFI_ERROR (Status
)) {
1738 KeyboardError (ConsoleIn
, L
"\n\r");
1742 // Test the mouse enabling bit
1744 if (CommandByte
& 0x20) {
1745 EnableMouseInterface
= FALSE
;
1747 EnableMouseInterface
= TRUE
;
1752 // 8042 controller is not setup yet:
1753 // 8042 controller selftest;
1754 // Don't enable mouse interface later.
1757 // Disable keyboard and mouse interfaces
1759 Status
= KeyboardCommand (ConsoleIn
, 0xad);
1760 if (EFI_ERROR (Status
)) {
1761 KeyboardError (ConsoleIn
, L
"\n\r");
1765 Status
= KeyboardCommand (ConsoleIn
, 0xa7);
1766 if (EFI_ERROR (Status
)) {
1767 KeyboardError (ConsoleIn
, L
"\n\r");
1771 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1773 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_SELF_TEST
,
1774 ConsoleIn
->DevicePath
1777 // 8042 Controller Self Test
1779 Status
= KeyboardCommand (ConsoleIn
, 0xaa);
1780 if (EFI_ERROR (Status
)) {
1781 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1785 Status
= KeyboardWaitForValue (ConsoleIn
, 0x55);
1786 if (EFI_ERROR (Status
)) {
1787 KeyboardError (ConsoleIn
, L
"8042 controller self test failed!\n\r");
1791 // Don't enable mouse interface later
1793 EnableMouseInterface
= FALSE
;
1797 if (Ps2Policy
!= NULL
) {
1798 Ps2Policy
->Ps2InitHardware (ConsoleIn
->Handle
);
1801 // Write 8042 Command Byte, set System Flag
1802 // While at the same time:
1803 // 1. disable mouse interface,
1804 // 2. enable kbd interface,
1805 // 3. enable PC/XT kbd translation mode
1806 // 4. enable mouse and kbd interrupts
1808 // ( Command Byte bits:
1810 // 6: PC/XT translation mode
1811 // 5: Disable Auxiliary device interface
1812 // 4: Disable keyboard interface
1815 // 1: Enable Auxiliary device interrupt
1816 // 0: Enable Keyboard interrupt )
1818 Status
= KeyboardCommand (ConsoleIn
, 0x60);
1819 if (EFI_ERROR (Status
)) {
1820 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1824 Status
= KeyboardWrite (ConsoleIn
, 0x67);
1825 if (EFI_ERROR (Status
)) {
1826 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1831 // Clear Memory Scancode Buffer
1833 ConsoleIn
->ScancodeBufStartPos
= 0;
1834 ConsoleIn
->ScancodeBufEndPos
= KEYBOARD_BUFFER_MAX_COUNT
- 1;
1835 ConsoleIn
->ScancodeBufCount
= 0;
1836 ConsoleIn
->Ctrled
= FALSE
;
1837 ConsoleIn
->Alted
= FALSE
;
1840 // Reset the status indicators
1842 ConsoleIn
->Ctrl
= FALSE
;
1843 ConsoleIn
->Alt
= FALSE
;
1844 ConsoleIn
->Shift
= FALSE
;
1845 ConsoleIn
->CapsLock
= FALSE
;
1846 ConsoleIn
->NumLock
= FALSE
;
1847 ConsoleIn
->ScrollLock
= FALSE
;
1850 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1851 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1852 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
1853 // and normally during booting an OS, it's skipped.
1855 if (ExtendedVerification
&& CheckKeyboardConnect (ConsoleIn
)) {
1857 // Additional verifications for keyboard interface
1860 // Keyboard Interface Test
1862 Status
= KeyboardCommand (ConsoleIn
, 0xab);
1863 if (EFI_ERROR (Status
)) {
1864 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1868 Status
= KeyboardWaitForValue (ConsoleIn
, 0x00);
1869 if (EFI_ERROR (Status
)) {
1872 L
"Some specific value not aquired from 8042 controller!\n\r"
1877 // Keyboard reset with a BAT(Basic Assurance Test)
1879 Status
= KeyboardWrite (ConsoleIn
, 0xff);
1880 if (EFI_ERROR (Status
)) {
1881 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1885 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1886 if (EFI_ERROR (Status
)) {
1887 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1891 // wait for BAT completion code
1893 mWaitForValueTimeOut
= KEYBOARD_BAT_TIMEOUT
;
1895 Status
= KeyboardWaitForValue (ConsoleIn
, 0xaa);
1896 if (EFI_ERROR (Status
)) {
1897 KeyboardError (ConsoleIn
, L
"Keyboard self test failed!\n\r");
1901 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
1904 // Set Keyboard to use Scan Code Set 2
1906 Status
= KeyboardWrite (ConsoleIn
, 0xf0);
1907 if (EFI_ERROR (Status
)) {
1908 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1912 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1913 if (EFI_ERROR (Status
)) {
1914 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1918 Status
= KeyboardWrite (ConsoleIn
, 0x02);
1919 if (EFI_ERROR (Status
)) {
1920 KeyboardError (ConsoleIn
, L
"8042 controller data write error!!\n\r");
1924 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1925 if (EFI_ERROR (Status
)) {
1926 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1931 // Clear Keyboard Scancode Buffer
1933 Status
= KeyboardWrite (ConsoleIn
, 0xf4);
1934 if (EFI_ERROR (Status
)) {
1935 KeyboardError (ConsoleIn
, L
"8042 controller data write error!\n\r");
1939 Status
= KeyboardWaitForValue (ConsoleIn
, 0xfa);
1940 if (EFI_ERROR (Status
)) {
1941 KeyboardError (ConsoleIn
, L
"Some specific value not aquired from 8042 controller!\n\r");
1945 if (Ps2Policy
!= NULL
) {
1946 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_CAPSLOCK
) == EFI_KEYBOARD_CAPSLOCK
) {
1947 ConsoleIn
->CapsLock
= TRUE
;
1950 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_NUMLOCK
) == EFI_KEYBOARD_NUMLOCK
) {
1951 ConsoleIn
->NumLock
= TRUE
;
1954 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_SCROLLLOCK
) == EFI_KEYBOARD_SCROLLLOCK
) {
1955 ConsoleIn
->ScrollLock
= TRUE
;
1959 // Update Keyboard Lights
1961 Status
= UpdateStatusLights (ConsoleIn
);
1962 if (EFI_ERROR (Status
)) {
1963 KeyboardError (ConsoleIn
, L
"Update keyboard status lights error!\n\r");
1968 // At last, we can now enable the mouse interface if appropriate
1972 if (EnableMouseInterface
) {
1974 // Enable mouse interface
1976 Status1
= KeyboardCommand (ConsoleIn
, 0xa8);
1977 if (EFI_ERROR (Status1
)) {
1978 KeyboardError (ConsoleIn
, L
"8042 controller command write error!\n\r");
1979 return EFI_DEVICE_ERROR
;
1983 if (!EFI_ERROR (Status
)) {
1986 return EFI_DEVICE_ERROR
;
1993 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
1997 Routine Description:
1999 Disable the keyboard interface of the 8042 controller
2003 ConsoleIn - the device instance
2010 // GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
2015 // Disable keyboard interface
2017 Status
= KeyboardCommand (ConsoleIn
, 0xad);
2018 if (EFI_ERROR (Status
)) {
2019 KeyboardError (ConsoleIn
, L
"\n\r");
2020 return EFI_DEVICE_ERROR
;
2027 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
2028 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
2029 should not be in system.
2031 @param[in] BiosKeyboardPrivate Keyboard Private Data Structure
2033 @retval TRUE Keyboard in System.
2034 @retval FALSE Keyboard not in System.
2038 CheckKeyboardConnect (
2039 IN KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
2043 UINTN WaitForValueTimeOutBcakup
;
2045 Status
= EFI_SUCCESS
;
2047 // enable keyboard itself and wait for its ack
2048 // If can't receive ack, Keyboard should not be connected.
2050 Status
= KeyboardWrite (
2055 if (EFI_ERROR (Status
)) {
2061 WaitForValueTimeOutBcakup
= mWaitForValueTimeOut
;
2062 mWaitForValueTimeOut
= KEYBOARD_WAITFORVALUE_TIMEOUT
;
2063 Status
= KeyboardWaitForValue (
2065 KEYBOARD_CMDECHO_ACK
2067 mWaitForValueTimeOut
= WaitForValueTimeOutBcakup
;
2069 if (EFI_ERROR (Status
)) {