TianoCore EDK2 master
Loading...
Searching...
No Matches
CommPs2.c
Go to the documentation of this file.
1
9#include "Ps2Mouse.h"
10#include "CommPs2.h"
11
12UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };
13
14UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 };
15
24 VOID
25 )
26{
27 EFI_STATUS Status;
28 UINT8 Data;
29
30 //
31 // Keyboard controller self test
32 //
33 Status = Out8042Command (SELF_TEST);
34 if (EFI_ERROR (Status)) {
35 return Status;
36 }
37
38 //
39 // Read return code
40 //
41 Status = In8042Data (&Data);
42 if (EFI_ERROR (Status)) {
43 return Status;
44 }
45
46 if (Data != 0x55) {
47 return EFI_DEVICE_ERROR;
48 }
49
50 //
51 // Set system flag
52 //
53 Status = Out8042Command (READ_CMD_BYTE);
54 if (EFI_ERROR (Status)) {
55 return Status;
56 }
57
58 Status = In8042Data (&Data);
59 if (EFI_ERROR (Status)) {
60 return Status;
61 }
62
63 Status = Out8042Command (WRITE_CMD_BYTE);
64 if (EFI_ERROR (Status)) {
65 return Status;
66 }
67
68 Data |= CMD_SYS_FLAG;
69 Status = Out8042Data (Data);
70 if (EFI_ERROR (Status)) {
71 return Status;
72 }
73
74 return EFI_SUCCESS;
75}
76
84 VOID
85 )
86{
87 //
88 // Send 8042 enable mouse command
89 //
90 return Out8042Command (ENABLE_AUX);
91}
92
102 VOID
103 )
104{
105 //
106 // Send 8042 disable mouse command
107 //
108 return Out8042Command (DISABLE_AUX);
109}
110
120 VOID
121 )
122{
123 //
124 // Send 8042 enable keyboard command
125 //
126 return Out8042Command (ENABLE_KB);
127}
128
136 VOID
137 )
138{
139 //
140 // Send 8042 disable keyboard command
141 //
142 return Out8042Command (DISABLE_KB);
143}
144
154 OUT BOOLEAN *KeyboardEnable
155 )
156{
157 EFI_STATUS Status;
158 UINT8 Data;
159
160 //
161 // Send command to read KBC command byte
162 //
163 Status = Out8042Command (READ_CMD_BYTE);
164 if (EFI_ERROR (Status)) {
165 return Status;
166 }
167
168 Status = In8042Data (&Data);
169 if (EFI_ERROR (Status)) {
170 return Status;
171 }
172
173 //
174 // Check keyboard enable or not
175 //
176 if ((Data & CMD_KB_STS) == CMD_KB_DIS) {
177 *KeyboardEnable = FALSE;
178 } else {
179 *KeyboardEnable = TRUE;
180 }
181
182 return EFI_SUCCESS;
183}
184
192 VOID
193 )
194{
195 EFI_STATUS Status;
196 UINT8 Data;
197
198 Status = Out8042AuxCommand (RESET_CMD, FALSE);
199 if (EFI_ERROR (Status)) {
200 return Status;
201 }
202
203 Status = In8042AuxData (&Data);
204 if (EFI_ERROR (Status)) {
205 return Status;
206 }
207
208 //
209 // Check BAT Complete Code
210 //
211 if (Data != PS2MOUSE_BAT1) {
212 return EFI_DEVICE_ERROR;
213 }
214
215 Status = In8042AuxData (&Data);
216 if (EFI_ERROR (Status)) {
217 return Status;
218 }
219
220 //
221 // Check BAT Complete Code
222 //
223 if (Data != PS2MOUSE_BAT2) {
224 return EFI_DEVICE_ERROR;
225 }
226
227 return EFI_SUCCESS;
228}
229
239 IN MOUSE_SR SampleRate
240 )
241{
242 EFI_STATUS Status;
243
244 //
245 // Send auxiliary command to set mouse sample rate
246 //
247 Status = Out8042AuxCommand (SETSR_CMD, FALSE);
248 if (EFI_ERROR (Status)) {
249 return Status;
250 }
251
252 Status = Out8042AuxData (SampleRateTbl[SampleRate]);
253
254 return Status;
255}
256
266 IN MOUSE_RE Resolution
267 )
268{
269 EFI_STATUS Status;
270
271 //
272 // Send auxiliary command to set mouse resolution
273 //
274 Status = Out8042AuxCommand (SETRE_CMD, FALSE);
275 if (EFI_ERROR (Status)) {
276 return Status;
277 }
278
279 Status = Out8042AuxData (ResolutionTbl[Resolution]);
280
281 return Status;
282}
283
293 IN MOUSE_SF Scaling
294 )
295{
296 //
297 // Send auxiliary command to set mouse scaling data
298 //
299 return Out8042AuxCommand (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD, FALSE);
300}
301
309 VOID
310 )
311{
312 //
313 // Send auxiliary command to enable mouse
314 //
315 return Out8042AuxCommand (ENABLE_CMD, FALSE);
316}
317
329 PS2_MOUSE_DEV *MouseDev
330 )
331
332{
333 EFI_STATUS Status;
334 BOOLEAN KeyboardEnable;
335 UINT8 Packet[PS2_PACKET_LENGTH];
336 UINT8 Data;
337 UINTN Count;
338 UINTN State;
339 INT16 RelativeMovementX;
340 INT16 RelativeMovementY;
341 BOOLEAN LButton;
342 BOOLEAN RButton;
343
344 KeyboardEnable = FALSE;
345 State = PS2_READ_BYTE_ONE;
346
347 //
348 // State machine to get mouse packet
349 //
350 while (1) {
351 switch (State) {
352 case PS2_READ_BYTE_ONE:
353 //
354 // Read mouse first byte data, if failed, immediately return
355 //
356 KbcDisableAux ();
357 Count = 1;
358 Status = PS2MouseRead (&Data, &Count, State);
359 if (EFI_ERROR (Status)) {
360 KbcEnableAux ();
361 return EFI_NOT_READY;
362 }
363
364 if (Count != 1) {
365 KbcEnableAux ();
366 return EFI_NOT_READY;
367 }
368
369 if (IS_PS2_SYNC_BYTE (Data)) {
370 Packet[0] = Data;
371 State = PS2_READ_DATA_BYTE;
372
373 CheckKbStatus (&KeyboardEnable);
374 KbcDisableKb ();
375 KbcEnableAux ();
376 }
377
378 break;
379
380 case PS2_READ_DATA_BYTE:
381 Count = 2;
382 Status = PS2MouseRead ((Packet + 1), &Count, State);
383 if (EFI_ERROR (Status)) {
384 if (KeyboardEnable) {
385 KbcEnableKb ();
386 }
387
388 return EFI_NOT_READY;
389 }
390
391 if (Count != 2) {
392 if (KeyboardEnable) {
393 KbcEnableKb ();
394 }
395
396 return EFI_NOT_READY;
397 }
398
399 State = PS2_PROCESS_PACKET;
400 break;
401
402 case PS2_PROCESS_PACKET:
403 if (KeyboardEnable) {
404 KbcEnableKb ();
405 }
406
407 //
408 // Decode the packet
409 //
410 RelativeMovementX = Packet[1];
411 RelativeMovementY = Packet[2];
412 //
413 // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
414 // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn
415 // Byte 1 | 8 bit X Movement
416 // Byte 2 | 8 bit Y Movement
417 //
418 // 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.
419 // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.
420 //
421 //
422 // First, Clear X and Y high 8 bits
423 //
424 RelativeMovementX = (INT16)(RelativeMovementX & 0xFF);
425 RelativeMovementY = (INT16)(RelativeMovementY & 0xFF);
426 //
427 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
428 //
429 if ((Packet[0] & 0x10) != 0) {
430 RelativeMovementX = (INT16)(RelativeMovementX | 0xFF00);
431 }
432
433 if ((Packet[0] & 0x20) != 0) {
434 RelativeMovementY = (INT16)(RelativeMovementY | 0xFF00);
435 }
436
437 RButton = (UINT8)(Packet[0] & 0x2);
438 LButton = (UINT8)(Packet[0] & 0x1);
439
440 //
441 // Update mouse state
442 //
443 MouseDev->State.RelativeMovementX += RelativeMovementX;
444 MouseDev->State.RelativeMovementY -= RelativeMovementY;
445 MouseDev->State.RightButton = (UINT8)(RButton ? TRUE : FALSE);
446 MouseDev->State.LeftButton = (UINT8)(LButton ? TRUE : FALSE);
447 MouseDev->StateChanged = TRUE;
448
449 return EFI_SUCCESS;
450 }
451 }
452}
453
465 OUT UINT8 *Buffer,
466 IN OUT UINTN *BufSize,
467 IN UINTN State
468 )
469{
470 EFI_STATUS Status;
471 UINTN BytesRead;
472
473 Status = EFI_SUCCESS;
474
475 if (State == PS2_READ_BYTE_ONE) {
476 //
477 // Check input for mouse
478 //
479 Status = CheckForInput ();
480
481 if (EFI_ERROR (Status)) {
482 return Status;
483 }
484 }
485
486 for (BytesRead = 0; BytesRead < *BufSize; BytesRead++) {
487 Status = WaitOutputFull (TIMEOUT);
488 if (EFI_ERROR (Status)) {
489 break;
490 }
491
492 Buffer[BytesRead] = IoRead8 (KBC_DATA_PORT);
493 }
494
495 //
496 // Verify the correct number of bytes read
497 //
498 if ((BytesRead == 0) || (BytesRead != *BufSize)) {
499 Status = EFI_NOT_FOUND;
500 }
501
502 *BufSize = BytesRead;
503 return Status;
504}
505
506//
507// 8042 I/O function
508//
509
520 IN UINT8 Command
521 )
522{
523 EFI_STATUS Status;
524
525 //
526 // Wait keyboard controller input buffer empty
527 //
528 Status = WaitInputEmpty (TIMEOUT);
529 if (EFI_ERROR (Status)) {
530 return Status;
531 }
532
533 //
534 // Send command
535 //
536 IoWrite8 (KBC_CMD_STS_PORT, Command);
537
538 Status = WaitInputEmpty (TIMEOUT);
539 if (EFI_ERROR (Status)) {
540 return Status;
541 }
542
543 return EFI_SUCCESS;
544}
545
556 IN UINT8 Data
557 )
558{
559 EFI_STATUS Status;
560
561 //
562 // Wait keyboard controller input buffer empty
563 //
564 Status = WaitInputEmpty (TIMEOUT);
565 if (EFI_ERROR (Status)) {
566 return Status;
567 }
568
569 IoWrite8 (KBC_DATA_PORT, Data);
570 return WaitInputEmpty (TIMEOUT);
571}
572
583 IN OUT UINT8 *Data
584 )
585{
586 UINTN Delay;
587
588 Delay = TIMEOUT / 50;
589
590 do {
591 //
592 // Check keyboard controller status bit 0(output buffer status)
593 //
594 if ((IoRead8 (KBC_CMD_STS_PORT) & KBC_OUTB) == KBC_OUTB) {
595 break;
596 }
597
598 gBS->Stall (50);
599 Delay--;
600 } while (Delay != 0);
601
602 if (Delay == 0) {
603 return EFI_TIMEOUT;
604 }
605
606 *Data = IoRead8 (KBC_DATA_PORT);
607
608 return EFI_SUCCESS;
609}
610
622 IN UINT8 Command,
623 IN BOOLEAN Resend
624 )
625{
626 EFI_STATUS Status;
627 UINT8 Data;
628
629 //
630 // Wait keyboard controller input buffer empty
631 //
632 Status = WaitInputEmpty (TIMEOUT);
633 if (EFI_ERROR (Status)) {
634 return Status;
635 }
636
637 //
638 // Send write to auxiliary device command
639 //
640 IoWrite8 (KBC_CMD_STS_PORT, WRITE_AUX_DEV);
641
642 Status = WaitInputEmpty (TIMEOUT);
643 if (EFI_ERROR (Status)) {
644 return Status;
645 }
646
647 //
648 // Send auxiliary device command
649 //
650 IoWrite8 (KBC_DATA_PORT, Command);
651
652 //
653 // Read return code
654 //
655 Status = In8042AuxData (&Data);
656 if (EFI_ERROR (Status)) {
657 return Status;
658 }
659
660 if (Data == PS2_ACK) {
661 //
662 // Receive mouse acknowledge, command send success
663 //
664 return EFI_SUCCESS;
665 } else if (Resend) {
666 //
667 // Resend fail
668 //
669 return EFI_DEVICE_ERROR;
670 } else if (Data == PS2_RESEND) {
671 //
672 // Resend command
673 //
674 Status = Out8042AuxCommand (Command, TRUE);
675 if (EFI_ERROR (Status)) {
676 return Status;
677 }
678 } else {
679 //
680 // Invalid return code
681 //
682 return EFI_DEVICE_ERROR;
683 }
684
685 return EFI_SUCCESS;
686}
687
698 IN UINT8 Data
699 )
700{
701 EFI_STATUS Status;
702
703 //
704 // Wait keyboard controller input buffer empty
705 //
706 Status = WaitInputEmpty (TIMEOUT);
707 if (EFI_ERROR (Status)) {
708 return Status;
709 }
710
711 //
712 // Send write to auxiliary device command
713 //
714 IoWrite8 (KBC_CMD_STS_PORT, WRITE_AUX_DEV);
715
716 Status = WaitInputEmpty (TIMEOUT);
717 if (EFI_ERROR (Status)) {
718 return Status;
719 }
720
721 IoWrite8 (KBC_DATA_PORT, Data);
722
723 Status = WaitInputEmpty (TIMEOUT);
724 if (EFI_ERROR (Status)) {
725 return Status;
726 }
727
728 return EFI_SUCCESS;
729}
730
741 IN OUT UINT8 *Data
742 )
743{
744 EFI_STATUS Status;
745
746 //
747 // wait for output data
748 //
749 Status = WaitOutputFull (BAT_TIMEOUT);
750 if (EFI_ERROR (Status)) {
751 return Status;
752 }
753
754 *Data = IoRead8 (KBC_DATA_PORT);
755
756 return EFI_SUCCESS;
757}
758
767 VOID
768 )
769{
770 UINT8 Data;
771
772 Data = IoRead8 (KBC_CMD_STS_PORT);
773
774 //
775 // Check keyboard controller status, if it is output buffer full and for auxiliary device
776 //
777 if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {
778 return EFI_NOT_READY;
779 }
780
781 return EFI_SUCCESS;
782}
783
794 IN UINTN Timeout
795 )
796{
797 UINTN Delay;
798 UINT8 Data;
799
800 Delay = Timeout / 50;
801
802 do {
803 Data = IoRead8 (KBC_CMD_STS_PORT);
804
805 //
806 // Check keyboard controller status bit 1(input buffer status)
807 //
808 if ((Data & KBC_INPB) == 0) {
809 break;
810 }
811
812 gBS->Stall (50);
813 Delay--;
814 } while (Delay != 0);
815
816 if (Delay == 0) {
817 return EFI_TIMEOUT;
818 }
819
820 return EFI_SUCCESS;
821}
822
833 IN UINTN Timeout
834 )
835{
836 UINTN Delay;
837 UINT8 Data;
838
839 Delay = Timeout / 50;
840
841 do {
842 Data = IoRead8 (KBC_CMD_STS_PORT);
843
844 //
845 // Check keyboard controller status bit 0(output buffer status)
846 // & bit5(output buffer for auxiliary device)
847 //
848 if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {
849 break;
850 }
851
852 gBS->Stall (50);
853 Delay--;
854 } while (Delay != 0);
855
856 if (Delay == 0) {
857 return EFI_TIMEOUT;
858 }
859
860 return EFI_SUCCESS;
861}
UINT64 UINTN
EFI_STATUS PS2MouseReset(VOID)
Definition: CommPs2.c:191
EFI_STATUS In8042AuxData(IN OUT UINT8 *Data)
Definition: CommPs2.c:740
EFI_STATUS CheckKbStatus(OUT BOOLEAN *KeyboardEnable)
Definition: CommPs2.c:153
EFI_STATUS PS2MouseSetResolution(IN MOUSE_RE Resolution)
Definition: CommPs2.c:265
EFI_STATUS Out8042AuxCommand(IN UINT8 Command, IN BOOLEAN Resend)
Definition: CommPs2.c:621
EFI_STATUS Out8042Data(IN UINT8 Data)
Definition: CommPs2.c:555
EFI_STATUS Out8042AuxData(IN UINT8 Data)
Definition: CommPs2.c:697
EFI_STATUS PS2MouseRead(OUT UINT8 *Buffer, IN OUT UINTN *BufSize, IN UINTN State)
Definition: CommPs2.c:464
EFI_STATUS In8042Data(IN OUT UINT8 *Data)
Definition: CommPs2.c:582
EFI_STATUS KbcEnableAux(VOID)
Definition: CommPs2.c:83
EFI_STATUS CheckForInput(VOID)
Definition: CommPs2.c:766
EFI_STATUS PS2MouseSetSampleRate(IN MOUSE_SR SampleRate)
Definition: CommPs2.c:238
EFI_STATUS PS2MouseSetScaling(IN MOUSE_SF Scaling)
Definition: CommPs2.c:292
EFI_STATUS PS2MouseEnable(VOID)
Definition: CommPs2.c:308
EFI_STATUS PS2MouseGetPacket(PS2_MOUSE_DEV *MouseDev)
Definition: CommPs2.c:328
EFI_STATUS WaitInputEmpty(IN UINTN Timeout)
Definition: CommPs2.c:793
EFI_STATUS KbcDisableAux(VOID)
Definition: CommPs2.c:101
EFI_STATUS KbcSelfTest(VOID)
Definition: CommPs2.c:23
EFI_STATUS WaitOutputFull(IN UINTN Timeout)
Definition: CommPs2.c:832
EFI_STATUS KbcDisableKb(VOID)
Definition: CommPs2.c:135
EFI_STATUS KbcEnableKb(VOID)
Definition: CommPs2.c:119
EFI_STATUS Out8042Command(IN UINT8 Command)
Definition: CommPs2.c:519
#define KBC_INPB
Definition: CommPs2.h:111
#define KBC_OUTB
Definition: CommPs2.h:117
#define KBC_AUXB
Definition: CommPs2.h:87
UINT8 EFIAPI IoWrite8(IN UINTN Port, IN UINT8 Value)
Definition: IoLibArmVirt.c:200
UINT8 EFIAPI IoRead8(IN UINTN Port)
Definition: IoLibArmVirt.c:175
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS