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