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