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