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