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