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