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