]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
aa22b5cf3e1ad9cfd0571f1927e688b79416daae
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2MouseDxe / CommPs2.c
1 /** @file
2 PS2 Mouse Communication Interface.
3
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Ps2Mouse.h"
16 #include "CommPs2.h"
17
18 UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };
19
20 UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 };
21
22 /**
23 Issue self test command via IsaIo interface.
24
25 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
26
27 @return EFI_SUCCESS Success to do keyboard self testing.
28 @return others Fail to do keyboard self testing.
29 **/
30 EFI_STATUS
31 KbcSelfTest (
32 IN EFI_ISA_IO_PROTOCOL *IsaIo
33 )
34 {
35 EFI_STATUS Status;
36 UINT8 Data;
37
38 //
39 // Keyboard controller self test
40 //
41 Status = Out8042Command (IsaIo, SELF_TEST);
42 if (EFI_ERROR (Status)) {
43 return Status;
44 }
45 //
46 // Read return code
47 //
48 Status = In8042Data (IsaIo, &Data);
49 if (EFI_ERROR (Status)) {
50 return Status;
51 }
52
53 if (Data != 0x55) {
54 return EFI_DEVICE_ERROR;
55 }
56 //
57 // Set system flag
58 //
59 Status = Out8042Command (IsaIo, READ_CMD_BYTE);
60 if (EFI_ERROR (Status)) {
61 return Status;
62 }
63
64 Status = In8042Data (IsaIo, &Data);
65 if (EFI_ERROR (Status)) {
66 return Status;
67 }
68
69 Status = Out8042Command (IsaIo, WRITE_CMD_BYTE);
70 if (EFI_ERROR (Status)) {
71 return Status;
72 }
73
74 Data |= CMD_SYS_FLAG;
75 Status = Out8042Data (IsaIo, Data);
76 if (EFI_ERROR (Status)) {
77 return Status;
78 }
79
80 return EFI_SUCCESS;
81 }
82
83 /**
84 Issue command to enable keyboard AUX functionality.
85
86 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
87
88 @return Status of command issuing.
89 **/
90 EFI_STATUS
91 KbcEnableAux (
92 IN EFI_ISA_IO_PROTOCOL *IsaIo
93 )
94 {
95 //
96 // Send 8042 enable mouse command
97 //
98 return Out8042Command (IsaIo, ENABLE_AUX);
99 }
100
101 /**
102 Issue command to disable keyboard AUX functionality.
103
104 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
105
106 @return Status of command issuing.
107 **/
108 EFI_STATUS
109 KbcDisableAux (
110 IN EFI_ISA_IO_PROTOCOL *IsaIo
111 )
112 {
113 //
114 // Send 8042 disable mouse command
115 //
116 return Out8042Command (IsaIo, DISABLE_AUX);
117 }
118
119 /**
120 Issue command to enable keyboard.
121
122 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
123
124 @return Status of command issuing.
125 **/
126 EFI_STATUS
127 KbcEnableKb (
128 IN EFI_ISA_IO_PROTOCOL *IsaIo
129 )
130 {
131 //
132 // Send 8042 enable keyboard command
133 //
134 return Out8042Command (IsaIo, ENABLE_KB);
135 }
136
137 /**
138 Issue command to disable keyboard.
139
140 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
141
142 @return Status of command issuing.
143 **/
144 EFI_STATUS
145 KbcDisableKb (
146 IN EFI_ISA_IO_PROTOCOL *IsaIo
147 )
148 {
149 //
150 // Send 8042 disable keyboard command
151 //
152 return Out8042Command (IsaIo, DISABLE_KB);
153 }
154
155 /**
156 Issue command to check keyboard status.
157
158 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
159 @param KeyboardEnable return whether keyboard is enable.
160
161 @return Status of command issuing.
162 **/
163 EFI_STATUS
164 CheckKbStatus (
165 IN EFI_ISA_IO_PROTOCOL *IsaIo,
166 OUT BOOLEAN *KeyboardEnable
167 )
168 {
169 EFI_STATUS Status;
170 UINT8 Data;
171
172 //
173 // Send command to read KBC command byte
174 //
175 Status = Out8042Command (IsaIo, READ_CMD_BYTE);
176 if (EFI_ERROR (Status)) {
177 return Status;
178 }
179
180 Status = In8042Data (IsaIo, &Data);
181 if (EFI_ERROR (Status)) {
182 return Status;
183 }
184 //
185 // Check keyboard enable or not
186 //
187 if ((Data & CMD_KB_STS) == CMD_KB_DIS) {
188 *KeyboardEnable = FALSE;
189 } else {
190 *KeyboardEnable = TRUE;
191 }
192
193 return EFI_SUCCESS;
194 }
195
196 /**
197 Issue command to reset keyboard.
198
199 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
200
201 @return Status of command issuing.
202 **/
203 EFI_STATUS
204 PS2MouseReset (
205 IN EFI_ISA_IO_PROTOCOL *IsaIo
206 )
207 {
208 EFI_STATUS Status;
209 UINT8 Data;
210
211 Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE);
212 if (EFI_ERROR (Status)) {
213 return Status;
214 }
215
216 Status = In8042AuxData (IsaIo, &Data);
217 if (EFI_ERROR (Status)) {
218 return Status;
219 }
220 //
221 // Check BAT Complete Code
222 //
223 if (Data != PS2MOUSE_BAT1) {
224 return EFI_DEVICE_ERROR;
225 }
226
227 Status = In8042AuxData (IsaIo, &Data);
228 if (EFI_ERROR (Status)) {
229 return Status;
230 }
231 //
232 // Check BAT Complete Code
233 //
234 if (Data != PS2MOUSE_BAT2) {
235 return EFI_DEVICE_ERROR;
236 }
237
238 return EFI_SUCCESS;
239 }
240
241 /**
242 Issue command to set mouse's sample rate
243
244 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
245 @param SampleRate value of sample rate
246
247 @return Status of command issuing.
248 **/
249 EFI_STATUS
250 PS2MouseSetSampleRate (
251 IN EFI_ISA_IO_PROTOCOL *IsaIo,
252 IN MOUSE_SR SampleRate
253 )
254 {
255 EFI_STATUS Status;
256
257 //
258 // Send auxiliary command to set mouse sample rate
259 //
260 Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE);
261 if (EFI_ERROR (Status)) {
262 return Status;
263 }
264
265 Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]);
266
267 return Status;
268 }
269
270 /**
271 Issue command to set mouse's resolution.
272
273 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
274 @param Resolution value of resolution
275
276 @return Status of command issuing.
277 **/
278 EFI_STATUS
279 PS2MouseSetResolution (
280 IN EFI_ISA_IO_PROTOCOL *IsaIo,
281 IN MOUSE_RE Resolution
282 )
283 {
284 EFI_STATUS Status;
285
286 //
287 // Send auxiliary command to set mouse resolution
288 //
289 Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE);
290 if (EFI_ERROR (Status)) {
291 return Status;
292 }
293
294 Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]);
295
296 return Status;
297 }
298
299 /**
300 Issue command to set mouse's scaling.
301
302 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
303 @param Scaling value of scaling
304
305 @return Status of command issuing.
306 **/
307 EFI_STATUS
308 PS2MouseSetScaling (
309 IN EFI_ISA_IO_PROTOCOL *IsaIo,
310 IN MOUSE_SF Scaling
311 )
312 {
313 UINT8 Command;
314
315 Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD);
316
317 //
318 // Send auxiliary command to set mouse scaling data
319 //
320 return Out8042AuxCommand (IsaIo, Command, FALSE);
321 }
322
323 /**
324 Issue command to enable Ps2 mouse.
325
326 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
327
328 @return Status of command issuing.
329 **/
330 EFI_STATUS
331 PS2MouseEnable (
332 IN EFI_ISA_IO_PROTOCOL *IsaIo
333 )
334 {
335 //
336 // Send auxiliary command to enable mouse
337 //
338 return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE);
339 }
340
341 /**
342 Get mouse packet . Only care first 3 bytes
343
344 @param MouseDev Pointer of PS2 Mouse Private Data Structure
345
346 @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet
347 @retval EFI_SUCCESS The data packet is gotten successfully.
348
349 **/
350 EFI_STATUS
351 PS2MouseGetPacket (
352 PS2_MOUSE_DEV *MouseDev
353 )
354
355 {
356 EFI_STATUS Status;
357 BOOLEAN KeyboardEnable;
358 UINT8 Packet[PS2_PACKET_LENGTH];
359 UINT8 Data;
360 UINTN Count;
361 UINTN State;
362 INT16 RelativeMovementX;
363 INT16 RelativeMovementY;
364 BOOLEAN LButton;
365 BOOLEAN RButton;
366
367 KeyboardEnable = FALSE;
368 Count = 1;
369 State = PS2_READ_BYTE_ONE;
370
371 //
372 // State machine to get mouse packet
373 //
374 while (1) {
375
376 switch (State) {
377 case PS2_READ_BYTE_ONE:
378 //
379 // Read mouse first byte data, if failed, immediately return
380 //
381 KbcDisableAux (MouseDev->IsaIo);
382 Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State);
383 if (EFI_ERROR (Status)) {
384 KbcEnableAux (MouseDev->IsaIo);
385 return EFI_NOT_READY;
386 }
387
388 if (Count != 1) {
389 KbcEnableAux (MouseDev->IsaIo);
390 return EFI_NOT_READY;
391 }
392
393 if (IS_PS2_SYNC_BYTE (Data)) {
394 Packet[0] = Data;
395 State = PS2_READ_DATA_BYTE;
396
397 CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable);
398 KbcDisableKb (MouseDev->IsaIo);
399 KbcEnableAux (MouseDev->IsaIo);
400 }
401 break;
402
403 case PS2_READ_DATA_BYTE:
404 Count = 2;
405 Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State);
406 if (EFI_ERROR (Status)) {
407 if (KeyboardEnable) {
408 KbcEnableKb (MouseDev->IsaIo);
409 }
410
411 return EFI_NOT_READY;
412 }
413
414 if (Count != 2) {
415 if (KeyboardEnable) {
416 KbcEnableKb (MouseDev->IsaIo);
417 }
418
419 return EFI_NOT_READY;
420 }
421
422 State = PS2_PROCESS_PACKET;
423 break;
424
425 case PS2_PROCESS_PACKET:
426 if (KeyboardEnable) {
427 KbcEnableKb (MouseDev->IsaIo);
428 }
429 //
430 // Decode the packet
431 //
432 RelativeMovementX = Packet[1];
433 RelativeMovementY = Packet[2];
434 //
435 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
436 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn
437 // Byte 1 | 8 bit X Movement
438 // Byte 2 | 8 bit Y Movement
439 //
440 // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission.
441 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.
442 //
443 //
444 // First, Clear X and Y high 8 bits
445 //
446 RelativeMovementX = (INT16) (RelativeMovementX & 0xFF);
447 RelativeMovementY = (INT16) (RelativeMovementY & 0xFF);
448 //
449 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
450 //
451 if ((Packet[0] & 0x10) != 0) {
452 RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00);
453 }
454 if ((Packet[0] & 0x20) != 0) {
455 RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00);
456 }
457
458
459 RButton = (UINT8) (Packet[0] & 0x2);
460 LButton = (UINT8) (Packet[0] & 0x1);
461
462 //
463 // Update mouse state
464 //
465 MouseDev->State.RelativeMovementX += RelativeMovementX;
466 MouseDev->State.RelativeMovementY -= RelativeMovementY;
467 MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE);
468 MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE);
469 MouseDev->StateChanged = TRUE;
470
471 return EFI_SUCCESS;
472 }
473 }
474 }
475
476 /**
477 Read data via IsaIo protocol with given number.
478
479 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
480 @param Buffer Buffer receive data of mouse
481 @param BufSize The size of buffer
482 @param State Check input or read data
483
484 @return status of reading mouse data.
485 **/
486 EFI_STATUS
487 PS2MouseRead (
488 IN EFI_ISA_IO_PROTOCOL *IsaIo,
489 OUT VOID *Buffer,
490 IN OUT UINTN *BufSize,
491 IN UINTN State
492 )
493 {
494 EFI_STATUS Status;
495 UINTN BytesRead;
496
497 Status = EFI_SUCCESS;
498 BytesRead = 0;
499
500 if (State == PS2_READ_BYTE_ONE) {
501 //
502 // Check input for mouse
503 //
504 Status = CheckForInput (IsaIo);
505
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509 }
510
511 while (BytesRead < *BufSize) {
512
513 Status = WaitOutputFull (IsaIo, TIMEOUT);
514 if (EFI_ERROR (Status)) {
515 break;
516 }
517
518 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer);
519
520 BytesRead++;
521 Buffer = (UINT8 *) Buffer + 1;
522 }
523 //
524 // Verify the correct number of bytes read
525 //
526 if (BytesRead == 0 || BytesRead != *BufSize) {
527 Status = EFI_NOT_FOUND;
528 }
529
530 *BufSize = BytesRead;
531 return Status;
532 }
533 //
534 // 8042 I/O function
535 //
536 /**
537 I/O work flow of outing 8042 command.
538
539 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
540 @param Command I/O command.
541
542 @retval EFI_SUCCESS Success to excute I/O work flow
543 @retval EFI_TIMEOUT Keyboard controller time out.
544 **/
545 EFI_STATUS
546 Out8042Command (
547 IN EFI_ISA_IO_PROTOCOL *IsaIo,
548 IN UINT8 Command
549 )
550 {
551 EFI_STATUS Status;
552 UINT8 Data;
553
554 //
555 // Wait keyboard controller input buffer empty
556 //
557 Status = WaitInputEmpty (IsaIo, TIMEOUT);
558 if (EFI_ERROR (Status)) {
559 return Status;
560 }
561 //
562 // Send command
563 //
564 Data = Command;
565 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
566
567 Status = WaitInputEmpty (IsaIo, TIMEOUT);
568 if (EFI_ERROR (Status)) {
569 return Status;
570 }
571
572 return EFI_SUCCESS;
573 }
574
575 /**
576 I/O work flow of outing 8042 data.
577
578 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
579 @param Data Data value
580
581 @retval EFI_SUCCESS Success to excute I/O work flow
582 @retval EFI_TIMEOUT Keyboard controller time out.
583 **/
584 EFI_STATUS
585 Out8042Data (
586 IN EFI_ISA_IO_PROTOCOL *IsaIo,
587 IN UINT8 Data
588 )
589 {
590 EFI_STATUS Status;
591 UINT8 Temp;
592 //
593 // Wait keyboard controller input buffer empty
594 //
595 Status = WaitInputEmpty (IsaIo, TIMEOUT);
596 if (EFI_ERROR (Status)) {
597 return Status;
598 }
599
600 Temp = Data;
601 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);
602
603 Status = WaitInputEmpty (IsaIo, TIMEOUT);
604 if (EFI_ERROR (Status)) {
605 return Status;
606 }
607
608 return EFI_SUCCESS;
609 }
610
611 /**
612 I/O work flow of in 8042 data.
613
614 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
615 @param Data Data value
616
617 @retval EFI_SUCCESS Success to excute I/O work flow
618 @retval EFI_TIMEOUT Keyboard controller time out.
619 **/
620 EFI_STATUS
621 In8042Data (
622 IN EFI_ISA_IO_PROTOCOL *IsaIo,
623 IN OUT UINT8 *Data
624 )
625 {
626 UINTN Delay;
627 UINT8 Temp;
628
629 Delay = TIMEOUT / 50;
630
631 do {
632 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);
633
634 //
635 // Check keyboard controller status bit 0(output buffer status)
636 //
637 if ((Temp & KBC_OUTB) == KBC_OUTB) {
638 break;
639 }
640
641 gBS->Stall (50);
642 Delay--;
643 } while (Delay != 0);
644
645 if (Delay == 0) {
646 return EFI_TIMEOUT;
647 }
648
649 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);
650
651 return EFI_SUCCESS;
652 }
653
654 /**
655 I/O work flow of outing 8042 Aux command.
656
657 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
658 @param Command Aux I/O command
659 @param Resend Whether need resend the Aux command.
660
661 @retval EFI_SUCCESS Success to excute I/O work flow
662 @retval EFI_TIMEOUT Keyboard controller time out.
663 **/
664 EFI_STATUS
665 Out8042AuxCommand (
666 IN EFI_ISA_IO_PROTOCOL *IsaIo,
667 IN UINT8 Command,
668 IN BOOLEAN Resend
669 )
670 {
671 EFI_STATUS Status;
672 UINT8 Data;
673
674 //
675 // Wait keyboard controller input buffer empty
676 //
677 Status = WaitInputEmpty (IsaIo, TIMEOUT);
678 if (EFI_ERROR (Status)) {
679 return Status;
680 }
681 //
682 // Send write to auxiliary device command
683 //
684 Data = WRITE_AUX_DEV;
685 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
686
687 Status = WaitInputEmpty (IsaIo, TIMEOUT);
688 if (EFI_ERROR (Status)) {
689 return Status;
690 }
691 //
692 // Send auxiliary device command
693 //
694 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command);
695
696 //
697 // Read return code
698 //
699 Status = In8042AuxData (IsaIo, &Data);
700 if (EFI_ERROR (Status)) {
701 return Status;
702 }
703
704 if (Data == PS2_ACK) {
705 //
706 // Receive mouse acknowledge, command send success
707 //
708 return EFI_SUCCESS;
709
710 } else if (Resend) {
711 //
712 // Resend fail
713 //
714 return EFI_DEVICE_ERROR;
715
716 } else if (Data == PS2_RESEND) {
717 //
718 // Resend command
719 //
720 Status = Out8042AuxCommand (IsaIo, Command, TRUE);
721 if (EFI_ERROR (Status)) {
722 return Status;
723 }
724
725 } else {
726 //
727 // Invalid return code
728 //
729 return EFI_DEVICE_ERROR;
730
731 }
732
733 return EFI_SUCCESS;
734 }
735
736 /**
737 I/O work flow of outing 8042 Aux data.
738
739 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
740 @param Data Buffer holding return value
741
742 @retval EFI_SUCCESS Success to excute I/O work flow
743 @retval EFI_TIMEOUT Keyboard controller time out.
744 **/
745 EFI_STATUS
746 Out8042AuxData (
747 IN EFI_ISA_IO_PROTOCOL *IsaIo,
748 IN UINT8 Data
749 )
750 {
751 EFI_STATUS Status;
752 UINT8 Temp;
753 //
754 // Wait keyboard controller input buffer empty
755 //
756 Status = WaitInputEmpty (IsaIo, TIMEOUT);
757 if (EFI_ERROR (Status)) {
758 return Status;
759 }
760 //
761 // Send write to auxiliary device command
762 //
763 Temp = WRITE_AUX_DEV;
764 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);
765
766 Status = WaitInputEmpty (IsaIo, TIMEOUT);
767 if (EFI_ERROR (Status)) {
768 return Status;
769 }
770
771 Temp = Data;
772 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);
773
774 Status = WaitInputEmpty (IsaIo, TIMEOUT);
775 if (EFI_ERROR (Status)) {
776 return Status;
777 }
778
779 return EFI_SUCCESS;
780 }
781
782 /**
783 I/O work flow of in 8042 Aux data.
784
785 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
786 @param Data Buffer holding return value.
787
788 @retval EFI_SUCCESS Success to excute I/O work flow
789 @retval EFI_TIMEOUT Keyboard controller time out.
790 **/
791 EFI_STATUS
792 In8042AuxData (
793 IN EFI_ISA_IO_PROTOCOL *IsaIo,
794 IN OUT UINT8 *Data
795 )
796 {
797 EFI_STATUS Status;
798
799 //
800 // wait for output data
801 //
802 Status = WaitOutputFull (IsaIo, BAT_TIMEOUT);
803 if (EFI_ERROR (Status)) {
804 return Status;
805 }
806
807 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);
808
809 return EFI_SUCCESS;
810 }
811
812
813 /**
814 Check keyboard controller status, if it is output buffer full and for auxiliary device.
815
816 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
817
818 @retval EFI_SUCCESS Keyboard controller is ready
819 @retval EFI_NOT_READY Keyboard controller is not ready
820 **/
821 EFI_STATUS
822 CheckForInput (
823 IN EFI_ISA_IO_PROTOCOL *IsaIo
824 )
825 {
826 UINT8 Data;
827
828 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
829
830 //
831 // Check keyboard controller status, if it is output buffer full and for auxiliary device
832 //
833 if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {
834 return EFI_NOT_READY;
835 }
836
837 return EFI_SUCCESS;
838 }
839
840 /**
841 I/O work flow to wait input buffer empty in given time.
842
843 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
844 @param Timeout Wating time.
845
846 @retval EFI_TIMEOUT if input is still not empty in given time.
847 @retval EFI_SUCCESS input is empty.
848 **/
849 EFI_STATUS
850 WaitInputEmpty (
851 IN EFI_ISA_IO_PROTOCOL *IsaIo,
852 IN UINTN Timeout
853 )
854 {
855 UINTN Delay;
856 UINT8 Data;
857
858 Delay = Timeout / 50;
859
860 do {
861 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
862
863 //
864 // Check keyboard controller status bit 1(input buffer status)
865 //
866 if ((Data & KBC_INPB) == 0) {
867 break;
868 }
869
870 gBS->Stall (50);
871 Delay--;
872 } while (Delay != 0);
873
874 if (Delay == 0) {
875 return EFI_TIMEOUT;
876 }
877
878 return EFI_SUCCESS;
879 }
880
881 /**
882 I/O work flow to wait output buffer full in given time.
883
884 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
885 @param Timeout given time
886
887 @retval EFI_TIMEOUT output is not full in given time
888 @retval EFI_SUCCESS output is full in given time.
889 **/
890 EFI_STATUS
891 WaitOutputFull (
892 IN EFI_ISA_IO_PROTOCOL *IsaIo,
893 IN UINTN Timeout
894 )
895 {
896 UINTN Delay;
897 UINT8 Data;
898
899 Delay = Timeout / 50;
900
901 do {
902 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
903
904 //
905 // Check keyboard controller status bit 0(output buffer status)
906 // & bit5(output buffer for auxiliary device)
907 //
908 if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {
909 break;
910 }
911
912 gBS->Stall (50);
913 Delay--;
914 } while (Delay != 0);
915
916 if (Delay == 0) {
917 return EFI_TIMEOUT;
918 }
919
920 return EFI_SUCCESS;
921 }