]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/CommPs2.c
2 PS2 Mouse Communication Interface.
4 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
5 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
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.
18 UINT8 SampleRateTbl
[ MaxSampleRate
] = { 0xa , 0x14 , 0x28 , 0x3c , 0x50 , 0x64 , 0xc8 };
20 UINT8 ResolutionTbl
[ MaxResolution
] = { 0 , 1 , 2 , 3 };
23 Issue self test command via IsaIo interface.
25 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
27 @return EFI_SUCCESS Success to do keyboard self testing.
28 @return others Fail to do keyboard self testing.
32 IN EFI_ISA_IO_PROTOCOL
* IsaIo
39 // Keyboard controller self test
41 Status
= Out8042Command ( IsaIo
, SELF_TEST
);
42 if ( EFI_ERROR ( Status
)) {
48 Status
= In8042Data ( IsaIo
, & Data
);
49 if ( EFI_ERROR ( Status
)) {
54 return EFI_DEVICE_ERROR
;
59 Status
= Out8042Command ( IsaIo
, READ_CMD_BYTE
);
60 if ( EFI_ERROR ( Status
)) {
64 Status
= In8042Data ( IsaIo
, & Data
);
65 if ( EFI_ERROR ( Status
)) {
69 Status
= Out8042Command ( IsaIo
, WRITE_CMD_BYTE
);
70 if ( EFI_ERROR ( Status
)) {
75 Status
= Out8042Data ( IsaIo
, Data
);
76 if ( EFI_ERROR ( Status
)) {
84 Issue command to enable keyboard AUX functionality.
86 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
88 @return Status of command issuing.
92 IN EFI_ISA_IO_PROTOCOL
* IsaIo
96 // Send 8042 enable mouse command
98 return Out8042Command ( IsaIo
, ENABLE_AUX
);
102 Issue command to disable keyboard AUX functionality.
104 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
106 @return Status of command issuing.
110 IN EFI_ISA_IO_PROTOCOL
* IsaIo
114 // Send 8042 disable mouse command
116 return Out8042Command ( IsaIo
, DISABLE_AUX
);
120 Issue command to enable keyboard.
122 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
124 @return Status of command issuing.
128 IN EFI_ISA_IO_PROTOCOL
* IsaIo
132 // Send 8042 enable keyboard command
134 return Out8042Command ( IsaIo
, ENABLE_KB
);
138 Issue command to disable keyboard.
140 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
142 @return Status of command issuing.
146 IN EFI_ISA_IO_PROTOCOL
* IsaIo
150 // Send 8042 disable keyboard command
152 return Out8042Command ( IsaIo
, DISABLE_KB
);
156 Issue command to check keyboard status.
158 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
159 @param KeyboardEnable return whether keyboard is enable.
161 @return Status of command issuing.
165 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
166 OUT BOOLEAN
* KeyboardEnable
173 // Send command to read KBC command byte
175 Status
= Out8042Command ( IsaIo
, READ_CMD_BYTE
);
176 if ( EFI_ERROR ( Status
)) {
180 Status
= In8042Data ( IsaIo
, & Data
);
181 if ( EFI_ERROR ( Status
)) {
185 // Check keyboard enable or not
187 if (( Data
& CMD_KB_STS
) == CMD_KB_DIS
) {
188 * KeyboardEnable
= FALSE
;
190 * KeyboardEnable
= TRUE
;
197 Issue command to reset keyboard.
199 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
201 @return Status of command issuing.
205 IN EFI_ISA_IO_PROTOCOL
* IsaIo
211 Status
= Out8042AuxCommand ( IsaIo
, RESET_CMD
, FALSE
);
212 if ( EFI_ERROR ( Status
)) {
216 Status
= In8042AuxData ( IsaIo
, & Data
);
217 if ( EFI_ERROR ( Status
)) {
221 // Check BAT Complete Code
223 if ( Data
!= PS2MOUSE_BAT1
) {
224 return EFI_DEVICE_ERROR
;
227 Status
= In8042AuxData ( IsaIo
, & Data
);
228 if ( EFI_ERROR ( Status
)) {
232 // Check BAT Complete Code
234 if ( Data
!= PS2MOUSE_BAT2
) {
235 return EFI_DEVICE_ERROR
;
242 Issue command to set mouse's sample rate
244 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
245 @param SampleRate value of sample rate
247 @return Status of command issuing.
250 PS2MouseSetSampleRate (
251 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
252 IN MOUSE_SR SampleRate
258 // Send auxiliary command to set mouse sample rate
260 Status
= Out8042AuxCommand ( IsaIo
, SETSR_CMD
, FALSE
);
261 if ( EFI_ERROR ( Status
)) {
265 Status
= Out8042AuxData ( IsaIo
, SampleRateTbl
[ SampleRate
]);
271 Issue command to set mouse's resolution.
273 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
274 @param Resolution value of resolution
276 @return Status of command issuing.
279 PS2MouseSetResolution (
280 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
281 IN MOUSE_RE Resolution
287 // Send auxiliary command to set mouse resolution
289 Status
= Out8042AuxCommand ( IsaIo
, SETRE_CMD
, FALSE
);
290 if ( EFI_ERROR ( Status
)) {
294 Status
= Out8042AuxData ( IsaIo
, ResolutionTbl
[ Resolution
]);
300 Issue command to set mouse's scaling.
302 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
303 @param Scaling value of scaling
305 @return Status of command issuing.
309 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
315 Command
= ( UINT8
) ( Scaling
== Scaling1
? SETSF1_CMD
: SETSF2_CMD
);
318 // Send auxiliary command to set mouse scaling data
320 return Out8042AuxCommand ( IsaIo
, Command
, FALSE
);
324 Issue command to enable Ps2 mouse.
326 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
328 @return Status of command issuing.
332 IN EFI_ISA_IO_PROTOCOL
* IsaIo
336 // Send auxiliary command to enable mouse
338 return Out8042AuxCommand ( IsaIo
, ENABLE_CMD
, FALSE
);
342 Get mouse packet . Only care first 3 bytes
344 @param MouseDev Pointer of PS2 Mouse Private Data Structure
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.
352 PS2_MOUSE_DEV
* MouseDev
357 BOOLEAN KeyboardEnable
;
358 UINT8 Packet
[ PS2_PACKET_LENGTH
];
362 INT16 RelativeMovementX
;
363 INT16 RelativeMovementY
;
367 KeyboardEnable
= FALSE
;
369 State
= PS2_READ_BYTE_ONE
;
372 // State machine to get mouse packet
377 case PS2_READ_BYTE_ONE
:
379 // Read mouse first byte data, if failed, immediately return
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
;
389 KbcEnableAux ( MouseDev
-> IsaIo
);
390 return EFI_NOT_READY
;
393 if ( IS_PS2_SYNC_BYTE ( Data
)) {
395 State
= PS2_READ_DATA_BYTE
;
397 CheckKbStatus ( MouseDev
-> IsaIo
, & KeyboardEnable
);
398 KbcDisableKb ( MouseDev
-> IsaIo
);
399 KbcEnableAux ( MouseDev
-> IsaIo
);
403 case PS2_READ_DATA_BYTE
:
405 Status
= PS2MouseRead ( MouseDev
-> IsaIo
, ( Packet
+ 1 ), & Count
, State
);
406 if ( EFI_ERROR ( Status
)) {
407 if ( KeyboardEnable
) {
408 KbcEnableKb ( MouseDev
-> IsaIo
);
411 return EFI_NOT_READY
;
415 if ( KeyboardEnable
) {
416 KbcEnableKb ( MouseDev
-> IsaIo
);
419 return EFI_NOT_READY
;
422 State
= PS2_PROCESS_PACKET
;
425 case PS2_PROCESS_PACKET
:
426 if ( KeyboardEnable
) {
427 KbcEnableKb ( MouseDev
-> IsaIo
);
432 RelativeMovementX
= Packet
[ 1 ];
433 RelativeMovementY
= Packet
[ 2 ];
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
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.
444 // First, Clear X and Y high 8 bits
446 RelativeMovementX
= ( INT16
) ( RelativeMovementX
& 0xFF );
447 RelativeMovementY
= ( INT16
) ( RelativeMovementY
& 0xFF );
449 // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff
451 if (( Packet
[ 0 ] & 0x10 ) != 0 ) {
452 RelativeMovementX
= ( INT16
) ( RelativeMovementX
| 0xFF00 );
454 if (( Packet
[ 0 ] & 0x20 ) != 0 ) {
455 RelativeMovementY
= ( INT16
) ( RelativeMovementY
| 0xFF00 );
459 RButton
= ( UINT8
) ( Packet
[ 0 ] & 0x2 );
460 LButton
= ( UINT8
) ( Packet
[ 0 ] & 0x1 );
463 // Update mouse state
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
;
477 Read data via IsaIo protocol with given number.
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
484 @return status of reading mouse data.
488 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
490 IN OUT UINTN
* BufSize
,
497 Status
= EFI_SUCCESS
;
500 if ( State
== PS2_READ_BYTE_ONE
) {
502 // Check input for mouse
504 Status
= CheckForInput ( IsaIo
);
506 if ( EFI_ERROR ( Status
)) {
511 while ( BytesRead
< * BufSize
) {
513 Status
= WaitOutputFull ( IsaIo
, TIMEOUT
);
514 if ( EFI_ERROR ( Status
)) {
518 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Buffer
);
521 Buffer
= ( UINT8
*) Buffer
+ 1 ;
524 // Verify the correct number of bytes read
526 if ( BytesRead
== 0 || BytesRead
!= * BufSize
) {
527 Status
= EFI_NOT_FOUND
;
530 * BufSize
= BytesRead
;
537 I/O work flow of outing 8042 command.
539 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
540 @param Command I/O command.
542 @retval EFI_SUCCESS Success to excute I/O work flow
543 @retval EFI_TIMEOUT Keyboard controller time out.
547 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
555 // Wait keyboard controller input buffer empty
557 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
558 if ( EFI_ERROR ( Status
)) {
565 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
567 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
568 if ( EFI_ERROR ( Status
)) {
576 I/O work flow of outing 8042 data.
578 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
579 @param Data Data value
581 @retval EFI_SUCCESS Success to excute I/O work flow
582 @retval EFI_TIMEOUT Keyboard controller time out.
586 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
593 // Wait keyboard controller input buffer empty
595 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
596 if ( EFI_ERROR ( Status
)) {
601 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Temp
);
603 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
604 if ( EFI_ERROR ( Status
)) {
612 I/O work flow of in 8042 data.
614 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
615 @param Data Data value
617 @retval EFI_SUCCESS Success to excute I/O work flow
618 @retval EFI_TIMEOUT Keyboard controller time out.
622 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
629 Delay
= TIMEOUT
/ 50 ;
632 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Temp
);
635 // Check keyboard controller status bit 0(output buffer status)
637 if (( Temp
& KBC_OUTB
) == KBC_OUTB
) {
643 } while ( Delay
!= 0 );
649 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Data
);
655 I/O work flow of outing 8042 Aux command.
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.
661 @retval EFI_SUCCESS Success to excute I/O work flow
662 @retval EFI_TIMEOUT Keyboard controller time out.
666 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
675 // Wait keyboard controller input buffer empty
677 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
678 if ( EFI_ERROR ( Status
)) {
682 // Send write to auxiliary device command
684 Data
= WRITE_AUX_DEV
;
685 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
687 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
688 if ( EFI_ERROR ( Status
)) {
692 // Send auxiliary device command
694 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Command
);
699 Status
= In8042AuxData ( IsaIo
, & Data
);
700 if ( EFI_ERROR ( Status
)) {
704 if ( Data
== PS2_ACK
) {
706 // Receive mouse acknowledge, command send success
714 return EFI_DEVICE_ERROR
;
716 } else if ( Data
== PS2_RESEND
) {
720 Status
= Out8042AuxCommand ( IsaIo
, Command
, TRUE
);
721 if ( EFI_ERROR ( Status
)) {
727 // Invalid return code
729 return EFI_DEVICE_ERROR
;
737 I/O work flow of outing 8042 Aux data.
739 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
740 @param Data Buffer holding return value
742 @retval EFI_SUCCESS Success to excute I/O work flow
743 @retval EFI_TIMEOUT Keyboard controller time out.
747 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
754 // Wait keyboard controller input buffer empty
756 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
757 if ( EFI_ERROR ( Status
)) {
761 // Send write to auxiliary device command
763 Temp
= WRITE_AUX_DEV
;
764 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Temp
);
766 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
767 if ( EFI_ERROR ( Status
)) {
772 IsaIo
-> Io
. Write ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , & Temp
);
774 Status
= WaitInputEmpty ( IsaIo
, TIMEOUT
);
775 if ( EFI_ERROR ( Status
)) {
783 I/O work flow of in 8042 Aux data.
785 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
786 @param Data Buffer holding return value.
788 @retval EFI_SUCCESS Success to excute I/O work flow
789 @retval EFI_TIMEOUT Keyboard controller time out.
793 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
800 // wait for output data
802 Status
= WaitOutputFull ( IsaIo
, BAT_TIMEOUT
);
803 if ( EFI_ERROR ( Status
)) {
807 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_DATA_PORT
, 1 , Data
);
814 Check keyboard controller status, if it is output buffer full and for auxiliary device.
816 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
818 @retval EFI_SUCCESS Keyboard controller is ready
819 @retval EFI_NOT_READY Keyboard controller is not ready
823 IN EFI_ISA_IO_PROTOCOL
* IsaIo
828 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
831 // Check keyboard controller status, if it is output buffer full and for auxiliary device
833 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) != ( KBC_OUTB
| KBC_AUXB
)) {
834 return EFI_NOT_READY
;
841 I/O work flow to wait input buffer empty in given time.
843 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
844 @param Timeout Wating time.
846 @retval EFI_TIMEOUT if input is still not empty in given time.
847 @retval EFI_SUCCESS input is empty.
851 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
858 Delay
= Timeout
/ 50 ;
861 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
864 // Check keyboard controller status bit 1(input buffer status)
866 if (( Data
& KBC_INPB
) == 0 ) {
872 } while ( Delay
!= 0 );
882 I/O work flow to wait output buffer full in given time.
884 @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL
885 @param Timeout given time
887 @retval EFI_TIMEOUT output is not full in given time
888 @retval EFI_SUCCESS output is full in given time.
892 IN EFI_ISA_IO_PROTOCOL
* IsaIo
,
899 Delay
= Timeout
/ 50 ;
902 IsaIo
-> Io
. Read ( IsaIo
, EfiIsaIoWidthUint8
, KBC_CMD_STS_PORT
, 1 , & Data
);
905 // Check keyboard controller status bit 0(output buffer status)
906 // & bit5(output buffer for auxiliary device)
908 if (( Data
& ( KBC_OUTB
| KBC_AUXB
)) == ( KBC_OUTB
| KBC_AUXB
)) {
914 } while ( Delay
!= 0 );