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