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