]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
The unicode char and shift unicode char should be unicode but not ascii char.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdCtrller.c
CommitLineData
05fbd06d 1/**@file\r
2 PS/2 Keyboard driver\r
3 Routines that access 8042 keyboard controller\r
4\r
df0dcb5e 5Copyright (c) 2006 - 2007, Intel Corporation\r
6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
05fbd06d 13\r
14**/\r
15\r
05fbd06d 16#include "Ps2Keyboard.h"\r
17\r
819d1488 18struct {\r
67319626 19 UINT8 ScanCode; ///< follows value defined in Scan Code Set1\r
05fbd06d 20 UINT16 EfiScanCode;\r
21 CHAR16 UnicodeChar;\r
22 CHAR16 ShiftUnicodeChar;\r
23}\r
24ConvertKeyboardScanCodeToEfiKey[] = {\r
25\r
26 {\r
27 0x01, // Escape\r
28 SCAN_ESC,\r
67319626 29 0x0000,\r
30 0x0000\r
05fbd06d 31 },\r
32 {\r
33 0x02,\r
34 SCAN_NULL,\r
67319626 35 L'1',\r
36 L'!'\r
05fbd06d 37 },\r
38 {\r
39 0x03,\r
40 SCAN_NULL,\r
67319626 41 L'2',\r
42 L'@'\r
05fbd06d 43 },\r
44 {\r
45 0x04,\r
46 SCAN_NULL,\r
67319626 47 L'3',\r
48 L'#'\r
05fbd06d 49 },\r
50 {\r
51 0x05,\r
52 SCAN_NULL,\r
67319626 53 L'4',\r
54 L'$'\r
05fbd06d 55 },\r
56 {\r
57 0x06,\r
58 SCAN_NULL,\r
67319626 59 L'5',\r
60 L'%'\r
05fbd06d 61 },\r
62 {\r
63 0x07,\r
64 SCAN_NULL,\r
67319626 65 L'6',\r
66 L'^'\r
05fbd06d 67 },\r
68 {\r
69 0x08,\r
70 SCAN_NULL,\r
67319626 71 L'7',\r
72 L'&'\r
05fbd06d 73 },\r
74 {\r
75 0x09,\r
76 SCAN_NULL,\r
67319626 77 L'8',\r
78 L'*'\r
05fbd06d 79 },\r
80 {\r
81 0x0A,\r
82 SCAN_NULL,\r
67319626 83 L'9',\r
84 L'('\r
05fbd06d 85 },\r
86 {\r
87 0x0B,\r
88 SCAN_NULL,\r
67319626 89 L'0',\r
90 L')'\r
05fbd06d 91 },\r
92 {\r
93 0x0C,\r
94 SCAN_NULL,\r
67319626 95 L'-',\r
96 L'_'\r
05fbd06d 97 },\r
98 {\r
99 0x0D,\r
100 SCAN_NULL,\r
67319626 101 L'=',\r
102 L'+'\r
05fbd06d 103 },\r
104 {\r
105 0x0E, // BackSpace\r
106 SCAN_NULL,\r
67319626 107 0x0008,\r
108 0x0008\r
05fbd06d 109 },\r
110 {\r
111 0x0F, // Tab\r
112 SCAN_NULL,\r
67319626 113 0x0009,\r
114 0x0009\r
05fbd06d 115 },\r
116 {\r
117 0x10,\r
118 SCAN_NULL,\r
67319626 119 L'q',\r
120 L'Q'\r
05fbd06d 121 },\r
122 {\r
123 0x11,\r
124 SCAN_NULL,\r
67319626 125 L'w',\r
126 L'W'\r
05fbd06d 127 },\r
128 {\r
129 0x12,\r
130 SCAN_NULL,\r
67319626 131 L'e',\r
132 L'E'\r
05fbd06d 133 },\r
134 {\r
135 0x13,\r
136 SCAN_NULL,\r
67319626 137 L'r',\r
138 L'R'\r
05fbd06d 139 },\r
140 {\r
141 0x14,\r
142 SCAN_NULL,\r
67319626 143 L't',\r
144 L'T'\r
05fbd06d 145 },\r
146 {\r
147 0x15,\r
148 SCAN_NULL,\r
67319626 149 L'y',\r
150 L'Y'\r
05fbd06d 151 },\r
152 {\r
153 0x16,\r
154 SCAN_NULL,\r
67319626 155 L'u',\r
156 L'U'\r
05fbd06d 157 },\r
158 {\r
159 0x17,\r
160 SCAN_NULL,\r
67319626 161 L'i',\r
162 L'I'\r
05fbd06d 163 },\r
164 {\r
165 0x18,\r
166 SCAN_NULL,\r
67319626 167 L'o',\r
168 L'O'\r
05fbd06d 169 },\r
170 {\r
171 0x19,\r
172 SCAN_NULL,\r
67319626 173 L'p',\r
174 L'P'\r
05fbd06d 175 },\r
176 {\r
177 0x1a,\r
178 SCAN_NULL,\r
67319626 179 L'[',\r
180 L'{'\r
05fbd06d 181 },\r
182 {\r
183 0x1b,\r
184 SCAN_NULL,\r
67319626 185 L']',\r
186 L'}'\r
05fbd06d 187 },\r
188 {\r
189 0x1c, // Enter\r
190 SCAN_NULL,\r
67319626 191 0x000d,\r
192 0x000d\r
05fbd06d 193 },\r
194 {\r
195 0x1d,\r
196 SCAN_NULL,\r
67319626 197 0x0000,\r
198 0x0000\r
05fbd06d 199 },\r
200 {\r
201 0x1e,\r
202 SCAN_NULL,\r
67319626 203 L'a',\r
204 L'A'\r
05fbd06d 205 },\r
206 {\r
207 0x1f,\r
208 SCAN_NULL,\r
67319626 209 L's',\r
210 L'S'\r
05fbd06d 211 },\r
212 {\r
213 0x20,\r
214 SCAN_NULL,\r
67319626 215 L'd',\r
216 L'D'\r
05fbd06d 217 },\r
218 {\r
219 0x21,\r
220 SCAN_NULL,\r
67319626 221 L'f',\r
222 L'F'\r
05fbd06d 223 },\r
224 {\r
225 0x22,\r
226 SCAN_NULL,\r
67319626 227 L'g',\r
228 L'G'\r
05fbd06d 229 },\r
230 {\r
231 0x23,\r
232 SCAN_NULL,\r
67319626 233 L'h',\r
234 L'H'\r
05fbd06d 235 },\r
236 {\r
237 0x24,\r
238 SCAN_NULL,\r
67319626 239 L'j',\r
240 L'J'\r
05fbd06d 241 },\r
242 {\r
243 0x25,\r
244 SCAN_NULL,\r
67319626 245 L'k',\r
246 L'K'\r
05fbd06d 247 },\r
248 {\r
249 0x26,\r
250 SCAN_NULL,\r
67319626 251 L'l',\r
252 L'L'\r
05fbd06d 253 },\r
254 {\r
255 0x27,\r
256 SCAN_NULL,\r
67319626 257 L';',\r
258 L':'\r
05fbd06d 259 },\r
260 {\r
261 0x28,\r
262 SCAN_NULL,\r
67319626 263 L'\'',\r
264 L'"'\r
05fbd06d 265 },\r
266 {\r
267 0x29,\r
268 SCAN_NULL,\r
67319626 269 L'`',\r
270 L'~'\r
05fbd06d 271 },\r
272 {\r
273 0x2a, // Left Shift\r
274 SCAN_NULL,\r
67319626 275 0x0000,\r
276 0x0000\r
05fbd06d 277 },\r
278 {\r
279 0x2b,\r
280 SCAN_NULL,\r
67319626 281 L'\\',\r
282 L'|'\r
05fbd06d 283 },\r
284 {\r
285 0x2c,\r
286 SCAN_NULL,\r
67319626 287 L'z',\r
288 L'Z'\r
05fbd06d 289 },\r
290 {\r
291 0x2d,\r
292 SCAN_NULL,\r
67319626 293 L'x',\r
294 L'X'\r
05fbd06d 295 },\r
296 {\r
297 0x2e,\r
298 SCAN_NULL,\r
67319626 299 L'c',\r
300 L'C'\r
05fbd06d 301 },\r
302 {\r
303 0x2f,\r
304 SCAN_NULL,\r
67319626 305 L'v',\r
306 L'V'\r
05fbd06d 307 },\r
308 {\r
309 0x30,\r
310 SCAN_NULL,\r
67319626 311 L'b',\r
312 L'B'\r
05fbd06d 313 },\r
314 {\r
315 0x31,\r
316 SCAN_NULL,\r
67319626 317 L'n',\r
318 L'N'\r
05fbd06d 319 },\r
320 {\r
321 0x32,\r
322 SCAN_NULL,\r
67319626 323 L'm',\r
324 L'M'\r
05fbd06d 325 },\r
326 {\r
327 0x33,\r
328 SCAN_NULL,\r
67319626 329 L',',\r
330 L'<'\r
05fbd06d 331 },\r
332 {\r
333 0x34,\r
334 SCAN_NULL,\r
67319626 335 L'.',\r
336 L'>'\r
05fbd06d 337 },\r
338 {\r
339 0x35,\r
340 SCAN_NULL,\r
67319626 341 L'/',\r
342 L'?'\r
05fbd06d 343 },\r
344 {\r
345 0x36, //Right Shift\r
346 SCAN_NULL,\r
67319626 347 0x0000,\r
348 0x0000\r
05fbd06d 349 },\r
350 {\r
351 0x37, // Numeric Keypad *\r
352 SCAN_NULL,\r
67319626 353 L'*',\r
354 L'*'\r
05fbd06d 355 },\r
356 {\r
357 0x38, //Left Alt/Extended Right Alt\r
358 SCAN_NULL,\r
67319626 359 0x0000,\r
360 0x0000\r
05fbd06d 361 },\r
362 {\r
363 0x39,\r
364 SCAN_NULL,\r
67319626 365 L' ',\r
366 L' '\r
05fbd06d 367 },\r
368 {\r
369 0x3A, //CapsLock\r
370 SCAN_NULL,\r
67319626 371 0x0000,\r
372 0x0000\r
05fbd06d 373 },\r
374 {\r
375 0x3B,\r
376 SCAN_F1,\r
67319626 377 0x0000,\r
378 0x0000\r
05fbd06d 379 },\r
380 {\r
381 0x3C,\r
382 SCAN_F2,\r
67319626 383 0x0000,\r
384 0x0000\r
05fbd06d 385 },\r
386 {\r
387 0x3D,\r
388 SCAN_F3,\r
67319626 389 0x0000,\r
390 0x0000\r
05fbd06d 391 },\r
392 {\r
393 0x3E,\r
394 SCAN_F4,\r
67319626 395 0x0000,\r
396 0x0000\r
05fbd06d 397 },\r
398 {\r
399 0x3F,\r
400 SCAN_F5,\r
67319626 401 0x0000,\r
402 0x0000\r
05fbd06d 403 },\r
404 {\r
405 0x40,\r
406 SCAN_F6,\r
67319626 407 0x0000,\r
408 0x0000\r
05fbd06d 409 },\r
410 {\r
411 0x41,\r
412 SCAN_F7,\r
67319626 413 0x0000,\r
414 0x0000\r
05fbd06d 415 },\r
416 {\r
417 0x42,\r
418 SCAN_F8,\r
67319626 419 0x0000,\r
420 0x0000\r
05fbd06d 421 },\r
422 {\r
423 0x43,\r
424 SCAN_F9,\r
67319626 425 0x0000,\r
426 0x0000\r
05fbd06d 427 },\r
428 {\r
429 0x44,\r
430 SCAN_F10,\r
67319626 431 0x0000,\r
432 0x0000\r
05fbd06d 433 },\r
434 {\r
435 0x45, // NumLock\r
436 SCAN_NULL,\r
67319626 437 0x0000,\r
438 0x0000\r
05fbd06d 439 },\r
440 {\r
441 0x46, // ScrollLock\r
442 SCAN_NULL,\r
67319626 443 0x0000,\r
444 0x0000\r
05fbd06d 445 },\r
446 {\r
447 0x47,\r
448 SCAN_HOME,\r
67319626 449 L'7',\r
450 L'7'\r
05fbd06d 451 },\r
452 {\r
453 0x48,\r
454 SCAN_UP,\r
67319626 455 L'8',\r
456 L'8'\r
05fbd06d 457 },\r
458 {\r
459 0x49,\r
460 SCAN_PAGE_UP,\r
67319626 461 L'9',\r
462 L'9'\r
05fbd06d 463 },\r
464 {\r
465 0x4a,\r
466 SCAN_NULL,\r
67319626 467 L'-',\r
468 L'-'\r
05fbd06d 469 },\r
470 {\r
471 0x4b,\r
472 SCAN_LEFT,\r
67319626 473 L'4',\r
474 L'4'\r
05fbd06d 475 },\r
476 {\r
477 0x4c, // Numeric Keypad 5\r
478 SCAN_NULL,\r
67319626 479 L'5',\r
480 L'5'\r
05fbd06d 481 },\r
482 {\r
483 0x4d,\r
484 SCAN_RIGHT,\r
67319626 485 L'6',\r
486 L'6'\r
05fbd06d 487 },\r
488 {\r
489 0x4e,\r
490 SCAN_NULL,\r
67319626 491 L'+',\r
492 L'+'\r
05fbd06d 493 },\r
494 {\r
495 0x4f,\r
496 SCAN_END,\r
67319626 497 L'1',\r
498 L'1'\r
05fbd06d 499 },\r
500 {\r
501 0x50,\r
502 SCAN_DOWN,\r
67319626 503 L'2',\r
504 L'2'\r
05fbd06d 505 },\r
506 {\r
507 0x51,\r
508 SCAN_PAGE_DOWN,\r
67319626 509 L'3',\r
510 L'3'\r
05fbd06d 511 },\r
512 {\r
513 0x52,\r
514 SCAN_INSERT,\r
67319626 515 L'0',\r
516 L'0'\r
05fbd06d 517 },\r
518 {\r
519 0x53,\r
520 SCAN_DELETE,\r
67319626 521 L'.',\r
522 L'.'\r
05fbd06d 523 },\r
524 {\r
525 0x57,\r
526 SCAN_F11,\r
67319626 527 0x0000,\r
528 0x0000\r
05fbd06d 529 },\r
530 {\r
531 0x58,\r
532 SCAN_F12,\r
67319626 533 0x0000,\r
534 0x0000\r
05fbd06d 535 },\r
f3d1e940 536 {\r
537 0x5B, //Left LOGO\r
538 SCAN_NULL,\r
67319626 539 0x0000,\r
540 0x0000\r
f3d1e940 541 }, \r
542 {\r
543 0x5C, //Right LOGO\r
544 SCAN_NULL,\r
67319626 545 0x0000,\r
546 0x0000\r
f3d1e940 547 }, \r
548 {\r
549 0x5D, //Menu key\r
550 SCAN_NULL,\r
67319626 551 0x0000,\r
552 0x0000\r
f3d1e940 553 }, \r
05fbd06d 554 {\r
555 TABLE_END,\r
556 TABLE_END,\r
557 SCAN_NULL,\r
558 SCAN_NULL\r
559 },\r
560};\r
561\r
562\r
563//\r
564// The WaitForValue time out\r
565//\r
819d1488 566UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
05fbd06d 567\r
4fd730b3 568BOOLEAN mEnableMouseInterface;\r
569\r
9f6531d1 570//\r
571// Function declarations\r
572//\r
573UINT8\r
574KeyReadDataRegister (\r
575 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
576 );\r
577\r
578VOID\r
579KeyWriteDataRegister (\r
580 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
581 IN UINT8 Data\r
582 );\r
583\r
584VOID\r
585KeyWriteCommandRegister (\r
586 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
587 IN UINT8 Data\r
588 );\r
589\r
590VOID\r
591KeyboardError (\r
592 IN KEYBOARD_CONSOLE_IN_DEV*ConsoleIn,\r
593 IN CHAR16 *ErrMsg // should be a unicode string\r
594 );\r
595\r
596EFI_STATUS\r
597GetScancodeBufHead (\r
598 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
599 IN UINT32 Count,\r
600 OUT UINT8 *Buf\r
601 );\r
602\r
603EFI_STATUS\r
604PopScancodeBufHead (\r
605 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
606 IN UINT32 Count,\r
607 OUT UINT8 *Buf\r
608 );\r
609\r
610EFI_STATUS\r
611KeyboardWrite (\r
612 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
613 IN UINT8 Data\r
614 );\r
615\r
616EFI_STATUS\r
617KeyboardCommand (\r
618 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
619 IN UINT8 Data\r
620 );\r
621\r
622EFI_STATUS\r
623KeyboardWaitForValue (\r
624 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
625 IN UINT8 Value\r
626 );\r
627\r
bcd70414 628/**\r
629 Read data register \r
630\r
631 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
632\r
633 @return return the value \r
634\r
635**/\r
05fbd06d 636UINT8\r
637KeyReadDataRegister (\r
638 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
639 )\r
05fbd06d 640\r
05fbd06d 641{\r
642 EFI_ISA_IO_PROTOCOL *IsaIo;\r
643 UINT8 Data;\r
644\r
645 //\r
646 // Use IsaIo protocol to perform IO operations\r
647 //\r
648 IsaIo = ConsoleIn->IsaIo;\r
649\r
650 IsaIo->Io.Read (\r
651 IsaIo,\r
652 EfiIsaIoWidthUint8,\r
653 ConsoleIn->DataRegisterAddress,\r
654 1,\r
655 &Data\r
656 );\r
657\r
658 return Data;\r
659}\r
660\r
bcd70414 661/**\r
662 Write data register\r
663\r
664 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
665 @param Data value wanted to be written\r
666\r
667**/\r
05fbd06d 668VOID\r
669KeyWriteDataRegister (\r
670 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
671 IN UINT8 Data\r
672 )\r
05fbd06d 673\r
05fbd06d 674{\r
675 EFI_ISA_IO_PROTOCOL *IsaIo;\r
676\r
677 //\r
678 // Use IsaIo protocol to perform IO operations\r
679 //\r
680 IsaIo = ConsoleIn->IsaIo;\r
681\r
682 IsaIo->Io.Write (\r
683 IsaIo,\r
684 EfiIsaIoWidthUint8,\r
685 ConsoleIn->DataRegisterAddress,\r
686 1,\r
687 &Data\r
688 );\r
689\r
690 //\r
691 // outp(ConsoleIn->DataRegisterAddress, Data);\r
692 //\r
693}\r
694\r
bcd70414 695/**\r
696 Read status register\r
697\r
698 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
699\r
700 @return value in status register\r
701\r
702**/\r
05fbd06d 703UINT8\r
704KeyReadStatusRegister (\r
705 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
706 )\r
05fbd06d 707{\r
708 EFI_ISA_IO_PROTOCOL *IsaIo;\r
709 UINT8 Data;\r
710\r
711 //\r
712 // Use IsaIo protocol to perform IO operations\r
713 //\r
714 IsaIo = ConsoleIn->IsaIo;\r
715\r
716 IsaIo->Io.Read (\r
717 IsaIo,\r
718 EfiIsaIoWidthUint8,\r
719 ConsoleIn->StatusRegisterAddress,\r
720 1,\r
721 &Data\r
722 );\r
723\r
724 return Data;\r
725\r
726}\r
727\r
bcd70414 728/**\r
729 Write command register \r
730\r
731 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
732 @param Data The value wanted to be written\r
733\r
734**/\r
735\r
05fbd06d 736VOID\r
737KeyWriteCommandRegister (\r
738 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
739 IN UINT8 Data\r
740 )\r
05fbd06d 741{\r
742 EFI_ISA_IO_PROTOCOL *IsaIo;\r
743\r
744 //\r
745 // Use IsaIo protocol to perform IO operations\r
746 //\r
747 IsaIo = ConsoleIn->IsaIo;\r
748\r
749 IsaIo->Io.Write (\r
750 IsaIo,\r
751 EfiIsaIoWidthUint8,\r
752 ConsoleIn->CommandRegisterAddress,\r
753 1,\r
754 &Data\r
755 );\r
756\r
757}\r
758\r
bcd70414 759/**\r
760 Display error message\r
761\r
762 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
763 @param ErrMsg Unicode string of error message\r
764 \r
765**/\r
05fbd06d 766VOID\r
767KeyboardError (\r
768 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
769 IN CHAR16 *ErrMsg\r
770 )\r
05fbd06d 771{\r
772 ConsoleIn->KeyboardErr = TRUE;\r
773\r
774 //\r
775 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");\r
776 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);\r
777 //\r
778}\r
779\r
bcd70414 780/**\r
05fbd06d 781 Timer event handler: read a series of scancodes from 8042\r
782 and put them into memory scancode buffer.\r
783 it read as much scancodes to either fill\r
784 the memory buffer or empty the keyboard buffer.\r
785 It is registered as running under TPL_NOTIFY\r
786\r
bcd70414 787 @param Event - The timer event\r
788 @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer\r
05fbd06d 789\r
bcd70414 790**/\r
791VOID\r
792EFIAPI\r
793KeyboardTimerHandler (\r
794 IN EFI_EVENT Event,\r
795 IN VOID *Context\r
796 )\r
05fbd06d 797\r
05fbd06d 798{\r
799 UINT8 Data;\r
800 EFI_TPL OldTpl;\r
801 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
802\r
803 ConsoleIn = Context;\r
804\r
805 //\r
806 // Enter critical section\r
807 //\r
808 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
809\r
810 if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {\r
811 //\r
812 // Leave critical section and return\r
813 //\r
814 gBS->RestoreTPL (OldTpl);\r
815 return ;\r
816 }\r
817 //\r
818 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that\r
819 // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
820 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
821 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
822 // Just skip the 'resend' process simply.\r
823 //\r
824\r
825 Data = 0;\r
826\r
827 //\r
828 // if there is no key present, just return\r
829 //\r
830 if ((KeyReadStatusRegister (Context) & 0x21) != 0x1) {\r
831 //\r
832 // Leave critical section and return\r
833 //\r
834 gBS->RestoreTPL (OldTpl);\r
835\r
836 return ;\r
837 }\r
838 //\r
839 // Read one byte of the scan code and store it into the memory buffer\r
840 //\r
841 if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {\r
842\r
843 Data = KeyReadDataRegister (Context);\r
844 //\r
845 // put the scancode into the memory scancode buffer\r
846 //\r
847 ConsoleIn->ScancodeBufCount++;\r
848 ConsoleIn->ScancodeBufEndPos++;\r
849 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
850 ConsoleIn->ScancodeBufEndPos = 0;\r
851 }\r
852\r
853 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;\r
854\r
855 //\r
856 // Handle Alt+Ctrl+Del Key combination\r
857 //\r
858 switch (Data) {\r
859 case SCANCODE_CTRL_MAKE:\r
860 ConsoleIn->Ctrled = TRUE;\r
861 break;\r
862\r
863 case SCANCODE_CTRL_BREAK:\r
864 ConsoleIn->Ctrled = FALSE;\r
865 break;\r
866\r
867 case SCANCODE_ALT_MAKE:\r
868 ConsoleIn->Alted = TRUE;\r
869 break;\r
870\r
871 case SCANCODE_ALT_BREAK:\r
872 ConsoleIn->Alted = FALSE;\r
873 break;\r
874 }\r
875 //\r
876 // if Alt+Ctrl+Del, Reboot the System\r
877 //\r
878 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {\r
879 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
880 }\r
881 }\r
882 //\r
883 // Leave critical section and return\r
884 //\r
885 gBS->RestoreTPL (OldTpl);\r
886\r
887 return ;\r
888}\r
889\r
bcd70414 890/**\r
891 Read several bytes from the scancode buffer without removing them.\r
892 This function is called to see if there are enough bytes of scancode\r
893 representing a single key.\r
894\r
895 @param Count - Number of bytes to be read\r
896 @param Buf - Store the results\r
897\r
898 @retval EFI_SUCCESS success to scan the keyboard code\r
899 @retval EFI_NOT_READY invalid parameter\r
900**/\r
05fbd06d 901EFI_STATUS\r
902GetScancodeBufHead (\r
903 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
904 IN UINT32 Count,\r
905 OUT UINT8 *Buf\r
906 )\r
05fbd06d 907{\r
908 UINT32 Index;\r
909 UINT32 Pos;\r
910\r
911 Index = 0;\r
912 Pos = 0;\r
913\r
914 //\r
915 // check the valid range of parameter 'Count'\r
916 //\r
917 if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {\r
918 return EFI_NOT_READY;\r
919 }\r
920 //\r
921 // retrieve the values\r
922 //\r
923 for (Index = 0; Index < Count; Index++) {\r
924\r
925 if (Index == 0) {\r
926\r
927 Pos = ConsoleIn->ScancodeBufStartPos;\r
928 } else {\r
929\r
930 Pos = Pos + 1;\r
931 if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
932 Pos = 0;\r
933 }\r
934 }\r
935\r
936 Buf[Index] = ConsoleIn->ScancodeBuf[Pos];\r
937 }\r
938\r
939 return EFI_SUCCESS;\r
940}\r
941\r
bcd70414 942/**\r
943\r
944 Read & remove several bytes from the scancode buffer.\r
945 This function is usually called after GetScancodeBufHead()\r
946\r
947 @param Count - Number of bytes to be read\r
948 @param Buf - Store the results\r
949\r
950 @retval EFI_SUCCESS success to scan the keyboard code\r
951 @retval EFI_NOT_READY invalid parameter\r
952**/\r
05fbd06d 953EFI_STATUS\r
954PopScancodeBufHead (\r
955 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
956 IN UINT32 Count,\r
957 OUT UINT8 *Buf\r
958 )\r
05fbd06d 959{\r
960 UINT32 Index;\r
961\r
962 Index = 0;\r
963\r
964 //\r
965 // Check the valid range of parameter 'Count'\r
966 //\r
967 if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {\r
968 return EFI_NOT_READY;\r
969 }\r
970 //\r
971 // Retrieve and remove the values\r
972 //\r
973 for (Index = 0; Index < Count; Index++) {\r
974\r
975 if (Index != 0) {\r
976\r
977 ConsoleIn->ScancodeBufStartPos++;\r
978 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
979 ConsoleIn->ScancodeBufStartPos = 0;\r
980 }\r
981 }\r
982\r
983 Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];\r
984 ConsoleIn->ScancodeBufCount--;\r
985 }\r
986\r
987 ConsoleIn->ScancodeBufStartPos++;\r
988 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
989 ConsoleIn->ScancodeBufStartPos = 0;\r
990 }\r
991\r
992 return EFI_SUCCESS;\r
993}\r
994\r
bcd70414 995/**\r
996 Read key value \r
997\r
998 @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
999 @param Data - Pointer to outof buffer for keeping key value\r
1000\r
1001 @retval EFI_TIMEOUT Status resigter time out\r
1002 @retval EFI_SUCCESS Success to read keyboard\r
1003\r
1004**/\r
05fbd06d 1005EFI_STATUS\r
1006KeyboardRead (\r
1007 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1008 OUT UINT8 *Data\r
1009 )\r
05fbd06d 1010\r
05fbd06d 1011{\r
1012 UINT32 TimeOut;\r
1013 UINT32 RegFilled;\r
1014\r
1015 TimeOut = 0;\r
1016 RegFilled = 0;\r
1017\r
1018 //\r
1019 // wait till output buffer full then perform the read\r
1020 //\r
1021 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1022 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
1023 RegFilled = 1;\r
1024 *Data = KeyReadDataRegister (ConsoleIn);\r
1025 break;\r
1026 }\r
1027\r
1028 gBS->Stall (30);\r
1029 }\r
1030\r
1031 if (!RegFilled) {\r
1032 return EFI_TIMEOUT;\r
1033 }\r
1034\r
1035 return EFI_SUCCESS;\r
1036}\r
1037\r
bcd70414 1038/**\r
1039 write key to keyboard\r
1040\r
1041 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1042 @param Data value wanted to be written\r
1043\r
1044 @retval EFI_TIMEOUT - GC_TODO: Add description for return value\r
1045 @retval EFI_SUCCESS - GC_TODO: Add description for return value\r
1046\r
1047**/\r
05fbd06d 1048EFI_STATUS\r
1049KeyboardWrite (\r
1050 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1051 IN UINT8 Data\r
1052 )\r
05fbd06d 1053{\r
1054 UINT32 TimeOut;\r
1055 UINT32 RegEmptied;\r
1056\r
1057 TimeOut = 0;\r
1058 RegEmptied = 0;\r
1059\r
1060 //\r
1061 // wait for input buffer empty\r
1062 //\r
1063 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1064 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1065 RegEmptied = 1;\r
1066 break;\r
1067 }\r
1068\r
1069 gBS->Stall (30);\r
1070 }\r
1071\r
1072 if (!RegEmptied) {\r
1073 return EFI_TIMEOUT;\r
1074 }\r
1075 //\r
1076 // Write it\r
1077 //\r
1078 KeyWriteDataRegister (ConsoleIn, Data);\r
1079\r
1080 return EFI_SUCCESS;\r
1081}\r
1082\r
bcd70414 1083/**\r
1084 Issue keyboard command\r
1085\r
1086 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1087 @param Data The buff holding the command \r
1088\r
1089 @retval EFI_TIMEOUT Keyboard is not ready to issuing \r
1090 @retval EFI_SUCCESS Success to issue keyboard command\r
1091\r
1092**/\r
05fbd06d 1093EFI_STATUS\r
1094KeyboardCommand (\r
1095 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1096 IN UINT8 Data\r
1097 )\r
05fbd06d 1098{\r
1099 UINT32 TimeOut;\r
1100 UINT32 RegEmptied;\r
1101\r
1102 TimeOut = 0;\r
1103 RegEmptied = 0;\r
1104\r
1105 //\r
1106 // Wait For Input Buffer Empty\r
1107 //\r
1108 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1109 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1110 RegEmptied = 1;\r
1111 break;\r
1112 }\r
1113\r
1114 gBS->Stall (30);\r
1115 }\r
1116\r
1117 if (!RegEmptied) {\r
1118 return EFI_TIMEOUT;\r
1119 }\r
1120 //\r
1121 // issue the command\r
1122 //\r
1123 KeyWriteCommandRegister (ConsoleIn, Data);\r
1124\r
1125 //\r
1126 // Wait For Input Buffer Empty again\r
1127 //\r
1128 RegEmptied = 0;\r
1129 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1130 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1131 RegEmptied = 1;\r
1132 break;\r
1133 }\r
1134\r
1135 gBS->Stall (30);\r
1136 }\r
1137\r
1138 if (!RegEmptied) {\r
1139 return EFI_TIMEOUT;\r
1140 }\r
1141\r
1142 return EFI_SUCCESS;\r
1143}\r
1144\r
bcd70414 1145/**\r
1146 wait for a specific value to be presented on\r
1147 8042 Data register by keyboard and then read it,\r
1148 used in keyboard commands ack\r
1149\r
1150 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1151 @param Value the value wanted to be waited.\r
1152\r
1153 @retval EFI_TIMEOUT Fail to get specific value in given time\r
1154 @retval EFI_SUCCESS Success to get specific value in given time.\r
1155 \r
1156**/\r
05fbd06d 1157EFI_STATUS\r
1158KeyboardWaitForValue (\r
1159 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1160 IN UINT8 Value\r
1161 )\r
05fbd06d 1162{\r
1163 UINT8 Data;\r
1164 UINT32 TimeOut;\r
1165 UINT32 SumTimeOut;\r
1166 UINT32 GotIt;\r
1167\r
1168 GotIt = 0;\r
1169 TimeOut = 0;\r
1170 SumTimeOut = 0;\r
1171\r
1172 //\r
1173 // Make sure the initial value of 'Data' is different from 'Value'\r
1174 //\r
1175 Data = 0;\r
1176 if (Data == Value) {\r
1177 Data = 1;\r
1178 }\r
1179 //\r
1180 // Read from 8042 (multiple times if needed)\r
1181 // until the expected value appears\r
1182 // use SumTimeOut to control the iteration\r
1183 //\r
1184 while (1) {\r
1185 //\r
1186 // Perform a read\r
1187 //\r
1188 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1189 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
1190 Data = KeyReadDataRegister (ConsoleIn);\r
1191 break;\r
1192 }\r
1193\r
1194 gBS->Stall (30);\r
1195 }\r
1196\r
1197 SumTimeOut += TimeOut;\r
1198\r
1199 if (Data == Value) {\r
1200 GotIt = 1;\r
1201 break;\r
1202 }\r
1203\r
1204 if (SumTimeOut >= mWaitForValueTimeOut) {\r
1205 break;\r
1206 }\r
1207 }\r
1208 //\r
1209 // Check results\r
1210 //\r
1211 if (GotIt) {\r
1212 return EFI_SUCCESS;\r
1213 } else {\r
1214 return EFI_TIMEOUT;\r
1215 }\r
1216\r
1217}\r
1218\r
bcd70414 1219/**\r
05fbd06d 1220 Show keyboard status lights according to\r
1221 indicators in ConsoleIn.\r
1222\r
bcd70414 1223 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV\r
1224 \r
1225 @return status\r
05fbd06d 1226\r
bcd70414 1227**/\r
1228EFI_STATUS\r
1229UpdateStatusLights (\r
1230 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1231 )\r
05fbd06d 1232{\r
1233 EFI_STATUS Status;\r
1234 UINT8 Command;\r
1235\r
1236 //\r
1237 // Send keyboard command\r
1238 //\r
1239 Status = KeyboardWrite (ConsoleIn, 0xed);\r
1240 if (EFI_ERROR (Status)) {\r
1241 return Status;\r
1242 }\r
1243\r
1244 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1245\r
1246 //\r
1247 // Light configuration\r
1248 //\r
1249 Command = 0;\r
1250 if (ConsoleIn->CapsLock) {\r
1251 Command |= 4;\r
1252 }\r
1253\r
1254 if (ConsoleIn->NumLock) {\r
1255 Command |= 2;\r
1256 }\r
1257\r
1258 if (ConsoleIn->ScrollLock) {\r
1259 Command |= 1;\r
1260 }\r
1261\r
1262 Status = KeyboardWrite (ConsoleIn, Command);\r
1263\r
1264 if (EFI_ERROR (Status)) {\r
1265 return Status;\r
1266 }\r
1267\r
1268 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1269 return Status;\r
1270}\r
1271\r
bcd70414 1272/**\r
05fbd06d 1273 Get scancode from scancode buffer\r
1274 and translate into EFI-scancode and unicode defined by EFI spec\r
1275 The function is always called in TPL_NOTIFY\r
1276\r
bcd70414 1277 @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer\r
05fbd06d 1278\r
bcd70414 1279 @retval EFI_NOT_READY - Input from console not ready yet.\r
1280 @retval EFI_SUCCESS - Function executed successfully.\r
05fbd06d 1281\r
bcd70414 1282**/\r
1283EFI_STATUS\r
1284KeyGetchar (\r
1285 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1286 )\r
05fbd06d 1287{\r
1288 EFI_STATUS Status;\r
1289 UINT8 ScanCode;\r
1290 UINT8 Readed;\r
1291 BOOLEAN Extended;\r
1292 UINT8 ScancodeArr[4];\r
1293 UINTN Index;\r
1294 //\r
1295 // 4 bytes most\r
1296 //\r
1297 UINT32 ScancodeArrPos;\r
1298 //\r
1299 // point to the current position in ScancodeArr\r
1300 //\r
1301\r
1302 Readed = 0;\r
1303 Extended = FALSE;\r
1304 ScancodeArrPos = 0;\r
1305\r
1306 //\r
1307 // Read one byte of the scan code and store it into the memory buffer\r
1308 // This block of code is added to insert an action that is equivalent to\r
1309 // the timer event handling function, so as to increase the frequency of\r
1310 // detecting the availability of keys. Timer event has a max frequency of\r
1311 // 18Hz which is insufficient\r
1312 //\r
1313 //\r
1314 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that\r
1315 // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
1316 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
1317 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
1318 // Just skip the 'resend' process simply.\r
1319 //\r
1320\r
1321\r
1322 if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {\r
1323\r
1324 Readed = KeyReadDataRegister (ConsoleIn);\r
1325 //\r
1326 // put the scancode into the memory scancode buffer\r
1327 //\r
1328 ConsoleIn->ScancodeBufCount++;\r
1329 ConsoleIn->ScancodeBufEndPos++;\r
1330 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
1331 ConsoleIn->ScancodeBufEndPos = 0;\r
1332 }\r
1333\r
1334 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;\r
1335\r
1336 //\r
1337 // Handle Alt+Ctrl+Del Key combination\r
1338 //\r
1339 switch (Readed) {\r
1340\r
1341 case SCANCODE_CTRL_MAKE:\r
1342 ConsoleIn->Ctrled = TRUE;\r
1343 break;\r
1344\r
1345 case SCANCODE_CTRL_BREAK:\r
1346 ConsoleIn->Ctrled = FALSE;\r
1347 break;\r
1348\r
1349 case SCANCODE_ALT_MAKE:\r
1350 ConsoleIn->Alted = TRUE;\r
1351 break;\r
1352\r
1353 case SCANCODE_ALT_BREAK:\r
1354 ConsoleIn->Alted = FALSE;\r
1355 break;\r
1356 }\r
1357 //\r
1358 // if Alt+Ctrl+Del, Reboot the System\r
1359 //\r
1360 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {\r
1361 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1362 }\r
1363 }\r
1364 //\r
1365 // Check if there are enough bytes of scancode representing a single key\r
1366 // available in the buffer\r
1367 //\r
1368 while (1) {\r
1369\r
1370 Status = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);\r
1371 ScancodeArrPos = 0;\r
1372 if (EFI_ERROR (Status)) {\r
1373 return EFI_NOT_READY;\r
1374 }\r
1375\r
1376 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
1377 Extended = TRUE;\r
1378 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
1379 ScancodeArrPos = 1;\r
1380 if (EFI_ERROR (Status)) {\r
1381 return EFI_NOT_READY;\r
1382 }\r
1383 }\r
1384 //\r
1385 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5\r
1386 // if present, ignore them\r
1387 //\r
1388 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
1389\r
1390 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
1391 ScancodeArrPos = 1;\r
1392\r
1393 if (EFI_ERROR (Status)) {\r
1394 return EFI_NOT_READY;\r
1395 }\r
1396\r
1397 Status = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
1398 ScancodeArrPos = 2;\r
1399\r
1400 if (EFI_ERROR (Status)) {\r
1401 return EFI_NOT_READY;\r
1402 }\r
1403\r
1404 PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
1405 return EFI_NOT_READY;\r
1406 }\r
1407 //\r
1408 // if we reach this position, scancodes for a key is in buffer now,pop them\r
1409 //\r
1410 Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);\r
1411 if (EFI_ERROR (Status)) {\r
1412 return EFI_NOT_READY;\r
1413 }\r
1414 //\r
1415 // store the last available byte, this byte of scancode will be checked\r
1416 //\r
1417 ScanCode = ScancodeArr[ScancodeArrPos];\r
1418\r
1419 //\r
1420 // Check for special keys and update the driver state.\r
1421 //\r
1422 switch (ScanCode) {\r
1423\r
1424 case SCANCODE_CTRL_MAKE:\r
1425 ConsoleIn->Ctrl = TRUE;\r
1426 break;\r
1427\r
1428 case SCANCODE_CTRL_BREAK:\r
1429 ConsoleIn->Ctrl = FALSE;\r
1430 break;\r
1431\r
1432 case SCANCODE_ALT_MAKE:\r
1433 ConsoleIn->Alt = TRUE;\r
1434 break;\r
1435\r
1436 case SCANCODE_ALT_BREAK:\r
1437 ConsoleIn->Alt = FALSE;\r
1438 break;\r
1439\r
1440 case SCANCODE_LEFT_SHIFT_MAKE:\r
f3d1e940 1441 if (!Extended) {\r
1442 ConsoleIn->Shift = TRUE;\r
1443 ConsoleIn->LeftShift = TRUE;\r
1444 } \r
1445 break;\r
05fbd06d 1446 case SCANCODE_RIGHT_SHIFT_MAKE:\r
1447 if (!Extended) {\r
1448 ConsoleIn->Shift = TRUE;\r
f3d1e940 1449 ConsoleIn->RightShift = TRUE;\r
05fbd06d 1450 }\r
1451 break;\r
1452\r
1453 case SCANCODE_LEFT_SHIFT_BREAK:\r
f3d1e940 1454 if (!Extended) {\r
1455 ConsoleIn->Shift = FALSE;\r
1456 ConsoleIn->LeftShift = FALSE;\r
1457 } else {\r
1458 ConsoleIn->SysReq = FALSE;\r
1459 } \r
1460 break;\r
05fbd06d 1461 case SCANCODE_RIGHT_SHIFT_BREAK:\r
1462 if (!Extended) {\r
1463 ConsoleIn->Shift = FALSE;\r
f3d1e940 1464 ConsoleIn->RightShift = FALSE;\r
05fbd06d 1465 }\r
1466 break;\r
1467\r
f3d1e940 1468 case SCANCODE_LEFT_LOGO_MAKE:\r
1469 ConsoleIn->LeftLogo = TRUE;\r
1470 break; \r
1471 case SCANCODE_LEFT_LOGO_BREAK:\r
1472 ConsoleIn->LeftLogo = FALSE;\r
1473 break; \r
1474 case SCANCODE_RIGHT_LOGO_MAKE:\r
1475 ConsoleIn->RightLogo = TRUE;\r
1476 break;\r
1477 case SCANCODE_RIGHT_LOGO_BREAK:\r
1478 ConsoleIn->RightLogo = FALSE;\r
1479 break; \r
1480 case SCANCODE_MENU_MAKE:\r
1481 ConsoleIn->Menu = TRUE;\r
1482 break;\r
1483 case SCANCODE_MENU_BREAK:\r
1484 ConsoleIn->Menu = FALSE;\r
1485 break; \r
1486 case SCANCODE_SYS_REQ_MAKE:\r
1487 if (Extended) {\r
1488 ConsoleIn->SysReq = TRUE;\r
1489 }\r
05fbd06d 1490 case SCANCODE_CAPS_LOCK_MAKE:\r
1491 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;\r
1492 UpdateStatusLights (ConsoleIn);\r
1493 break;\r
1494\r
1495 case SCANCODE_NUM_LOCK_MAKE:\r
1496 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;\r
1497 UpdateStatusLights (ConsoleIn);\r
1498 break;\r
1499\r
1500 case SCANCODE_SCROLL_LOCK_MAKE:\r
1501 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;\r
1502 UpdateStatusLights (ConsoleIn);\r
1503 break;\r
1504 }\r
1505 //\r
1506 // If this is a BREAK Key or above the valid range, ignore it\r
1507 //\r
1508 if (ScanCode >= SCANCODE_MAX_MAKE) {\r
1509 continue;\r
1510 } else {\r
1511 break;\r
1512 }\r
1513 }\r
1514 //\r
05fbd06d 1515 // Treat Numeric Key Pad "/" specially\r
1516 //\r
1517 if (Extended && ScanCode == 0x35) {\r
1518 ConsoleIn->Key.ScanCode = SCAN_NULL;\r
1519 ConsoleIn->Key.UnicodeChar = '/';\r
1520 return EFI_SUCCESS;\r
1521 }\r
1522 //\r
1523 // Convert Keyboard ScanCode into an EFI Key\r
1524 //\r
1525 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\r
1526 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {\r
1527 ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;\r
1528 if (ConsoleIn->Shift) {\r
1529 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
f3d1e940 1530 //\r
1531 // Need not return associated shift state if a class of printable characters that\r
1532 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
1533 //\r
1534 if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1535 ConsoleIn->LeftShift = FALSE;\r
1536 ConsoleIn->RightShift = FALSE;\r
1537 }\r
05fbd06d 1538 } else {\r
1539 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
1540 }\r
1541 //\r
1542 // alphabetic key is affected by CapsLock State\r
1543 //\r
1544 if (ConsoleIn->CapsLock) {\r
1545 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {\r
1546 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
1547 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1548 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
1549 }\r
1550 }\r
1f771698 1551 //\r
1552 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
1553 //\r
1554 if (ConsoleIn->Ctrled) {\r
1555 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {\r
1556 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'a' + 1);\r
1557 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1558 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'A' + 1);\r
1559 }\r
1560 }\r
05fbd06d 1561\r
1562 break;\r
1563 }\r
1564 }\r
1565\r
1566 //\r
1567 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
1568 //\r
1569 if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
1570\r
1571 if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
1572 ConsoleIn->Key.ScanCode = SCAN_NULL;\r
1573 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
1574 ConsoleIn->Key.UnicodeChar = 0x00;\r
1575 }\r
1576 }\r
1577 //\r
1578 // If the key can not be converted then just return.\r
1579 //\r
1580 if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {\r
1581 return EFI_NOT_READY;\r
1582 }\r
1583\r
f3d1e940 1584 //\r
1585 // Save the Shift/Toggle state\r
1586 //\r
1587 if (ConsoleIn->Ctrl) {\r
1588 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
1589 } \r
1590 if (ConsoleIn->Alt) { \r
1591 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
1592 } \r
1593 if (ConsoleIn->LeftShift) { \r
1594 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
1595 } \r
1596 if (ConsoleIn->RightShift) { \r
1597 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
1598 } \r
1599 if (ConsoleIn->LeftLogo) { \r
1600 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
1601 } \r
1602 if (ConsoleIn->RightLogo) { \r
1603 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
1604 } \r
1605 if (ConsoleIn->Menu) { \r
1606 ConsoleIn->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
1607 } \r
1608 if (ConsoleIn->SysReq) { \r
1609 ConsoleIn->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
1610 } \r
1611 if (ConsoleIn->CapsLock) {\r
1612 ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
1613 }\r
1614 if (ConsoleIn->NumLock) {\r
1615 ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
1616 }\r
1617 if (ConsoleIn->ScrollLock) {\r
1618 ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
1619 }\r
1620\r
05fbd06d 1621 return EFI_SUCCESS;\r
1622}\r
1623\r
bcd70414 1624/**\r
05fbd06d 1625 Perform 8042 controller and keyboard Initialization\r
1626 If ExtendedVerification is TRUE, do additional test for\r
1627 the keyboard interface\r
1628\r
bcd70414 1629 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer\r
1630 @param ExtendedVerification - indicates a thorough initialization\r
05fbd06d 1631\r
bcd70414 1632 @retval EFI_DEVICE_ERROR Fail to init keyboard\r
1633 @retval EFI_SUCCESS Success to init keyboard\r
1634**/\r
1635EFI_STATUS\r
1636InitKeyboard (\r
1637 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1638 IN BOOLEAN ExtendedVerification\r
1639 )\r
05fbd06d 1640{\r
1641 EFI_STATUS Status;\r
1642 EFI_STATUS Status1;\r
1643 UINT8 CommandByte;\r
05fbd06d 1644 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;\r
05f89b17 1645 UINT32 TryTime;\r
05fbd06d 1646\r
05f89b17 1647 Status = EFI_SUCCESS;\r
4fd730b3 1648 mEnableMouseInterface = TRUE;\r
05f89b17 1649 TryTime = 0;\r
05fbd06d 1650\r
1651 //\r
1652 // Get Ps2 policy to set this\r
1653 //\r
05f89b17
LG
1654 gBS->LocateProtocol (\r
1655 &gEfiPs2PolicyProtocolGuid,\r
1656 NULL,\r
1657 (VOID **) &Ps2Policy\r
1658 );\r
05fbd06d 1659\r
1660 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1661 EFI_PROGRESS_CODE,\r
1662 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,\r
1663 ConsoleIn->DevicePath\r
1664 );\r
1665\r
1666 //\r
1667 // Perform a read to cleanup the Status Register's\r
05f89b17 1668 // output buffer full bits within MAX TRY times\r
05fbd06d 1669 //\r
05f89b17 1670 while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {\r
05fbd06d 1671 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
05f89b17
LG
1672 TryTime ++;\r
1673 }\r
1674 //\r
1675 // Exceed the max try times. The device may be error.\r
1676 //\r
1677 if (TryTime == KEYBOARD_MAX_TRY) {\r
1678 Status = EFI_DEVICE_ERROR;\r
1679 goto Done;\r
05fbd06d 1680 }\r
1681 //\r
1682 // We should disable mouse interface during the initialization process\r
1683 // since mouse device output could block keyboard device output in the\r
1684 // 60H port of 8042 controller.\r
1685 //\r
1686 // So if we are not initializing 8042 controller for the\r
1687 // first time, we have to remember the previous mouse interface\r
1688 // enabling state\r
1689 //\r
1690 // Test the system flag in to determine whether this is the first\r
1691 // time initialization\r
1692 //\r
1693 if ((KeyReadStatusRegister (ConsoleIn) & 0x04)) {\r
1694 //\r
1695 // 8042 controller is already setup (by myself or by mouse driver):\r
1696 // See whether mouse interface is already enabled\r
1697 // which determines whether we should enable it later\r
1698 //\r
1699 //\r
1700 // Read the command byte of 8042 controller\r
1701 //\r
1702 Status = KeyboardCommand (ConsoleIn, 0x20);\r
1703 if (EFI_ERROR (Status)) {\r
1704 KeyboardError (ConsoleIn, L"\n\r");\r
1705 goto Done;\r
1706 }\r
1707\r
1708 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
1709 if (EFI_ERROR (Status)) {\r
1710 KeyboardError (ConsoleIn, L"\n\r");\r
1711 goto Done;\r
1712 }\r
1713 //\r
1714 // Test the mouse enabling bit\r
1715 //\r
1716 if (CommandByte & 0x20) {\r
4fd730b3 1717 mEnableMouseInterface = FALSE;\r
05fbd06d 1718 } else {\r
4fd730b3 1719 mEnableMouseInterface = TRUE;\r
05fbd06d 1720 }\r
1721\r
1722 } else {\r
1723 //\r
1724 // 8042 controller is not setup yet:\r
1725 // 8042 controller selftest;\r
1726 // Don't enable mouse interface later.\r
1727 //\r
1728 //\r
1729 // Disable keyboard and mouse interfaces\r
1730 //\r
1731 Status = KeyboardCommand (ConsoleIn, 0xad);\r
1732 if (EFI_ERROR (Status)) {\r
1733 KeyboardError (ConsoleIn, L"\n\r");\r
1734 goto Done;\r
1735 }\r
1736\r
1737 Status = KeyboardCommand (ConsoleIn, 0xa7);\r
1738 if (EFI_ERROR (Status)) {\r
1739 KeyboardError (ConsoleIn, L"\n\r");\r
1740 goto Done;\r
1741 }\r
1742\r
1743 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1744 EFI_PROGRESS_CODE,\r
1745 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
1746 ConsoleIn->DevicePath\r
1747 );\r
1748 //\r
1749 // 8042 Controller Self Test\r
1750 //\r
1751 Status = KeyboardCommand (ConsoleIn, 0xaa);\r
1752 if (EFI_ERROR (Status)) {\r
1753 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1754 goto Done;\r
1755 }\r
1756\r
1757 Status = KeyboardWaitForValue (ConsoleIn, 0x55);\r
1758 if (EFI_ERROR (Status)) {\r
1759 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");\r
1760 goto Done;\r
1761 }\r
1762 //\r
1763 // Don't enable mouse interface later\r
1764 //\r
4fd730b3 1765 mEnableMouseInterface = FALSE;\r
05fbd06d 1766\r
1767 }\r
1768\r
1769 if (Ps2Policy != NULL) {\r
1770 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);\r
1771 }\r
1772 //\r
1773 // Write 8042 Command Byte, set System Flag\r
1774 // While at the same time:\r
1775 // 1. disable mouse interface,\r
1776 // 2. enable kbd interface,\r
1777 // 3. enable PC/XT kbd translation mode\r
1778 // 4. enable mouse and kbd interrupts\r
1779 //\r
1780 // ( Command Byte bits:\r
1781 // 7: Reserved\r
1782 // 6: PC/XT translation mode\r
1783 // 5: Disable Auxiliary device interface\r
1784 // 4: Disable keyboard interface\r
1785 // 3: Reserved\r
1786 // 2: System Flag\r
1787 // 1: Enable Auxiliary device interrupt\r
1788 // 0: Enable Keyboard interrupt )\r
1789 //\r
1790 Status = KeyboardCommand (ConsoleIn, 0x60);\r
1791 if (EFI_ERROR (Status)) {\r
1792 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1793 goto Done;\r
1794 }\r
1795\r
1796 Status = KeyboardWrite (ConsoleIn, 0x67);\r
1797 if (EFI_ERROR (Status)) {\r
1798 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1799 goto Done;\r
1800 }\r
1801\r
1802 //\r
1803 // Clear Memory Scancode Buffer\r
1804 //\r
1805 ConsoleIn->ScancodeBufStartPos = 0;\r
1806 ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1;\r
1807 ConsoleIn->ScancodeBufCount = 0;\r
1808 ConsoleIn->Ctrled = FALSE;\r
1809 ConsoleIn->Alted = FALSE;\r
1810\r
1811 //\r
1812 // Reset the status indicators\r
1813 //\r
1814 ConsoleIn->Ctrl = FALSE;\r
1815 ConsoleIn->Alt = FALSE;\r
1816 ConsoleIn->Shift = FALSE;\r
1817 ConsoleIn->CapsLock = FALSE;\r
1818 ConsoleIn->NumLock = FALSE;\r
1819 ConsoleIn->ScrollLock = FALSE;\r
f3d1e940 1820 ConsoleIn->LeftShift = FALSE;\r
1821 ConsoleIn->RightShift = FALSE;\r
1822 ConsoleIn->LeftLogo = FALSE;\r
1823 ConsoleIn->RightLogo = FALSE;\r
1824 ConsoleIn->Menu = FALSE;\r
1825 ConsoleIn->SysReq = FALSE; \r
05fbd06d 1826\r
1827 //\r
1828 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
1829 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected\r
1830 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,\r
1831 // and normally during booting an OS, it's skipped.\r
1832 //\r
1833 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {\r
1834 //\r
1835 // Additional verifications for keyboard interface\r
1836 //\r
1837 //\r
1838 // Keyboard Interface Test\r
1839 //\r
1840 Status = KeyboardCommand (ConsoleIn, 0xab);\r
1841 if (EFI_ERROR (Status)) {\r
1842 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1843 goto Done;\r
1844 }\r
1845\r
1846 Status = KeyboardWaitForValue (ConsoleIn, 0x00);\r
1847 if (EFI_ERROR (Status)) {\r
1848 KeyboardError (\r
1849 ConsoleIn,\r
1850 L"Some specific value not aquired from 8042 controller!\n\r"\r
1851 );\r
1852 goto Done;\r
1853 }\r
1854 //\r
1855 // Keyboard reset with a BAT(Basic Assurance Test)\r
1856 //\r
1857 Status = KeyboardWrite (ConsoleIn, 0xff);\r
1858 if (EFI_ERROR (Status)) {\r
1859 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1860 goto Done;\r
1861 }\r
1862\r
1863 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1864 if (EFI_ERROR (Status)) {\r
1865 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1866 goto Done;\r
1867 }\r
1868 //\r
1869 // wait for BAT completion code\r
1870 //\r
1871 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;\r
1872\r
1873 Status = KeyboardWaitForValue (ConsoleIn, 0xaa);\r
1874 if (EFI_ERROR (Status)) {\r
1875 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");\r
1876 goto Done;\r
1877 }\r
1878\r
1879 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
1880\r
1881 //\r
1882 // Set Keyboard to use Scan Code Set 2\r
1883 //\r
1884 Status = KeyboardWrite (ConsoleIn, 0xf0);\r
1885 if (EFI_ERROR (Status)) {\r
1886 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1887 goto Done;\r
1888 }\r
1889\r
1890 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1891 if (EFI_ERROR (Status)) {\r
1892 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1893 goto Done;\r
1894 }\r
1895\r
1896 Status = KeyboardWrite (ConsoleIn, 0x02);\r
1897 if (EFI_ERROR (Status)) {\r
1898 KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");\r
1899 goto Done;\r
1900 }\r
1901\r
1902 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1903 if (EFI_ERROR (Status)) {\r
1904 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1905 goto Done;\r
1906 }\r
1907\r
1908 //\r
1909 // Clear Keyboard Scancode Buffer\r
1910 //\r
1911 Status = KeyboardWrite (ConsoleIn, 0xf4);\r
1912 if (EFI_ERROR (Status)) {\r
1913 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1914 goto Done;\r
1915 }\r
1916\r
1917 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1918 if (EFI_ERROR (Status)) {\r
1919 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1920 goto Done;\r
1921 }\r
1922 //\r
1923 if (Ps2Policy != NULL) {\r
1924 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {\r
1925 ConsoleIn->CapsLock = TRUE;\r
1926 }\r
1927\r
1928 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {\r
1929 ConsoleIn->NumLock = TRUE;\r
1930 }\r
1931\r
1932 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {\r
1933 ConsoleIn->ScrollLock = TRUE;\r
1934 }\r
1935 }\r
1936 //\r
1937 // Update Keyboard Lights\r
1938 //\r
1939 Status = UpdateStatusLights (ConsoleIn);\r
1940 if (EFI_ERROR (Status)) {\r
1941 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");\r
1942 goto Done;\r
1943 }\r
1944 }\r
1945 //\r
1946 // At last, we can now enable the mouse interface if appropriate\r
1947 //\r
1948Done:\r
1949\r
4fd730b3 1950 if (mEnableMouseInterface) {\r
05fbd06d 1951 //\r
1952 // Enable mouse interface\r
1953 //\r
1954 Status1 = KeyboardCommand (ConsoleIn, 0xa8);\r
1955 if (EFI_ERROR (Status1)) {\r
1956 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1957 return EFI_DEVICE_ERROR;\r
1958 }\r
1959 }\r
1960\r
1961 if (!EFI_ERROR (Status)) {\r
1962 return EFI_SUCCESS;\r
1963 } else {\r
1964 return EFI_DEVICE_ERROR;\r
1965 }\r
1966\r
1967}\r
1968\r
bcd70414 1969/**\r
05fbd06d 1970 Disable the keyboard interface of the 8042 controller\r
1971\r
bcd70414 1972 @param ConsoleIn - the device instance\r
05fbd06d 1973\r
bcd70414 1974 @return status of issuing disable command\r
05fbd06d 1975\r
bcd70414 1976**/\r
1977EFI_STATUS\r
1978DisableKeyboard (\r
1979 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1980 )\r
05fbd06d 1981{\r
1982 EFI_STATUS Status;\r
1983\r
1984 //\r
1985 // Disable keyboard interface\r
1986 //\r
1987 Status = KeyboardCommand (ConsoleIn, 0xad);\r
1988 if (EFI_ERROR (Status)) {\r
1989 KeyboardError (ConsoleIn, L"\n\r");\r
1990 return EFI_DEVICE_ERROR;\r
1991 }\r
1992\r
1993 return Status;\r
1994}\r
1995\r
1996/**\r
1997 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
1998 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
1999 should not be in system.\r
2000\r
fdb05fa3 2001 @param[in] ConsoleIn Keyboard Private Data Structure\r
05fbd06d 2002\r
f3d1e940 2003 @retval TRUE Keyboard in System.\r
2004 @retval FALSE Keyboard not in System.\r
05fbd06d 2005**/\r
2006BOOLEAN\r
2007EFIAPI\r
2008CheckKeyboardConnect (\r
2009 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
2010 )\r
2011{\r
2012 EFI_STATUS Status;\r
2013 UINTN WaitForValueTimeOutBcakup;\r
2014\r
2015 Status = EFI_SUCCESS;\r
2016 //\r
2017 // enable keyboard itself and wait for its ack\r
2018 // If can't receive ack, Keyboard should not be connected.\r
2019 //\r
2020 Status = KeyboardWrite (\r
2021 ConsoleIn,\r
2022 KEYBOARD_KBEN\r
2023 );\r
2024\r
2025 if (EFI_ERROR (Status)) {\r
2026 return FALSE;\r
2027 }\r
2028 //\r
2029 // wait for 1s\r
2030 //\r
2031 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;\r
2032 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
2033 Status = KeyboardWaitForValue (\r
2034 ConsoleIn,\r
2035 KEYBOARD_CMDECHO_ACK\r
2036 );\r
2037 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;\r
2038\r
2039 if (EFI_ERROR (Status)) {\r
2040 return FALSE;\r
2041 }\r
2042\r
2043 return TRUE;\r
2044}\r
bcd70414 2045\r