]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
2 PS2 Mouse Communication Interface.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 UINT8 SampleRateTbl
[ MaxSampleRate
] = { 0xa , 0x14 , 0x28 , 0x3c , 0x50 , 0x64 , 0xc8 };
14 UINT8 ResolutionTbl
[ MaxResolution
] = { 0 , 1 , 2 , 3 };
17 Issue self test command via IsaIo interface.
19 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
21 @return EFI_SUCCESS Success to do keyboard self testing.
22 @return others Fail to do keyboard self testing.
26 IN EFI_ISA_IO_PROTOCOL
* IsaIo
33 // Keyboard controller self test
35 Status
= Out8042Command ( IsaIo
, SELF_TEST
);
36 if ( EFI_ERROR ( Status
)) {
42 Status
= In8042Data ( IsaIo
, & Data
);
43 if ( EFI_ERROR ( Status
)) {
48 return EFI_DEVICE_ERROR
;
53 Status
= Out8042Command ( IsaIo
, READ_CMD_BYTE
);
54 if ( EFI_ERROR ( Status
)) {
58 Status
= In8042Data ( IsaIo
, & Data
);
59 if ( EFI_ERROR ( Status
)) {
63 Status
= Out8042Command ( IsaIo
, WRITE_CMD_BYTE
);
64 if ( EFI_ERROR ( Status
)) {
69 Status
= Out8042Data ( IsaIo
, Data
);
70 if ( EFI_ERROR ( Status
)) {
78 Issue command to enable keyboard AUX functionality.
80 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
82 @return Status of command issuing.
86 IN EFI_ISA_IO_PROTOCOL
* IsaIo
90 // Send 8042 enable mouse command
92 return Out8042Command ( IsaIo
, ENABLE_AUX
);
96 Issue command to disable keyboard AUX functionality.
98 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
100 @return Status of command issuing.
104 IN EFI_ISA_IO_PROTOCOL
* IsaIo
108 // Send 8042 disable mouse command
110 return Out8042Command ( IsaIo
, DISABLE_AUX
);
114 Issue command to enable keyboard.
116 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
118 @return Status of command issuing.
122 IN EFI_ISA_IO_PROTOCOL
* IsaIo
126 // Send 8042 enable keyboard command
128 return Out8042Command ( IsaIo
, ENABLE_KB
);
132 Issue command to disable keyboard.
134 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
136 @return Status of command issuing.
140 IN EFI_ISA_IO_PROTOCOL
* IsaIo
144 // Send 8042 disable keyboard command
146 return Out8042Command ( IsaIo
, DISABLE_KB
);
150 Issue command to check keyboard status.
152 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
153 @param KeyboardEnable return whether keyboard is enable.
155 @return Status of command issuing.
159 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
160 OUT BOOLEAN
* KeyboardEnable
167 // Send command to read KBC command byte
169 Status
= Out8042Command ( IsaIo
, READ_CMD_BYTE
);
170 if ( EFI_ERROR ( Status
)) {
174 Status
= In8042Data ( IsaIo
, & Data
);
175 if ( EFI_ERROR ( Status
)) {
179 // Check keyboard enable or not
181 if (( Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
182 * KeyboardEnable
= FALSE
;
184 * KeyboardEnable
= TRUE
;
191 Issue command to reset keyboard.
193 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
195 @return Status of command issuing.
199 IN EFI_ISA_IO_PROTOCOL
* IsaIo
205 Status
= Out8042AuxCommand ( IsaIo
, RESET_CMD
, FALSE
);
206 if ( EFI_ERROR ( Status
)) {
210 Status
= In8042AuxData ( IsaIo
, & Data
);
211 if ( EFI_ERROR ( Status
)) {
215 // Check BAT Complete Code
217 if ( Data
!= PS2MOUSE_BAT1
) {
218 return EFI_DEVICE_ERROR
;
221 Status
= In8042AuxData ( IsaIo
, & Data
);
222 if ( EFI_ERROR ( Status
)) {
226 // Check BAT Complete Code
228 if ( Data
!= PS2MOUSE_BAT2
) {
229 return EFI_DEVICE_ERROR
;
236 Issue command to set mouse's sample rate
238 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
239 @param SampleRate value of sample rate
241 @return Status of command issuing.
244 PS2MouseSetSampleRate (
245 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
246 IN MOUSE_SR SampleRate
252 // Send auxiliary command to set mouse sample rate
254 Status
= Out8042AuxCommand ( IsaIo
, SETSR_CMD
, FALSE
);
255 if ( EFI_ERROR ( Status
)) {
259 Status
= Out8042AuxData ( IsaIo
, SampleRateTbl
[ SampleRate
]);
265 Issue command to set mouse's resolution.
267 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
268 @param Resolution value of resolution
270 @return Status of command issuing.
273 PS2MouseSetResolution (
274 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
275 IN MOUSE_RE Resolution
281 // Send auxiliary command to set mouse resolution
283 Status
= Out8042AuxCommand ( IsaIo
, SETRE_CMD
, FALSE
);
284 if ( EFI_ERROR ( Status
)) {
288 Status
= Out8042AuxData ( IsaIo
, ResolutionTbl
[ Resolution
]);
294 Issue command to set mouse's scaling.
296 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
297 @param Scaling value of scaling
299 @return Status of command issuing.
303 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
309 Command
= ( UINT8
) ( Scaling
== Scaling1
? SETSF1_CMD
: SETSF2_CMD
);
312 // Send auxiliary command to set mouse scaling data
314 return Out8042AuxCommand ( IsaIo
, Command
, FALSE
);
318 Issue command to enable Ps2 mouse.
320 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
322 @return Status of command issuing.
326 IN EFI_ISA_IO_PROTOCOL
* IsaIo
330 // Send auxiliary command to enable mouse
332 return Out8042AuxCommand ( IsaIo
, ENABLE_CMD
, FALSE
);
336 Get mouse packet . Only care first 3 bytes
338 @param MouseDev Pointer of PS2 Mouse Private Data Structure
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.
346 PS2_MOUSE_DEV
* MouseDev
351 BOOLEAN KeyboardEnable
;
352 UINT8 Packet
[ PS2_PACKET_LENGTH
];
356 INT16 RelativeMovementX
;
357 INT16 RelativeMovementY
;
361 KeyboardEnable
= FALSE
;
363 State
= PS2_READ_BYTE_ONE
;
366 // State machine to get mouse packet
371 case PS2_READ_BYTE_ONE
:
373 // Read mouse first byte data, if failed, immediately return
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
;
383 KbcEnableAux ( MouseDev
-> IsaIo
);
384 return EFI_NOT_READY
;
387 if ( IS_PS2_SYNC_BYTE ( Data
)) {
389 State
= PS2_READ_DATA_BYTE
;
391 CheckKbStatus ( MouseDev
-> IsaIo
, & KeyboardEnable
);
392 KbcDisableKb ( MouseDev
-> IsaIo
);
393 KbcEnableAux ( MouseDev
-> IsaIo
);
397 case PS2_READ_DATA_BYTE
:
399 Status
= PS2MouseRead ( MouseDev
-> IsaIo
, ( Packet
+ 1 ), & Count
, State
);
400 if ( EFI_ERROR ( Status
)) {
401 if ( KeyboardEnable
) {
402 KbcEnableKb ( MouseDev
-> IsaIo
);
405 return EFI_NOT_READY
;
409 if ( KeyboardEnable
) {
410 KbcEnableKb ( MouseDev
-> IsaIo
);
413 return EFI_NOT_READY
;
416 State
= PS2_PROCESS_PACKET
;
419 case PS2_PROCESS_PACKET
:
420 if ( KeyboardEnable
) {
421 KbcEnableKb ( MouseDev
-> IsaIo
);
426 RelativeMovementX
= Packet
[ 1 ];
427 RelativeMovementY
= Packet
[ 2 ];
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
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.
438 // First, Clear X and Y high 8 bits
440 RelativeMovementX
= ( INT16
) ( RelativeMovementX
& 0xFF );
441 RelativeMovementY
= ( INT16
) ( RelativeMovementY
& 0xFF );
443 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
445 if (( Packet
[ 0 ] & 0x10 ) != 0 ) {
446 RelativeMovementX
= ( INT16
) ( RelativeMovementX
| 0xFF00 );
448 if (( Packet
[ 0 ] & 0x20 ) != 0 ) {
449 RelativeMovementY
= ( INT16
) ( RelativeMovementY
| 0xFF00 );
453 RButton
= ( UINT8
) ( Packet
[ 0 ] & 0x2 );
454 LButton
= ( UINT8
) ( Packet
[ 0 ] & 0x1 );
457 // Update mouse state
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
;
471 Read data via IsaIo protocol with given number.
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
478 @return status of reading mouse data.
482 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
484 IN OUT UINTN
* BufSize
,
491 Status
= EFI_SUCCESS
;
494 if ( State
== PS2_READ_BYTE_ONE
) {
496 // Check input for mouse
498 Status
= CheckForInput ( IsaIo
);
500 if ( EFI_ERROR ( Status
)) {
505 while ( BytesRead
< * BufSize
) {
507 Status
= WaitOutputFull ( IsaIo
, TIMEOUT
);
508 if ( EFI_ERROR ( Status
)) {
512 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Buffer
);
515 Buffer
= ( UINT8
*) Buffer
+ 1 ;
518 // Verify the correct number of bytes read
520 if ( BytesRead
== 0 || BytesRead
!= * BufSize
) {
521 Status
= EFI_NOT_FOUND
;
524 * BufSize
= BytesRead
;
531 I/O work flow of outing 8042 command.
533 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
534 @param Command I/O command.
536 @retval EFI_SUCCESS Success to execute I/O work flow
537 @retval EFI_TIMEOUT Keyboard controller time out.
541 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
549 // Wait keyboard controller input buffer empty
551 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
552 if ( EFI_ERROR ( Status
)) {
559 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
561 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
562 if ( EFI_ERROR ( Status
)) {
570 I/O work flow of outing 8042 data.
572 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
573 @param Data Data value
575 @retval EFI_SUCCESS Success to execute I/O work flow
576 @retval EFI_TIMEOUT Keyboard controller time out.
580 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
587 // Wait keyboard controller input buffer empty
589 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
590 if ( EFI_ERROR ( Status
)) {
595 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Temp
);
597 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
598 if ( EFI_ERROR ( Status
)) {
606 I/O work flow of in 8042 data.
608 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
609 @param Data Data value
611 @retval EFI_SUCCESS Success to execute I/O work flow
612 @retval EFI_TIMEOUT Keyboard controller time out.
616 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
623 Delay
= TIMEOUT
/ 50 ;
626 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Temp
);
629 // Check keyboard controller status bit 0(output buffer status)
631 if (( Temp
& KBC_OUTB
) == KBC_OUTB
) {
637 } while ( Delay
!= 0 );
643 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Data
);
649 I/O work flow of outing 8042 Aux command.
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.
655 @retval EFI_SUCCESS Success to execute I/O work flow
656 @retval EFI_TIMEOUT Keyboard controller time out.
660 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
669 // Wait keyboard controller input buffer empty
671 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
672 if ( EFI_ERROR ( Status
)) {
676 // Send write to auxiliary device command
678 Data
= WRITE_AUX_DEV
;
679 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
681 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
682 if ( EFI_ERROR ( Status
)) {
686 // Send auxiliary device command
688 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Command
);
693 Status
= In8042AuxData ( IsaIo
, & Data
);
694 if ( EFI_ERROR ( Status
)) {
698 if ( Data
== PS2_ACK
) {
700 // Receive mouse acknowledge, command send success
708 return EFI_DEVICE_ERROR
;
710 } else if ( Data
== PS2_RESEND
) {
714 Status
= Out8042AuxCommand ( IsaIo
, Command
, TRUE
);
715 if ( EFI_ERROR ( Status
)) {
721 // Invalid return code
723 return EFI_DEVICE_ERROR
;
731 I/O work flow of outing 8042 Aux data.
733 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
734 @param Data Buffer holding return value
736 @retval EFI_SUCCESS Success to execute I/O work flow
737 @retval EFI_TIMEOUT Keyboard controller time out.
741 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
748 // Wait keyboard controller input buffer empty
750 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
751 if ( EFI_ERROR ( Status
)) {
755 // Send write to auxiliary device command
757 Temp
= WRITE_AUX_DEV
;
758 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Temp
);
760 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
761 if ( EFI_ERROR ( Status
)) {
766 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Temp
);
768 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
769 if ( EFI_ERROR ( Status
)) {
777 I/O work flow of in 8042 Aux data.
779 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
780 @param Data Buffer holding return value.
782 @retval EFI_SUCCESS Success to execute I/O work flow
783 @retval EFI_TIMEOUT Keyboard controller time out.
787 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
794 // wait for output data
796 Status
= WaitOutputFull ( IsaIo
, BAT_TIMEOUT
);
797 if ( EFI_ERROR ( Status
)) {
801 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Data
);
808 Check keyboard controller status, if it is output buffer full and for auxiliary device.
810 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
812 @retval EFI_SUCCESS Keyboard controller is ready
813 @retval EFI_NOT_READY Keyboard controller is not ready
817 IN EFI_ISA_IO_PROTOCOL
* IsaIo
822 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
825 // Check keyboard controller status, if it is output buffer full and for auxiliary device
827 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) != ( KBC_OUTB
| KBC_AUXB
)) {
828 return EFI_NOT_READY
;
835 I/O work flow to wait input buffer empty in given time.
837 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
838 @param Timeout Wating time.
840 @retval EFI_TIMEOUT if input is still not empty in given time.
841 @retval EFI_SUCCESS input is empty.
845 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
852 Delay
= Timeout
/ 50 ;
855 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
858 // Check keyboard controller status bit 1(input buffer status)
860 if (( Data
& KBC_INPB
) == 0 ) {
866 } while ( Delay
!= 0 );
876 I/O work flow to wait output buffer full in given time.
878 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
879 @param Timeout given time
881 @retval EFI_TIMEOUT output is not full in given time
882 @retval EFI_SUCCESS output is full in given time.
886 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
893 Delay
= Timeout
/ 50 ;
896 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
899 // Check keyboard controller status bit 0(output buffer status)
900 // & bit5(output buffer for auxiliary device)
902 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) == ( KBC_OUTB
| KBC_AUXB
)) {
908 } while ( Delay
!= 0 );