]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
Update to support EFI_SIMPLE_INPUT_EX protocol
[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
638STATIC\r
639UINT8\r
640KeyReadDataRegister (\r
641 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
642 )\r
643/*++\r
644\r
645Routine Description:\r
646\r
647 GC_TODO: Add function description\r
648\r
649Arguments:\r
650\r
651 ConsoleIn - GC_TODO: add argument description\r
652\r
653Returns:\r
654\r
655 GC_TODO: add return values\r
656\r
657--*/\r
658{\r
659 EFI_ISA_IO_PROTOCOL *IsaIo;\r
660 UINT8 Data;\r
661\r
662 //\r
663 // Use IsaIo protocol to perform IO operations\r
664 //\r
665 IsaIo = ConsoleIn->IsaIo;\r
666\r
667 IsaIo->Io.Read (\r
668 IsaIo,\r
669 EfiIsaIoWidthUint8,\r
670 ConsoleIn->DataRegisterAddress,\r
671 1,\r
672 &Data\r
673 );\r
674\r
675 return Data;\r
676}\r
677\r
678STATIC\r
679VOID\r
680KeyWriteDataRegister (\r
681 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
682 IN UINT8 Data\r
683 )\r
684/*++\r
685\r
686Routine Description:\r
687\r
688 GC_TODO: Add function description\r
689\r
690Arguments:\r
691\r
692 ConsoleIn - GC_TODO: add argument description\r
693 Data - GC_TODO: add argument description\r
694\r
695Returns:\r
696\r
697 GC_TODO: add return values\r
698\r
699--*/\r
700{\r
701 EFI_ISA_IO_PROTOCOL *IsaIo;\r
702\r
703 //\r
704 // Use IsaIo protocol to perform IO operations\r
705 //\r
706 IsaIo = ConsoleIn->IsaIo;\r
707\r
708 IsaIo->Io.Write (\r
709 IsaIo,\r
710 EfiIsaIoWidthUint8,\r
711 ConsoleIn->DataRegisterAddress,\r
712 1,\r
713 &Data\r
714 );\r
715\r
716 //\r
717 // outp(ConsoleIn->DataRegisterAddress, Data);\r
718 //\r
719}\r
720\r
721UINT8\r
722KeyReadStatusRegister (\r
723 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
724 )\r
725/*++\r
726\r
727Routine Description:\r
728\r
729 GC_TODO: Add function description\r
730\r
731Arguments:\r
732\r
733 ConsoleIn - GC_TODO: add argument description\r
734\r
735Returns:\r
736\r
737 GC_TODO: add return values\r
738\r
739--*/\r
740{\r
741 EFI_ISA_IO_PROTOCOL *IsaIo;\r
742 UINT8 Data;\r
743\r
744 //\r
745 // Use IsaIo protocol to perform IO operations\r
746 //\r
747 IsaIo = ConsoleIn->IsaIo;\r
748\r
749 IsaIo->Io.Read (\r
750 IsaIo,\r
751 EfiIsaIoWidthUint8,\r
752 ConsoleIn->StatusRegisterAddress,\r
753 1,\r
754 &Data\r
755 );\r
756\r
757 return Data;\r
758\r
759}\r
760\r
761STATIC\r
762VOID\r
763KeyWriteCommandRegister (\r
764 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
765 IN UINT8 Data\r
766 )\r
767/*++\r
768\r
769Routine Description:\r
770\r
771 GC_TODO: Add function description\r
772\r
773Arguments:\r
774\r
775 ConsoleIn - GC_TODO: add argument description\r
776 Data - GC_TODO: add argument description\r
777\r
778Returns:\r
779\r
780 GC_TODO: add return values\r
781\r
782--*/\r
783{\r
784 EFI_ISA_IO_PROTOCOL *IsaIo;\r
785\r
786 //\r
787 // Use IsaIo protocol to perform IO operations\r
788 //\r
789 IsaIo = ConsoleIn->IsaIo;\r
790\r
791 IsaIo->Io.Write (\r
792 IsaIo,\r
793 EfiIsaIoWidthUint8,\r
794 ConsoleIn->CommandRegisterAddress,\r
795 1,\r
796 &Data\r
797 );\r
798\r
799}\r
800\r
801STATIC\r
802VOID\r
803KeyboardError (\r
804 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
805 IN CHAR16 *ErrMsg\r
806 )\r
807/*++\r
808\r
809Routine Description:\r
810\r
811 Display error message\r
812\r
813Arguments:\r
814\r
815Returns:\r
816\r
817--*/\r
818// GC_TODO: ConsoleIn - add argument and description to function comment\r
819// GC_TODO: ErrMsg - add argument and description to function comment\r
820{\r
821 ConsoleIn->KeyboardErr = TRUE;\r
822\r
823 //\r
824 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");\r
825 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);\r
826 //\r
827}\r
828\r
829VOID\r
830EFIAPI\r
831KeyboardTimerHandler (\r
832 IN EFI_EVENT Event,\r
833 IN VOID *Context\r
834 )\r
835/*++\r
836\r
837Routine Description:\r
838\r
839 Timer event handler: read a series of scancodes from 8042\r
840 and put them into memory scancode buffer.\r
841 it read as much scancodes to either fill\r
842 the memory buffer or empty the keyboard buffer.\r
843 It is registered as running under TPL_NOTIFY\r
844\r
845Arguments:\r
846\r
847 Event - The timer event\r
848 Context - A KEYBOARD_CONSOLE_IN_DEV pointer\r
849\r
850Returns:\r
851\r
852--*/\r
853{\r
854 UINT8 Data;\r
855 EFI_TPL OldTpl;\r
856 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
857\r
858 ConsoleIn = Context;\r
859\r
860 //\r
861 // Enter critical section\r
862 //\r
863 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
864\r
865 if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {\r
866 //\r
867 // Leave critical section and return\r
868 //\r
869 gBS->RestoreTPL (OldTpl);\r
870 return ;\r
871 }\r
872 //\r
873 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that\r
874 // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
875 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
876 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
877 // Just skip the 'resend' process simply.\r
878 //\r
879\r
880 Data = 0;\r
881\r
882 //\r
883 // if there is no key present, just return\r
884 //\r
885 if ((KeyReadStatusRegister (Context) & 0x21) != 0x1) {\r
886 //\r
887 // Leave critical section and return\r
888 //\r
889 gBS->RestoreTPL (OldTpl);\r
890\r
891 return ;\r
892 }\r
893 //\r
894 // Read one byte of the scan code and store it into the memory buffer\r
895 //\r
896 if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {\r
897\r
898 Data = KeyReadDataRegister (Context);\r
899 //\r
900 // put the scancode into the memory scancode buffer\r
901 //\r
902 ConsoleIn->ScancodeBufCount++;\r
903 ConsoleIn->ScancodeBufEndPos++;\r
904 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
905 ConsoleIn->ScancodeBufEndPos = 0;\r
906 }\r
907\r
908 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;\r
909\r
910 //\r
911 // Handle Alt+Ctrl+Del Key combination\r
912 //\r
913 switch (Data) {\r
914 case SCANCODE_CTRL_MAKE:\r
915 ConsoleIn->Ctrled = TRUE;\r
916 break;\r
917\r
918 case SCANCODE_CTRL_BREAK:\r
919 ConsoleIn->Ctrled = FALSE;\r
920 break;\r
921\r
922 case SCANCODE_ALT_MAKE:\r
923 ConsoleIn->Alted = TRUE;\r
924 break;\r
925\r
926 case SCANCODE_ALT_BREAK:\r
927 ConsoleIn->Alted = FALSE;\r
928 break;\r
929 }\r
930 //\r
931 // if Alt+Ctrl+Del, Reboot the System\r
932 //\r
933 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {\r
934 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
935 }\r
936 }\r
937 //\r
938 // Leave critical section and return\r
939 //\r
940 gBS->RestoreTPL (OldTpl);\r
941\r
942 return ;\r
943}\r
944\r
945STATIC\r
946EFI_STATUS\r
947GetScancodeBufHead (\r
948 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
949 IN UINT32 Count,\r
950 OUT UINT8 *Buf\r
951 )\r
952/*++\r
953\r
954Routine Description:\r
955\r
956 Read several bytes from the scancode buffer without removing them.\r
957 This function is called to see if there are enough bytes of scancode\r
958 representing a single key.\r
959\r
960Arguments:\r
961\r
962 Count - Number of bytes to be read\r
963 Buf - Store the results\r
964\r
965Returns:\r
966\r
967 EFI_STATUS\r
968\r
969--*/\r
970// GC_TODO: ConsoleIn - add argument and description to function comment\r
971// GC_TODO: EFI_NOT_READY - add return value to function comment\r
972// GC_TODO: EFI_SUCCESS - add return value to function comment\r
973{\r
974 UINT32 Index;\r
975 UINT32 Pos;\r
976\r
977 Index = 0;\r
978 Pos = 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 the values\r
988 //\r
989 for (Index = 0; Index < Count; Index++) {\r
990\r
991 if (Index == 0) {\r
992\r
993 Pos = ConsoleIn->ScancodeBufStartPos;\r
994 } else {\r
995\r
996 Pos = Pos + 1;\r
997 if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
998 Pos = 0;\r
999 }\r
1000 }\r
1001\r
1002 Buf[Index] = ConsoleIn->ScancodeBuf[Pos];\r
1003 }\r
1004\r
1005 return EFI_SUCCESS;\r
1006}\r
1007\r
1008STATIC\r
1009EFI_STATUS\r
1010PopScancodeBufHead (\r
1011 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1012 IN UINT32 Count,\r
1013 OUT UINT8 *Buf\r
1014 )\r
1015/*++\r
1016\r
1017Routine Description:\r
1018\r
1019 Read & remove several bytes from the scancode buffer.\r
1020 This function is usually called after GetScancodeBufHead()\r
1021\r
1022Arguments:\r
1023\r
1024 Count - Number of bytes to be read\r
1025 Buf - Store the results\r
1026\r
1027Returns:\r
1028\r
1029 EFI_STATUS\r
1030\r
1031--*/\r
1032// GC_TODO: ConsoleIn - add argument and description to function comment\r
1033// GC_TODO: EFI_NOT_READY - add return value to function comment\r
1034// GC_TODO: EFI_SUCCESS - add return value to function comment\r
1035{\r
1036 UINT32 Index;\r
1037\r
1038 Index = 0;\r
1039\r
1040 //\r
1041 // Check the valid range of parameter 'Count'\r
1042 //\r
1043 if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {\r
1044 return EFI_NOT_READY;\r
1045 }\r
1046 //\r
1047 // Retrieve and remove the values\r
1048 //\r
1049 for (Index = 0; Index < Count; Index++) {\r
1050\r
1051 if (Index != 0) {\r
1052\r
1053 ConsoleIn->ScancodeBufStartPos++;\r
1054 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
1055 ConsoleIn->ScancodeBufStartPos = 0;\r
1056 }\r
1057 }\r
1058\r
1059 Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];\r
1060 ConsoleIn->ScancodeBufCount--;\r
1061 }\r
1062\r
1063 ConsoleIn->ScancodeBufStartPos++;\r
1064 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
1065 ConsoleIn->ScancodeBufStartPos = 0;\r
1066 }\r
1067\r
1068 return EFI_SUCCESS;\r
1069}\r
1070\r
1071EFI_STATUS\r
1072KeyboardRead (\r
1073 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1074 OUT UINT8 *Data\r
1075 )\r
1076/*++\r
1077\r
1078Routine Description:\r
1079\r
1080 GC_TODO: Add function description\r
1081\r
1082Arguments:\r
1083\r
1084 ConsoleIn - GC_TODO: add argument description\r
1085 Data - GC_TODO: add argument description\r
1086\r
1087Returns:\r
1088\r
1089 EFI_TIMEOUT - GC_TODO: Add description for return value\r
1090 EFI_SUCCESS - GC_TODO: Add description for return value\r
1091\r
1092--*/\r
1093{\r
1094 UINT32 TimeOut;\r
1095 UINT32 RegFilled;\r
1096\r
1097 TimeOut = 0;\r
1098 RegFilled = 0;\r
1099\r
1100 //\r
1101 // wait till output buffer full then perform the read\r
1102 //\r
1103 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1104 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
1105 RegFilled = 1;\r
1106 *Data = KeyReadDataRegister (ConsoleIn);\r
1107 break;\r
1108 }\r
1109\r
1110 gBS->Stall (30);\r
1111 }\r
1112\r
1113 if (!RegFilled) {\r
1114 return EFI_TIMEOUT;\r
1115 }\r
1116\r
1117 return EFI_SUCCESS;\r
1118}\r
1119\r
1120STATIC\r
1121EFI_STATUS\r
1122KeyboardWrite (\r
1123 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1124 IN UINT8 Data\r
1125 )\r
1126/*++\r
1127\r
1128Routine Description:\r
1129\r
1130 GC_TODO: Add function description\r
1131\r
1132Arguments:\r
1133\r
1134 ConsoleIn - GC_TODO: add argument description\r
1135 Data - GC_TODO: add argument description\r
1136\r
1137Returns:\r
1138\r
1139 EFI_TIMEOUT - GC_TODO: Add description for return value\r
1140 EFI_SUCCESS - GC_TODO: Add description for return value\r
1141\r
1142--*/\r
1143{\r
1144 UINT32 TimeOut;\r
1145 UINT32 RegEmptied;\r
1146\r
1147 TimeOut = 0;\r
1148 RegEmptied = 0;\r
1149\r
1150 //\r
1151 // wait for input buffer empty\r
1152 //\r
1153 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1154 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1155 RegEmptied = 1;\r
1156 break;\r
1157 }\r
1158\r
1159 gBS->Stall (30);\r
1160 }\r
1161\r
1162 if (!RegEmptied) {\r
1163 return EFI_TIMEOUT;\r
1164 }\r
1165 //\r
1166 // Write it\r
1167 //\r
1168 KeyWriteDataRegister (ConsoleIn, Data);\r
1169\r
1170 return EFI_SUCCESS;\r
1171}\r
1172\r
1173STATIC\r
1174EFI_STATUS\r
1175KeyboardCommand (\r
1176 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1177 IN UINT8 Data\r
1178 )\r
1179/*++\r
1180\r
1181Routine Description:\r
1182\r
1183 GC_TODO: Add function description\r
1184\r
1185Arguments:\r
1186\r
1187 ConsoleIn - GC_TODO: add argument description\r
1188 Data - GC_TODO: add argument description\r
1189\r
1190Returns:\r
1191\r
1192 EFI_TIMEOUT - GC_TODO: Add description for return value\r
1193 EFI_TIMEOUT - GC_TODO: Add description for return value\r
1194 EFI_SUCCESS - GC_TODO: Add description for return value\r
1195\r
1196--*/\r
1197{\r
1198 UINT32 TimeOut;\r
1199 UINT32 RegEmptied;\r
1200\r
1201 TimeOut = 0;\r
1202 RegEmptied = 0;\r
1203\r
1204 //\r
1205 // Wait For Input Buffer Empty\r
1206 //\r
1207 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1208 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1209 RegEmptied = 1;\r
1210 break;\r
1211 }\r
1212\r
1213 gBS->Stall (30);\r
1214 }\r
1215\r
1216 if (!RegEmptied) {\r
1217 return EFI_TIMEOUT;\r
1218 }\r
1219 //\r
1220 // issue the command\r
1221 //\r
1222 KeyWriteCommandRegister (ConsoleIn, Data);\r
1223\r
1224 //\r
1225 // Wait For Input Buffer Empty again\r
1226 //\r
1227 RegEmptied = 0;\r
1228 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1229 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {\r
1230 RegEmptied = 1;\r
1231 break;\r
1232 }\r
1233\r
1234 gBS->Stall (30);\r
1235 }\r
1236\r
1237 if (!RegEmptied) {\r
1238 return EFI_TIMEOUT;\r
1239 }\r
1240\r
1241 return EFI_SUCCESS;\r
1242}\r
1243\r
1244STATIC\r
1245EFI_STATUS\r
1246KeyboardWaitForValue (\r
1247 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1248 IN UINT8 Value\r
1249 )\r
1250/*++\r
1251\r
1252Routine Description:\r
1253\r
1254 wait for a specific value to be presented on\r
1255 8042 Data register by keyboard and then read it,\r
1256 used in keyboard commands ack\r
1257\r
1258Arguments:\r
1259\r
1260 ConsoleIn - The KEYBOARD_CONSOLE_IN_DEV instance pointer\r
1261 Value - The value to be waited for\r
1262\r
1263Returns:\r
1264\r
1265 EFI_STATUS\r
1266\r
1267--*/\r
1268// GC_TODO: EFI_SUCCESS - add return value to function comment\r
1269// GC_TODO: EFI_TIMEOUT - add return value to function comment\r
1270{\r
1271 UINT8 Data;\r
1272 UINT32 TimeOut;\r
1273 UINT32 SumTimeOut;\r
1274 UINT32 GotIt;\r
1275\r
1276 GotIt = 0;\r
1277 TimeOut = 0;\r
1278 SumTimeOut = 0;\r
1279\r
1280 //\r
1281 // Make sure the initial value of 'Data' is different from 'Value'\r
1282 //\r
1283 Data = 0;\r
1284 if (Data == Value) {\r
1285 Data = 1;\r
1286 }\r
1287 //\r
1288 // Read from 8042 (multiple times if needed)\r
1289 // until the expected value appears\r
1290 // use SumTimeOut to control the iteration\r
1291 //\r
1292 while (1) {\r
1293 //\r
1294 // Perform a read\r
1295 //\r
1296 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
1297 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {\r
1298 Data = KeyReadDataRegister (ConsoleIn);\r
1299 break;\r
1300 }\r
1301\r
1302 gBS->Stall (30);\r
1303 }\r
1304\r
1305 SumTimeOut += TimeOut;\r
1306\r
1307 if (Data == Value) {\r
1308 GotIt = 1;\r
1309 break;\r
1310 }\r
1311\r
1312 if (SumTimeOut >= mWaitForValueTimeOut) {\r
1313 break;\r
1314 }\r
1315 }\r
1316 //\r
1317 // Check results\r
1318 //\r
1319 if (GotIt) {\r
1320 return EFI_SUCCESS;\r
1321 } else {\r
1322 return EFI_TIMEOUT;\r
1323 }\r
1324\r
1325}\r
1326\r
05fbd06d 1327EFI_STATUS\r
1328UpdateStatusLights (\r
1329 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1330 )\r
1331/*++\r
1332\r
1333Routine Description:\r
1334\r
1335 Show keyboard status lights according to\r
1336 indicators in ConsoleIn.\r
1337\r
1338Arguments:\r
1339\r
1340Returns:\r
1341\r
1342--*/\r
1343// GC_TODO: ConsoleIn - add argument and description to function comment\r
1344{\r
1345 EFI_STATUS Status;\r
1346 UINT8 Command;\r
1347\r
1348 //\r
1349 // Send keyboard command\r
1350 //\r
1351 Status = KeyboardWrite (ConsoleIn, 0xed);\r
1352 if (EFI_ERROR (Status)) {\r
1353 return Status;\r
1354 }\r
1355\r
1356 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1357\r
1358 //\r
1359 // Light configuration\r
1360 //\r
1361 Command = 0;\r
1362 if (ConsoleIn->CapsLock) {\r
1363 Command |= 4;\r
1364 }\r
1365\r
1366 if (ConsoleIn->NumLock) {\r
1367 Command |= 2;\r
1368 }\r
1369\r
1370 if (ConsoleIn->ScrollLock) {\r
1371 Command |= 1;\r
1372 }\r
1373\r
1374 Status = KeyboardWrite (ConsoleIn, Command);\r
1375\r
1376 if (EFI_ERROR (Status)) {\r
1377 return Status;\r
1378 }\r
1379\r
1380 KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1381 return Status;\r
1382}\r
1383\r
1384EFI_STATUS\r
1385KeyGetchar (\r
1386 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
1387 )\r
1388/*++\r
1389\r
1390Routine Description:\r
1391\r
1392 Get scancode from scancode buffer\r
1393 and translate into EFI-scancode and unicode defined by EFI spec\r
1394 The function is always called in TPL_NOTIFY\r
1395\r
1396Arguments:\r
1397\r
1398 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer\r
1399\r
1400Returns:\r
1401\r
1402 EFI_NOT_READY - Input from console not ready yet.\r
1403 EFI_SUCCESS - Function executed successfully.\r
1404\r
1405--*/\r
1406{\r
1407 EFI_STATUS Status;\r
1408 UINT8 ScanCode;\r
1409 UINT8 Readed;\r
1410 BOOLEAN Extended;\r
1411 UINT8 ScancodeArr[4];\r
1412 UINTN Index;\r
1413 //\r
1414 // 4 bytes most\r
1415 //\r
1416 UINT32 ScancodeArrPos;\r
1417 //\r
1418 // point to the current position in ScancodeArr\r
1419 //\r
1420\r
1421 Readed = 0;\r
1422 Extended = FALSE;\r
1423 ScancodeArrPos = 0;\r
1424\r
1425 //\r
1426 // Read one byte of the scan code and store it into the memory buffer\r
1427 // This block of code is added to insert an action that is equivalent to\r
1428 // the timer event handling function, so as to increase the frequency of\r
1429 // detecting the availability of keys. Timer event has a max frequency of\r
1430 // 18Hz which is insufficient\r
1431 //\r
1432 //\r
1433 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that\r
1434 // KB is not connected to system. If KB is not connected to system, driver will find there's something\r
1435 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since\r
1436 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.\r
1437 // Just skip the 'resend' process simply.\r
1438 //\r
1439\r
1440\r
1441 if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {\r
1442\r
1443 Readed = KeyReadDataRegister (ConsoleIn);\r
1444 //\r
1445 // put the scancode into the memory scancode buffer\r
1446 //\r
1447 ConsoleIn->ScancodeBufCount++;\r
1448 ConsoleIn->ScancodeBufEndPos++;\r
1449 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {\r
1450 ConsoleIn->ScancodeBufEndPos = 0;\r
1451 }\r
1452\r
1453 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;\r
1454\r
1455 //\r
1456 // Handle Alt+Ctrl+Del Key combination\r
1457 //\r
1458 switch (Readed) {\r
1459\r
1460 case SCANCODE_CTRL_MAKE:\r
1461 ConsoleIn->Ctrled = TRUE;\r
1462 break;\r
1463\r
1464 case SCANCODE_CTRL_BREAK:\r
1465 ConsoleIn->Ctrled = FALSE;\r
1466 break;\r
1467\r
1468 case SCANCODE_ALT_MAKE:\r
1469 ConsoleIn->Alted = TRUE;\r
1470 break;\r
1471\r
1472 case SCANCODE_ALT_BREAK:\r
1473 ConsoleIn->Alted = FALSE;\r
1474 break;\r
1475 }\r
1476 //\r
1477 // if Alt+Ctrl+Del, Reboot the System\r
1478 //\r
1479 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {\r
1480 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1481 }\r
1482 }\r
1483 //\r
1484 // Check if there are enough bytes of scancode representing a single key\r
1485 // available in the buffer\r
1486 //\r
1487 while (1) {\r
1488\r
1489 Status = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);\r
1490 ScancodeArrPos = 0;\r
1491 if (EFI_ERROR (Status)) {\r
1492 return EFI_NOT_READY;\r
1493 }\r
1494\r
1495 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {\r
1496 Extended = TRUE;\r
1497 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
1498 ScancodeArrPos = 1;\r
1499 if (EFI_ERROR (Status)) {\r
1500 return EFI_NOT_READY;\r
1501 }\r
1502 }\r
1503 //\r
1504 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5\r
1505 // if present, ignore them\r
1506 //\r
1507 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {\r
1508\r
1509 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);\r
1510 ScancodeArrPos = 1;\r
1511\r
1512 if (EFI_ERROR (Status)) {\r
1513 return EFI_NOT_READY;\r
1514 }\r
1515\r
1516 Status = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
1517 ScancodeArrPos = 2;\r
1518\r
1519 if (EFI_ERROR (Status)) {\r
1520 return EFI_NOT_READY;\r
1521 }\r
1522\r
1523 PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);\r
1524 return EFI_NOT_READY;\r
1525 }\r
1526 //\r
1527 // if we reach this position, scancodes for a key is in buffer now,pop them\r
1528 //\r
1529 Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);\r
1530 if (EFI_ERROR (Status)) {\r
1531 return EFI_NOT_READY;\r
1532 }\r
1533 //\r
1534 // store the last available byte, this byte of scancode will be checked\r
1535 //\r
1536 ScanCode = ScancodeArr[ScancodeArrPos];\r
1537\r
1538 //\r
1539 // Check for special keys and update the driver state.\r
1540 //\r
1541 switch (ScanCode) {\r
1542\r
1543 case SCANCODE_CTRL_MAKE:\r
1544 ConsoleIn->Ctrl = TRUE;\r
1545 break;\r
1546\r
1547 case SCANCODE_CTRL_BREAK:\r
1548 ConsoleIn->Ctrl = FALSE;\r
1549 break;\r
1550\r
1551 case SCANCODE_ALT_MAKE:\r
1552 ConsoleIn->Alt = TRUE;\r
1553 break;\r
1554\r
1555 case SCANCODE_ALT_BREAK:\r
1556 ConsoleIn->Alt = FALSE;\r
1557 break;\r
1558\r
1559 case SCANCODE_LEFT_SHIFT_MAKE:\r
f3d1e940 1560 if (!Extended) {\r
1561 ConsoleIn->Shift = TRUE;\r
1562 ConsoleIn->LeftShift = TRUE;\r
1563 } \r
1564 break;\r
05fbd06d 1565 case SCANCODE_RIGHT_SHIFT_MAKE:\r
1566 if (!Extended) {\r
1567 ConsoleIn->Shift = TRUE;\r
f3d1e940 1568 ConsoleIn->RightShift = TRUE;\r
05fbd06d 1569 }\r
1570 break;\r
1571\r
1572 case SCANCODE_LEFT_SHIFT_BREAK:\r
f3d1e940 1573 if (!Extended) {\r
1574 ConsoleIn->Shift = FALSE;\r
1575 ConsoleIn->LeftShift = FALSE;\r
1576 } else {\r
1577 ConsoleIn->SysReq = FALSE;\r
1578 } \r
1579 break;\r
05fbd06d 1580 case SCANCODE_RIGHT_SHIFT_BREAK:\r
1581 if (!Extended) {\r
1582 ConsoleIn->Shift = FALSE;\r
f3d1e940 1583 ConsoleIn->RightShift = FALSE;\r
05fbd06d 1584 }\r
1585 break;\r
1586\r
f3d1e940 1587 case SCANCODE_LEFT_LOGO_MAKE:\r
1588 ConsoleIn->LeftLogo = TRUE;\r
1589 break; \r
1590 case SCANCODE_LEFT_LOGO_BREAK:\r
1591 ConsoleIn->LeftLogo = FALSE;\r
1592 break; \r
1593 case SCANCODE_RIGHT_LOGO_MAKE:\r
1594 ConsoleIn->RightLogo = TRUE;\r
1595 break;\r
1596 case SCANCODE_RIGHT_LOGO_BREAK:\r
1597 ConsoleIn->RightLogo = FALSE;\r
1598 break; \r
1599 case SCANCODE_MENU_MAKE:\r
1600 ConsoleIn->Menu = TRUE;\r
1601 break;\r
1602 case SCANCODE_MENU_BREAK:\r
1603 ConsoleIn->Menu = FALSE;\r
1604 break; \r
1605 case SCANCODE_SYS_REQ_MAKE:\r
1606 if (Extended) {\r
1607 ConsoleIn->SysReq = TRUE;\r
1608 }\r
05fbd06d 1609 case SCANCODE_CAPS_LOCK_MAKE:\r
1610 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;\r
1611 UpdateStatusLights (ConsoleIn);\r
1612 break;\r
1613\r
1614 case SCANCODE_NUM_LOCK_MAKE:\r
1615 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;\r
1616 UpdateStatusLights (ConsoleIn);\r
1617 break;\r
1618\r
1619 case SCANCODE_SCROLL_LOCK_MAKE:\r
1620 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;\r
1621 UpdateStatusLights (ConsoleIn);\r
1622 break;\r
1623 }\r
1624 //\r
1625 // If this is a BREAK Key or above the valid range, ignore it\r
1626 //\r
1627 if (ScanCode >= SCANCODE_MAX_MAKE) {\r
1628 continue;\r
1629 } else {\r
1630 break;\r
1631 }\r
1632 }\r
1633 //\r
05fbd06d 1634 // Treat Numeric Key Pad "/" specially\r
1635 //\r
1636 if (Extended && ScanCode == 0x35) {\r
1637 ConsoleIn->Key.ScanCode = SCAN_NULL;\r
1638 ConsoleIn->Key.UnicodeChar = '/';\r
1639 return EFI_SUCCESS;\r
1640 }\r
1641 //\r
1642 // Convert Keyboard ScanCode into an EFI Key\r
1643 //\r
1644 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {\r
1645 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {\r
1646 ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;\r
1647 if (ConsoleIn->Shift) {\r
1648 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
f3d1e940 1649 //\r
1650 // Need not return associated shift state if a class of printable characters that\r
1651 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'\r
1652 //\r
1653 if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1654 ConsoleIn->LeftShift = FALSE;\r
1655 ConsoleIn->RightShift = FALSE;\r
1656 }\r
05fbd06d 1657 } else {\r
1658 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
1659 }\r
1660 //\r
1661 // alphabetic key is affected by CapsLock State\r
1662 //\r
1663 if (ConsoleIn->CapsLock) {\r
1664 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {\r
1665 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;\r
1666 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1667 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;\r
1668 }\r
1669 }\r
1f771698 1670 //\r
1671 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
1672 //\r
1673 if (ConsoleIn->Ctrled) {\r
1674 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {\r
1675 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'a' + 1);\r
1676 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {\r
1677 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'A' + 1);\r
1678 }\r
1679 }\r
05fbd06d 1680\r
1681 break;\r
1682 }\r
1683 }\r
1684\r
1685 //\r
1686 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'\r
1687 //\r
1688 if (ScanCode >= 0x47 && ScanCode <= 0x53) {\r
1689\r
1690 if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {\r
1691 ConsoleIn->Key.ScanCode = SCAN_NULL;\r
1692 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {\r
1693 ConsoleIn->Key.UnicodeChar = 0x00;\r
1694 }\r
1695 }\r
1696 //\r
1697 // If the key can not be converted then just return.\r
1698 //\r
1699 if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {\r
1700 return EFI_NOT_READY;\r
1701 }\r
1702\r
f3d1e940 1703 //\r
1704 // Save the Shift/Toggle state\r
1705 //\r
1706 if (ConsoleIn->Ctrl) {\r
1707 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;\r
1708 } \r
1709 if (ConsoleIn->Alt) { \r
1710 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;\r
1711 } \r
1712 if (ConsoleIn->LeftShift) { \r
1713 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
1714 } \r
1715 if (ConsoleIn->RightShift) { \r
1716 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
1717 } \r
1718 if (ConsoleIn->LeftLogo) { \r
1719 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;\r
1720 } \r
1721 if (ConsoleIn->RightLogo) { \r
1722 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;\r
1723 } \r
1724 if (ConsoleIn->Menu) { \r
1725 ConsoleIn->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
1726 } \r
1727 if (ConsoleIn->SysReq) { \r
1728 ConsoleIn->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
1729 } \r
1730 if (ConsoleIn->CapsLock) {\r
1731 ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
1732 }\r
1733 if (ConsoleIn->NumLock) {\r
1734 ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
1735 }\r
1736 if (ConsoleIn->ScrollLock) {\r
1737 ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
1738 }\r
1739\r
05fbd06d 1740 return EFI_SUCCESS;\r
1741}\r
1742\r
1743EFI_STATUS\r
1744InitKeyboard (\r
1745 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,\r
1746 IN BOOLEAN ExtendedVerification\r
1747 )\r
1748/*++\r
1749\r
1750Routine Description:\r
1751\r
1752 Perform 8042 controller and keyboard Initialization\r
1753 If ExtendedVerification is TRUE, do additional test for\r
1754 the keyboard interface\r
1755\r
1756Arguments:\r
1757\r
1758 ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer\r
1759 ExtendedVerification - indicates a thorough initialization\r
1760\r
1761Returns:\r
1762\r
1763 EFI_STATUS\r
1764\r
1765--*/\r
1766// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1767// GC_TODO: EFI_SUCCESS - add return value to function comment\r
1768// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
1769{\r
1770 EFI_STATUS Status;\r
1771 EFI_STATUS Status1;\r
1772 UINT8 CommandByte;\r
1773 STATIC BOOLEAN EnableMouseInterface;\r
1774 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;\r
1775\r
1776 Status = EFI_SUCCESS;\r
1777 EnableMouseInterface = TRUE;\r
1778\r
1779 //\r
1780 // Get Ps2 policy to set this\r
1781 //\r
1782 Status = gBS->LocateProtocol (\r
1783 &gEfiPs2PolicyProtocolGuid,\r
1784 NULL,\r
1785 (VOID **) &Ps2Policy\r
1786 );\r
1787\r
1788 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1789 EFI_PROGRESS_CODE,\r
1790 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,\r
1791 ConsoleIn->DevicePath\r
1792 );\r
1793\r
1794 //\r
1795 // Perform a read to cleanup the Status Register's\r
1796 // output buffer full bits\r
1797 //\r
1798 while (!EFI_ERROR (Status)) {\r
1799 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
1800 }\r
1801 //\r
1802 // We should disable mouse interface during the initialization process\r
1803 // since mouse device output could block keyboard device output in the\r
1804 // 60H port of 8042 controller.\r
1805 //\r
1806 // So if we are not initializing 8042 controller for the\r
1807 // first time, we have to remember the previous mouse interface\r
1808 // enabling state\r
1809 //\r
1810 // Test the system flag in to determine whether this is the first\r
1811 // time initialization\r
1812 //\r
1813 if ((KeyReadStatusRegister (ConsoleIn) & 0x04)) {\r
1814 //\r
1815 // 8042 controller is already setup (by myself or by mouse driver):\r
1816 // See whether mouse interface is already enabled\r
1817 // which determines whether we should enable it later\r
1818 //\r
1819 //\r
1820 // Read the command byte of 8042 controller\r
1821 //\r
1822 Status = KeyboardCommand (ConsoleIn, 0x20);\r
1823 if (EFI_ERROR (Status)) {\r
1824 KeyboardError (ConsoleIn, L"\n\r");\r
1825 goto Done;\r
1826 }\r
1827\r
1828 Status = KeyboardRead (ConsoleIn, &CommandByte);\r
1829 if (EFI_ERROR (Status)) {\r
1830 KeyboardError (ConsoleIn, L"\n\r");\r
1831 goto Done;\r
1832 }\r
1833 //\r
1834 // Test the mouse enabling bit\r
1835 //\r
1836 if (CommandByte & 0x20) {\r
1837 EnableMouseInterface = FALSE;\r
1838 } else {\r
1839 EnableMouseInterface = TRUE;\r
1840 }\r
1841\r
1842 } else {\r
1843 //\r
1844 // 8042 controller is not setup yet:\r
1845 // 8042 controller selftest;\r
1846 // Don't enable mouse interface later.\r
1847 //\r
1848 //\r
1849 // Disable keyboard and mouse interfaces\r
1850 //\r
1851 Status = KeyboardCommand (ConsoleIn, 0xad);\r
1852 if (EFI_ERROR (Status)) {\r
1853 KeyboardError (ConsoleIn, L"\n\r");\r
1854 goto Done;\r
1855 }\r
1856\r
1857 Status = KeyboardCommand (ConsoleIn, 0xa7);\r
1858 if (EFI_ERROR (Status)) {\r
1859 KeyboardError (ConsoleIn, L"\n\r");\r
1860 goto Done;\r
1861 }\r
1862\r
1863 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1864 EFI_PROGRESS_CODE,\r
1865 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,\r
1866 ConsoleIn->DevicePath\r
1867 );\r
1868 //\r
1869 // 8042 Controller Self Test\r
1870 //\r
1871 Status = KeyboardCommand (ConsoleIn, 0xaa);\r
1872 if (EFI_ERROR (Status)) {\r
1873 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1874 goto Done;\r
1875 }\r
1876\r
1877 Status = KeyboardWaitForValue (ConsoleIn, 0x55);\r
1878 if (EFI_ERROR (Status)) {\r
1879 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");\r
1880 goto Done;\r
1881 }\r
1882 //\r
1883 // Don't enable mouse interface later\r
1884 //\r
1885 EnableMouseInterface = FALSE;\r
1886\r
1887 }\r
1888\r
1889 if (Ps2Policy != NULL) {\r
1890 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);\r
1891 }\r
1892 //\r
1893 // Write 8042 Command Byte, set System Flag\r
1894 // While at the same time:\r
1895 // 1. disable mouse interface,\r
1896 // 2. enable kbd interface,\r
1897 // 3. enable PC/XT kbd translation mode\r
1898 // 4. enable mouse and kbd interrupts\r
1899 //\r
1900 // ( Command Byte bits:\r
1901 // 7: Reserved\r
1902 // 6: PC/XT translation mode\r
1903 // 5: Disable Auxiliary device interface\r
1904 // 4: Disable keyboard interface\r
1905 // 3: Reserved\r
1906 // 2: System Flag\r
1907 // 1: Enable Auxiliary device interrupt\r
1908 // 0: Enable Keyboard interrupt )\r
1909 //\r
1910 Status = KeyboardCommand (ConsoleIn, 0x60);\r
1911 if (EFI_ERROR (Status)) {\r
1912 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1913 goto Done;\r
1914 }\r
1915\r
1916 Status = KeyboardWrite (ConsoleIn, 0x67);\r
1917 if (EFI_ERROR (Status)) {\r
1918 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1919 goto Done;\r
1920 }\r
1921\r
1922 //\r
1923 // Clear Memory Scancode Buffer\r
1924 //\r
1925 ConsoleIn->ScancodeBufStartPos = 0;\r
1926 ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1;\r
1927 ConsoleIn->ScancodeBufCount = 0;\r
1928 ConsoleIn->Ctrled = FALSE;\r
1929 ConsoleIn->Alted = FALSE;\r
1930\r
1931 //\r
1932 // Reset the status indicators\r
1933 //\r
1934 ConsoleIn->Ctrl = FALSE;\r
1935 ConsoleIn->Alt = FALSE;\r
1936 ConsoleIn->Shift = FALSE;\r
1937 ConsoleIn->CapsLock = FALSE;\r
1938 ConsoleIn->NumLock = FALSE;\r
1939 ConsoleIn->ScrollLock = FALSE;\r
f3d1e940 1940 ConsoleIn->LeftShift = FALSE;\r
1941 ConsoleIn->RightShift = FALSE;\r
1942 ConsoleIn->LeftLogo = FALSE;\r
1943 ConsoleIn->RightLogo = FALSE;\r
1944 ConsoleIn->Menu = FALSE;\r
1945 ConsoleIn->SysReq = FALSE; \r
05fbd06d 1946\r
1947 //\r
1948 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
1949 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected\r
1950 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,\r
1951 // and normally during booting an OS, it's skipped.\r
1952 //\r
1953 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {\r
1954 //\r
1955 // Additional verifications for keyboard interface\r
1956 //\r
1957 //\r
1958 // Keyboard Interface Test\r
1959 //\r
1960 Status = KeyboardCommand (ConsoleIn, 0xab);\r
1961 if (EFI_ERROR (Status)) {\r
1962 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
1963 goto Done;\r
1964 }\r
1965\r
1966 Status = KeyboardWaitForValue (ConsoleIn, 0x00);\r
1967 if (EFI_ERROR (Status)) {\r
1968 KeyboardError (\r
1969 ConsoleIn,\r
1970 L"Some specific value not aquired from 8042 controller!\n\r"\r
1971 );\r
1972 goto Done;\r
1973 }\r
1974 //\r
1975 // Keyboard reset with a BAT(Basic Assurance Test)\r
1976 //\r
1977 Status = KeyboardWrite (ConsoleIn, 0xff);\r
1978 if (EFI_ERROR (Status)) {\r
1979 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
1980 goto Done;\r
1981 }\r
1982\r
1983 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
1984 if (EFI_ERROR (Status)) {\r
1985 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
1986 goto Done;\r
1987 }\r
1988 //\r
1989 // wait for BAT completion code\r
1990 //\r
1991 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;\r
1992\r
1993 Status = KeyboardWaitForValue (ConsoleIn, 0xaa);\r
1994 if (EFI_ERROR (Status)) {\r
1995 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");\r
1996 goto Done;\r
1997 }\r
1998\r
1999 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
2000\r
2001 //\r
2002 // Set Keyboard to use Scan Code Set 2\r
2003 //\r
2004 Status = KeyboardWrite (ConsoleIn, 0xf0);\r
2005 if (EFI_ERROR (Status)) {\r
2006 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
2007 goto Done;\r
2008 }\r
2009\r
2010 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
2011 if (EFI_ERROR (Status)) {\r
2012 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
2013 goto Done;\r
2014 }\r
2015\r
2016 Status = KeyboardWrite (ConsoleIn, 0x02);\r
2017 if (EFI_ERROR (Status)) {\r
2018 KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");\r
2019 goto Done;\r
2020 }\r
2021\r
2022 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
2023 if (EFI_ERROR (Status)) {\r
2024 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
2025 goto Done;\r
2026 }\r
2027\r
2028 //\r
2029 // Clear Keyboard Scancode Buffer\r
2030 //\r
2031 Status = KeyboardWrite (ConsoleIn, 0xf4);\r
2032 if (EFI_ERROR (Status)) {\r
2033 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");\r
2034 goto Done;\r
2035 }\r
2036\r
2037 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);\r
2038 if (EFI_ERROR (Status)) {\r
2039 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");\r
2040 goto Done;\r
2041 }\r
2042 //\r
2043 if (Ps2Policy != NULL) {\r
2044 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {\r
2045 ConsoleIn->CapsLock = TRUE;\r
2046 }\r
2047\r
2048 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {\r
2049 ConsoleIn->NumLock = TRUE;\r
2050 }\r
2051\r
2052 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {\r
2053 ConsoleIn->ScrollLock = TRUE;\r
2054 }\r
2055 }\r
2056 //\r
2057 // Update Keyboard Lights\r
2058 //\r
2059 Status = UpdateStatusLights (ConsoleIn);\r
2060 if (EFI_ERROR (Status)) {\r
2061 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");\r
2062 goto Done;\r
2063 }\r
2064 }\r
2065 //\r
2066 // At last, we can now enable the mouse interface if appropriate\r
2067 //\r
2068Done:\r
2069\r
2070 if (EnableMouseInterface) {\r
2071 //\r
2072 // Enable mouse interface\r
2073 //\r
2074 Status1 = KeyboardCommand (ConsoleIn, 0xa8);\r
2075 if (EFI_ERROR (Status1)) {\r
2076 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");\r
2077 return EFI_DEVICE_ERROR;\r
2078 }\r
2079 }\r
2080\r
2081 if (!EFI_ERROR (Status)) {\r
2082 return EFI_SUCCESS;\r
2083 } else {\r
2084 return EFI_DEVICE_ERROR;\r
2085 }\r
2086\r
2087}\r
2088\r
2089EFI_STATUS\r
2090DisableKeyboard (\r
2091 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
2092 )\r
2093/*++\r
2094\r
2095Routine Description:\r
2096\r
2097 Disable the keyboard interface of the 8042 controller\r
2098\r
2099Arguments:\r
2100\r
2101 ConsoleIn - the device instance\r
2102\r
2103Returns:\r
2104\r
2105 EFI_STATUS\r
2106\r
2107--*/\r
2108// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
2109{\r
2110 EFI_STATUS Status;\r
2111\r
2112 //\r
2113 // Disable keyboard interface\r
2114 //\r
2115 Status = KeyboardCommand (ConsoleIn, 0xad);\r
2116 if (EFI_ERROR (Status)) {\r
2117 KeyboardError (ConsoleIn, L"\n\r");\r
2118 return EFI_DEVICE_ERROR;\r
2119 }\r
2120\r
2121 return Status;\r
2122}\r
2123\r
2124/**\r
2125 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
2126 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
2127 should not be in system.\r
2128\r
2129 @param[in] BiosKeyboardPrivate Keyboard Private Data Structure\r
2130\r
f3d1e940 2131 @retval TRUE Keyboard in System.\r
2132 @retval FALSE Keyboard not in System.\r
05fbd06d 2133**/\r
2134BOOLEAN\r
2135EFIAPI\r
2136CheckKeyboardConnect (\r
2137 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn\r
2138 )\r
2139{\r
2140 EFI_STATUS Status;\r
2141 UINTN WaitForValueTimeOutBcakup;\r
2142\r
2143 Status = EFI_SUCCESS;\r
2144 //\r
2145 // enable keyboard itself and wait for its ack\r
2146 // If can't receive ack, Keyboard should not be connected.\r
2147 //\r
2148 Status = KeyboardWrite (\r
2149 ConsoleIn,\r
2150 KEYBOARD_KBEN\r
2151 );\r
2152\r
2153 if (EFI_ERROR (Status)) {\r
2154 return FALSE;\r
2155 }\r
2156 //\r
2157 // wait for 1s\r
2158 //\r
2159 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;\r
2160 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;\r
2161 Status = KeyboardWaitForValue (\r
2162 ConsoleIn,\r
2163 KEYBOARD_CMDECHO_ACK\r
2164 );\r
2165 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;\r
2166\r
2167 if (EFI_ERROR (Status)) {\r
2168 return FALSE;\r
2169 }\r
2170\r
2171 return TRUE;\r
2172}\r