]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2MouseDxe / 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 "Ps2Mouse.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 MouseDev Pointer of PS2 Mouse 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_DEV *MouseDev
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 (MouseDev->IsaIo);
376 Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State);
377 if (EFI_ERROR (Status)) {
378 KbcEnableAux (MouseDev->IsaIo);
379 return EFI_NOT_READY;
380 }
381
382 if (Count != 1) {
383 KbcEnableAux (MouseDev->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 (MouseDev->IsaIo, &KeyboardEnable);
392 KbcDisableKb (MouseDev->IsaIo);
393 KbcEnableAux (MouseDev->IsaIo);
394 }
395 break;
396
397 case PS2_READ_DATA_BYTE:
398 Count = 2;
399 Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State);
400 if (EFI_ERROR (Status)) {
401 if (KeyboardEnable) {
402 KbcEnableKb (MouseDev->IsaIo);
403 }
404
405 return EFI_NOT_READY;
406 }
407
408 if (Count != 2) {
409 if (KeyboardEnable) {
410 KbcEnableKb (MouseDev->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 (MouseDev->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 MouseDev->State.RelativeMovementX += RelativeMovementX;
460 MouseDev->State.RelativeMovementY -= RelativeMovementY;
461 MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE);
462 MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE);
463 MouseDev->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 // 8042 I/O function
529 //
530 /**
531 I/O work flow of outing 8042 command.
532
533 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
534 @param Command I/O command.
535
536 @retval EFI_SUCCESS Success to execute I/O work flow
537 @retval EFI_TIMEOUT Keyboard controller time out.
538 **/
539 EFI_STATUS
540 Out8042Command (
541 IN EFI_ISA_IO_PROTOCOL *IsaIo,
542 IN UINT8 Command
543 )
544 {
545 EFI_STATUS Status;
546 UINT8 Data;
547
548 //
549 // Wait keyboard controller input buffer empty
550 //
551 Status = WaitInputEmpty (IsaIo, TIMEOUT);
552 if (EFI_ERROR (Status)) {
553 return Status;
554 }
555 //
556 // Send command
557 //
558 Data = Command;
559 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
560
561 Status = WaitInputEmpty (IsaIo, TIMEOUT);
562 if (EFI_ERROR (Status)) {
563 return Status;
564 }
565
566 return EFI_SUCCESS;
567 }
568
569 /**
570 I/O work flow of outing 8042 data.
571
572 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
573 @param Data Data value
574
575 @retval EFI_SUCCESS Success to execute I/O work flow
576 @retval EFI_TIMEOUT Keyboard controller time out.
577 **/
578 EFI_STATUS
579 Out8042Data (
580 IN EFI_ISA_IO_PROTOCOL *IsaIo,
581 IN UINT8 Data
582 )
583 {
584 EFI_STATUS Status;
585 UINT8 Temp;
586 //
587 // Wait keyboard controller input buffer empty
588 //
589 Status = WaitInputEmpty (IsaIo, TIMEOUT);
590 if (EFI_ERROR (Status)) {
591 return Status;
592 }
593
594 Temp = Data;
595 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);
596
597 Status = WaitInputEmpty (IsaIo, TIMEOUT);
598 if (EFI_ERROR (Status)) {
599 return Status;
600 }
601
602 return EFI_SUCCESS;
603 }
604
605 /**
606 I/O work flow of in 8042 data.
607
608 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
609 @param Data Data value
610
611 @retval EFI_SUCCESS Success to execute I/O work flow
612 @retval EFI_TIMEOUT Keyboard controller time out.
613 **/
614 EFI_STATUS
615 In8042Data (
616 IN EFI_ISA_IO_PROTOCOL *IsaIo,
617 IN OUT UINT8 *Data
618 )
619 {
620 UINTN Delay;
621 UINT8 Temp;
622
623 Delay = TIMEOUT / 50;
624
625 do {
626 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);
627
628 //
629 // Check keyboard controller status bit 0(output buffer status)
630 //
631 if ((Temp & KBC_OUTB) == KBC_OUTB) {
632 break;
633 }
634
635 gBS->Stall (50);
636 Delay--;
637 } while (Delay != 0);
638
639 if (Delay == 0) {
640 return EFI_TIMEOUT;
641 }
642
643 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);
644
645 return EFI_SUCCESS;
646 }
647
648 /**
649 I/O work flow of outing 8042 Aux command.
650
651 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
652 @param Command Aux I/O command
653 @param Resend Whether need resend the Aux command.
654
655 @retval EFI_SUCCESS Success to execute I/O work flow
656 @retval EFI_TIMEOUT Keyboard controller time out.
657 **/
658 EFI_STATUS
659 Out8042AuxCommand (
660 IN EFI_ISA_IO_PROTOCOL *IsaIo,
661 IN UINT8 Command,
662 IN BOOLEAN Resend
663 )
664 {
665 EFI_STATUS Status;
666 UINT8 Data;
667
668 //
669 // Wait keyboard controller input buffer empty
670 //
671 Status = WaitInputEmpty (IsaIo, TIMEOUT);
672 if (EFI_ERROR (Status)) {
673 return Status;
674 }
675 //
676 // Send write to auxiliary device command
677 //
678 Data = WRITE_AUX_DEV;
679 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
680
681 Status = WaitInputEmpty (IsaIo, TIMEOUT);
682 if (EFI_ERROR (Status)) {
683 return Status;
684 }
685 //
686 // Send auxiliary device command
687 //
688 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command);
689
690 //
691 // Read return code
692 //
693 Status = In8042AuxData (IsaIo, &Data);
694 if (EFI_ERROR (Status)) {
695 return Status;
696 }
697
698 if (Data == PS2_ACK) {
699 //
700 // Receive mouse acknowledge, command send success
701 //
702 return EFI_SUCCESS;
703
704 } else if (Resend) {
705 //
706 // Resend fail
707 //
708 return EFI_DEVICE_ERROR;
709
710 } else if (Data == PS2_RESEND) {
711 //
712 // Resend command
713 //
714 Status = Out8042AuxCommand (IsaIo, Command, TRUE);
715 if (EFI_ERROR (Status)) {
716 return Status;
717 }
718
719 } else {
720 //
721 // Invalid return code
722 //
723 return EFI_DEVICE_ERROR;
724
725 }
726
727 return EFI_SUCCESS;
728 }
729
730 /**
731 I/O work flow of outing 8042 Aux data.
732
733 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
734 @param Data Buffer holding return value
735
736 @retval EFI_SUCCESS Success to execute I/O work flow
737 @retval EFI_TIMEOUT Keyboard controller time out.
738 **/
739 EFI_STATUS
740 Out8042AuxData (
741 IN EFI_ISA_IO_PROTOCOL *IsaIo,
742 IN UINT8 Data
743 )
744 {
745 EFI_STATUS Status;
746 UINT8 Temp;
747 //
748 // Wait keyboard controller input buffer empty
749 //
750 Status = WaitInputEmpty (IsaIo, TIMEOUT);
751 if (EFI_ERROR (Status)) {
752 return Status;
753 }
754 //
755 // Send write to auxiliary device command
756 //
757 Temp = WRITE_AUX_DEV;
758 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);
759
760 Status = WaitInputEmpty (IsaIo, TIMEOUT);
761 if (EFI_ERROR (Status)) {
762 return Status;
763 }
764
765 Temp = Data;
766 IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);
767
768 Status = WaitInputEmpty (IsaIo, TIMEOUT);
769 if (EFI_ERROR (Status)) {
770 return Status;
771 }
772
773 return EFI_SUCCESS;
774 }
775
776 /**
777 I/O work flow of in 8042 Aux data.
778
779 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
780 @param Data Buffer holding return value.
781
782 @retval EFI_SUCCESS Success to execute I/O work flow
783 @retval EFI_TIMEOUT Keyboard controller time out.
784 **/
785 EFI_STATUS
786 In8042AuxData (
787 IN EFI_ISA_IO_PROTOCOL *IsaIo,
788 IN OUT UINT8 *Data
789 )
790 {
791 EFI_STATUS Status;
792
793 //
794 // wait for output data
795 //
796 Status = WaitOutputFull (IsaIo, BAT_TIMEOUT);
797 if (EFI_ERROR (Status)) {
798 return Status;
799 }
800
801 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);
802
803 return EFI_SUCCESS;
804 }
805
806
807 /**
808 Check keyboard controller status, if it is output buffer full and for auxiliary device.
809
810 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
811
812 @retval EFI_SUCCESS Keyboard controller is ready
813 @retval EFI_NOT_READY Keyboard controller is not ready
814 **/
815 EFI_STATUS
816 CheckForInput (
817 IN EFI_ISA_IO_PROTOCOL *IsaIo
818 )
819 {
820 UINT8 Data;
821
822 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
823
824 //
825 // Check keyboard controller status, if it is output buffer full and for auxiliary device
826 //
827 if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {
828 return EFI_NOT_READY;
829 }
830
831 return EFI_SUCCESS;
832 }
833
834 /**
835 I/O work flow to wait input buffer empty in given time.
836
837 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
838 @param Timeout Wating time.
839
840 @retval EFI_TIMEOUT if input is still not empty in given time.
841 @retval EFI_SUCCESS input is empty.
842 **/
843 EFI_STATUS
844 WaitInputEmpty (
845 IN EFI_ISA_IO_PROTOCOL *IsaIo,
846 IN UINTN Timeout
847 )
848 {
849 UINTN Delay;
850 UINT8 Data;
851
852 Delay = Timeout / 50;
853
854 do {
855 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
856
857 //
858 // Check keyboard controller status bit 1(input buffer status)
859 //
860 if ((Data & KBC_INPB) == 0) {
861 break;
862 }
863
864 gBS->Stall (50);
865 Delay--;
866 } while (Delay != 0);
867
868 if (Delay == 0) {
869 return EFI_TIMEOUT;
870 }
871
872 return EFI_SUCCESS;
873 }
874
875 /**
876 I/O work flow to wait output buffer full in given time.
877
878 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
879 @param Timeout given time
880
881 @retval EFI_TIMEOUT output is not full in given time
882 @retval EFI_SUCCESS output is full in given time.
883 **/
884 EFI_STATUS
885 WaitOutputFull (
886 IN EFI_ISA_IO_PROTOCOL *IsaIo,
887 IN UINTN Timeout
888 )
889 {
890 UINTN Delay;
891 UINT8 Data;
892
893 Delay = Timeout / 50;
894
895 do {
896 IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
897
898 //
899 // Check keyboard controller status bit 0(output buffer status)
900 // & bit5(output buffer for auxiliary device)
901 //
902 if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {
903 break;
904 }
905
906 gBS->Stall (50);
907 Delay--;
908 } while (Delay != 0);
909
910 if (Delay == 0) {
911 return EFI_TIMEOUT;
912 }
913
914 return EFI_SUCCESS;
915 }